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 {
...
}
JavaMemoRepository ならこう。
// MemoRepository: Memo をファイルに保存・読み込みするクラス。
// ファイル形式や保存先を知っているが、UI のことは知らない。
public class MemoRepository {
...
}
JavaApp ならこう。
// MemoApp: ユーザーと会話し、メモの追加・一覧などの流れを制御するクラス。
// 永続化の詳細は MemoRepository に任せる。
public class MemoApp {
...
}
Javaこの「役割ラベル」を書いてみると、
自分のコードがその役割にちゃんと沿っているか、
ズレているかが見えてきます。
もしラベルと中身がズレていたら、
それは 責務を整理し直すチャンス です。
3日目で本当に持って帰ってほしいこと
3日目のテーマは、
「責務を頭の中だけでなく、コードの形として刻む」 ことでした。
まとめると、こうです。
クラスの名前と中身の役割をそろえる
「このクラスは何をする人?」と常に問い直す
他人の仕事(UI・永続化など)を勝手に奪わない
未来の変更シナリオを想像して、どこだけ直せるかを考える
役割ラベルをコメントとして書いてみる
ここまで来ているあなたは、
もう「クラスをなんとなく増やす人」ではなく、
「クラスに意味を持たせて設計する人」 です。
次の段階では、
この「意味のあるクラスたち」に
インターフェースや抽象クラスという“設計の道具” を重ねていく世界に進めます。

