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

これだけは知っておきたいクラス設計の基礎知識 version 2

これだけは知っておきたいクラス設計の基礎知識 version 2

クラス設計の考え方とやり方

クラス設計の目的
- ソフトウェアの複雑さを扱いやすくする
- ソフトウェアの変更を楽で安全にする

クラス設計の三つの視点
- 関心の分離
- 依存関係
- モジュール性

クラス設計の5つの技法
- 計算判断と入出力の分離
- 中核と周辺の分離
- 業務特化のデータ型
- 契約プログラミング
- 不変(イミュータブル)

増田 亨

April 09, 2025
Tweet

More Decks by 増田 亨

Other Decks in Programming

Transcript

  1. これだけは知っておきたい クラス設計の基礎知識 有限会社システム 増田 亨 Original Version : JJUG CCC

    2023 Spring Step Up Session 2023年6月4日 Revised : HireRoo Re:TechTalk #02 2025年4月9日
  2. ソフトウェアの設計 2025/4/9 3 プログラム 永続化 通信 ⇒ クラス設計 ⇒ 変更容易性

    ⇒ テーブル設計 ⇒ データ完全性 ⇒ プロトコル設計 ⇒ 相互運用性
  3. クラス設計のスキル 習得シナリオ 2025/4/9 6 外部の参考情報 ⇒ 自分の知識体系に取り入れる ⇒ 習熟する クラス設計の

    参考情報 クラス設計の 知識を構築 クラス設計に 習熟する 外部 自分 今日の内容 書籍 ドキュメント サンプルコード 外部から得た情報を 自分の体験と関連づけて 自分なりの知識を構築する 手を動かして 体で覚える 直観的に使える 活きた知識に変換
  4. 関心の分離の失敗パターンと改善方法 10 混在 断片化 分離 集約 重複 一元化 いろいろ 同時に考える

    異なる関心事は 別々に考える あちこちを 同時に考える 関連が強い関心事は 一箇所に集めて考える あちこちで 同じことを考える 一つの関心事は ただ一箇所で考える 2025/4/9
  5. モジュール性 モジュール性が高いクラス設計 • 関心が分離できている • 依存関係を明示できている ⇒ 複雑さが扱いやすい ⇒ 変更が楽で安全

    クラスの初期設計とリファクタリング活動は モジュール性を向上するためのコスト • 費用対効果の高い個所を特定して、そこにコストをかける • 費用対効果の低い個所を特定して、そこにコストはかけない 2025/4/9 12
  6. 計算判断クラスと入出力クラス 計算判断クラスの例 • LocalDate • BigDecimal • String • ArrayList

    入出力クラスの例 • PrintStream (System.out、System.err) • java.io.*, java.nio.*, java.net.*, java.sql.*, … • @Controller, @Repository, @Entity, … 2025/4/9 19 計算判断のための専用クラス (入出力に依存しない) 入出力は専用のクラス/パッケージに 分離して閉じ込める
  7. ②ソフトウェアの中核と周辺を分離する 2025/4/9 20 業務視点の クラス群 中核 通信アダプター HTTP @Controller @RestController

    RestTemplate 通信アダプター JMS @JmsListner JmsTemplate 永続化アダプター JDBC @Repository @Entity 周辺 周辺 スケジュール アダプター @Scheduled 周辺 周辺
  8. 中核と周辺を分離するシナリオ 2025/4/9 21 いろいろな 関心事 いろいろな 関心事 業務視点の 計算判断クラス (業務ロジック)

    いろいろな 関心事 業務視点の 計算判断クラス (業務ロジック) 業務視点の 入出力クラス 記録/参照、通知/転送 業務視点の 計算判断クラス (業務ロジック) 通信 アダプター 永続化 アダプター 設計 設計 設計 業務視点の 入出力クラス 記録/参照、通知/転送 中核 中核 中核 中核 中核 周辺 周辺 周辺 ライブラリやフレームワークを アダプターの設計と実装に活用する
  9. ③ 業務特化のデータ型 計算判断専用のクラス • 計算判断の関心事と入出力の関心事を分離する 計算判断に使うデータと計算判断ロジックを一箇所にまとめる • 計算判断ロジック記述の断片化を防ぐ • 計算判断ロジック記述の重複を防ぐ

    業務視点の関心事を表現する • 業務に特化したデータ型(intやStringは汎用のデータ型) • 業務ルールに基づく複雑な業務ロジックを表現する基本語彙 2025/4/9 23
  10. 汎用データ型の有効な操作 • int型 ==, !=, <, >, +,- , *,

    /, % • BigDecimal型 add(), devide(), multiply(), … • LocalDate型 isAfter(), isBefore(), plus(), with(), … • DayOfWeek型 from(), valueOf(), plus(), minus(), … • String型 isEmpty(), length(), substring(), … 2025/4/9 26 基礎知識として参考にする
  11. 業務特化のデータ型と有効な操作の候補 単一値(金額、数量、日付、時刻など) • 同値の判定 isSame() • 比較 isGreaterThan()/isLessThan(), isAfter(), isBefore()

    • 加算・減算 add(), plus(), subtract(), minus() • 掛算・乗算 multiply() (整数倍と単位付き数量倍の違い) • 割算・除算 devide() (整数除算と単位付き割算の違い) • 最大・最小 MAX, MIN (有効な範囲) • 基本型と変換 toString()/parse(), intValue()/of() 2025/4/9 27 アプリケーションに必要十分な操作セットを見つける
  12. 業務特化のデータ型と有効な操作の候補 範囲型(金額範囲、数量範囲、日付範囲など) • 範囲の判定 範囲の重なり、前後、包含、… • 範囲の合成 二つの範囲を一つにまとめる • 部分範囲

    一つの範囲から部分範囲を取り出す 区分型(顧客区分、商品区分、支払い区分など) • 区分に変換 from(), of(), parse(), … • 区分の判定 for() • 移動 next(), previous() 2025/4/9 28 こういうクラス設計の考え方を 自分の体験と関連づけて知識を構築し 手を動かして体で覚える
  13. 業務特化のデータ型と有効な操作の候補 多値を扱うデータ型:業務視点のデータ配列 • 絞り込み filter() 部分配列 • 変換 map() あるデータ型の配列を別のデータ型の配列へ変換

    • 集約 reduce() 多値を単一値に集約(集計、最大、…) 多値を扱うデータ型:業務視点のデータ集合 • 集合どうしの和(足し算) • 集合どうしの差(引き算) • 共通集合 • 要素を含むか検査 2025/4/9 29 こういうクラス設計の考え方を 自分の体験と関連づけて知識を構築し 手を動かして体で覚える
  14. ④ 契約プログラミング 基本アイデア • クラスをつなぐ唯一の手段はメソッドの公開 • メソッドの仕様を明確にするとモジュール性が改善する • 関係がわかりやすくなり、連係動作が安定する メソッドの仕様を明確に定義する

    メソッドを提供するクラスとメソッドを利用するクラスの責任を明示する • 事後条件(提供クラスの義務) メソッドの返す型 • 事前条件(利用クラスの義務) メソッドの引数の型と数 • 不変条件(提供クラスの義務) インスタンスの状態の整合性の保障 2025/4/9 30
  15. 引数の型と返す値の型が変われば契約が変わる divideBy(整数型) ⇒ 金額型 ゼロ除算が起きる可能性がある 負数で割り算する可能性がある divideBy(自然数型) ⇒ 金額型 ゼロ除算や負数除算はできない

    巨大な除数での割り算の可能性がある 端数に関する契約は不明 divideBy(数量型) ⇒ 単価型 数量型で除数の有効範囲を定義 単価型で小数点以下の有効桁数を定義 2025/4/9 31 例:金額型の割算(divideByメソッド)の契約 業務視点での契約プログラミング
  16. ⑤ 不変(イミュータブル) 実行中にクラスの状態が変わると、使う側の負担が大きい • 挙動が不安定になる • 防御的なコードが不必要に増殖する 基本アイデア • 一度作ったインスタンスは状態を変えない

    • 状態の変更の代わりに同じ型の別のインスタンスを生成する 2025/4/9 32 クラスのつなぎ方と連係動作を安定させる 不変方式のクラスの使い勝手を評価する(String, BigDecimal, LocalDate) 可変方式のクラスの使い勝手を評価する(StringBuilder, ArrayList, HashSet)
  17. クラス設計のスキル 習得シナリオ 2025/4/9 34 外部の参考情報 ⇒ 自分の知識体系に取り入れる ⇒ 習熟する クラス設計の

    参考情報 クラス設計の 知識を構築 クラス設計に 習熟する 外部 自分 今日の内容 書籍 ドキュメント サンプルコード 外部から得た情報を 自分の体験と関連づけて 自分なりの知識を構築する 手を動かして 体で覚える 直観的に使える 活きた知識に変換