Slide 1

Slide 1 text

大きな泥団子に立ち向かうための ソフトウェア設計実践入門 2024年5月22日 有限会社システム設計 増田 亨 アーキテクチャを突き詰める Online Conference 1

Slide 2

Slide 2 text

自己紹介 業務系アプリケーションソフトウェアの開発者 モデル駆動設計 Java/Spring Boot/IntelliJ IDEA/JIG 有限会社システム設計 代表 コミューン株式会社 技術顧問 2 増田 亨(ますだ とおる) 著書

Slide 3

Slide 3 text

アジェンダ ① 大きな泥団子問題 ② 銀の弾丸 関心の分離 ③ 関心の分離の枠組み ④ 計算を分離する実践技法 ⑤ 関心の分離:その他の実践技法 3 (計算、アクション、アダプター)

Slide 4

Slide 4 text

大きな泥団子 4 不適切な設計

Slide 5

Slide 5 text

大きな泥団子とは? • 場当たり的な構造、無秩序な拡張、急場しのぎの修正 • 乱雑でグローバルな情報共有 • 重要な情報の安易な複製 すこしでもアーキテクチャ感覚があるプログラマーであれば、避けて通る泥沼のはず しかし、現実は… 5 「アーキテクチャに無頓着で、おそらくは、このような崩壊した穴を補 修する日々の惰性的な作業に安住しているものだけが、このようなシス テムに、満足して取り組むのである」 Brian Foote and Joseph Yoder on Patterns Languages of Programs (PLoP 1997)

Slide 6

Slide 6 text

大きな泥団子は何が問題か? 6 複雑さ 発展性 設計の基本課題 大きな泥団子 対応できない 本質的な 不必要な複雑さ 変更がやっかいで危険

Slide 7

Slide 7 text

大きな泥団子 3つのシナリオ 7 大きな泥団子 修正 拡張 修正 修正 修正 修正 拡張 拡張 拡張 拡張 拡張 修正 修正 修正 拡張 修正 シナリオ① 卓越した設計でスタート シナリオ② 最少の設計でスタート シナリオ③ 小さな泥団子でスタート 積みあがるバックログ 無理な日程 度重なる仕様変更 限られたリソース 人の入れ替わり ビジネスの圧力 結果は同じ…

Slide 8

Slide 8 text

大きな泥団子だらけ おそらく、現在、もっとも主流のアーキテクチャ 修正と拡張を積み重ねれば、結局は、大きな泥団子に行きつく 修正がやっかいで危険 ちょっとした変更に時間がかかる どこに何か書いてあるか確認がたいへん 変更内容に対して書き換え個所が多い 変更が怖い コメントアウトコード、明らかなデッドコード、typoの放置 8

Slide 9

Slide 9 text

大きな泥団子の悪影響 • 開発のスピードが落ち、品質が下がる • ちょっとした修正を苦労してやり抜くことで、仕事をしている つもりになれる • 設計を考え、設計の効果を体験する機会の強奪 9 事業的損失 成長機会の損失 まちがった達成感

Slide 10

Slide 10 text

関心の分離 10 銀の弾丸

Slide 11

Slide 11 text

関心の分離 根底の設計原則 あらゆる設計技法(アーキテクチャスタイル、設計原則、設計パターン、 リファクタリングパターン、…)は、関心の分離が目的 大きな泥団子とは、要するに、関心の分離の失敗例 11

Slide 12

Slide 12 text

銀の弾丸 • どんな場合でも通用する万能の解決策 • どうするか? 場合ごとの、具体的な解決策の習得と実践を積み重ねる 12 そういうものは存在しない 経験則 習熟 共創 暗黙知 読書 言語化 実験 練習 習慣 会話 レビュー 提案

Slide 13

Slide 13 text

そもそも関心の分離とは? 人は、たくさんのことは同時に考えられない だから ・考えるべきことを小さくする ・つまり、一度に考えるのは、狭い範囲に集中する ・そのほうが、楽で確実 13

Slide 14

Slide 14 text

関心の分離の失敗パターンと改善方法 14 混在 断片化 分離 集約 重複 一元化 いろいろ 同時に考える 異なる関心事は 別々に考える あちこちを 同時に考える 関連が強い関心事は 一箇所に集めて考える あちこちで 同じことを考える 一つの関心事は ただ一箇所で考える

Slide 15

Slide 15 text

計算、アクション、アダプター 15 関心の分離の枠組み

Slide 16

Slide 16 text

