0. この投稿の概要
- 最近話題の「良いコード/悪いコードで学ぶ設計入門」を読んだので学んだことをまとめます。どれくらいのレベル感の内容が説明されているか知るための参考になれば幸いです。
- 本書はJavaのサンプルコードが記載されています。自分はオブジェクト指向言語ではPythonを多用するので、Pythonで実現する場合の文法も調べて併記しました。
1. 学んだこと
クラス設計の基本
- 完全コンストラクタ: 初期化時点でインスタンス変数を指定し終え、その後はsetterなどで値を変更しない。値を更新する必要があれば新しくインスタンスを生成して返す。→思わぬ場所で値が変更されることを防ぎ、実行結果が毎回同じになるためテストもしやすくなる。
- Pythonでも3.8からFinal型注釈を付けられるようになっています。 PEP 591 – Adding a final qualifier to typing | peps.python.org
- ローカル変数や引数も基本的には不変にしておくことが推奨されています。可変にするのは大量のデータ処理などでパフォーマンスに影響があるケースなど。
- getterやsetterを実装することはカプセル化ではない。
- 値オブジェクト: 値をプリミティブ型ではなくクラスとして表現する。これにより不正な値を防ぐことができる。また、その値に関する計算も備えさせると、そのロジックが色々な場所に実装されることを防げる。
- 基本的にはインスタンス変数を用いるメソッドをクラスに持たせ、ログ出力用のような汎用的なもの以外でstaticメソッドを避ける。
- 目的別に異なる初期化をするためのファクトリメソッドもstaticメソッドとして実装される。
- コレクション型についても同様にコレクションとそれを操作するメソッドをクラスにまとめる(ファーストクラスコレクション)。
- Pythonではリストの要素の変更を禁止するメソッドは見当たりませんでした。代わりにcopyメソッドで別のオブジェクトとして返せばいいかと思います。
- サブクラスはスーパークラスに大きく依存するため、継承は安易に使うべきではない。継承より委譲、コンポジションとして使いたいクラスをもたせると変更の影響を受けにくい。
ネストを浅くするテクニック
- 早期リターンでif文のネストやif-else文をすっきりさせる。
- 種類毎に処理を切り替えたい場合はswitch文の代わりにinterfaceを用いて実装する(ストラテジパターン)。mapから使いたいインスタンスを持ってきて、共通のメソッドをコールする。
- Pythonではinterfaceはabcモジュールを使って実装できます。(使わなくても実装できますが…) abc — Abstract Base Classes — Python 3.10.4 documentation
- フラグ引数でメソッド内の処理を切り替える場合もストラテジパターンを使った方がいい。
- 複数の条件をチェックしたい場合はポリシーパターンを使う。これは条件判定のinterfaceを作り、それを元に具体的な条件を1つ1つ実装する。ルールを集約するクラスに必要な条件をコレクションとして持たせてfor文で全て確認する。
名前設計
- たとえ現実世界のオブジェクトが1つだとしても、関心事や目的に応じてより具体的なクラスへ分割する。例: Userを個人認証のためにPersonalAccount、特徴表現のためにProfileとして定義する。
- 開発中の会話の中で頻発するキーワードや形容詞はそのままコード上のクラス名などに実装する。
- Manager, Processor, Controllerという単語をclass名に入れると巨大なクラスになりがち。具体的にやることで名付けるべき。
- 「動詞+目的語」のメソッドに注意。この場合目的語の概念を表現するクラスを作り、そのクラスに動詞1語のメソッドを追加するとよい。
2. 総評
- オブジェクト指向プログラミングにまだ自信のない自分としては、参考になるテクニックを見つけることができました。ただ章と章の結びつきが弱く、ストーリー性が薄いためTips集のような印象を受けました。逆に言えばどの章からでも読み始められる利点はあるのですが…
- interfaceの理解は特に重要だと思いますが、本書のように初心者向けの本でわかりやすい説明が書かれたものは少ないように思います。言語の本は機能だけの説明になりがちですし、OOPの本でさえポリモーフィズムの説明はありますがそれが実践の場でどのように役立つのかイメージしづらいです。
- そういった意味でJavaエンジニアの初心者には文法を学んだ次の一冊としておすすめします。初心者にとって他言語で書かれた本はとっつきにくい所ではありますが、オブジェクト指向の言語を使うのであればJavaエンジニア以外も選択肢に入れて良いと思います。
3. その他の参考書
- 現場で役立つシステム設計の原則: 業務システムを例としたシステム設計の入門書です。言語はJavaで、データベースやUIなどについても説明されているため本書よりも範囲が広いです。本書でも紹介されていますが、業務システムを開発するなら次に読む本として丁度いいかと思います。
- 私はいつもトップダウンで考えていたので、「実現したい機能を分解するとその分解の仕方に部品が依存してしまうので、ボトムアップで業務の関心事を独立した部品(ドメインオブジェクト)として実装していく」というオブジェクト指向設計の説明は印象的でした。