第4章:YAGNIを支える実装スタイル(小さく作って育てる)🧱🌿✨
この章はひとことで言うと―― 「今ちょうどいい最小サイズで作って、あとから気持ちよく育てられる形にする」 だよ〜😊🌱
4-0. この章でできるようになること 🎯✨
- 「あとで足せる」最小の作り方がわかる🧰
- ちょいリファクタ前提で進める“安全な手順”が身につく🔧💡
- テストをほんの少しだけ入れて、YAGNIでも安心して進められる🧪🙂
- AI(Copilot / Codex系)に盛られずに手伝ってもらえる🤖✂️
ちなみに今どきの基準だと、.NET 10(LTS)+ C# 14が“最新のど真ん中”だよ〜🆕✨(C# 14は最新で .NET 10 対応って明記されてるよ) (Microsoft Learn) Visual Studio も Visual Studio 2026 が出てる〜💻✨ (Microsoft Learn)
4-1. YAGNIを支える「実装の4つのクセ」🍀
クセ①:まず“動く最小”を作る(完成を先に見に行く)🏃♀️💨

- 最初に「登録できる」「一覧で見れる」だけ作る📌
- UIがキレイとか、保存がDBとか、検索とかは一旦ぜんぶ置いとく🧊
✅ 合言葉:「まず動く。次に整える。」 ✨
クセ②:拡張ポイントは“作らない”。代わりに“切り出しやすく”する✂️
よくある「未来に備えた拡張ポイント」は👇みたいなやつ:
IRepositoryを先に作る📦- DIコンテナ前提の構造にする🧩
- なんでも汎用化ジェネリクスにする🧬
これ、今の段階だと コスト先払い になりがち😵💫
代わりにやるのはコレ👇
- クラスやメソッドを小さめにして、あとで分けやすくする🧱
- 責務の境目だけうっすら作る(“分けられる形”だけ作る)🌿
クセ③:リファクタは「小さく・すぐ・こまめに」🔧✨
YAGNIは「作らない」けど、整えるのはサボらない🙂 おすすめのリズム👇
- まず通す(動く)✅
- 目立つ1箇所だけ整える(名前、分割、重複除去)🧹
- すぐ止める(やりすぎない)🛑✨
クセ④:テストは“最小の防波堤”だけ作る🧪🧱

