インベントリシステム(持ち物)サンプルのリファクタリングいろいろ
インベントリシステムは業務アプリケーションやゲームなど幅広く使われている仕組みです
プログラミングの基本構成の1つと考えていいでしょう
ここでは、どのように考えていくのかをみていくことにしましょう
仕様を考える
今回は、インベントリシステムのアイテム管理に絞って考えていきます
アイテム管理
ゲーム内のアイテムやリソース(武器、防具、食料、材料など)を一元管理し、プレイヤーキャラクターが持っているものを表示します。
クラス図で確認する構成
アイコンの説明
最初にクラス図で使われているアクセス修飾子の説明をしておきます

アクセス修飾子は、クラス設計やソフトウェアアーキテクチャの設計において、情報隠蔽やセキュリティの観点から非常に重要です。 PlantUMLを使用することで、これらのアクセス修飾子を含むクラス図を効果的に表現できます。
クラス図
以降のコードの「List版に戻して比較」をベースにしています

クラス図の説明
- ItemType (列挙型): ItemType は列挙型で、アイテムの種類を表します。この列挙型には “斧" と “剣" の2つの値が含まれています。
- OwnedItem (クラス): OwnedItem は、所有しているアイテムを表すクラスです。このクラスには以下のフィールドとメソッドが含まれています:
- Type フィールド: アイテムの種類を保持します。
- Number フィールド: アイテムの数量を保持します。
- OwnedItem(type: ItemType, number: int = 0) コンストラクタ: アイテムの種類と数量を指定して OwnedItem オブジェクトを初期化します。
- IncreaseNumber(number: int) メソッド: アイテムの数量を増やします。
- Inventory (クラス): Inventory はアイテムの在庫を管理するクラスで、所有している複数の
OwnedItem
オブジェクトを保持します。このクラスには以下のフィールドとメソッドが含まれています:- ownedItems フィールド: OwnedItem オブジェクトのリストを保持します。
- Add(type: ItemType, number: int = 1) メソッド: アイテムを在庫に追加し、既存のアイテムがある場合は数量を増やします。
- PrintOwnedItems() メソッド: 所有しているアイテムの一覧をコンソールに出力します。
- Program (クラス): Program はアプリケーションのエントリーポイントを含むクラスで、Inventory クラスを使用してアイテムの追加と表示を行います。
クラス図はこれらのクラスとそれらの間の関連を視覚的に示しており、アイテムの種類、在庫管理、アイテムの数量増加、およびアプリケーションのエントリーポイントとの関連を表現しています。
様々なリファクタリング
リファクタリングをしていく経緯を含め、複数のコードサンプルを示します
どのコードも同じ動きをします
様々な実装方法があり、その仕様に応じて考えていくことになります
最初からベストを求める必要はないでしょう
また、自分の知識範疇から始めるのが良いでしょう
知識がついてくれrば、新しく知った仕組みを採用してみると良いでしょう
Gitが管理すれば、自分の成長も感じることができるでしょう
初期バージョン
Mainメソッドを記述しないトップレベルステートメントとしています
class Inventoryの宣言前までがMainメソッドのブロック内に該当します
斧:3
剣:10
アイテムの追加で種類だけを引数にすると新しいインスタンスを作成
Dictionaryを採用
主な変更点は以下の通りです:
Inventory
クラス内で所有アイテムの情報をDictionary
で管理するように変更し、アイテムの種類をキーとして扱います。これにより、アイテムの検索が効率的に行えます。OwnedItem
クラスのNumber
プロパティをprivate set
に変更し、外部から直接アクセスできないようにしました。アイテムの数を変更するために、IncreaseNumber
メソッドを使用します。PrintOwnedItems
メソッドをInventory
クラスに追加し、所有アイテムの一覧を表示するための専用メソッドを提供しました。Main
メソッドを含むProgram
クラスを追加し、実行可能なプログラムのエントリーポイントとして使用します。
これにより、コードがより整理され、拡張性が向上し、アイテム管理が効率的に行えるようになります。
メソッドのオーバーロードをデフォルト引数に置き換え
ドキュメントコメントの追加
List版に戻して比較
さらに付け加える機能など
シングルトンにする
唯一のインスタンスとして(1つしか作れないようにする)使えるようにしてみましょう
保存機能の追加
PlayerPrefsクラス
string型のデータを外部記憶装置に保存読み出しできるようにしましょう
Jsonでの管理
持ち物のリストのインスタンスをJsonフォーマットに変換して外部記憶装置に保存読み出しできるようにしましょう
Saveメソッドを追加してみましょう
持ち物を使う機能の追加
Useメソッドを追加してみましょう
インナークラスの採用
ItemType列挙型をまたItemクラスのブロックに戻して、ownedItemクラスをInventoryクラスのインナークラスとしてみましょう
補足
リストに含まれているかをチェックするコード
このコードは、C#言語で書かれたコードの一部であり、リストまたはコレクション内で指定された条件に一致する最初の要素を見つけるためのLINQ(Language-Integrated Query)クエリを使用しています。以下にコードの要点を説明します:
ownedItems
は、リストやコレクションのようなデータ構造を表す変数です。このリストにはOwnedItem
という型の要素が含まれているものと仮定します。FirstOrDefault
メソッドは、LINQクエリを使用してリスト内で指定された条件に一致する最初の要素を取得するためのメソッドです。このメソッドは、条件に一致する要素が見つからない場合にはデフォルトの値を返します。item => item.Type == type
は、LINQのラムダ式です。これは、リスト内の各要素に対して条件をチェックし、Type
プロパティが指定されたtype
変数の値と一致する要素を探します。existingItem
は、条件に一致する最初の要素を格納するための変数です。条件に一致する要素が見つからない場合、existingItem
にはデフォルトの値(null
またはdefault(OwnedItem)
)が格納されます。
したがって、このコードは、ownedItemsリスト内の要素から、指定されたtypeに一致する最初の要素を検索し、その要素をexistingItem変数に格納します。この方法は、特定の型やプロパティに基づいて要素をフィルタリングおよび検索するために一般的に使用されます。
このラムダ式は、引数がitem
という名前の変数で、条件式がitem.Type == type
である匿名関数を表しています。分解して説明します:
item
:これはラムダ式の引数です。item
はコレクション内の各要素を代表します。=>
:この記号はラムダ式のパラメータリストと本体を区別します。左側が引数リストで、右側が本体です。item.Type == type
:これはラムダ式の本体です。item.Type
は、item
オブジェクトのType
プロパティを表し、type
は外部の変数です。
このラムダ式は、コレクション内の各要素(item
)に対して、その要素のType
プロパティが外部のtype
変数の値と一致するかどうかをチェックします。ラムダ式の評価結果は真偽値(true
またはfalse
)で、条件が一致した場合にtrue
を返し、それ以外の場合にfalse
を返します。このラムダ式はLINQクエリ内で使用され、条件に一致する最初の要素を見つけるために使用されます。
メソッドに置き換えると
ラムダ式をメソッドに置き換えることは可能です。これにより、コードがより読みやすくなり、同じ条件を複数の場所で再利用できます。次に、ラムダ式をメソッドに置き換えた例を示します
元のラムダ式
これをメソッドに変換すると
新しいメソッド IsMatchingType は OwnedItem 型の item
オブジェクトと ItemType 型の type パラメータを受け取り、条件を評価して真偽値を返します。これでラムダ式の代わりにメソッドを使用することができます。
LINQクエリ内でメソッドを使用する場合、次のようになります
このように、IsMatchingType メソッドを呼び出すことで、コードがより読みやすくなり、条件の詳細をメソッド内でカプセル化できます。また、同じ条件を複数の場所で再利用する際にも便利です。
参考
PlantUMLクラス図アクセス修飾子説明
このPlantUMLのコードでは、MyClassというクラスを定義して、さまざまなアクセス修飾子を示しています。アクセス修飾子の記号とその意味は以下の通りです:
-
: プライベート (Private) アクセス修飾子は、同じクラス内からのみアクセスできるフィールドやメソッドを示します。他のクラスからはアクセスできません。#
: プロテクテッド (Protected) アクセス修飾子は、同じクラス内およびそのサブクラスからのみアクセスできるフィールドやメソッドを示します。~
: パッケージ (Package) アクセス修飾子は、同じパッケージ内からのみアクセスできるフィールドやメソッドを示します。パッケージは特定のプログラミング言語の概念で、Javaなどで使用されます。+
: パブリック (Public) アクセス修飾子は、どのクラスからでもアクセスできるフィールドやメソッドを示します。
アクセス修飾子は、クラス設計やソフトウェアアーキテクチャの設計において、情報隠蔽やセキュリティの観点から非常に重要です。 PlantUMLを使用することで、これらのアクセス修飾子を含むクラス図を効果的に表現できます。
クラス図コード
innerClassProject
ディスカッション
コメント一覧
まだ、コメントがありません