2018年7月28日土曜日

現場で役立つシステム設計の原則

最近は会社の金で本が買えるので、金の心配より読書する時間を作るのが大変。
自然に見たい本がある時は人のレビューを参考するようになっている。
そんな中で「癖がある」とレビューされている、この本を選んでみた。

■総評
現場で色んな経験を積んで、更に色んな本からの知識を実践しているように見える。
確かいい事取り、と言ってもいいぐらい間違ったことは言ってない。
ただし、同じく現場経験が長い立場としては言い過ぎるところが多い気がする。
それゆえに「こんな考えをしている人もいるよなー」感じで面白く(?)読めた。
酒場などで設計の話で盛り上がりそう。ただし、この作者と同じ現場になるのは避けたい。

■いくつかの内容抜粋&感想

データクラスを使うと同じロジックがあちこち重複する(71page)
そもそもデータクラスと機能クラスを分ける設計は、「クラス」本来の使い方ではありません。むしろJava言語のしくみとしてクラスを採用した意図とは正反対の使い方です。

→一般的に広がっていたデータクラスの概念を否定している。
だが、個人的には共感している。確かにクラスなのにデータの構造しか持たないvalue objectなどは凄い無駄な感じがしたところだった。

利用する側と提供する側の合意を明確にする(165page)
サービスを利用する側と、サービスを提供する側とで、サービス提供の約束ごとを決め、設計をシンプルに保つ技法を「契約による設計」と呼びます。
契約による設計と対象的な技法が「防御的なプログラミング」です。防御的プログラミングでは、「サービスを提供する側は、利用する側が何をしてくるかわからない」という前提でさまざまな防御的なロジックを書きます。
利用する側も、提供側が何を返してくれるかわからないという前提で、戻ってきた値のnullチェックや、さまざまな防御的なロジックを書きます。
防御的プログラミングは、無意味にコードを複雑にし読みにくくします。そして、どれだけ防御をしても、想定外の使われ方が起き、想定外の戻り値が起きてしまうのが現実です。
→これはcase by caseでどちらかと一方的では言えない問題。どのみち、利用する側は使う機能にどのような副作用があるのか調べるべきである。これは言語から提供する機能も同じである。

記録のタイミングが異なるデータはテーブルを分ける(183page)
コトの記録でNOT NULL制約を徹底するひとつの方法は、記録のタイミング(コトの発送のタイミング)が異なる事実は、別のテーブルに記録することです。
→ここは強引すぎ。確かに記録のタイミングも大事だが、使われている頻度・パフォーマンスも考えて設計するべきであろう。

記録の変更を禁止する(183page)
過去の記録ですから、コトの記録テーブルのデータを変更してはいけません。UPDATE文を使うべきではありません。
過去の記録を修正したい場合は、まず過去の記録の「取り消し」を記録します。そして、修正する事実を別の記録として追加します。
→これも強引すぎ。変更を不要にするべき・可能にするべきは設計時に判断するべきであろう。

カラムの追加はテーブルを追加する(184page)
既存テーブルへのカラム追加は好ましくありません。追加するそのカラムには過去データが存在しないため、NULLを許容するか、NOT NULL制約を逃げるための「嘘」のデータを登録することになります。
→これは少し共感できるが、やっぱりcase by case。

UPDATE文は使わない(186page)
UPDATE文はデータの不整合が混入しやすい動作です。それは、コトの記録のところで述べた「記録の同時性」に違反するからです。
そうではなく、レコード単位で古い残高をDELETEし、新しい残高をINSERTするのが正しいデータの記録方法です。
→どれだけUPDATE嫌いなのよ・・・

派生的な情報を転記して作成する(188page)
コトの記録と、集計情報やコト」の記録のサブセットの参照を分けることは、修正や拡張の柔軟性を高める方法として良い方向です。
しかし、すべてを小さなシステムに分散し、非同期メッセージングを駄使して連携することが良いかどうかは、非機能要件も含めた検討が必要です。
→これは共感できる。ただし、非同期処理ができない言語もあるので・・・

業務ロジックはオブジェクトで、事実の記録はテーブルで(194page)
ドメインオブジェクトとテーブルを機械的にマッピングする方法は、好ましくありません。設計に不要な制約を持ち込み、設計を歪めます。マッピングの自動化は、ドメインオブジェクトの設計にも、テーブル設計にも良いことはないのです。
ドメインオブジェクトはドメインオブジェクトで、テーブルはテーブルで別々に正しく設計します。
→これも共感できる。何よりこのようにはっきりと文書化してもらって感謝している。

HTMLのclass属性をドメインオブジェクトから出力する(215page)
ドメインオブジェクト側にclass属性を返すメソッドを用意するやり方で、画面の表示ロジックからif文をなくすことができます。

String readStatus(){
    if(usUnread()) return "unread";
    return "";
}

//HTML記述での使い方
//<p class="${mail.readSattus}">

ドメインオブジェクトで表現する論理的な状態を、ビュー側が利用する、という考え方です。

→これも共感できる。周りから何か言われそうだが、私はやってみたい。

画面項目のグルーピング(220page)
画面デザインの4原則
近接:関係ある情報は近づける、関係のない情報は離す
整列:同じ意味のあるものは同じラインにそろえる、意味が異なれば異なるラインにそろえる
対比:意味の重みの違いを文字の大きさや色の違いで区別する
反復:同じ意味は同じパターンで可視化する

→これは良い内容だったので、メモ

■参考書籍について
色んな本を参考しているように見える。以下の書籍は読んでみたい。
・SQLアンチパターン
・リファクタリング (アジャイルソフトウェア開発技術シリーズ・応用編)
・ノンデザイナーズ・デザインブック