読書ノート - 現場で役立つシステム設計の原則
現場で役立つシステム設計の原則の読書ノートです。
正誤表
ノート
第1章
- P24 リーダブルコードにもあるが、数値を定義するときは単位を含めたほうがベター (金額だったら円なのか銭なのかドルなのか)
- P24 セミコロンの前のスペースとか if の条件式の前後のスペースとか一貫性のないスタイリングがすごい気になる
-
P24
shippingCost()
に// 送料を算出する
とコメントが添えられているが、こんなわかりきったコメントいらないのでは (Javadoc ならまだしも) - P30 定数定義の書き方がここと P24 で違う (大文字スネークケース対キャメルケース)
- 値オブジェクト、こんなにオブジェクト作ったらパフォーマンスインパクトありそう
- ドメイン駆動設計を実践する上では不可欠だが、ボトルネックになるならば分析した上でチューニングしたい
- サーバーサイドなら札束で殴ればいいけど、組み込みでは限界ある
- ファーストクラスコレクションのほうはオブジェクト数は +1 するだけなのでパフォーマンスインパクトはほとんどない
- 値オブジェクトで DB (ORM) 絡むときは DB の型と値オブジェクトの相互変換のためのコンバーターを書く必要があり、ボイラープレート的に変換コードをゴリゴリ実装する必要がある
第2章
-
P51 早期リターン、リーダブルコードを読んだときも同じ議論をしたね
- Scala ではそもそも非推奨とか。
- return 1個主義派の主張: Excel でフローチャートが書きやすい
- P53 網羅性、相互独立性がコードから検査できないのがこのパターンの怖いところ
- P57 なんでセミコロンがあったりなかったりするのか?誤植?
-
P65
EnumSet.of
は使ってるのにEnumMap
は使わないんだ・・・ -
P66 Enum のアプローチも良いけど最近の Better Java 系などの言語だと網羅性検査がある型のパターンマッチで済ませることも
- Go の type switch は網羅性チェックない・・・
- Java だと
instanceof
は良くないものという認識があるが、C# とかだと動的型も部分的に持ち込こまれているのでナチュラルにやることがある
第3章
-
P68 ORマッパー使ってるとデータクラス量産してしまいやすい
- ドメインモデル貧血症のことだね
- Lombok とか使ってナチュラルにデータクラスを量産してしまうシステムをよく見る
-
P73 GopherCon 2017 の Anti-patterns (33スライド目) でも同じ話題あったような
- StringUtils 的な業務ロジック・ドメインと関係ないものなら util 合ってもいいような気もするけど、いろんなライブラリがこの名前で実装しててなんだかなぁとも思う
- util とか common とかあると困ったらここに突っ込んでしまう、肥溜め化する
-
P81 ドメインオブジェクト用のユーティリティメソッド (インスタンス変数はさわらない) は無理に移動せずそのまま static メソッドでぶらさげても良いのでは?
- Customer 用に Customers クラス作って static メソッドおくとかやらない?
- この本だと複数形はファーストクラスコレクションに付ける名前って感じ
-
P82 でかすぎる API は使うのもつらいよね
- RxJava の Observable とか Flowable とか
第4章
-
P94 本当に重複なくなるの!?
- 継承とか使いまくって重複とか見かけ上消えてもあんまりうれしくないんだよね
- 日本語の業務ロジック、無理やり英語に直訳したせいでどこに何か書いてあるのかわからなくなったりすることもある。ユビキタス言語的にちゃんと定義するか、あとは日本語のままプログラミングするとかしないとね
- P107 パッケージ図の依存関係、DI 使うとある程度変えることもできたりするね
- P121 こういったバリデーション系は C# の Attribute や Java の Annotation 使っていい感じにできるよって ThoughtWorks アンソロジーに書いてあった
- P123 「ちょっとした if 文の追加は (中略) まちがった方向です」とあるが、数値の比較とかバリデーションとかの if 文まで NG といっている?過激な主張な気がする
-
P129
ok
あるんだしng
いらないと思う、API が冗長 -
P129 Java 8 の
Optional
紹介するんなら、コード中の for 文をStream#anyMatch
使うぐらいはやってほしい - P137 ようはコミュ力の話だね
第5章
- P150 この図で言うと、ドメインモデルはデータソースを触れない
- P150 この図は Spring Framework に振りすぎている気がする、他のフレームワークだとこはならなかったりする
-
P152
@Autowired
のフィールドインジェクションは非推奨、コンストラクタの引数で注入する - P160 登録参照を分けるスタイルは CQRS と呼ばれる
- P164 ここで言うシナリオはサービスでよいが、CQRS 的なのはリポジトリでやることじゃないかな
- P165 「契約による設計」と「防御的プログラミング」の双方に違和感。Twitter でディスカッション
柴田さんからのコメント:
確かに「契約による設計」と「防御的プログラミング」の両方を勘違いしている説明になっていますね。不正な値や不正な呼び出し順序に対する振る舞いもきちんと「契約として設計」し、その契約を守った呼び出しであるかを防御的にプログラミングしないと、無駄なデバッグ工数が発生するだけですからね。
— Yoshiki Shibata/柴田芳樹 (@yoshiki_shibata) 2018年1月21日
対する著者の反論:
メイヤーは、呼び出す側が必ず契約を守ることを前提にしてコードを書くスタイルを重視して、それを契約による設計と名付けたと思います。契約の表明は実行用のコードとは別にすべきだと。
— 増田 亨. (@masuda220) 2018年1月21日
私の理解はこの回答に近いですね。https://t.co/XEKToVvMcb
本でうまく説明できていないかもしれませんが。
第6章
-
P174 データベースが複雑だとプログラムも複雑になるってホント?
- オブジェクト構造にデータベースを合わせれば、そうはならないのでは
- ひどいデータベース構造でプログラムが複雑になる例は体験したことがある
-
P179 NONNULL 全適用は本当に現実的?やりすぎなケースも一部あるんじゃないかなと
- 人間の都合、イレギュラーなオペレーションで NULL が必要になったときとか (そのためだけにテーブルを作るのか)
-
P187 たいていの DB は UPSERT イディオムがあるので、ロジックのシンプル度は DELETE / INSERT のほうが悪いのでは
- 記録系テーブルで UPDATE 使わないのはわかるが、残高テーブルは状態なので UPDATE 排除する論理がわからない
-
P187 記録と残高の更新をトランザクションにしないと、同時に更新するときに不整合が発生するのでは
- 非同期メッセージなら結果整合性保てるけど
- 「要求にもよりますが」うまい逃げ方だな~
-
P194 JPAディスられている・・・
- ドメインオブジェクトを一切汚さないために (JPA では不要な) SQL を書く犠牲をはらってることを忘れてはならない
- P195 NoSQL の論点もほしいな・・・
第7章
- P205 図7-1, フッターのコピーライトにもモザイクれたほうが・・・ SB Human Capital Corp は求人サイトの模様。競合調査かな?
-
P214 文言とか class 属性とか、画面の変更にドメインオブジェクトが引っ張られて良くない。多言語対応も入れづらくなる
- 画面毎に個別に重複コード用意するなとかいてあるが、そのごのセクションでは画面のHTMLタグに癒着したデータ構造や画面に出力する文字列をドメインオブジェクトの文字列にする言及がある
-
P217 画面は画面、モデルはモデルでは
- 並び順なんてプラットフォームによって変わることだってあるし
-
P219 消えた
long id
とかはどうすんのさ-
Book
とは別にBookSummary
作れといっている?
-
第8章
-
P227 ファイル転送はなるべくさけたい
- 書き込み中に読み込む怖さ
- スケジューリングミドルウェアが必要
-
P228 データベース共有は「マイクロサービスアーキテクチャ」では避けるものと書かれていた
- セキュリティの観点から好ましくないというのは・・・?
- カラムベースでアクセス制御できる、ただ使いづらいしわかりづらい
-
P229 Web API、「変更することが難しくなりやすい」・・・?
- バージョニングすればいいじゃん (あとのセクションで否定している)
- テストちゃんとすれば変更は怖くないのでは
- Spring Cloud Contract とか使って
-
P233 PUT は変更に使うことが多いかな (リソース ID がわかってるときは登録に使うけど)
- 変更には PATCH を使うことも多い
- P233 DELETE のステータスはいつも迷う
-
P247 Swagger UI はあくまで YAML のビューワーで、フレームワークは Swagger そのものでは
- 仕様は Open API (参考: API Platform, Open API 仕様)
-
P252 こんなゲッターだらけの API 細かすぎて使いたくないな…
- パスの区切りは違和感ないんだけど…
-
P253 絶対安定レベルまで小さくすればバージョン管理不要ってこと・・・?
- それでは P251 の予約の確認 API の中身変わったらどうなるんだ
-
P259 タイムスタンプをフォーマット vs. API の契約に追い出す
第9章
- P270 基本の流れは、このV字モデルに変わりありませんってあるけど、テスト駆動だとそうはならないよね
- P280 分析設計の時点では言語を決めないことも多いけれどこの場合は Java って決め打ってクラス書いてくってことなのかな
第10章
-
P290 オブジェクト指向どうやって学んだ?
- 大学の講義と本 (入門 UML 2.0) (頭で覚えた)
- Java の本 (頭で覚えた)
- Clean Code (頭で覚えた)
- 体で覚えてから頭で補強というのは全員に当てはまるわけではないよね
- P291 ここでいうオブジェクト指向の利点はあくまで過去の手続き型との比較の文脈でないと納得いかない (関数型もあるわけで)
- P294 「リファクタリング」では自動テストを書いてからリファクタリングすることを大原則としていたはずだが、この本ではその一番大事なところが一切触れられていない・・・
- P296 リファクタリングする→クラス増える→パッケージを整理する→ Java のパッケージしょぼい・・・
-
P303 1行につきドットは1つまでルールはメソッドチェーンな API だとつらい
- ここでの意図は複数の型の操作を1行に書いてしまうことだと思うので、型が同一のままチェーンできる API ならオブジェクト指向的な正しさは保てるような感じもする
- P308 「実装パターン」は絶版・・・図書館に行くしかない