Upgrade to Pro — share decks privately, control downloads, hide ads and more …

変更を楽に安全にするための設計の考え方とやり方

 変更を楽に安全にするための設計の考え方とやり方

シンプレクス株式会社さん( https://www.simplex.inc/ )の社内勉強会で使った資料です。

・変更を楽に安全にする設計の基本原則は「関心の分離」
・どういう枠組みと視点で関心を分離するか
・事業活動の仕組みと決め事に焦点を合わせたクラス設計の考え方とやり方
・事実の記録に焦点を合わせたテーブル設計の考え方とやり方

増田 亨

August 03, 2021
Tweet

More Decks by 増田 亨

Other Decks in Technology

Transcript

  1. 書籍のもとになった体験 ⚫大炎上中のプロダクトの火消し役に呼ばれた ⚫マルチテナントの人材採用業務のSaaSでリリース済 • 重大な不具合だけで100件以上 • 毎日のように重大な不具合が追加される • 次年度の新卒採用業務に導入したため使うしかない(ちゃんと動いている機能の評 価は悪くはない)

    ⚫不具合の例 • 他のテナントの応募者情報が見える • 集計表が一時間待っても出力されない(408 リクエストタイムアウト) • 選考プロセスを進めると登録した応募データが消える、消えたと思ったら別の検索 条件で復活する
  2. 影響の大きかった本 『リファクタリング』 マーチンファウラー 『実装パターン』 ケントベック 『ドメイン駆動設計』 エリックエヴァンス 『理論から学ぶデータベース実践入門』 奥野幹夫 『オブジェクト指向入門』バートランドメイヤー

    これらを参考にしつつ、現場での実験を通してうまくいったやり方とその背景に ある考え方(なぜそうするのか)を言葉にしてみたのが 『現場で役立つシステム設計の原則』 ~変更を楽に安全にするオブジェクト指向の実装技法
  3. 学んだこと・効果があったこと 変更を楽で安全にする設計 小さなクラス イミュータブルな クラス getter/setter 撲滅 型による モジュール化 名前へのこだわり

    パッケージ構造の 価値 一意制約 NOT NULL制約 外部キー制約 イミュータブル データモデル 画面の分割 用途別の画面 値オブジェクト 区分オブジェクト ドメインモデル ビジネスアクショ ンクラス アクティビティク ラス 範囲オブジェクト コレクション オブジェクト 関心の分離 自己文書化
  4. ドメインオブジェクト ビジネスルールを記述する基本部品 値オブジェクト 基本データを使う計算・判断ロジック をカプセル化 金額、数量、率 日付、日数、時刻、時間 区分オブジェクト 区分の列挙(enum) 区分ごとのデータとロジックや区分の

    判定ロジックのカプセル化 顧客種別、配送区分、 在庫区分、… 範囲オブジェクト 値の範囲内・範囲外の判定や範囲どう しの演算をカプセル化 金額範囲、数量範囲 期間、時間帯 コレクション オブジェクト 値・区分・範囲のコレクションの リスト処理・集合演算・写像操作のカ プセル化 受注明細 スキルセット 価格表
  5. ビジネスアクションのクラス設計 シナリオクラス 主要な活動の流れを表現(数は少ない) 詳細はアクティビティクラスで記述 予約受付シナリオ アクティビティクラス 商流・物流・金流などで、事業活動をグ ルーピングしたクラス群 要素サービスクラスを組み合わせて記述 受注アクティビティ

    出荷アクティビティ 請求支払アクティビティ 要素サービスクラス リソースごとのアクションを表現 原則として一つのリポジトリを持つ 注文の記録と参照 出荷時の通知 関心事が異なる:視点・粒度
  6. テーブル設計の考え方 テーブル設計が悪いとプログラムが複雑になる ⇒ 変更がやっかいで危険になる ⇒ データの品質が劣化→プログラムが複雑になる 良いテーブル設計 ⇒ 関心事を徹底的に分離する(第6正規形まで分解可能であることを意識) ⇒

    事実の記録と状態の参照を分離する ⇒ 発生タイミングが異なる事実、参照単位が異なる事実は別テーブルに分ける ⇒ 事実の記録テーブルは更新と削除不可(イミュータブル) ⇒ 状態参照用のテーブルはインデックスやキャッシュと同じ位置づけ
  7. テーブル設計のやり方 事実を記録するテーブル(主) ① 事実の発生のタイミングごとのテーブル ② NOT NULL 制約(NULLという事実はない) ③ 更新・削除不可

    ④ 外部キー制約(事実と事実の関係の記録) 状態を参照するためのテーブル(補助:インデックスやキャッシュと同じ扱い) ① 状態が事実の記録から動的に導出可能であれば補助テーブルは作らない ② 削除あるいは有効性は、事実の記録とは別のテーブルで表現して結合する ③ 最新を表現するテーブル(ポインタ式 or 完全な実体) 共通 ① スキーマ名・テーブル名・カラム名を日本語(文書化、スキーマで名前空間の整理) ② 更新日時カラムは作らない(すべてINSERT:作成日時のみになる)
  8. ソースコードの自己文書化 ⚫大量のドキュメント作成と更新は費用対効果が悪い ✓ 費用がかかる ✓ 効果は? ⚫ソースコードの自己文書化で多くのドキュメントの作成・更新が不要になる ✓ 常に最新かつ設計と実装が完全に同期している ✓

    より現実的で具体的な進捗管理と品質管理が可能 ⚫段階的な詳細化の活動は、ソースコードの段階的な改善活動になる ✓ ソースコードを設計文書として書き始めレビューと改善を繰り返す ✓ ソフトウェアの変更活動が開発の初期から常に回っている状態
  9. 自己文書化の実際 仕様記述と 詳細設計 プログラミング言語で記述する(正確、IDEで高度な編集環境) ツールで可視化(依存関係や全体構成の俯瞰、構造化された用語集) ドキュメントの作成と更新=コードの作成とリファクタリング(設計改善) テーブル定義 DDL文で記述→実データベース構築 実データベースのデータカタログからツールを使って設計を可視化 スキーマ名・テーブル名・カラム名は日本語(文書化)

    品質管理 コードレビュー=設計レビュー(関心の分離のレビューに重点) コードレビュー=要件や仕様の理解度のレビューを兼ねる コンパイラやコードインスペクションで記述の正確性・妥当性を常に検査 進捗管理 ソースコードリポジトリの変化を可視化 issueでタスク分解、commitでタスク完了(分析設計の進捗もソースコード) 早い段階からCI/CD : 動くプロダクトで進捗を確認