Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

アジャイルなソフトウェア設計を目指して

8,064 views

Published on

変更を楽に安全にする4つの根底技法の紹介。

Published in: Software
  • Be the first to comment

アジャイルなソフトウェア設計を目指して

  1. 1. 変更を楽で安全に アジャイルなソフトウエア設計を目指して 有限会社 システム設計 増田 亨
  2. 2. ソフトウェアの開発
  3. 3. ソフトウェアの開発 = プログラミング プログラミング = 設計 設計 = ソースコードで表現
  4. 4. よい設計とは?
  5. 5. よい設計とは? 変更が楽で安全であること
  6. 6. ソフトウェア開発のさまざまな課題
  7. 7. 開発スコープ 開発スピード 性能問題 ビジネス要求 費用 開発の労力 セキュリティ 要件 安定運用 操作性 機能追加 データ管理 外部連携 バグ対応 個人情報保護
  8. 8. ソフトウェアの変更容易性
  9. 9. 変更が 楽で安全 開発スコープ 開発スピード 性能問題 ビジネス要求 開発費用 開発の労力 セキュリティ 対策 安定運用 操作性 機能追加 データ管理 外部連携 バグ対応 個人情報保護
  10. 10. 変更が やっかいで危険 開発スコープ 開発スピード 性能問題 ビジネス要求 開発費用 開発の労力 セキュリティ 対策 安定運用 操作性 機能追加 データ管理 外部連携 バグ対応 個人情報保護
  11. 11. なぜ変更がやっかいで危険になるのか?
  12. 12. 硬直したモジュール構造 ソースファイルの肥大化とコードの重複 動けばOK症候群 力ずくのプログラミング
  13. 13. 硬直化したモジュール構造
  14. 14. 開発のスタイル 技法やドキュメント 関心の焦点 モジュール構造 機能分割駆動 三階層の機能一覧/機能詳細 部門/業務/職務の分解 アプリケーション層 トランザクション スクリプト データモデル駆動 ER図 テーブル定義書 CRUD分析 データソース層 データベーススクリプト スマート Entity ワークフロー・ ユースケース駆動 アクテビティ図 ユースケースモデル ユースケース記述 アプリケーション層 トランザクション スクリプト 画面/API 駆動 (インタフェース駆動) ワイヤフレーム 画面一覧/画面遷移 API一覧/API定義 プレゼンテーション層 スマートUI ファットコントローラ 開発のスタイルとモジュール構造 どの開発スタイルでも、データ処理の手続き単位のモジュールになる (モジュール=ソースコードファイルの分割単位)
  15. 15. 手続き的なモジュール構造と変化への対応 モジュール構造(ファイル単位)は変えない 既存のソースファイルに変更をねじ込む ロジックの部分的な再利用はできない/やらない モジュールの組み立てなおしはできない/やらない
  16. 16. モジュール構造を変えずに変更をねじ込む その場しのぎの if 文の追加 その場しのぎの switch文のcaseの追加 その場しのぎの enum(区分定数)の追加 丸ごとコピーして一部修正 同じ計算式や類似の条件判定があちこちに重複する
  17. 17. さらに状況を悪化させる悪しき習慣
  18. 18. 動けばOK症候群 その場しのぎの修正 いいかげんな名前づけ ゆがんだ分岐構造の放置 重複コード/類似コードの放置 使わなくなったコードの放置
  19. 19. 力ずくのプログラミングの横行 言語が提供する型だけでがんばる int, long, boolean String, BigDecimal, LocalDate, LocalTime, List, Map, Set 大きなクラス、長いメソッド、たくさんのパラメータでがんばる
  20. 20. 硬直したモジュール構造 肥大化するソースファイル 動けばOK症候群 力ずくのプログラミングの横行 その繰り返しの結果…
  21. 21. 変更が やっかいで危険 開発スコープ 開発スピード 性能問題 ビジネス要求 開発費用 開発の労力 セキュリティ 対策 安定運用 操作性 機能追加 データ管理 外部連携 バグ対応 個人情報保護
  22. 22. 変更を楽で安全にする設計技法
  23. 23. 変更が 楽で安全 開発スコープ 開発スピード 性能問題 ビジネス要求 開発費用 開発の労力 セキュリティ 対策 安定運用 操作性 機能追加 データ管理 外部連携 バグ対応 個人情報保護
  24. 24. アジャイルなソフトウェア設計 私たちは、ソフトウェア開発の実践を通じて よりよい設計方法を見つけつつある データや機能よりビジネスルールを 手続き的プログラミングより型指向のプログラミングを 動くだけのソフトウェアより読みやすいソフトウェアを バックログより全体像を
  25. 25. ビジネスルールの分離 型指向のプログラミング コードの読みやすさに投資する 全体を見渡す習慣 変更を楽で安全にする4つの根底技法
  26. 26. ビジネスルールの分離 型指向のプログラミング コードの読みやすさに投資する 全体を見渡す習慣 変更を楽で安全にする4つの根底技法
  27. 27. ビジネスルールの記述を 独立したモジュールに分離する
  28. 28. ビジネスルールの記述を独立させる プレゼンテーション層の モジュール群 アプリケーション層の モジュール群 データソース層の モジュール群 ビジネスルールを 記述したモジュール群 利用する
  29. 29. ソフトウエアが複雑になる理由 ビジネスルール 金額、数量、期日、場所などの計算と判定 ビジネスルールを適用する条件による分岐 顧客区分、商品種別、有効期間、地域区分、金額区分、数量区分、 取引種類、取引状態、支払い方法、支払いタイミング、 割り増し条件、割引条件、キャンセル可能条件、…
  30. 30. 従来のモジュール構造とビジネスルール トランザクションスクリプト 機能(データ処理手続き)で縦割りした蛸壺式モジュール群 ビジネスルールの記述、特に条件判定が、 あちこちのモジュールに分散し、かつ、重複する 変更がやっかいで危険
  31. 31. ビジネスルールの記述を独立させる プレゼンテーション層の モジュール群 アプリケーション層の モジュール群 データソース層の モジュール群 ビジネスルールを 記述したモジュール群 利用する
  32. 32. ビジネスルールの記述を独立させる効果 プレゼンテーション層のモジュール群がシンプルになる アプリケーション層のモジュール群がシンプルになる データソース層のモジュール群がシンプルになる 三つの層から区分判定などの条件分岐が激減する 三つの層のモジュール群の設計がパターン化し安定する
  33. 33. ビジネスルール層は?
  34. 34. ビジネスルールを記述するモジュール群に 複雑さが集中する ビジネスルールをわかりやすく整理できる 設計スタイルを採用する
  35. 35. ビジネスルールの分離 型指向のプログラミング コードの読みやすさに投資する 全体を見渡す習慣 変更を楽で安全にする4つの根底技法
  36. 36. 型指向のプログラミング ビジネスルール(計算/判定)の記述をモジュール化する基本 値の種類(=型)ごとにクラス(モジュール)定義する 例:数値を扱う BigDecimal型, 日付を扱う LocalDate型 ただし、個々のビジネスルールを記述するには汎用的すぎる
  37. 37. 型指向のプログラミング ビジネスルールに登場する値を分類する 値の種類(=型)ごとに、独自のクラスを定義する 値の種類ごとに有効な値の範囲を定義する 値の種類ごとに必要な計算・判定のロジックを特定する
  38. 38. ビジネスルールを 型指向のプログラミングで記述する
  39. 39. ビジネスルールを記述する3要素 Fact 事実の表現 ビジネスの状況の記録や通知に使う型 ・ 数値、日付、場所、識別番号、名称、… Rule Factを使った 計算や判定のロジック 計算式 同一性の判定式 大小の比較式 Goal 知りたいこと 計算結果や判定結果を表現する型
  40. 40. ビジネスルールをFact-Rule-Goalで記述する 3つの基本パターン 値オブジェクト ロジックを持ったenum コレクションのカプセル化
  41. 41. 値オブジェクト
  42. 42. 値オブジェクトとは?  Fact の表現  数値、時間、場所、識別番号、識別名称、…  オブジェクトのフィールド変数(インスタンス変数)とメソッドの引数  ビジネスとして適切な値の範囲を定義する  Rule (計算ロジックや判定ロジック)の置き場所  Factを使う計算や判定をメソッドとして記述する  Factと持つオブジェクトに、関連するロジックを集める  Goal 知りたいこと(計算結果、判定結果)の表現手段  知りたいことを表現した型(値の種類)を設計する  メソッドの返す型として使う
  43. 43. 値オブジェクトの分類表 単一の値 from-to [ from-to, … ] 数 値 金額型 Amount, Money 金額範囲 x円以上 y円未満 金額範囲のコレクション 価格帯 数量型 Quantity, NumberOfXxx 数量範囲 m人以上 n人以下 数量範囲のコレクション 数量別割引率 時 間 日付型 DueDate, XxxDate 期間 開始日 - 終了日 期間のコレクション シーズン 時刻型 HourTime, XxxTime 時間 開始時刻 – 終了時刻 時間のコレクション 時間帯 空 間 地点型 Point 接続 Path:出発点 – 到達点 接続のコレクション Route [Path,…] 地域型 Area, Zone - 地域のコレクション 階層、fuzzy、重複、… 参考: アナリシスパターン 基本型
  44. 44. 値オブジェクトの効果  値オブジェクト=ビジネスに特化した値の種類  動かすだけなら、プログラミング言語が提供する汎用的な型だけでよい  ビジネスに特化した型  プログラムが、ビジネスルールの記述そのものになる  値の種類ごとにビジネスロジックの計算判定の記述が一か所にまとまる  あちこちに重複しなくなる  ビジネスルールの変更にかかわるソフトウェアの変更が楽で安全になる
  45. 45. 値オブジェクトの設計 計算の種類を特定する
  46. 46. 計算の種類 説明、メソッド例 結果の型 等値判定 isEqual( other ) , notEqual( other ) boolean / enum 大小判定 greaterThan( other ), lessThan( other ), … boolean / enum 加算・減算 同じ型同士の計算 同じ型 乗算 同じ型同士の乗算は意味がないことが多い 別の数値型 除算 同じ型の除算と、異なる型の除算では、意味が異なる 別の数値型 境界 Max, Min の存在 同じ型(の固定値) 列挙 prev(), next() が可能な集合 (循環が可/不可) 同じ型 文字列表現 その値の標準的な文字列表現 toString() 文字列 文字列からの生成 標準的な文字列表現からのオブジェクト生成 parse() 同じ型 どんな計算が必要か、値の種類ごとに検討する 計算の意図を、結果の型とメソッド名で説明する
  47. 47. 値オブジェクトを使って変更を安全にする 契約による設計
  48. 48. 契約による設計 変更を楽で安全にするための設計技法 事前条件(クラスを使う側の責任) 事後条件(計算を提供するクラスの責任) assert による表明 型による表明 暗黙のビジネスルールの明文化につながる 値の範囲と計算の種類を限定する→動作が安定する 出典:バートランドメイヤー オブジェクト指向入門
  49. 49. enumを使った区分ごとのロジックの整理
  50. 50. 区分ごとのロジックを扱う 区分ごとの条件分岐が複雑さの大きな原因 enumは区分ごとのロジックを整理する強力な手段 enumを使うと区分体系の問題の発見と改善が進む
  51. 51. 区分を列挙しただけのenumを作る 区分ごとの定数をenumのフィールド変数に移動 区分ごとの計算や判定のロジックをenumのメソッドに移動 コードがゆがむ(フィールド変数やメソッドの一貫性が崩れる) 区分のリファクタリング(区分の分解、再定義) ビジネスルール記述のわかりやすさにブレークスルーが起きる
  52. 52. コレクションのカプセル化
  53. 53. コレクション操作の問題と改善 問題 あちこちにコレクションを操作する類似の記述が分散 バグが紛れ込みやすい(不整合が起きやすい) コレクション操作の手続きは、ビジネスの関心事ではない 改善策 目的別のコレクション型を独自につくる コレクション操作のロジックをそのクラスに集める コレクション操作の詳細を隠蔽する
  54. 54. コレクションのカプセル化の効果 コレクション操作がちらばっていたコードのぐちゃぐちゃ感が消える コレクション操作を集めることで、リファクタリングがやりやすくなる コレクション操作の整合性と一貫性が向上する コレクション操作という技術手段が隠蔽され クラス名とメソッド名でビジネスの関心事が前面に登場する
  55. 55. 型指向のプログラミング 具体例
  56. 56. 時給ベースの給与計算 https://github.com/system-sekkei/isolating-the-domain
  57. 57. attendance.Attendance 勤怠 attendance.AttendanceStatus 勤怠状況 attendance.Recorded 勤務記録有無 attendance.TimeRecords 勤務実績一覧 attendance.TotalWorkTime 総勤務時間 attendance.WorkMonth 勤務月 contract.Contract 従業員契約 contract.Contracts 従業員契約一覧 contract.ContractStartingDate 契約開始日 contract.ContractStatus 契約状態 contract.ContractWage 契約給与 contract.ContractWages 契約給与一覧 contract.HourlyWage 時給 contract.MidnightHourlyExtraWage 深夜時給割増額 contract.OverTimeHourlyExtraWage 深夜時給割増額 contract.WageCondition 給与条件 employee.ContractingEmployees 契約中従業員一覧 employee.Employee 従業員 employee.EmployeeNumber 従業員番号 employee.MailAddress メールアドレス employee.Name 氏名 employee.PhoneNumber 電話番号 legislation.DailyOvertimeWork 時間外労働 legislation.ExtraPayRate 割増率(%) legislation.Midnight 深夜 legislation.MidnightExtraRate 深夜割増率 legislation.OverTimeExtraRate 時間外割増率 payroll.PaymentAmount 支払い金額 payroll.PaymentWorkTime 支払い対象時間 payroll.Payroll 給与 payroll.Payrolls 給与一覧 payroll.PayrollStatus 給与ステータス timerecord.ActualWorkTime 勤務時間実績 timerecord.bindingtime.BindingTime 拘束時間 timerecord.bindingtime.DaytimeBindingTime 日中拘束時間 timerecord.bindingtime.MidnightBindingTime 深夜拘束時間 timerecord.breaktime.BreakTime 休憩時間合計 timerecord.breaktime.DaytimeBreakTime 日中休憩時間 timerecord.breaktime.MidnightBreakTime 休憩時間(深夜) timerecord.DaytimeWorkTime 日中勤務時間 timerecord.EndTime 勤務終了時刻 timerecord.MidnightWorkTime 深夜勤務時間 timerecord.OverWorkTime 時間外勤務時間 timerecord.StartTime 勤務開始時刻 timerecord.TimeRange 勤務の開始と終了 timerecord.TimeRecord 勤務実績 timerecord.WorkDate 勤務日付 timerecord.WorkTime 勤務時間 amount.Amount 金額 amount.Percentage 率(割増や税などの金額に掛けられるもの) amount.RoundingMode 端数処理 date.Date 日付 date.DayOfWeek 曜日 date.Month 月 date.Year 年 date.YearMonth 年月 time.ClockTime 時刻を時分単位で表す time.ClockTimeRange 開始時刻と終了時刻を表現する(時刻間の時間間隔を返す time.Hour 時間(数) time.HourAndMinute x時間y分 time.Minute 分(数) time.QuarterHour 15分単位の時間 time.QuarterRoundClockTime 15分単位の時刻 time.QuarterRoundClockTimeRange 15分単位の時刻 給与計算に関するFact-Rule-Goalを表現したクラス群=ビジネスルール用語集 (ソースコードから自動生成したドキュメント)
  58. 58. 60種類の独自の型を 9つのパッケージで整理 パッケージ構造が ビジネスルールの概要説明になっている (ソースコードから自動生成したパッケージ図)
  59. 59. 区分ごとのロジックの整理 区分に依存するロジックの視覚化 (ソースコードから自動生成した区分の関連図) ソフトウェアの複雑さの大きな原因である、区分ごと のロジックをenumで整理 enumを参照するクラスを特定し、区分構造の影響範 囲を視覚化する
  60. 60. 型指向のプログラミングの効果 画面、テーブル、APIフォーマットの見方が変わる データ項目のフラットな集り → 計算元データと計算結果の集合体 「計算」という意味ごとの項目グループに分かれて見えるようになる ビジネスルールの計算・判定に分解して解釈するようになる ビジネスの関心事と開発者の関心事の単位(モジュール構造)が一致する
  61. 61. ビジネスルールの分離 型指向のプログラミング コードの読みやすさに投資する 全体を見渡す習慣 変更を楽で安全にする4つの根底技法
  62. 62. 従来のモジュール設計と可読性 (手続き的なプログラミング) コードの読みやすさに投資する動機に欠ける モジュール構造が固定なので クラス名、パッケージ名、メソッド名を考える機会が少ない 引数名と変数名だけ工夫しても、あまり効果がない 動けばOK症候群や力ずくプログラミングでは 読みやすさへの関心は弱い
  63. 63. ビジネスルールを型で記述するプログラミング コードの読みやすさに投資する効果が大きくなる パッケージ名、クラス名、メソッド名がそのままビジネスルールの記述の語彙になる 名前のわかりやすさの改善が、コードの読みやすさに直結する 型を使う側に型名の効果が波及する 型名がいいかげんだとわかりにくさや不自然さがきわだつようになる 型名の改善の before/afterの差が歴然となる 改善効果を実感できる機会が増え 読みやすさの改善に自然に取り組むようになる
  64. 64. ビジネスルールの分離 型指向のプログラミング コードの読みやすさに投資する 全体を見渡す習慣 変更を楽で安全にする4つの根底技法
  65. 65. 全体を見渡す習慣 従来のモジュール構造では、全体を見る機会が少ない その結果、コードの重複がはびこる ビジネスルールを型を使って記述する設計スタイルだと、 どのロジックがどこを使われているかがわかりやすくなる 全体を意識したモジュール構造や名前の改善が習慣になる
  66. 66. パッケージ間の依存関係が見えてこない ツリー構造を眺めても、あまり有用な情報がない あちこちに同じロジックが重複して記述される それに気が付かない ツリー構造 (ソースコードから自動生成したパッケージツリー図)
  67. 67. ビジネスルール層の型名を使って、アプリケーション全体が型のネットワーク構造になる どこに何が書いてあるか、どこの変更がどこに影響するか/しないかが、構造的にはっきりする IDEのfind Usageや定義場所へ移動で、日常的に全体の関連性を意識するようになる 型のネットワーク構造 (ソースコードから自動生成した型の関連図)
  68. 68. ビジネスルールの分離 型指向のプログラミング コードの読みやすさに投資する 全体を見渡す習慣 変更を楽で安全にする4つの根底技法
  69. 69. 分析設計のアプローチ ビジネスルール層 アプリケーション層
  70. 70. ビジネスルール層の分析設計のアプローチ
  71. 71. ビジネスルールの3つの源泉 価値提供の約束と支払いの約束 ビジネス活動の連鎖/契約の連鎖 競争優位の獲得策/競争劣位の防止策 契約 バリュー チェーン 事業運営 ポリシー
  72. 72. 約束 何を(区分) どのくらい(数量) いつ(日時) いくらで(金額) 誰に(区分)
  73. 73. 約束の履行の監視と促進の決め事 いつ何が起きるべきか(イベント区分、状態区分) 起きたことの検知 起きなかったことの検知 起きた場合のアクション 起きなかった場合のアクション
  74. 74. 約束違反の扱いの決め事 約束のキャンセル(可否の判断、可能な場合の補償) 価値を提供できなかった時のルール(返品、返金、…) 対価の支払いができなかった時のルール(ペナルティ、…)
  75. 75. ビジネスルール発見の着眼点 金額の計算 数量の計算 時点や期間の計算 場所や経路の計算 それらに影響する分類軸(区分) 顧客、商品特性、取引種類、支払い方法、配送方法、… 在庫特性、進捗マイルストーン、担当、時間帯、曜日、季節、地域、….
  76. 76. アプリケーション層の分析設計技法
  77. 77. ビジネスルールの記述を独立させる プレゼンテーション層の モジュール群 アプリケーション層の モジュール群 データソース層の モジュール群 ビジネスルールを 記述したモジュール群 利用する
  78. 78. アプリケーション層の複雑さ ビジネスルールの記述を、ビジネスロジック層に移動する 理論的にはアプリケーション層はとてもシンプルになる 現実はアプリケーション層に複雑なロジックが残りやすい アプリケーション層の複雑さの分析と整理 (VETRO, Saga)
  79. 79. VETRO分析
  80. 80. VETRO 分析とは? ビジネストランザクションをビジネスメッセージの処理としてとらえる メッセージ処理を5種類のアクション(VETRO)に分解してみる アクションごとに、どのルールをどのタイミングで適用するか検討する
  81. 81. VETRO Validation 妥当性検証 Enrich 情報付加 Translate 情報導出 Routing 分岐判定 Operation 通知/記録ビジネス メッセージ 出典: Camel Design Patterns 非同期メッセージングを使った EIP: Enterprise Integration Patternsの応用パターン
  82. 82. VETRO ビジネス メッセージ Event 通知、Document送付 Query 問い合わせ、Command 指示 Validation 妥当性検証 メッセージ内容の妥当性を検証する データ形式、必須属性、値範囲、… Enrich 情報付加 メッセージに含まれたIDなどから、関連する情報 を収集するルール(ex. 顧客ID->顧客購買履歴) Translate 情報導出 付加された情報を元に、新たな情報を導出する ルール (ex. 購買履歴 → 顧客ランク ) Routing 分岐判定 導出された情報を元に、適切なオペレーションに 分岐させるルール ( ex. 顧客ランクごとの対応 ) Operation 通知/記録 通知ルール:誰に何を通知すべきか? 記録ルール:どこに何を記録すべき?
  83. 83. Saga 複合トランザクションに分解する
  84. 84. Sagaとは? ③が不成立だった場合、①と②にキャンセル処理を実行する という、さまざまな状況とその対応方法(undo)の物語を用意する ①②③を、独立して、順不同で実行する (それぞれの物語) 三つともOKであれば、それで完了(Happy Goal) 独立したトランザクション A 独立したトランザクション B 独立したトランザクション C ビジネス メッセージ コーディ ネータ ひとつの大きなトランザクション → 独立した複数の小さなトランザクションに分割
  85. 85. Sagaとは?  独立したトランザクションのコミット  個々のトランザクションは独立して確定する(できる)  undo の仕組み  どこかで不都合な状況が発生した場合、キャンセル処理など適切なカウン タートランザクションを実行する仕組みを用意する  ビジネスレベルでの代替アクションの分析と実装  自動的なundo以外に、人間系の代替プロセスや取消プロセスの実行に引き 継ぐパターンも選択肢  その場合の支援機能を用意する
  86. 86. まとめ
  87. 87. よい設計とは? 変更が楽で安全であること
  88. 88. 変更が 楽で安全 開発スコープ 開発スピード 性能問題 ビジネス要求 開発費用 開発の労力 セキュリティ 対策 安定運用 操作性 機能追加 データ管理 外部連携 バグ対応 個人情報保護
  89. 89. ビジネスルールの分離 型指向のプログラミング コードの読みやすさに投資する 全体を見渡す習慣 変更を楽で安全にする4つの根底技法
  90. 90. ビジネスルールの3つの源泉 価値提供の約束と支払いの約束 ビジネス活動の連鎖/契約の連鎖 競争優位の獲得策/競争劣位の防止策 契約 バリュー チェーン 事業運営 ポリシー
  91. 91. Validation 妥当性検証 Enrich 情報付加 Translate 情報導出 Routing 分岐判定 Operation 通知/記録ビジネス メッセージ 独立したトランザクション A 独立したトランザクション B 独立したトランザクション C ビジネス メッセージ コーディ ネータ VETRO Saga アプリケーション層の分析設計
  92. 92. アジャイルなソフトウェア設計の学び方
  93. 93. 参考書籍
  94. 94. コードを使ったワークショップなど  リファクタリングの1stサンプルを使った体験学習  サンプルアプリケーション(時給ベースの給与計算)の解説  型指向のプログラミングの体験学習  ビジネスルールの分析設計の体験学習

×