アプリケーションアーキテクチャ 関心の分離の枠組み、設計指針 さまざまなアーキテクチャスタイル • レイヤード • オニオン • ヘキサゴナル • ポートとアダプター • クリーン • … 16 強調する点や用語は異なるが 基本原則は共通

Slide 17

Slide 17 text

計算、アクション、アダプター 17 IN アダプター OUT アダプター アクション (業務機能) 計算 HTTP(IN) サブスクライバー バッチスクリプト テストドライバー データベース操作 HTTP(OUT) パブリッシャー 算術演算、比較演算 条件分岐、 コレクション操作 記録、参照 通知、応答

Slide 18

Slide 18 text

計算、アクション、アダプター 18 HTTP(IN) サブスクライバー バッチスクリプト テストドライバー データベース操作 HTTP(OUT) パブリッシャー 算術演算、比較演算 条件分岐、 コレクション操作 記録、参照 通知、応答 使う 使う IN アダプター OUT アダプター アクション (業務機能) 計算 使う ポ ー ト ポ ー ト

Slide 19

Slide 19 text

アダプター駆動アーキテクチャ 19 IN アダプター OUT アダプター 計算の混在、断片化、重複 とりあえずどこにでも書ける アクションの暗黙化 (業務機能) アダプターの 具体性と実装の制約に 引きずられた構造

Slide 20

Slide 20 text

大きな泥団子から関心の分離へ 20 How?

Slide 21

Slide 21 text

「計算」を分離する 21 計算は、記述の自由度が高いために あちこちに混在、断片化、重複する 逆に言えば、計算は、 独立性が高く、自由に移動できる 計算 算術演算、比較演算 条件分岐、 コレクション操作 どこにでも書ける=移動できる

Slide 22

Slide 22 text

計算を分離する効果 22 計算 算術演算、比較演算 条件分岐、 コレクション操作 この三つを実感できると大きく変わる ③ 業務を正しく深く理解して実装できるようになる 事業活動の最適化⇒業務ルール⇒計算判定ロジック 計算仕様の理解⇒仕様の誤認や誤実装の防止 ① 計算の複雑さを分離できれば、他が単純になる • 計算の混在、断片化、重複がシステムの複雑さの大きな原因 ② 品質保証(テスト)を重点的に実施できる • 境界値と計算結果の妥当性(境界値テスト) • 複合条件の判定(デシジョンテーブルテスト) • 状態の判定と分岐(状態遷移テスト)

Slide 23

Slide 23 text

「計算」以外の設計指針 アダプター • 事業活動の独自性、競争優位性に結び付くことはない • できるだけ、既存の技術(フレームワーク、ライブラリ)と実績ある設計パ ターンですませる アクション(業務機能) • 業務機能と基本手順は、(計算以外は)単純で、他社と同じでよい • 事業活動の独自性、競争優位性に結びつくことは少ない • INアダプターに業務機能を提供する(INアダプターの知識を持たない) • OUTアダプターを抽象化したインターフェースを定義して使う(OUTアダプ ターの知識を持たない) 23 凝った設計は不要

Slide 24

Slide 24 text

計算を分離するための実践技法 24

Slide 25

Slide 25 text

計算の分離の基礎となる設計技法① 抽象データ型 • アプリケーション特化の独自のデータ型を作る • プログラミング言語の組み込み型や標準的なライブラリで用意されているデータ 型は、汎用的 • アプリケーションを表現するための型の体系を用意する • 計算ロジックを値の種類ごとにまとめてモジュール化する 25 アプリケーション特化のデータ型で計算ロジックを整理する

Slide 26

Slide 26 text

抽象データ型の作り方、使い方 • 値の種類を特定し分類する • 関心の対象(商品、顧客、注文、進行過程、資源状況)を表現する属 性(データ項目)に注目 • 数値の単位、データ項目の名称を手がかりに値の種類を特定し分類 • 値の種類ごとに、値の特徴と用途を定義する • 値の有効範囲(妥当な入力値、妥当な計算結果) • 有効な操作(必要な比較演算と算術演算の特定) • テストではなく静的な構造(宣言的記述)で正しさを保証する 26 計算を分離するための部品を充実させる

Slide 27

Slide 27 text

計算の分離の基礎となる設計技法② イミュータブル • 不変性:オブジェクトを生成したら状態を変えない 結果として、オブジェクトIDは不要。等値性の判断は必要。 • 計算結果として新たなオブジェクトを生成する 入力と出力を分離して固定する • 考えることを減らす 変数の状態の変化とその影響を頭の中で考える負担をなくす • プログラムの挙動が単純になり、安定する • テストが単純になる 27 現代的なプログラミングの常識

