簡単に分かる悪い設計と良い設計
最近自分が悪い設計のコードを苦しみながら書いて、書いたあとに考えたら悪い設計をしていたことに気づいたので、今回自戒のために書いた。
自分自身プログラミングの技術が高いわけじゃないけどそれでも書いたあとにこれはマズかったと分かる例の話をする。
細かいコードの書き方に話が飛ぶとダルすぎるのであくまで文章だけで書く。
例:テキストファイルが10ファイルあって10ファイル全てのテキストファイルを合わせた合計の文字数を数えたい
注:それぞれのテキストファイルのファイルサイズが巨大で10TBを超えるとか10ファイルが時間差で揃うから逐次的に処理しなければいけないとかそういう込み入った前提ではないとする
明らかに悪い設計:
1ファイルずつ開いて1行毎の文字数をカウントして1ファイル毎に変数を1つずつ作って変数に保持する。最後に10個の変数を合計する。
普通と思われがちだが悪い設計:
1ファイルずつ開いて1ファイル毎の文字数を1つの変数に足していく。それを10ファイル全てに対して繰り返す。
いちばんマシな設計:
10ファイル全てを結合して1つのファイルにする。その結合してできたファイルを1ファイル全ての文字数を数える関数で文字数をカウントする(変数を使わず繰り返しも行わない)。
いちばんマシな設計の例をシェルスクリプトで書いた(改行込みならtrコマンド部分を除いてコマンド2つで書ける)
別のアナロジーを試したので書く。
目的:野菜スープを作りたい
悪い例:ニンジン畑に行ってニンジンを1つ掘り返し、その場で掘り返したニンジンを洗って切って、鍋に入れて、入れたニンジンの量に比例する水を鍋に足す。→ジャガイモ畑に行ってジャガイモを1つ掘り返し、その場で掘り返したジャガイモを洗って切って、鍋に入れて、入れたジャガイモの量に比例する水を鍋に足す。→玉ねぎ畑に行って玉ねぎを1つ掘り返し、その場で掘り返した玉ねぎを洗って切って、鍋に入れて、入れた玉ねぎの量に比例する水を鍋に足す。→他の野菜も同様に繰り返す→鍋を火にかけて煮る。→もう一人分の鍋が必要なので鍋を用意する(驚くべきことに先程の鍋は一人分だったのだ)→ニンジン畑に行って.......→鍋は10人分必要なので合計10回繰り返す。
→調理人はあまりの手際の悪さにキレて帰る。
良い例:ニンジン畑に行って10人分のニンジンを掘る。他のジャガイモと玉ねぎも同様に掘る。全部の野菜を1箇所に集める→全て洗う→全て切る→10人分の鍋に入れる→10人分の水を入れる→鍋を火にかける。
→どうにか鍋は1人分と同じ手順で作れて調理人も満足。
つまり何が言いたいかというと、作業工程を混合してそれを何度も繰り返すというのは複雑で理解が難しく(ソースコードを書きづらく読みづらい)、作業工程を混ぜず繰り返しをしないほうが完結で理解が簡単(ソースコードが書きやすく読みやすい)。