Clean Code関数設計リファクタリング
Clean Codeの第3章「関数」を1時間で体感する方法
Robert C. Martinの『Clean Code』第3章「関数」は、多くの開発者が「読んだはずなのに身についていない」章No.1です。
理由はシンプル。教科書の例と自分のコードが結びついていないから。
第3章の核心
Uncle Bobは第3章で、良い関数の特徴をこう定義しています。
- 小さく書け — 関数は20行以内
- 1つのことだけを行え — 単一責任の原則(SRP)
- 抽象レベルを統一せよ — 高レベルと低レベルのロジックを混ぜるな
- 引数は少なく — 理想は0、多くても3つまで
- 副作用を持つな — 関数名が示す以外のことをするな
読めば「当たり前じゃん」と思います。でも実際に自分のコードを見返すと、どうでしょうか?
よくあるコード
async function processUser(userId: string) {
const user = await db.user.findUnique({ where: { id: userId } });
if (!user) throw new Error("not found");
// メール送信
await sendgrid.send({
to: user.email,
subject: "Welcome",
html: `<p>Hello ${user.name}</p>`,
});
// ログ記録
await db.auditLog.create({
data: { userId, action: "welcome_sent", timestamp: new Date() },
});
// キャッシュ更新
await redis.set(`user:${userId}:welcomed`, "1", "EX", 86400);
return user;
}
この関数、何をしていますか?
- ユーザー取得
- メール送信
- 監査ログ記録
- キャッシュ更新
4つのことをしています。関数名はprocessUser— 何も伝わりません。
Clean Code視点でのリファクタリング
async function sendWelcomeToUser(userId: string) {
const user = await fetchUser(userId);
await sendWelcomeEmail(user);
await recordWelcomeSent(user.id);
return user;
}
高レベルの関数は「何をするか」だけを記述。詳細は下位の関数に任せる。これが抽象レベルの統一です。
CodeSenseiで体感する
このレッスンをCodeSenseiで受けると、AIがあなたの実際のコードを題材に同じ原則を解説してくれます。
架空のUserクラスの例ではなく、あなたが昨日書いたprocessOrderやupdateProfileを題材に「ここから Clean Code 第3章が体感できる」と教えてくれます。