EurekaMoments

This is my studying logs about Autonomous driving, Machine learning technologies and etc.

「現場で役立つシステム設計の原則」を読んで為になったことのメモ

背景

既にざっと1周読んだが、じっくりと2周目を読んだので、
参考になった部分をメモした。

目次

設計とはソフトウェア全体をすっきりした形に整えること

この時点で、設計に対する認識のずれがあるとわかった。
自分は今まで、ソフト設計は詳細な実装方法を決めることだと思っていた。

設計の最終アウトプットはソースコード

これも自分の認識と違っていた。
今までは、実装方法の詳細をドキュメント化したものだと思っていた。

目的ごとにローカル変数を用意する

メモリ使用量を少しでも節約しようと一つのローカル変数を
使いまわしがちだったが、それは可読性を低下させることになる。

特定の関心事に特化した小さなクラスが、コードの見通しを良くし、変更をやりやすくする

最初は小さく作ろうとしてても、時間が経つにつれて
どんどん大きくなってしまうので、そこで小さく保てるように
リファクタリングをこまめにしないといけない。

業務を理解するために要求を分析し、そこで発見した関心事の単位を、そのままプログラム単位としてクラスで表現する

クラス設計においてこういうことは意識していなかった。
自分達の業務を正しく反映させたクラス設計になっている
必要がある。

値を扱うための専用クラスを作る

これは今まで考えたこともなく、標準で用意されている
型しか使ってこなかった。その値の目的に応じて、取りうる
範囲を制限したりできるのは便利だと思った。

オブジェクトを外部に渡す際は変更不可な状態にして渡すこと

そもそも、オブジェクトを外部に渡さないといけないような
設計とならないようにしないといけない。
でも、これが本当に難しい。

複文を単文に分けてelse句を無くす

1つのソフトウェアでいろんな条件に対応させるようにすると、
自ずとif~else文が増えてくる。こういった部分をもっと理解しやすく
したいと思ってたので、これから意識していきたい。

区分ごとに別クラスを作り、インターフェースを使って同じ型として扱えるようにする

今までクラス設計で継承を全然使いこなしていなかったので、
これを参考に積極的に取り入れたい。

クラス間の結びつきは、知らないことが少ないほど弱くなる

結びつきは弱い方がいいのは分かっていたけど、
そのための上手い考え方が分からずにいた。
お互いに情報を必要以上に公開し合わないようにすればいい
というこの教えを見てなるほどと思った。

共通機能ライブラリは失敗しやすい

よくCommonとかUtilityみたいな感じで共通化した関数をまとめたり
するけど、バグがあったりすると全体に悪影響が出るし、途中で仕様
変更があったりすると回帰テストの手間も増える。
果たしてこのやり方は正解なのかという疑問がずっとあった。

コードを重複させない設計の基本は、インスタンス変数を返すだけのgetterを作らないこと

これは本当によくやってしまうことの一つ。
getterが必要になったときは、恐らくクラス設計の見直しが
必要なときなのだろう。

変だと気が付いたら、TO-DOとしてコメントを残す

今まで習慣付てなかったこと。
わざわざコメントとして書くまでもないことばかり書いて、
こういう大事なことは書いていなかった。

メソッドは必ずインスタンス変数を使う

クラスの責務を見直すのに良い判断材料だと思う。
インスタンス変数をまったく使ってないメソッドがあれば、
それはそのクラスが持つべきものじゃない。

ドメインモデルは対象業務をオブジェクトの集合として表現する技法

ドメインモデルとは何かがやっとわかった気がする。
オブジェクトの基本設計パターンは、
値オブジェクト、コレクションオブジェクト、
区分オブジェクト、列挙型の集合操作の4つ。

機能中心にプログラムを書くと、プログラムが処理の順番に依存する

最初はそのつもりじゃなくても、設計を進めるにつれて
いつの間にか機能中心の設計になってしまっている。

業務の関心事はヒト、モノ、コトに分類する

自分の業務の分析をする際の指針になる。
関心事のパターンは、
口座、期日、方針、状態の4つ。

コトはヒトとモノとの関係として出現する

クラス間の関係を定義する際の指針になる。
コトは時間軸に沿って明確な前後関係を持つ。

状態に依存する場合、使う側が事前に確認する

これは迷うところ。
使う側は何も考えずに呼び出せばいいように作るという手もある。

値がない場合に別の値で埋めるようなNULL逃れをしない

そういったカラムは別のテーブルに分ける。
横着して無理やり一つのテーブルにまとめようとしてしまうのを反省。

データベースには正しいデータのみを記録し、それを担保するのが設計の基本目的

今まで考えたことなかった。
おかしなデータが含まれていた時は前処理とかで
排除すればいいとばかり思っていた。

記録のタイミングが異なるデータはテーブルを分ける

これを分けないとNULLが含まれてしまうことになる。
横着して無理やり一つにまとめようとするなという話。

カラムの追加はテーブルを追加する

元のテーブルにどんどん追加するようにしてしまっていた。
こういう時も、目的や記録タイミングに合わせて分けないといけない。

画面に引きずられた設計はソフトウェアの設計を大変にする

画面に欲張っていろんな機能を盛り込んでしまうとこうなりやすい。

何でもできる汎用画面ではなく、用途ごとのシンプルな画面に分ける

こうすることで、画面に引きずられる設計にはなりにくくなりそう。

画面の表示ロジックと業務ロジックを分離する

今まで画面操作を伴うアプリを作るときは、両ロジックをごちゃごちゃに
書いてしまっていた。

画面をタスクベースに分解する

これを意識することで、画面のデザインをシンプルにできそう。
まずは、やりたいタスクの分析を事前にちゃんとやらないといけない。

画面の関心事とクラス設計を一致させる

こうすることでコードが理解しやすいものにできる。

画面デザインの4原則

近接、整列、対比、反復

画面以外の利用者向け情報もソフトウェアと整合させる

こういう情報の整備はついつい疎かにしてしまいがちだし、
ただ詳しく書いているだけでもダメということ。