増田 亨. 現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法 (Japanese Edition). Kindle 版.
恥ずかしながら今の会社に来てから初めて「ソフトウェア設計」というものに向き合った気がする。
しかし、これまで見様見真似や感覚でしかやってこなかったため、意思を疎通できなかった。
あるいは体系的に学び直すことで今後のエンジニア人生においても豊かになるのではと考え、この本を読んだのでまとめていく。
まとめ方は、この本の10あるCHATERの項目ごとに自分が考えた・感じ取ったことを書いていくことで、中身をしっかりと把握していくことにした。
なお、そのため目次だけは書いているが、以下に公開されているのでここに書いても大丈夫かなと判断。
https://gihyo.jp/book/2017/978-4-7741-9087-7
もちろん中身や詳細は買って読んでください。
なぜソフトウェアの変更は大変なのか
ソフトウェアの変更に立ち向かう
曰く、「ソフトウェア設計」を一言で表すと「どこに何が書いてあるのかわかりやすくする」。
これは設計に向き合うようになって初めに感じたことと一致して納得。
ソースコードも変数もメソッドもそれぞれ役割があって、どこに居るべきかが決まっていれば良く、それを関係者全員が同じように実現する ために必要なのが設計なんだなと。
変更が大変なプログラムの特徴
メソッドやクラスの大きさ、引数の多さが変更を大変にする。
実際プロダクトの一部で実際にこういうことがおこっていて、とにかく変数や条件分岐や無駄なステップが多く、そうなると関心事が増えて くるというのは体感である。
変更するたびに変更が大変になる
ちょっとした修正の積み重ねから、コードのじわじわと増えて構造が入れ組んでくる。
成長や機能改修が多い箇所はかなりの頻度でこういうことが起こりそうで、変更に強い(腐りにくい)ソースとなる設計が必要。
プログラムの変更が楽になる書き方
わかりやすい名前を使う
変数を一目瞭然の名称にするということで、現在、実際の業務で使っている変数名そのものが載っていてびっくりした。
もしかしたらシステムの種類、規模によっては英語圏の全世界共通で使えるユビキタス言語のようなものが実はあるのかもしれない。
というか、まあプログラミングは英数字を使うので、「英語の単語でこう書くよね」というのに則れば、そんな変な変数名にならないのかな。
長いメソッドは「段落」に分けて読みやすくする
ここら辺もリーダブルコードに書いてあった気がする。
目的ごとに変数を用意する
Scala では Immutable に実装すること(変数の値が変わらないように実装すること - Scala にはその仕組がある)を推奨していて、Immutabel に実装していけばこれは起こらない。
メソッドとして独立させる
「メソッドの抽出」はリファクタリングの第一歩。
異なるクラスの重複したコードをなくす
「メソッドの抽出」後は異なるクラス間で重複するコードをなくしていくとのこと。参照関係があれば書き換え、なければ別クラスに抽出するといった手順でリファクタリングしていく。
狭い関心事に特化したクラスにする
送料に関する値、メソッドだけ切り出して、「送料クラス」という小さな専用のクラスを作成する。これを「ドメインオブジェクト」と呼ぶ。
メソッドは短く、クラスは小さく
とにかく共通化と小分けしてコードの重複をなくすようにしていく。こうすることで変更箇所の特定が容易になるだけではなく、修正箇所が1過所になったりする。
小さなクラスでわかりやすく安全に
データとロジック
基本データ型を数値、日付、文字とし、プログラムの基本である演算(判断、加工、計算)を記述するのが業務ロジック。
この組み合わせをロジックの最小単位とする。
基本データ型の落とし穴
しかし、例えば数値の基本である int は-21億から+21億まであるので、一般的に金額項目に使用するのは危ない。
値の範囲を制限してプログラムをわかりやすく安全にする
そのため、「独自クラス(=例えば金額クラス)」の内部でバリデーションをかけることで、値の整合性を担保する。
このように、目的に特化した「型」を宣言することでソースコードは見違えるように意図が明確になり、動作が安定する。
「型」最高。
「値」を扱うための専用のクラスを作る
この「独自クラス」を「値オブジェクト(Value Object) 」と呼ぶ。
「値オブジェクト」は業務の用語そのもの。
DDD と親和性高そう。
「値オブジェクト」は「不変」にする
内部のインスタンス変数が変化しない不変な「値オブジェクト」は、副作用を減らしてバグが混入しにくくなる。
これを「完全コンストラクタ」と呼ぶ。
「値オブジェクト」を不変にするやりかたは
「型」を使ってコードをわかりやすく安全にする
「値オブジェクト」は業務の関心事を直接的に表現する。
「値オブジェクト」を作るには、実務で使っている具体的なデータを考えてみると良いとのこと。
例えば範囲が決まっている数値があったり、一定期間に収まっている必要があるなどの決め事があるはずで、妥当な範囲だけを扱うように設計する。
複雑さを閉じ込める
配列やコレクションはコードを複雑にする
コレクション型を扱うコードの整理
コレクション型を扱うロジックを専用クラスに閉じ込める
「値オブジェクト」のように「コレクション型」というものを作って、配列と業務ロジックを閉じ込めるテクニック。
コレクションのっデータとロジックを専用のクラスにして、オブジェクトを1つだけコレクションを持つ専用クラスを作る。
これを「コレクションオブジェクト」もしくは「ファーストクラスコレクション」と呼ぶ。
コレクションオブジェクトを安定させる
「値オブジェクト」と同様に、コレクションオブジェクトも不変にする。
コレクションオブジェクトは業務の関心事
コレクションオブジェクトの使い所として、例えば「売れ行きが好調な商品一覧」などに使用する。
まとめ
リーダブルコードに書いてあることもあれば、オブジェクト指向プログラミングの基礎から応用まであって振り返りのようなCHAPTERだった。
リファクタリングの基礎的な手順や、漠然とイメージしていた「ドメインオブジェクト」「値オブジェクト」「コレクションオブジェクト」などの理解が進んだ。