本記事は READYFOR 株式会社の READYFOR Advent Calendar 2023 の22日目です。 昨日は @asaitoの CSVダウンロード機能を非同期化するでした。
はじめに
こんにちは、READYFORでプロダクトエンジニアをやっておりますtoyocです。
さて、この数年で「技術的負債!」「リファクタリング!」「変更容易性!」とかコードの品質と生産性の関係についてワイワイする機会が増えたように自分は感じております。皆さんはいかがでしょう? そんなことない? そうですか…。
ともあれ読みやすいコードをなるべく保ちたいと思っているエンジニアは少なからずいるはずで、どうしてそういうふうに考えてるのかイメージつきづらいエンジニア以外の方もまた、少なからずいるんじゃないかと思っております。具体的には自分の奥さんとか。
そんな方向けに、今回はカレーのレシピが色々な仕様変更にさらされる小話で一緒に考えてみたいと思います。
ではどうぞ!
シンプルなカレーのレシピ
花子「お母さん、こんどバイト先で賄いのカレーを作ることになったんだけど、作り方教えてくれない?」
母「いいわよ、はい、レシピ」
1. タマネギを薄切りにする
2. ジャガイモ・ニンジンを一口大に切る
3. 鍋でタマネギを炒める
4. 鍋に豚肉・水、ジャガイモ・ニンジンをいれて煮る
5. 沸騰したらカレールーを入れて火を弱める
6. 10分ほど煮込んで完成
花子「シンプルだね」
母「分量や細かな材料の指定は割愛してるからそこは自分で考えて」
花子「(そこが大事なのでは…?)…わかった、これで頑張ってみる」
仕様変更1 〜季節感が欲しい〜
〜〜1週間後〜〜
花子「お父さん、お母さんいる?」
父「母さんなら会社でRails4から7にアップデートしようとして失敗したからまだ帰ってこれないらしいぞ」
花子「なんでそんな無茶なことを…」
とりあえず季節ごとの野菜を用意しました
花子「まぁいいや、かくかくしかじかでバイト先でカレー作ったんだけど、店長にもっと季節感のあるカレーが食べたいって言われてどうしようかと思ってるの」
父「なるほどな。」
花子「お母さんにもらったレシピを自分なりにアレンジしてみたんだけど…」
父「どれどれ見せてごらんなさい。」
1. タマネギを薄切りにする
2. もし、今が春ならタケノコ・菜の花・新じゃがを一口大に切る。
3. もし、今が夏ならナス・ゴーヤ・トマトを輪切りにする。
4. もし、今が秋ならさつまいも・かぼちゃを一口大に切って、しめじを食べやすい大きさに千切る。
5. もし、今が冬ならジャガイモ・ニンジン・春菊を一口大に切る
6. 鍋でタマネギを炒める
7. 鍋に豚肉・水、玉ねぎ以外の野菜をいれて煮る
8. 沸騰したらカレールーを入れて火を弱める
9. 10分ほど煮込んで完成
父「(分量とかないの…?)…なるほど、玉ねぎ以外の具材を季節感ある野菜にしたんだね」
花子「うん、でもなんだかレシピが読みにくくなっちゃって」
父「たしかにもしもの分岐が増えたし、野菜によって切り方も違うってなると複雑になってるね」
変更しやすい工程としづらい工程に分解する
父「カレーを作る、と一言で言うのは簡単だけれど、このレシピを見るといろんなことをやっているね?」
花子「そうね、野菜を切って炒めて水を加えて煮て…」
父「そうそう、じゃあカレーを作る工程を、具材によって変わるものとそうでないものに分けるとどうなるかな?」
花子「うーーん…、野菜を切った後はもうほぼ煮るだけだし、『下ごしらえ』と『煮込む』とかかなぁ」
父「いいね、じゃあ今言ったようにレシピを分けてみようか。こんな感じでどうだい?」
1. タマネギを薄切りにする
2. もし、今が春ならタケノコ・菜の花・新じゃがを一口大に切る。
3. もし、今が夏ならナス・ゴーヤ・トマトを輪切りにする。
4. もし、今が秋ならさつまいも・かぼちゃを一口大に切って、しめじを食べやすい大きさに千切る。
5. もし、今が冬ならジャガイモ・ニンジン・春菊を一口大に切る
6. タマネギ(A)とそれ以外(B)で分けておく
1. 鍋で 3-1の(A) を炒める
2. 鍋に豚肉・水、 3-1の(B) をいれて煮る
3. 沸騰したらカレールーを入れて火を弱める
4. 10分ほど煮込んで完成
花子「ちょっと読みやすくなった気がする。意味があるまとまりにざっくり分けるだけでもちがうんだねー」
父「そうだろう?それに、これなら材料が今後変わるとしても 3-1:下ごしらえ
の中だけ変えればいい。」
花子「なるほどー、 変更されやすい部分を切り離してるのね。これなら季節以外で材料変える時も変えやすいわ。」
父「あとは 3-2
で使うことになる単位であらかじめ 3-1
で作ったものを分けておくのもポイントだ」
花子「あー、確かに AとかBとか名前を振ってるからその後のレシピで参照しやすくなってるね」
父「そう、玉ねぎを先に炒めてからそれ以外を入れる、という工程は変わらなそうだから、それを意識してあらかじめ分けとくのも良いと思うんだ」
花子「なるほどねー、ありがとう!これで作ってみるよ!」
仕様変更2 〜子供用もついでに〜
〜〜2週間後〜〜
花子「お姉ちゃん、お父さんいない?」
姉「お父さんは会社でRuby1.3から3.1にアップデートしようとしたけど失敗したから帰れないんだって。」
花子「どこかで聞いたような話だなぁ…お母さんは?」
姉「お母さんは、Railsのアップデート差分を確認するって書き置きして出て行ったよ」
花子「どこへ……?」
変わりうるのは材料だけだと思ってたのに…
花子「まぁいいや、じゃあお姉ちゃんに相談なんだけど、かくかくしかじかでカレーを作ってるのね。」
姉「ふむふむ」
花子「で、店長のお子さんのご飯もついでに作って欲しいって言われてて困ってるの。」
姉「どう困ってるの?」
花子「子供用はルーを甘口にして、具材も小さくして欲しいんだって。しかも大人用と一緒に作ってくれって言われちゃって。」
姉「なるほどねぇ」
花子「一応レシピをアレンジしてみたんだけど…」
姉「うんうん。」
1. タマネギを薄切りにする
2. もし、今が春ならタケノコ・菜の花・新じゃがを一口大に切る。
3. もし、今が夏ならナス・ゴーヤ・トマトを輪切りにする。
4. もし、今が秋ならさつまいも・かぼちゃを一口大に切って、しめじを食べやすい大きさに千切る。
5. もし、今が冬ならジャガイモ・ニンジン・春菊を一口大に切る
6. タマネギ(A)とそれ以外(B)で分けておく
1. タマネギを5mm角に切る
2. もし、今が春ならタケノコ・菜の花・新じゃがを5mm角に切る
3. もし、今が夏ならナス・ゴーヤ・トマトを5mm角に切る
4. もし、今が秋ならさつまいも・かぼちゃ・しめじを5mm角に切る
5. もし、今が冬ならジャガイモ・ニンジン・春菊を5mm角に切る
6. タマネギ(A)とそれ以外(B)で分けておく
1. 鍋で 4-1の(A) を炒める
2. 鍋に豚肉・水、 4-1の(B) をいれて煮る
3. 沸騰したらカレールーを入れて火を弱める
4. 10分ほど煮込んで完成
1. 鍋で 4-2の(A) を炒める
2. 鍋に豚肉・水、 4-2の(B) をいれて煮る
3. 沸騰したら甘口カレールーを入れて火を弱める
4. 10分ほど煮込んで完成
花子「なんか似たような手順が増えちゃって読みづらくなっちゃって。」
姉「うーん確かにこれは読みづらいわね。大人用と子供用の違いがわかりづらい。」
花子「そうなの…それにこの通りにやると結局二度手間だし…」
姉「同じ材料を別々に切って、それぞれを同じように煮込むんだから確かに二度手間ね。」
花子「全く違うことやってるわけじゃないからなんとか整理して効率化したいんだけど、どうすればいいかなぁ」
使いまわせるものは使いまわしてみる
姉「一度材料を大人用のサイズに切ってから、子供用のサイズにさらに切ってもいいんじゃない?」
花子「あー、どっちにしろ細かく切るもんね。最初に全部まとめて切っちゃった方がやりやすいかも」
姉「そうそう、使いまわせるものは使いまわした方が効率的だと思うな」
花子「そしたらこうかな?」
1. タマネギを薄切りにする
2. もし、今が春ならタケノコ・菜の花・新じゃがを一口大に切る。
3. もし、今が夏ならナス・ゴーヤ・トマトを輪切りにする。
4. もし、今が秋ならさつまいも・かぼちゃを一口大に切って、しめじを食べやすい大きさに千切る。
5. もし、今が冬ならジャガイモ・ニンジン・春菊を一口大に切る
6. タマネギ(A)とそれ以外(B)で分けておく
1. (A)の半分を5mm角に切る (C)
2. (B)の半分を5mm角に切る (D)
1. 鍋で (A) を炒める
2. 鍋に豚肉・水、 (B) をいれて煮る
3. 沸騰したらカレールーを入れて火を弱める
4. 10分ほど煮込んで完成
1. 鍋で (C) を炒める
2. 鍋に豚肉・水、 (D) をいれて煮る
3. 沸騰したら甘口カレールーを入れて火を弱める
4. 10分ほど煮込んで完成
姉「うん、すっきりしたね。材料も(A)~(D)で見分けやすくなったと思う」
花子「煮込む工程の 4. 10分ほど煮込んで完成
は共通してるからまとめた方がいいのかな?」
姉「うーん、せっかく『煮込む』でひとまとまりになっているところだし、そこは変に分けない方がわかりやすいと思うよ。」
花子「なるほどね。ありがとう!これで作れそう!」
仕様変更3 〜やっぱ肉じゃがで〜
〜〜 3週間後 〜〜
花子「お兄ちゃん、みんなは?」
兄「母さんは先週から帰ってこないし、父さんもRubyのソースコードを読みにいくって書き置きしていなくなった。」
兄「姉さんは母さんの職場から電話かかってきて、謝りながら代わりに働きに行ってるよ」
花子「えぇ…うちの親やばすぎでは…?」
まさかカレーですら無くなるとは…
花子「……一旦忘れておくとして、そしたらお兄ちゃんに聞きたいんだけど、かくかくしかじかでカレーを(以下略」
兄「ふむふむ」
花子「で、店長が自分だけ肉じゃが食べたいから作ってくれって言い出して困ってるの」
兄「そんなわがままな」
花子「ひどいよねー。でもカレーと肉じゃがは具材が大体同じっていうからいけるかなと思ってレシピ考えてみたの。」
兄「ほうほう」
1. タマネギを薄切りにする
2. もし、肉じゃがも作るならジャガイモ・ニンジンを一口大に切る
3. もし、今が春ならタケノコ・菜の花・新じゃがを一口大に切る。
4. もし、今が夏ならナス・ゴーヤ・トマトを輪切りにする。
5. もし、今が秋ならさつまいも・かぼちゃを一口大に切って、しめじを食べやすい大きさに千切る。
6. もし、今が冬ならジャガイモ・ニンジン・春菊を一口大に切る
7. タマネギ(A)とそれ以外(B)と肉じゃが用(C)で分けておく
1. (A)の半分を5mm角に切る (D)
2. (B)の半分を5mm角に切る (E)
1. 鍋で (A) を炒める
2. 鍋に豚肉・水、 (B) をいれて煮る
3. 沸騰したらカレールーを入れて火を弱める
4. 10分ほど煮込んで完成
1. 鍋に豚肉・水、 (C) をいれて煮る
2. 沸騰したらしょうゆ・酒・砂糖・みりんを入れて火を弱める
3. 10分ほど煮込んで完成
1. 鍋で (D) を炒める
2. 鍋に豚肉・水、 (E) をいれて煮る
3. 沸騰したら甘口カレールーを入れて火を弱める
4. 10分ほど煮込んで完成
花子「大人用の下ごしらえが『もし』が多くて冗長に感じちゃうんだよね…」
兄「なるほどなぁ。そしたらそこだけでも整理してみようか。」
複雑な要望への答えは複雑になっちゃう
兄「とりあえず大人用下ごしらえがいろんなパターンに対応しすぎてるからちょっと分解したよ。」
1. タマネギを薄切りにする(A)
2. 肉じゃがを作るなら `7-2` を用意する
3. 季節野菜のカレーを作るなら `7-3` を用意する(B1)
1. ジャガイモ・ニンジンを一口大に切る
2. カレー用(B2)と肉じゃが用(C)で分ける
1. もし、今が春ならタケノコ・菜の花・新じゃがを一口大に切る。
2. もし、今が夏ならナス・ゴーヤ・トマトを輪切りにする。
3. もし、今が秋ならさつまいも・かぼちゃを一口大に切って、しめじを食べやすい大きさに千切る。
4. もし、今が冬ならジャガイモ・ニンジン・春菊を一口大に切る
1. (A)の半分を5mm角に切る (D)
2. (B1かB2)の半分を5mm角に切る (E)
1. 鍋で (A) を炒める
2. 鍋に豚肉・水、 (B1かB2) をいれて煮る
3. 沸騰したらカレールーを入れて火を弱める
4. 10分ほど煮込んで完成
1. 鍋に豚肉・水、 (C) をいれて煮る
2. 沸騰したらしょうゆ・酒・砂糖・みりんを入れて火を弱める
3. 10分ほど煮込んで完成
1. 鍋で (D) を炒める
2. 鍋に豚肉・水、 (E) をいれて煮る
3. 沸騰したら甘口カレールーを入れて火を弱める
4. 10分ほど煮込んで完成
花子「さっきより読みやすくなったような気がするけど、やっぱり長いなぁ…」
兄「もともとの要望が複雑だからしょうがないよね。
要するに、『季節ごとの味も欲しいし幼児食もついでに作って欲しいし、肉じゃが食べたい時もあるけど柔軟に対応してカレー作って欲しい』
っていうことでしょ?」
花子「確かに……」
兄「これを短くしたいなら要望の方をなんとかする方が楽だと思うよ」
花子「そっかー、ちょっと店長と相談してみるよ。ありがとう!」
兄「うん、じゃあ僕も出かけてくるよ」
花子「どこ行くの?」
兄「父さんの代わりにWindows3.0からWindows11にアップデートする仕事を頼まれてるんだ」
花子「それ絶対終わらないから断った方がいいと思う」
おしまい
おわりに
最初はシンプルだったカレーのレシピが、店長の要望をどんどん聞き入れてどんどん長く複雑になってしまいましたね。花子さんはその度に家族に相談してレシピを整理していましたが、結局複雑さからは逃げきれませんでした。
それでも整理しないまま要望を取り入れ続けていたら、きっともっと長く複雑でとても読む気のしないレシピになっていたでしょう。
さて、あなただったらどんなふうにレシピを整理していたでしょうか。
料理ごとにレシピをまとめなおしたり、書かなくてもわかるような部分は省略したり、そもそも分量かけよ!等々、色々思いつくこと・突っ込みたいことはあるかもしれません。
今回はカレーのレシピと店長の要望を例え話として書いてみましたが、同じような構造はいろんなところにあるような気がしています。エンジニアがコードをリファクタすること、PdMが仕様を整理すること、主婦が夕飯の支度を考えること、一見バラバラに思えますが、わかりやすさ・進めやすさを突き詰めていくところで共通する部分もままあるんじゃないかと。そんな思いつきでこの記事を書いてみました。
思いつきの勢いと実験的な気持ちで書いたので、綺麗な結論をきちんと言葉に表せるわけでもなく、どうにも中途半端な記事になってしまいました。考えずに感じてください、お手数おかけします。
来年はもうちょっと歯切れのいい記事になるように精進します!
ぐだぐだでしたが、ここまで読んでいただけてとても嬉しいです。ありがとうございました!
さて明日は23日目 @s-mori の担当です!お楽しみに!