良いコード/悪いコードで学ぶ設計入門 メモ
リーダブルコードの発展版との噂
著者はクソコード動画というチャンネル名でyoutubeに動画投稿してるらしい
一部twitterやzenn記事などで鵜呑みにするのは良くない部分があるとの情報もある
低凝集
データとロジックの実装が離れた位置にあると、各実装者が見つけにくく、複数実装してしまいがち
クラスの初期化時にバリデーション、値の再代入を防ぐ、プリミティブを避け独自に定義したクラスを利用するなど
とにかく不正、不完全なオブジェクトが作られないようにすることは大事
未初期化のオブジェクトを生焼けオブジェクトっていうらしい
コンストラクタでバリデーション、未初期化のインスタンス変数がないようにする
完全コンストラクタ
できるだけイミュータブル
基本は不変が理想で
可変にしても良いのは
インスタンス生成にパフォーマンスが求められる場合、スコープが局所的な場合はok とのこと
static クラスもインスタンス変数もたず低凝集な状態を引き起こす、ログ出力やフォーマット変換など凝集度に関係ない物ならok
ファクトリメソッドとしてのstatic も ok
コンストラクタを守るために
生成ロジックにファクトリメソッド、また、増えすぎたらファクトリクラス
デメタルの法則
オブジェクト内部の情報を他のオブジェクトが知るべきではない、
オブジェクト内の変更はそのオブジェクト自身に任せる
ddd の集約のオブジェクト操作でも聞いた
デメタルの法則によるとメソッドを呼び出すオブジェクトは
オブジェクト自身
引数として渡されたオブジェクト
インスタンス変数
直接インスタンスかしたオブジェクト
ポリシーパターン初めて聞いた
インターフェースを実装した部品化したルールを複数組み合わせてポリシーを作る
下記のような流れになる
policy.add(rule1)
policy.add(rule2)
policy.add(rule3)
policy.check()
継承による共通化は設計上手くやらないと
親クラスが複数の責務を持ってしまったり、別継承クラスにとって無関係なメソッドが実装されてしまったりと
気をつけないといけない
振る舞いの差分のみを実装する template method など 上手くやらないと
例外握りつぶし
try catch で catch した例外に合わせて適切に処理しておらず、
不具合調査などが大変になる
実際に見たことがある。
ドメインエラー等以外の予期してないエラーはきちんとサーバーエラーにするべきと思う。
名前で関心を分離する
例えば商品というクラスに予約、注文、発送という関心事が実装されている場合、
密となり影響範囲が大きくなる
上記の場合は、
予約商品、発送品などいった具合に分離して関心事に適した名前をつける
本書によると目的駆動名前をつける上でのポイントが下記
・可能な限り具体的で、意味範囲が狭い、特化した名前を
・存在ベースでなく、目的ベースで名前を考える
存在ベース | 目的ベース |
---|---|
住所 | 配送元、配送先、勤務先、本籍地 |
金額 | 請求金額、消費税額、キャンペーン割引額 |
ユーザー | アカウント、個人プロフィール |
ユーザー名 | アカウント名、表示名、本名、法人名 |
商品 | 入庫品、予約品、注文品、配送品 |
(具体的な名前が良い?)
・どんな関心ごとがあるか分析する
・声に出して話す
・利用規約を読む
・違う名前に置き換えられないか検討
・疎結合高凝縮になっているか点検
ラバーダッキングも思考の整理に有効、声に出して読んでみる
よく聞く
コンテキストの違いを考慮してクラス設計を行う
本書の例では
配送パッケージ
自動車が貨物として配送されるコンテキスト
Car |
---|
id |
配送元 |
配送経路 |
販売コンテキスト
ディーラーにより顧客にじて自動車が販売されるコンテキスト
Car |
---|
id |
販売価格 |
販売オプション |
ddd の 境界付けられたコンテキストにあたる?
ロジック構造をなぞった名前
ロジックをなぞっただけの関数の意図や目的が明確に伝わらない名前
下記は本書の例
isMemberHpMoreThanZeroAndIsMemberCanAct
魔法が唱えられるかどうかを判定する関数のため、canChant とする
結構見たことあるやつ
可能な限り動詞1語で住む名前にする
「動詞 + 目的語の」メソッド
目的語の概念を表現するクラスを作る
そのクラスに動詞1語のメソッドを追加する
本書の例だと
addItemToParty 関数
PartyItem クラスを作成し、addメソッドを定義、ファーストコレクションパターン
11章
退化コメント
ロジックの挙動をそのままなぞったコメントするだけのコメントは退化(のちにメンテナンスされず、挙動と異なるコメントになってしまう)しやすい
ロジックの意図や仕様変更時の注意が必要になる点などをコメントする
リファクタはコアドメイン部分が費用対効果高い、それはそう
テストを書いてからリファクタすると安全
15 章以降の内容について
この方の意見、確かにと思った
技術的負債のトレードオフって、時間、知識以外は何だろう?
12章
CQS メソッドはコマンドかくえりどちらか一方だけを行うように設計する
コマンドとクエリを同時に行うメソッドは例外としてなるべく避ける(混乱しやすい)
エラーは戻り値で返さない、例外をスローする
本書の例では
無効な座標のエラー値として、Location(-1,-1)
を返すメソッドが挙げられていた
呼び出し側でLocation(-1,-1)
のエラー処理を確実にに実装する必要が出てくる。
ある値に複数の意味を持たせる→ダブルミーニング
この場合、座標とエラーであるという二つの意味
13章 モデリング
本書では下記と述べている
モデルはシステムの構成要素です。つまり、モデルは目的達成手段の一部です。特定の目的達成のため最低限考慮が必要な要素を備えたものがモデル
本書はモデルに複数の要素がある、複数の目的があるのは良くないと述べている
例えば商品モデルに、注文や配送など
現実世界では物理的な存在と、情報システム上のモデルが 1:1 になるとは限らず、1:多 の関係になるケースがあることが大きな特商です。
例としてアカウントを、個人アカウント、法人アカウント、プロフィールと目的ごとに分けてモデルを表現するケースがあるという
テーブルの持ち方ってどうするのだろう、テーブルもモデルに合わせて正規化するのかな?
モデルは相互にフィードバックする
モデリングに関してまだまだ分からないところがある、ddd 関連の本など読みたい
14章
本書で書かれてる手法
テストコードを用いたリファクタリングの流れ
1 . あるべき構造の雛形クラスをある程度作る
2. 雛形クラスに対して仕様を満たすテストコードを書く。
3. テストを失敗させる。
4. テストを成功させるための最低限のコードを書く
5. 雛形クラス内ぶでリファクタリング対象のコードを呼び出す
6. テストが成功するよう、あるべき構造へロジックを少しづつリファクタしていく
16章 開発を妨げる開発プロセスとの戦い
心理的安全性
「自分が発言することを恥じたり、拒絶されるなど、不利益を被ることがないことをチームて共有されている心理状態」とか「安心して自由に発言したり、行動できる状態」という定義がなされています。
ジョシュアツリーの法則
名前を知って初めて存在を知覚できるようになる、逆に名前を知らないと存在を知覚できないとする認知法則です。
ストラテジーとか、イミュータブルとかそもそもどういったものなのか知覚していなければ、良い悪いを判断できず改善できないということ
UML図 積極的に書いていきたい
単一責任の原則について
そのプロジェクト内の中で目的が単一
コードが重複していようと
本書で紹介されてた勉強会の流れ、やりたい
メンバーと一緒にノウハウを読み合わせて、プロダクションコードに適応できるところがあれば適応してみる
どう改善したか before after で振り返り
6章
enum で 定数を管理している場合など、
同じようにな switch の処理が複数箇所存在してしまう問題
単一責任の原則に基づき1つのクラスにまとめる
ストラテジパターンも適切か検討
9章
技術駆動パッケージング
mvc フレームワークなどはデフォルトでそうなってる
ビジネス概念として関係し合うもの同士になるようにフォルダ分けすると良い