質問: いつもお世話になっております。 オブジェクト指向プログラミングについて勉強中の者です。 表題の件ですが、オブジェクト指向プログラミングをするにあたってクラスを作成する時があると思いますが、皆様はクラスを作成する際に、どのような考え方でクラスを作成してますでしょうか? 例えば、じゃんけんゲームを作成するとして私の場合、自分クラス、相手クラス、結果クラスを作成しその中でグー、チョキ、パー等の変数を用意して結果クラスに値を渡して結果を返して表示するというような考え方になります。 じゃんけんゲームというような単純なシステムならともかく、これが大きなシステムを作るとなった時に、どのような考え方でクラスを作成すれば誰が読んでも理解しやすいコードになるか教えていただけると幸いです。 そんなのシステムの仕様によっていくらでも変わってくるという風に思えてきますが、 皆様のクラスを作成する場合はこのように考えてクラスを作成しているという様な事を教えていただければと思います。 よろしくお願いいたします。
回答: まず、大きめの紙かホワイトボードに、作りたいものを説明するときに登場する思いつく限りの単語を書き出します。(これれらをビジネスドメイン用語という) このうち、何かの名前であるものはすべてオブジェクトの候補です。 オブジェクト名をよく眺めると似たもの同士で集めたグループができます。 そのグループを表す名前があれば、それはクラスの候補です。 グループのメンバーにさらに役割や動作の異なる種類がりそれに名前があれば、それはサブクラスの候補です。 グループのメンバーが状態や種別を表すのなら、クラスの代わりに列挙(enum)できるかもしれません。 クラスの集まり眺めるとまた性質や扱いに似た者同士が集まります。 そのクラスの集まりに名前が付けられたら、○○的なものという抽象クラス(あるいはインターフェース)の候補です。 単語のうち、何らかの動詞であるものはオブジェクトの機能でありメソッドの候補です。 メソッド名をよく眺めると関連するもの同士を集めたグループができます。 そのグループを表す名前があれば、○○するものというインターフェースの候補です。 余った単語のうち、あるオブジェクトの一部や状態のことだったら、それはプロパティの候補です。 この時点でプロパティは出し切れません。 同じクラスのオブジェクトの集まりを管理するオブジェクトが必要になるでしょう。 そのためのクラスを定義してもいいですが、とりあえずありもののコレクションライブラリでいいでしょう。 最後にこれらのクラスを作りたかったビジネスロジックを実装するアプリケーションクラスを作ります。 しかしこれはなんとかというアンチパターンで実装後ほどなく破たんします。 そうならないようもう一度書き出して、各単語間の関係を線や丸囲みで整理します。 その線や丸がなるべく階層性を持つように整理します。 依存性の矢印がなるべく重なったりループにならないよう整理します。 クラスを分けたりくっつけたり移動したり消したりインターフェースを切ったりつぶしたりします。 よく見ると、結合度によって境界と島ができます。 この島も階層性を表すように整理します。 この島と島を結ぶ線をなるべく少なくなるように整理します。 依存性が逆流している線をなるべく少なくなるように整理します。 島と島を突き抜けた矢印がなるべく少なくなるように整理します。 この整理で悩んだところが、デザインパターンの候補です。 この島の構成をなぜこうしたのか説明できる言葉を持つことが、人にわかってもらう気もためのキモです。 島のレイヤーが増えて境界に晒すインターフェースをたくさんきるでしょう。 オブジェクト間の関連もまたオブジェクトであることに気づきクラスとインターフェースを切るでしょう。 複雑なオブジェクトの生成方法に悩むでしょう。 オブジェクトの責務が上に行ったり下に行ったりするでしょう。 ビジネスドメイン以外のクラスも必要ですが、これらはとりあえずありもののライブラリやフレームワークを試します。 何日か経ちます。 ファイルやDBといった外部リソースはありもののライブラリやフレームワークを試します。 何日か経ちます 各クラスのテストクラスもそろそろ用意します。 設定クラス、定数クラス、例外クラス、ロガーなど、今は使わなくても追加しておきます。 アプリケーションコンテナの規約にそった実装も必要になります。 これは何時でもすぐにスタートアップできるテンプレートを用意しておきまましょう。 実装を開始します。 うかつな設計に気づきます。 あるオブジェクトがある特殊な状態を表現できないことに気づきます。 あるオブジェクトを取り出すのが異常に面倒くさいことに気づきます。 あるオブジェクトが多対多でなければならなかったことに気づきます。 認証やセキュリティ対策を後から入れるのは大変なことに気づきます。 ライブラリやフレームワークの選択に間違えたことに気づきます。 設計破りの穴をあける決断を迫られミジメな気持ちになります。 自分の愚かさとうぬぼれに気づきのたうちまわります。 以下略・・・