記事を書く目的
情報をインプットしてアウトプットする練習のため、毎週本を読み理解したことや気になったことをまとめてみようと思い、投稿します。
以下記載する内容は個人の見解であり、内容が正しいかどうかは保証できないことをご理解ください。
3章 クラス設計-すべてにつながる設計の基盤-
保守や変更がしやすいコードを書くには、関心の分離が重要である。
不変で思わぬ動作を防ぐ
変数に値が再代入されると、値がいつ変更されたのかや今どのような値が入っているかが追いづらい。
その結果、仕様が変わった場合に意図しない値に書き変わってしまういわゆる「副作用」を起こし兼ねない。
これを防止するために、インスタンス変数やメソッドの引数を不変(イミュータブル)にすることを検討する。
もし、値を変更したくなったら値を変更した新しいインスタンスを生成する。
値オブジェクト
値オブジェクトとは、値の概念そのものをクラスとして表現することである。
例えば、お金を表したい時には「BigDecimal」を利用するのではなく(内部的には利用するかもしれないが)、「Money」クラスを自分で作成するべし。
こうすることで、誤って異なるBigDecimal型の変数をメソッドの引数に渡してしまったり、お金に関連するロジックが複数箇所に散らばってしまうことを未然に防ぐことができる。
5章 低凝集-バラバラになったモノたち-
凝集度とは、モジュール内におけるデータとロジックの関係性の強さのことである。
ここでいうモジュールとはクラス、パッケージ、レイヤーなどさまざまな粒度があるが、クラスとして話を進める。
凝集度の低いクラスとは、データとロジックの関係性が弱いクラスのことである。
低凝集なクラスはデータとロジックが散らばっているため、変更に弱い。
一方で、高凝集なクラスはデータとロジックがまとまっているため、変更に強い設計であるといえる。
staticメソッドはデータとロジックを分離してしまう。
staticなメソッドはインスタンス変数を使うことができないため、データ(インスタンス変数)とそれを操作するロジックが乖離してしまう。
従って、可能であればインスタンスメソッドで代替できないか検討する。
ただし、staticなメソッドが有効なケースもある。
例えば、横断的に使用するログ出力用のメソッドやファクトリメソッドなど凝集度を意識する必要がない場面では検討するべし。
6章 条件分岐-迷宮化した分岐処理を解きほぐす手法-
ネストについて考える
条件がネストされていると仕様を把握しづらい。
また、if文が更に必要になった場合にネストがまた深くなってしまうだろう。
そこで、条件を満たしていない場合はただちにreturnで抜けてしまう早期returnを検討すると良い。
enumを使う前に考えたいこと
似ている特徴を持ちながら各々のオブジェクトに異なる振る舞いを持たせたい場合、よくenumとswitch文の組み合わせが用いられる。
しかし、enumとswitch文の組み合わせには、複数のデメリットがある。
- 同じ条件のswitch文が複数書かれていく。
- case文を追加漏れが起こりうる。
そこで、interfaceの導入を検討する。
interfaceの最大のメリットは、分岐処理を書かずに機能の切り替えを実装することができることである。
また、実装クラスでinterfaceをimplementsしていればコンパイラが自動的に未実装箇所を教えてくれるので、仕様変更時の実装漏れも起こりにくい。
(その他、ネストしたif文をinterfaceで解決する設計パターンとして、ポリシーパターンというのも紹介されていました。)
9章 設計の健全性をそこなう様々な悪魔たち
null問題
nullはさまざまな問題を起こしうる。
従って、「nullを返さない。渡さない」ようにすることを検討する。
例えば、値がないことを表現したい場合、static finalな変数の利用(Moneyクラスなら、Money.ZERO やMoney.Emptyなど)を検討する。
例外の握り潰し
例外を握りつぶしてしまうと、外から内部の不正な状態を検知する術がなくなります。
従って、問題を検出した場合は握り潰さず、即座に検知できる仕組みを作ることを検討する。
参考
来週読む予定の本
最後に、しっくりきた言葉を載せておきます。
「ソフトウェア開発に銀の弾丸はない。」
設計にbestはない。常にbetterを目指しましょう
おしまい。