プロのプログラマとはただ仕様通りに動くプログラムを作ればいいという物ではない。
保守性や拡張性を考慮し、変更に強くバグの混在しにくいプログラムを効率よく作る必要がある。
その為に、プログラミングする上で心に留めておかなくてはならない事がある。
今回はその中でも、オブジェクト指向言語においてプログラミングする際に私が意識している事を書き留めたい。
保守性や拡張性を考慮し、変更に強くバグの混在しにくいプログラムを効率よく作る必要がある。
その為に、プログラミングする上で心に留めておかなくてはならない事がある。
今回はその中でも、オブジェクト指向言語においてプログラミングする際に私が意識している事を書き留めたい。
- デメテルの法則
オブジェクト間の依存度を最小限にする為に任意のオブジェクトが参照出来る範囲を下記の4つに制限する。(メソッドチェーンを許容しない)
但し、メソッドの戻り値が呼び出し元インスタンスと同じクラスの場合はメソッドチェーンを許容する。- 任意のオブジェクト自身
- メソッドの引数に渡されたオブジェクト
- メソッドの内部で新たにインスタンス化されたオブジェクト
- 任意のオブジェクトを直接的に構成するオブジェクト(任意のオブジェクトのインスタンス変数)
- Command-Query分離原則
オブジェクトの状態を意図せず変えてしまう事が無いように、
オブジェクトが持つメソッドは自身のインスタンスへの変更のみを行うCommandと
自身のインスタンスの状態を返すQueryに分離する事。
具体的にはインスタンスの状態を変えてしまうメソッドは戻り値を持たないvoidで定義し、
戻り値を返すメソッドの中ではインスタンスの状態を一切変更しない。
*Command:オブジェクトに対しての操作。オブジェクトの状態を変更する。
*Query:オブジェクトからのデータ取得。オブジェクトの状態を変更しない。 - オペランド引数基本原則
メソッドの引数は基本的にオペランドのみとし、オプション(デフォルト値が存在する引数)はCommandにて設定するべきである。
*名前付き引数等、オプションをオプションとして扱える仕様の言語が増えてきている(C#、Ruby、Python等)のであまり気にしなくてよい?
staticクラス・メソッドのみ名前付き引数を使い、インスタンスメソッドの引数はオペランドのみを引数とすべき?
個人的には名前付き引数がある言語ならオプション引数使ってもいいのではと思う…
- SOLID原則
オブジェクト指向設計における5大原則の頭文字を並べたもの。
それぞれ下記の通り。 - 単一責任の原則
クラスは1つの責務を持つ。
十得ナイフのクラスを作る場合、1つのクラスに10種類の処理を持つメソッドを用意するのではなく、10種類のクラスとそれらのインスタンスを持つ十得ナイフクラスを持つ。 - 開放・閉鎖原則
クラスは拡張に対して開かれていて、修正に対して閉じているべきである。
作成したクラスに対する修正は原則的にバグの修正のみとし、新たな機能を追加する場合は同じインターフェイスまたは抽象クラスを実装した新しいクラスを作成するべきである。 - リスコフの置換原則
基本クラスは派生クラスに置き換える事ができなければならない。
派生クラスがOverrideした事によって基本クラスの処理を利用側のオブジェクトが意図せぬ内容にしてはならない。(基本クラスでは-1,0,1のいずれかが返ると定義している処理を派生クラスによってい-255~255の間で返す、基本クラスで定義していない例外が発生する等) - インターフェイス分離の原則
クライアントに不要なメソッドを提供する肥大したインターフェイスを作成しない。
複数のクライアントで一部のメソッドを共通で使用するインターフェイスが存在する場合、共通となるメソッドを持つ親インターフェイスを作成し、必要なインターフェイスに継承させる。 - 依存性逆転の原則
上位のモジュールは下位のモジュールに依存してはならず、「抽象」に依存すべきである。
「抽象」は実装に依存してはならず、実装が「抽象」に依存すべきである。
上位レイヤーで発生した変更は下位レイヤーに影響するが、下位レイヤーで発生した変更は上位レイヤーに影響すべきでない。
そのうち時間をとってそれぞれしっかり掘り下げて書きたいけど、とりあえず今は知識の棚卸し…
*DRY原則やYAGNI等のオブジェクト指向と直接関係の無いデザインルールは今回除外してます。
*DRY原則やYAGNI等のオブジェクト指向と直接関係の無いデザインルールは今回除外してます。