Slide 28

Slide 28 text

事業活動の最適化機会に焦点を合わせる 28 契約履行活動 出荷業務の効率化 サービスレベル vs.コスト 経営資源の有効活用 在庫、機材、設備、人員、… 販売増 vs. 物理制約、費用増 商談機会の創出 マーケティング活動 費用対効果の最適化 商談活動 営業担当者の 行動最適化 契約条件の調整 価格、納期、支払方法 売上最大化 vs. 利益確保 計算の目的と背景を理解する

Slide 29

Slide 29 text

分析設計パターン:おすすめ10選 29 事業活動の観測と計算 ・測定値の表現 ・整数型⇒単位付き値型 ・金額、数量、日付、時刻 範囲演算 ・範囲内、範囲外 ・範囲の重なり ・範囲の合成 分類と判定 ・区分ごとの定数 ・区分ごとのロジック ・階段関数 状態遷移 ・状態遷移モデル ・制限ルール ・刺激ルール 集合演算 ・分配ルール ・スキルセットの マッチング 複合条件 ・決定表 ・論理演算の合成 資源管理 ・実在庫、未来在庫 ・過剰予約 ・複合手配 知識の伝達 ・知識の表現 ・会話履歴 ・体系化 最適化 ・目的関数 ・制約条件 契約と当事者 ・権利と義務 ・基本契約と個別契約 ・与信 計算を表現するためのパターンカタログ 6/16(日) 17:00~ @新宿野村ビル JJUG CCC 2024 Spring で発表予定

Slide 30

Slide 30 text

その他の実践技法 30

Slide 31

Slide 31 text

関心の分離:その他の実践技法 ① ファイルとディレクトリ ② 選択と集中 ③ 実験と観察 ④ 関心の分離のレビュー ⑤ 雑音の除去 31

Slide 32

Slide 32 text

①ファイルとディレクトリ ファイル • 関心を物理的に分離する手段 • 一つのファイル内で修正作業が完結するのが理想 • アンチパターン • ファイル内に雑音が多い • あちこちのファイルを参照する必要がある • 同時に修正するファイル数が多い ディレクトリ • 関心を物理的に整理する手段 • 関心事の記述場所へのパスを表現した階層構造(名前空間) • 継続的なリファクタリングの重要課題 32 論理的な分離より 物理的な分離のほうが 思考の負担が少ない

Slide 33

Slide 33 text

②選択と集中 時間は限られている • 費用対効果を意識する • 費用対効果の認識を合わせる 候補 • 変更が多い • 計算条件が複雑 • 計算ロジックが重複 33 業務的に重要で 改善効果が大きそうな ところを探す

Slide 34

Slide 34 text

③実験と観察 • 設計改善のアイデアが見つかったら、あれこれ考えるよりは、実際 にリファクタリングして結果を観察したほうが早くて確実 • IDE, git, dockerなどで実験的なリファクタリングがやりやすく なった(費用対効果が高くなった) • 論より証拠、抽象的な設計用語よりソースコード表現 and • 実験内容と観察結果を言語化する(会話、コミットログ、発表) 34 うまく、はやく学ぶ

Slide 35

Slide 35 text

④関心の分離のレビュー • 関心の分離をコードレビューの重点課題とする • 計算の混在、断片化、重複の検出 • 関心の分離について会話する • 関心の分離について認識の違いを確認する • 目的を言語化し、認識を合わせる • 計算を混在、断片化、重複を改善する技法の共有 35 関心の分離を意識し、言語化する効果

Slide 36

Slide 36 text

⑤雑音の除去 コメントアウトされたコードを物理削除する あきらかなデッドコードを削除する ・いったんコメントアウト⇒確認⇒物理削除 typoを放置しない(即時修正) 36 コードの雑音を気にしない開発チームに明るい未来はやってこない

Slide 37

Slide 37 text

最後に 37

Slide 38

Slide 38 text

ソフトウェア設計の知識と技能 38 共創 経験則 習熟 暗黙的な経験則 技能⇒知識 成功体験 失敗体験 言語化/可視化された経験則 設計原則 (文脈に依存しない一般化) 設計パターン (文脈の類型化) 体験談 (個別の文脈) 設計の知識と技能を お互いに持ち寄って 組み合わせる 制約の多い実際の文脈で 手を動かして 体で覚える 知識⇒技能 相乗効果(三つの掛け算) 足し算ではなく掛け算