手続き型じゃなく、オブジェクト指向っぽく書くためには。
ただ、全て守ればいいというわけではなくこれに近づけるとオブジェクト指向っぽくなるので実際に使う際はある程度緩めても良いかもしれない。
クラス設計
継承を使うのであればできるだけ「抽象クラス」を使う
クラスの用途をできるだけ限定するため。クラス名の先頭に「Abstract〜」などと付けてこれは継承することが前提のものですよということを他の開発者に伝えるようにすると良いでしょう。
クラス内部実装で心掛けた方が良いこと
メソッドないのインデントは1段まで
例えば、for文の中にif文を書いたりすることもできない。
そうすることで1つのメソッドの持つ役割を小さくすることができる。
elseは禁止
早期リターン(ガード節)などをしても良い。
1 2 |
if (isXXX) return calcXXX if (isYYY) return calcYYY |
プリミティブ型(int、boolean)と文字列型(string)はラップする。
以下のようにしてはダメ
1 2 |
private int age private string name |
別途クラスを作った上でこうする。
1 2 |
private Age age private Name name |
なぜかと言えば、Ageクラス側でマイナスの値を受け付けないなどの処理を書くなどをする。(普通に考えて年齢にマイナスはあり得ないので、普通にプリミティブな型を使うよりもageらしい型を作ることができる。)
これをいわゆる「値オブジェクト(valueオブジェクト)」と呼びます。
1クラスは50行まで、1ディレクトリ(パッケージ)10ファイルまで
1クラスにつきインスタンス変数は2つまで
例えば、userクラスには10個くらいインスタンス変数があったとしても無理にでも意味づけして別クラスにして抽象化すること。そうするとオブジェクト指向っぽく書ける。
ファーストクラスコレクションを使用する。
配列や、コレクションなどをそのまま使うのではなくクラスでラップすること。
getter、setter、publicプロパティ禁止
publicプロパティ
勝手に外から書き換えられてしまうことになってしまう。必ずprivateプロパティにしましょう。
getter、setter
せっかくprivateにしてもこれで直接書き換えられてしまったら意味がないです。getter、setterは不要であることが望ましいです。
では、そのオブジェクトのメンバーの値が知りたい場合は知りたい用途などがあると思うので、isXXXなどのメソッドを作るなどしてオブジェクト側で制御構文を記述するような作りにしましょう。
なぜこうするかというと、以下の理由があるため。
- 原則データは隠すもののため。
- 値の変更に強くなるため。(クラスの外側で値を参照させてしまうとクラスの外側で具体的に値を参照することになるので色んな箇所を修正する必要が出てきてしまう。)
デメテルの法則を守る。
オブジェクト指向のメソッド呼び出しに秩序をもたらすガイドラインです。
メソッドを呼び出すオブジェクトは次の4つに限定されます。
オブジェクト自身
引数として渡されたオブジェクト
インスタンス変数
直接インスタンス 化したオブジェクト
例えば
「親クラス.子クラス.子クラスのメソッド」みたいな形でメソッドを呼び出すのはNGということですね。
守らないことによるデメリット
密結合になる。
例えば、子クラスでメソッドやプロパティを削除したときに親クラスまで参照して直さないといけなくなってしまう。
テストがしづらくなる。
対策
Railsでは
delegateを使ってメンバーを呼び出すという方法もあるみたいです。(厳密には対策になってないかもしれない)
この記事へのコメントはありません。