「全部テストしよう!」ってやると、逆にYAGNI違反になりがち😅 この章では 2〜3本だけ入れるよ👇
- 入力のルール(空文字はダメ、長すぎはダメなど)🧾
- 追加したら件数が増える✅
- 一覧が期待どおり返る✅
xUnit は v3 系が進んでて、.NET 8 以降対応って書かれてるよ〜📦 (nuget.org)
4-2. ミニ演習:小さなアプリを作る(登録 → 一覧)☕📝✨
題材はゆるくてOK!ここでは 「カフェメモ」☕:行ったお店を登録して一覧で見る を作るよ〜😊🌸
4-3. プロジェクト構成(“最小なのに育つ”)📁🌱
最初から分厚い層は作らないけど、育てやすさは残すために、こうするよ👇
CafeMemo.Core:アプリの中心(ルール&処理)🧠CafeMemo.App:コンソールで動かすだけ(UIっぽい所)🖥️CafeMemo.Tests:最小テスト🧪
「Webにしたい」「保存したい」が来たら、あとで増築できる形🏗️✨
4-4. 実装(コード)👩💻✨
① CafeMemo.Core:ドメイン&処理(いちばん大事な所)🧠
namespace CafeMemo.Core;
public sealed record CafeVisit(
Guid Id,
string ShopName,
string? Note,
DateTimeOffset VisitedAt
);
public sealed class CafeLog
{
private readonly List<CafeVisit> _visits = new();
public CafeVisit Add(string shopName, string? note, DateTimeOffset? visitedAt = null)
{
shopName = (shopName ?? "").Trim();
if (shopName.Length == 0)
throw new ArgumentException("店名は必須だよ🥺", nameof(shopName));
if (shopName.Length > 50)
throw new ArgumentException("店名が長すぎるよ🥺(50文字まで)", nameof(shopName));
var visit = new CafeVisit(
Id: Guid.NewGuid(),
ShopName: shopName,
Note: string.IsNullOrWhiteSpace(note) ? null : note.Trim(),
VisitedAt: visitedAt ?? DateTimeOffset.Now
);
_visits.Add(visit);
return visit;
}
public IReadOnlyList<CafeVisit> GetAll()
=> _visits
.OrderByDescending(v => v.VisitedAt)
.ToList();
}
ポイントはここ👇😊✨
CafeLogの中に保存は とりあえず List(今必要)🧺- でも
Add/GetAllに入口を寄せて、あとで差し替えやすい形🌿 DateTimeOffsetで時刻を扱って、将来の困りごとを減らす🕰️✨(これは“お得な最小”)
② CafeMemo.App:動かして確認(登録→一覧)🖥️☕
using CafeMemo.Core;
var log = new CafeLog();
while (true)
{
Console.WriteLine();
Console.WriteLine("=== カフェメモ ☕ ===");
Console.WriteLine("1) 登録する");
Console.WriteLine("2) 一覧を見る");
Console.WriteLine("0) 終了");
Console.Write("選んでね👉 ");
var input = Console.ReadLine()?.Trim();
if (input == "0") break;
if (input == "1")
{
Console.Write("店名:");
var shop = Console.ReadLine();
Console.Write("メモ(任意):");
var note = Console.ReadLine();
try
{
var added = log.Add(shop ?? "", note);
Console.WriteLine($"登録したよ〜✨ ID={added.Id}");
}
catch (ArgumentException ex)
{
Console.WriteLine($"エラーだよ💦 {ex.Message}");
}
}
else if (input == "2")
{
var all = log.GetAll();
if (all.Count == 0)
{
Console.WriteLine("まだ0件だよ〜🙂");
continue;
}
Console.WriteLine("---- 一覧 ----");
foreach (var v in all)
{
Console.WriteLine($"{v.VisitedAt:yyyy-MM-dd HH:mm} {v.ShopName} ({v.Note ?? "メモなし"})");
}
}
else
{
Console.WriteLine("0〜2で選んでね🙂");
}
}
🎉これで「登録→一覧」が完成! ここまでが MVP だよ〜✅✨
4-5. テスト(“最小の防波堤”2〜3本)🧪🧱✨
CafeMemo.Tests:xUnitで守る
using CafeMemo.Core;
using Xunit;
public sealed class CafeLogTests
{
[Fact]
public void Add_店名が空なら例外()
{
var log = new CafeLog();
Assert.Throws<ArgumentException>(() => log.Add(" ", "note"));
}
[Fact]
public void Add_追加したら一覧が1件になる()
{
var log = new CafeLog();
log.Add("コーヒー天国", "おいしかった");
var all = log.GetAll();
Assert.Single(all);
Assert.Equal("コーヒー天国", all[0].ShopName);
}
}
このくらいで十分だよ〜😊✨ 「未来の拡張」じゃなくて、今日の安心のためのテスト🧡
4-6. “小リファクタ”の例:やるならコレだけ🔧✨
✅ いまやってOK(効果がすぐ出る)🙆♀️
- 変数名をわかりやすくする(
v→visit)📝 - 長いメソッドを2つに分ける(入力処理と表示処理)✂️
Trim()と空チェックをまとめる🧹
❌ いまはやらない(盛りやすい)🙅♀️🎈
IRepository作る- DIコンテナ導入
- “将来の検索”のための抽象化
- “汎用ログ基盤”を先に整備
こういうのは「痛み」が出た瞬間が買い時だよ🛒✨(第5章以降で判断が上手くなる!)
4-7. AI活用:盛らせないプロンプト集🤖✂️💡
Copilot/Codexに投げるときは、最初にこれを付けるだけで事故りにくいよ〜🙂✨
🧾 ① 雛形づくり(盛り禁止)
C#で「登録→一覧」だけの最小実装にして。
将来拡張のためのRepository/DI/抽象化は入れないで。
データはListでOK。クラスは少なめ、読みやすさ重視。
🧪 ② テスト(最小の2本だけ)
テストは2本だけ提案して。
(1) 店名が空なら例外 (2) 追加したら件数が増える
それ以外は不要。
🕵️♀️ ③ 過剰設計チェック
このコード、YAGNI的に“今いらない仕組み”が混ざってない?
混ざってたら、削る案を短く3つ出して。
Visual Studio 2026 は AI の統合も強めていく流れが書かれてるので、こういう使い方がめちゃ相性いいよ〜🤖✨ (Microsoft Learn)
4-8. 仕上げチェック(この章のゴール)✅🎉
次の条件を満たしたら合格〜💮✨
- 登録できる☕
- 一覧が見れる📋
- 店名が空だとちゃんと止まる🧯
- テストが2本通る🧪✅
- 「将来のための仕組み」を増やしてない✂️🙂
4-9. まとめ(今日のいちばん大事)🧡
YAGNIで詰まないコツはこれ👇😊✨
- 小さく完成させる(完成が先)🏁
- リファクタ前提で、ちょいちょい整える🔧
- テストは最小(安心のためにちょっとだけ)🧪
- AIは盛らせず、最小で出させる🤖✂️
次の章では、C#で特にやりがちな「未来用設計」をどう安全に先送りするかを、もっと具体例つきでいくよ〜🧯🧠✨