Java | 1 日 120 分 × 7 日アプリ学習 中級編:オブジェクト指向(OOP) - クラス責務分離アプリ

Web APP Java
スポンサーリンク

2日目のゴール

2日目のテーマも同じく 「1クラス1役割」
ただし今日は、
「クラス同士がどう関わるか」
という視点を強く意識します。

1日目は
「1人1仕事に分けよう」
という話でした。

2日目は
「じゃあ、その1人1仕事たちを、どう“つなぐ”のがキレイか」
を、ファイル保存アプリを題材にして掘り下げます。


責務と分離を「関係性」で見る

クラスは“孤立”していてはいけない

1クラス1役割と言うと、
「クラスはバラバラに独立している」
というイメージを持ちがちですが、
実際は逆です。

クラスは
「はっきりした役割を持った上で、協力し合う」
必要があります。

メモアプリで言えば、

Memo は「メモというデータ」を表す
MemoRepository は「メモの保存・読み込み」を担当する
App は「ユーザーとの会話とアプリの流れ」を担当する

この3つは、
バラバラではなく、
ちゃんと“つながって”動きます。

ここで大事になるのが、
「どうつなぐか」=依存関係の設計 です。


悪い例:App が何でも知っているパターン

なんでも知ってる司会者は、すぐ潰れる

まず、よくある「ちょっと残念な中級者コード」を見てみます。

public class MemoAppBad {
    private final String fileName = "memo.txt";

    public void run() {
        // ユーザー入力
        // ここで直接 FileWriter / FileReader を使う
        // ここで行のフォーマット "ID|日付|本文" を決める
        // ここで ID 採番もやる
    }
}
Java

このクラスは、
1日目の「BadMemoApp」ほどひどくはないけれど、
まだこういう問題を抱えています。

ファイル名を知っている
ファイルの形式も知っている
ファイルの書き方・読み方も知っている
ID 採番のルールも知っている

つまり、
「司会者のくせに、裏方の仕事まで全部知っている」 状態です。

この状態だと、

ファイル形式を変えたい
保存先を変えたい
保存方法を変えたい(DBにしたい)

となったときに、
App をガッツリ書き換える必要が出てきます。

これは 保守性が低い 典型パターンです。


良い例:依存を“細く・はっきり”させる

App は「何をしてほしいか」だけ知る

理想の姿はこうです。

App は
「メモを保存してほしい」
「メモ一覧を取り出してほしい」
「このIDのメモを消してほしい」

という “お願いの言葉”だけ知っている

「どうやって保存するか」は、
MemoRepository に丸投げする。

コードで見ると、こうなります。

public class MemoApp {
    private final MemoRepository repository;

    public MemoApp(MemoRepository repository) {
        this.repository = repository;
    }

    public void run() {
        // ユーザー入力
        // 例えば「1: 追加」が選ばれたら
        addMemo();
    }

    private void addMemo() {
        // Scanner で本文を受け取る
        String body = ...;
        String date = "2026-06-07"; // 仮

        Memo memo = new Memo(0, date, body); // ID は Repository 側で決めてもいい
        repository.save(memo);
    }
}
Java

ここでのポイントは、
App は 「MemoRepository が何をしてくれるか」だけ知っていて、
「どうやってやっているか」は知らない
ということです。

これが
責務の分離が“関係性”にまで浸透している状態 です。


依存方向を意識する:どっちがどっちを知っているか

「上の層」から「下の層」へだけ依存させる

ファイル保存アプリを層で見ると、こうなります。

アプリ層(App)
ドメイン層(Memo)
永続化層(MemoRepository)
ファイルシステム(OSの世界)

ここで大事なルールがあります。

「上の層は下の層を知っていていいが、
下の層は上の層を知らないほうがいい」

具体的に言うと、

App は MemoRepository を知っていていい
MemoRepository は App を知らないほうがいい

