現場で役立つシステム設計の原則 Chapter 7 画面とドメインオブジェクトの設計を連動させる


## 画面アプリケーションの開発の難しさ

### アプリケーションの画面はシンプルに

- アプリケーションの画面はしばしば複座になりすぎる
- その開発コードも重服や副作用によって複雑になる
- アプリケーションの画面はシンプルにあるべき
  - なんでもできる汎用画面ではなく、用途ごとのシンプルな画面
  - 画面のロジックと業務のロジックを分離する

## 画面の関心ごとを小さく分けて独立させる

### 画面は小分けにする

- 大量の情報を一度に入力するのはユーザーにとって負担が大きい
- 注文情報の入力においても、配送手段、連絡先、注文の確定など、画面ごとに小分けにする。
- その方がロジックもシンプルに整理される
- このような小さな単位に分けた画面の提供を ** タスクベースのユーザーインターフェース ** という
- Amazon が良い例

## 画面とメインオブジェクトを連動させる

### 画面はドメインオブジェクトを視覚的に表現したもの

画面とは、ユーザーの関心ごとそのものであり、それはつまり、ドメインオブジェクトが表現するものでもある。
であるならば、画面の表示にもドメインオブジェクトをそのまま利用するのが適切なはずだ。
しかしながら、ドメインオブジェクトに画面表示のための全てのロジックを含めるべきではない。

### ドメインオブジェクトに持たせるべきロジック

持たせるべきロジック: 論理的なビュー

- 例えば、複数の段落があるとする、これを表現するための String[]
- 段落がいくつあるか、最も長い段落の文字数のカウント、最初の 20 文字のみを取得 など
- Map<String, String[]> による用語と解説の定義付け
- 画面に出力すべき情報の文字列表現 "%s 件見つかりました。" など
- css class 名にできるようなオブジェクトの状態 unread など

持たせるべきでないロジック: 物理的なビュー

- <p> や css など
- <dl> や <dt> <dd> など

## 画面とソフトウェアを関係づける

### 画面表示に最適化されたドメインオブジェクト

- Book のような書籍についての膨大な情報をもったクラスが存在しても、画面に表示する情報のみをもった Booksummary クラスを作るべき
- 情報の並び方なども画面の順番に揃える

### 画面項目をグルーピングをドメインオブジェクトの構成に落とし込む

#### **🔍 画面デザインの 4 原則**

| **原則**               | **説明**                                                                 |
| ---------------------- | ------------------------------------------------------------------------ |
| **近接（Proximity）**  | 関係のある情報は近づけ、関係のない情報は離す                             |
| **整列（Alignment）**  | 意味のある項目を同じラインに揃え、異なる意味のものはインデントなどで区別 |
| **対比（Contrast）**   | 重要度の違いを、フォントの大きさや色の違いで強調                         |
| **反復（Repetition）** | 同じ意味の情報は、同じパターンで視覚化                                   |

---

#### **📖 1. 近接（Proximity）**

**「関連する情報は近くに配置する」** という原則。  
プログラムでは、**ドメインオブジェクトの単位（クラス）と一致** させるべき。

---

##### **✅ 具体例：ユーザープロフィールの設計**

**🖥 画面の項目の配置**

```
ユーザー情報
-----------------
名前: 田中 太郎
メール: tanaka@example.com
生年月日: 1990-01-01

アカウント設定
-----------------
ログインID: tanaka123
パスワード変更: ********
```

**📌 関連する情報（個人情報とアカウント情報）が分かれている**

---

**🖥 ドメインオブジェクト**

```java
class User {
    String name;
    String email;
    LocalDate birthDate;
}

class Account {
    String loginId;
    String password;
}
```

**📌 「User クラス」と「Account クラス」を分けることで、プログラムの設計も画面の配置と一致する**

---

#### **📖 2. 整列（Alignment）**

**「意味のある項目を同じラインに揃える」** という原則。  
プログラムでは、**インデントされた情報を別のオブジェクトとして扱う** と良い。

---

##### **✅ 具体例：注文履歴の設計**

**🖥 画面のレイアウト**

```
注文履歴
----------------------
注文番号: 12345
注文日: 2024-03-18
合計金額: 10,000円

    商品一覧:
    - 商品A (2,000円) x 2
    - 商品B (6,000円) x 1
```

**📌 「注文情報」と「商品情報」でレイアウトが分かれている**

---

**🖥 ドメインオブジェクト**

```java
class Order {
    int orderId;
    LocalDate orderDate;
    int totalPrice;
    List<OrderItem> items;
}

class OrderItem {
    String productName;
    int price;
    int quantity;
}
```

**📌 Order クラスと OrderItem クラスを分けることで、画面とプログラムの構造が一致する！**

---

#### **📖 3. 対比（Contrast）**

**「重要な情報は目立つようにする」** という原則。  
プログラムでは、**重要なクラスを目立たせる、もしくは他のクラスを隠蔽する**。

---

##### **✅ 具体例：商品一覧の設計**

**🖥 画面のデザイン**

```
おすすめ商品 ★
----------------------
商品名: 高級ノートPC
価格: 150,000円

通常商品
----------------------
商品名: 標準ノートPC
価格: 100,000円
```

**📌 おすすめ商品は強調表示される**

---

**🖥 ドメインオブジェクト**

```java
class Product {
    String name;
    int price;
}

class FeaturedProduct extends Product {
    boolean isFeatured = true;
}
```

**📌 「おすすめ商品（FeaturedProduct）」は、通常の商品とは別のクラスにすることで、プログラムでも区別できる**

---

#### **📖 4. 反復（Repetition）**

**「繰り返される情報は同じ型で扱う」** という原則。  
プログラムでは、**インターフェースや共通クラスを利用する**。

---

##### **✅ 具体例：通知システム**

**🖥 画面の通知リスト**

```
通知一覧
----------------------
[メール] 新しいメッセージが届きました
[アプリ] 友達リクエストが届きました
[SMS] 認証コード: 123456
```

**📌 メール・アプリ・SMS の通知は共通のフォーマットで表示される**

---

**🖥 ドメインオブジェクト**

```java
interface Notification {
    void send(String message);
}

class EmailNotification implements Notification {
    public void send(String message) { System.out.println("[メール] " + message); }
}

class AppNotification implements Notification {
    public void send(String message) { System.out.println("[アプリ] " + message); }
}

class SMSNotification implements Notification {
    public void send(String message) { System.out.println("[SMS] " + message); }
}
```

**📌 「Notification インターフェース」を作ることで、異なる通知を共通の形で扱える！**

---

#### **✨ まとめ**

✅ **画面デザインの「近接・整列・対比・反復」の原則は、ドメインオブジェクトの設計と一致する**  
✅ **「関連情報をまとめる」「インデントされた情報を別クラスにする」「重要な情報を目立たせる」「共通情報を統一する」ことが重要**  
✅ **画面のデザインが適切なら、ドメインオブジェクトの設計の良し悪しも判断しやすくなる**

📌 **UI/UX とプログラム設計を一致させることで、保守しやすく直感的なシステムを作れる！**