2022年11月7日(月) 「現場で役立つシステム設計の原則 - Forkwell Library #9」 発表資料
良い設計と悪い設計の違い2022年11月7日有限会社システム設計 増田 亨Forkwell-Library #9
View Slide
自己紹介アプリケーション開発者業務系アプリケーションドメイン駆動設計/リファクタリングJava/Spring/IntelliJ IDEA/JIG著書『現場で役立つシステム設計の原則』~変更を楽で安全にするオブジェクト指向の実践技法技術者コミュニティ「現場から学ぶモデル駆動の設計」主催2022/11/7 2
お話すること1. 良い設計と悪い設計の違い2. 良い設計が生み出す効果3. 良い設計をするための知識と技能2022/11/7 3
良い設計と悪い設計の違い2022/11/7 4
良い設計は悪い設計より変更が楽で安全である2022/11/7 5
設計の良し悪しをどう判断するか実際に変更しようとしてやっかいで危険であれば悪い設計あらゆる箇所を実際に変更して良し悪しの評価はできないそこで悪い設計のコードには特徴がある(不吉な臭い)そういう臭いをコードに持ち込まない考え方とやり方を習得する2022/11/7 6
良い設計が生み出す効果2022/11/7 7
ソフトウェアを変更する理由(複合)• 事業の存続性の改善(存続優位・存続劣位)• 事業環境(社会経済・市場の競合・顧客の価値観)が変わる• 事業の遂行能力(組織・人材・仕事のやり方)を変える• 開発者の事業活動の理解が変わる• 開発者の設計能力が変わる• 利用できる技術の費用対効果が変わる(メモリ、帯域、…)2022/11/7 8
ソフトウェアの変更が楽で安全であれば• 事業活動の変化のスピードを上げられる• 事業活動の変化のコストを下げられる• 開発者の成長の機会を増やせる• 開発者の学びと成長をソフトウェアに反映できる• 費用対効果の高い技術に移行できる2022/11/7 9
ソフトウェアの変更がやっかいで危険になると• 事業活動の変化のスピードを落とす• 事業活動の変化のコストが増える• 開発者の成長の機会が減る• 開発者の学びと成長をソフトウェア開発に活かせない• 費用対効果の悪い技術を使い続ける2022/11/7 10
良い設計をするための知識と技能を習得する2022/11/7 11
良い設計をするための知識と技能• コードの不吉な臭い(設計の良し悪しを判断する嗅覚)• 「良い形」の習得• 「分け方・集め方・つなぎ方」の習得2022/11/7 12
コードの不吉な臭い• 怪しげな名前(クラス名、パッケージ名、変数名)• 長いメソッド• 大きなクラス/大きなパッケージ• 可変性(ミュータブル, setter, 変数への再代入)• 重複(式、if文/switch文、for文/Streamメソッドチェイン)• データクラス(getter, setter)• 基本データ型の群れ(int, int, int, String, String, String )2022/11/7 13
良い形の習得値オブジェクト区分オブジェクトコレクションオブジェクト名前空間(パッケージ構造)2022/11/7 14
良い形:値オブジェクト• アプリケーションで扱う値の計算ロジックの置き場所• 業務ルール(計算式など)に登場する値の名称• 正しい値・正しい計算の詳細仕様をコードで記述• 基本データ型の隠蔽• 不変性の徹底(値が異なれば別のオブジェクトを作る)2022/11/7 15
良い形:区分オブジェクト• if文/switch文のコードの重複の防止• 業務活動で起きる「場合」の構造と名前をコードに取り入れる• 表形式の業務ルールの表現(例:年齢別料金、時間帯割引)• 既存の区分を整理(排他的網羅に)→ 不必要な複雑さの解消2022/11/7 16
良い形:コレクションオブジェクトfor文/Streamメソッドチェーンのコードの重複の防止業務で関心のある対象の「集まり」の呼び方を名前にする• 出荷待ち一覧要素の選択条件・値の集約方法の仕様化• 優先出荷対象の抽出• 商品別の出荷待ち数の集計2022/11/7 17
良い形:名前空間(パッケージ構造)• 最小要素(クラス=業務ルールを説明する基本語彙)• コンポーネント(クラスのグループ、業務ルールの種類)• サブドメイン(コンポーネントのグルーピング、業務領域)• ドメイン(サブドメインのグルーピング、事業領域)• 業務知識を整理する構造• 業務ルールを説明する用語の関連付けと一貫性の維持2022/11/7 18
「良い形」の背景にある考え方型(値の種類の分類)• 操作の集合として値の種類を定義する(金額、数量、日付、区分、コレクション)• データの抽象化カプセル化• データ操作とデータ表現を同じモジュールに凝集させる• クラス構文(Java, C# …)、メソッド構文(Rust, Go)契約プログラミング• クラス間のつなぎ方の約束• 事前条件:引数の型で制限する• 事後条件:メソッドの返す型で制限する• 不変条件:オブジェクトの状態を変更しないことを確約2022/11/7 19
分け方・集め方・つなぎ方の知識と技能の習得2022/11/7 20
設計原則と設計パターン原則とパターンは他人の経験知自分の経験知にするために、手を動かして効果を実感する変更がやっかいで危険なコードをリファクタリングした結果「なるほど」となることが多いあらゆる設計原則と設計パターンは変更を楽で安全にする考え方とやり方の言語化分け方・集め方・つなぎ方の考え方とやり方の言語化2022/11/7 21
分け方・集め方・つなぎ方を学ぶコードレベルの原則とパターンの習得• クラス/パッケージの設計と実装、リファクタリング• テーブル/スキーマの設計と実装、リファクタリング• 通知・転送(API/メッセージング)の設計と実装、リファクタリング中範囲の原則とパターンの習得• 単一のアプリケーションのアーキテクチャの実装と運用・保守・改善広い範囲の原則とパターンの習得• 分散アーキテクチャの実装と運用・保守・改善2022/11/7 22
永続化クライアント@RepositoryJDBC TemplateSQLMapper通信クライアント@ComponentRest TemplateJMS Templateアクションの起動@Controller@RestController@MessageListener@Scheduledビジネスアクションクラス計算判断の実行通知・依頼記録・参照@Serviceビジネスルールクラス事業活動の決め事計算判断ロジックの宣言的な記述POJO単純複雑フレームワークで単純化フレームワークで単純化ドメインモデル中範囲の分け方・集め方・つなぎ方2022/11/7 23Java/Spring Bootの実装例使う単一のアプリケーション
広い範囲の分け方・集め方・つなぎ方2022/11/7 24➢ アーキテクチャの分解➢ 業務データの分解➢ サービスの粒度◆データの所有権◆分散ワークフロー◆トランザクショナルサーガ◆コントラクト◆分散分析データ分散アーキテクチャ
まとめ2022/11/7 25
良い設計は悪い設計より変更が楽で安全である2022/11/7 26
ソフトウェアの変更が楽で安全であれば• 事業活動の変化のスピードを上げられる• 事業活動の変化のコストを下げられる• 開発者の成長の機会を増やせる• 開発者の学びと成長をソフトウェアに反映できる• 費用対効果の高い技術に移行できる2022/11/7 27
変更を楽で安全にする設計それが開発者がやるべき仕事私が実践している設計の考え方とやり方は、この価値観に基づいている2022/11/7 28