App は Memo を知っていていい
Memo は App を知らないほうがいい

この「依存の向き」が揃っていると、
設計はとても安定します。


例題:依存の向きが崩れたときに何が起きるか

悪いパターン:Repository が App を呼び出す

もし、こんなコードを書いてしまったらどうでしょう。

public class MemoRepository {
    private MemoApp app; // これがすでに怪しい

    public void save(Memo memo) {
        // 保存したあとに、画面にメッセージを出したくなった
        app.showMessage("保存しました");
    }
}
Java

一見「便利そう」に見えますが、
これはかなり危険です。

MemoRepository は
「ファイル保存の専門家」であるべきなのに、
「画面表示」という App の仕事に手を出しています。

結果として、

App は MemoRepository を知っている
MemoRepository も App を知っている

という “お互い様依存” が発生します。

こうなると、

どちらかをテストしたいときに、
もう片方も一緒に引きずられる
片方を変えると、もう片方も壊れやすい

という 保守性の低い状態 になります。


「責務」と「依存」はセットで考える

責務を分けたら、「誰が誰を知るか」も決める

1クラス1役割をやるとき、
よくある落とし穴はこうです。

クラスは分けた
でも、依存関係はぐちゃぐちゃ

これだと、
見た目は「クラスがいっぱいある」けれど、
中身は「大きな1クラスがバラバラに散っただけ」
という状態になりがちです。

大事なのは、

このクラスは何を担当するか(責務)
このクラスは誰を知っていていいか(依存)

この2つを セットで決めること です。


具体例で整理する:ファイル保存アプリの責務と依存

Memo の責務と依存

責務:
「メモというデータ(ID・日付・本文)を表す」

依存:
基本的に、他のアプリクラスを知らない。
(標準ライブラリの String や int などだけ)

つまり、
「一番“純粋な”クラス」 です。


MemoRepository の責務と依存

責務:
「メモをファイルに保存・読み込みする」

依存:
Memo を知っていていい
ファイル関連のクラス(Path, Files, Reader, Writer)を知っていていい
App(UI)は知らないほうがいい

ここでのポイントは、
「下の層(永続化)は、上の層(UI)を知らない」 ということです。


App の責務と依存

責務:
「ユーザーと会話し、アプリの流れを制御する」

依存:
Memo を知っていていい
MemoRepository を知っていていい
Scanner や System.out を知っていていい

App は一番“上の層”なので、
下の層を知っていて構いません。


保守性をもう一段深く見る

「変更の波及」をイメージする

保守性とは、
「変更したときに、どれだけ影響が広がるか」
と言い換えられます。

例えば、こう考えてみてください。

ファイル形式を ID|日付|本文 から
ID,日付,本文(カンマ区切り)に変えたい

このとき、
どのクラスを直せばいいか?

理想はこうです。

MemoRepository の parseLineformatLine だけ直せばいい
App は一切触らない
Memo も一切触らない

これができているなら、
「責務と依存がうまく設計されている」 と言えます。

逆に、
App の中にもファイル形式の知識が散らばっていたら、
あちこちを直さないといけません。

これが 保守性の差 です。


2日目で身につけてほしい感覚

1クラス1役割は「分けて終わり」ではない

今日のポイントを、感覚としてまとめるとこうです。

クラスは「私はこれを担当します」と名乗る存在
その上で、「誰とどう関わるか」も設計する必要がある
上の層は下の層を知っていていいが、下の層は上の層を知らないほうがいい
責務と依存をセットで考えると、変更に強い設計になる

1日目は「分ける」話でした。
2日目は「分けたもの同士を、どうつなぐか」の話でした。

ここまで来ると、
あなたの頭の中にはもう
「クラス=役割を持った登場人物」
というイメージができているはずです。

次のステップでは、
その登場人物たちに
「インターフェース」という“共通の約束” を持たせていく、
という世界に進んでいけます。

タイトルとURLをコピーしました