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

Web APP Java
スポンサーリンク

3日目のゴール

3日目のテーマも引き続き 「1クラス1役割」
ただし今日は、
「役割をコードに“見える形”で刻む」 ところまで行きます。

1日目で「1人1仕事」という感覚をつかみ、
2日目で「誰が誰を知るか(依存)」を整理しました。

3日目は、
「このクラスは何をするクラスなのか」を、
コードの構造と名前でハッキリさせる練習
をします。


責務を「名前」と「中身」でそろえる

名前だけ立派で、中身がぐちゃぐちゃなクラス

よくある“惜しい”コードがこれです。

public class MemoService {
    public void saveMemo() {
        // ユーザー入力を受け取る
        // ID を決める
        // 日付を決める
        // ファイルに書き込む
        // 画面に「保存しました」と表示する
    }
}
Java

名前は「MemoService」で、
なんとなく「メモ関連の処理をまとめたクラス」に見えます。

でも中身は、

ユーザー入力
ID採番
日付生成
ファイル保存
画面表示

が全部入りです。

つまり、
「名前は1役割っぽいのに、実態は何役割も持っている」 状態です。

これが、
中級者が最初にぶつかる「責務のズレ」です。


「このクラスは何をする人?」と問い直す

MemoService を分解してみる

さっきの MemoService に対して、
一つずつ問いを立ててみます。

ユーザー入力を受け取るのは誰の仕事か?
IDを決めるのは誰の仕事か?
日付を決めるのは誰の仕事か?
ファイルに書き込むのは誰の仕事か?
画面にメッセージを出すのは誰の仕事か?

ファイル保存アプリの文脈で考えると、
自然にこう分かれます。

ユーザー入力と画面表示 → アプリ本体(UI担当)
ID・日付・本文という“メモの形” → Memo
ファイルへの保存・読み込み → MemoRepository

つまり、MemoService は
本来は存在しなくてもいい“なんでも屋”だったわけです。


「役割ごとにクラスを分ける」をもう一段具体的に

役割をはっきりさせた3人組

ファイル保存アプリの基本メンバーを、
改めてコードで整理します。

Memo:データの形だけを担当する

public class Memo {
    private final int id;
    private final String date;
    private final String body;

    public Memo(int id, String date, String body) {
        this.id = id;
        this.date = date;
        this.body = body;
    }

    public int getId() { return id; }
    public String getDate() { return date; }
    public String getBody() { return body; }
}
Java

ここには「メモとは何か」しか書いていません。
ファイルも、ユーザーも、画面も、何も知りません。
これが 責務が純粋なクラス です。

MemoRepository:保存と読み込みだけを担当する

public class MemoRepository {
    private final String fileName;

    public MemoRepository(String fileName) {
        this.fileName = fileName;
    }

    public void save(Memo memo) {
        // Memo を 1行 "ID|日付|本文" にしてファイルに追記する
    }

    public List<Memo> findAll() {
        // ファイルを読み込んで List<Memo> に変換して返す
    }
}
Java

ここには「どう保存するか」「どう読み込むか」だけが書かれます。
ユーザー入力も、画面表示も、一切出てきません。

MemoApp:ユーザーとの会話と流れだけを担当する

public class MemoApp {
    private final MemoRepository repository;

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

    public void run() {
        // メニュー表示
        // ユーザー入力
        // repository に「保存して」「読み込んで」と依頼する
    }
}
Java

ここには「ユーザーが何をしたいか」「次に何をするか」だけが書かれます。
ファイルの形式も、保存先も、知らなくていい世界です。


「責務のズレ」を見抜く目を育てる

例題:MemoRepository に画面表示を入れてしまった場合

こんなコードを書いてしまったとします。

public class MemoRepository {
    public void save(Memo memo) {
        // ファイルに保存する
        System.out.println("メモを保存しました"); // つい書いてしまった
    }
}
Java

一見、便利そうです。
「保存したら自動でメッセージ出してくれるし」と。

でも、ここで立ち止まってほしい。

MemoRepository の責務は何か?
「メモをファイルに保存・読み込みすること」だったはずです。

画面表示は誰の責務か?
それは App(UI担当)の仕事です。

つまり、この一行は
「他人の仕事を奪っている」 わけです。

結果として、

MemoRepository が UI に依存し始める
テストするときに、標準出力が邪魔になる
将来 GUI に変えたくなったときに、Repository まで直さないといけない

という 保守性の低下 を招きます。


保守性を「未来の自分の楽さ」で測る

変更シナリオを具体的に想像する

保守性は、
「未来の自分がどれだけ楽できるか」
で測ると分かりやすいです。

例えば、こういう未来を想像してみます。

コンソールアプリから、GUIアプリに変えたくなった
ファイル保存から、データベース保存に変えたくなった
メモに「タグ」や「優先度」を追加したくなった

このとき、
どのクラスを直せばいいかを考えます。

GUIに変えたい → App だけを差し替えたい
DBに変えたい → MemoRepository だけを差し替えたい
メモの項目を増やしたい → Memo と MemoRepository だけを直したい

これが実現できているなら、
責務と分離がうまく設計されている と言えます。

逆に、
どの変更でも App/Memo/Repository 全部をいじらないといけないなら、
責務が混ざっているサインです。


3日目の実践:自分のコードに「役割ラベル」を貼る

クラスごとに「一言で役割を書く」

今日やってほしい具体的な練習はこれです。

自分のファイル保存アプリの各クラスの先頭に、
「このクラスは何をするクラスか」を一文でコメントする

例えば Memo ならこう。

// Memo: 1件のメモ(ID・日付・本文)を表すだけのクラス。
// ファイル保存や画面表示のことは一切知らない。
public class Memo {
    ...
}
Java

MemoRepository ならこう。

// MemoRepository: Memo をファイルに保存・読み込みするクラス。
// ファイル形式や保存先を知っているが、UI のことは知らない。
public class MemoRepository {
    ...
}
Java

App ならこう。

// MemoApp: ユーザーと会話し、メモの追加・一覧などの流れを制御するクラス。
// 永続化の詳細は MemoRepository に任せる。
public class MemoApp {
    ...
}
Java

この「役割ラベル」を書いてみると、
自分のコードがその役割にちゃんと沿っているか、
ズレているかが見えてきます。

もしラベルと中身がズレていたら、
それは 責務を整理し直すチャンス です。


3日目で本当に持って帰ってほしいこと

3日目のテーマは、
「責務を頭の中だけでなく、コードの形として刻む」 ことでした。

まとめると、こうです。

クラスの名前と中身の役割をそろえる
「このクラスは何をする人?」と常に問い直す
他人の仕事(UI・永続化など)を勝手に奪わない
未来の変更シナリオを想像して、どこだけ直せるかを考える
役割ラベルをコメントとして書いてみる

ここまで来ているあなたは、
もう「クラスをなんとなく増やす人」ではなく、
「クラスに意味を持たせて設計する人」 です。

次の段階では、
この「意味のあるクラスたち」に
インターフェースや抽象クラスという“設計の道具” を重ねていく世界に進めます。

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