確かリーダブルコードか, code completeに乗っていた方法な気がします。
まさかり歓迎
忙しいんだけど
楽に理解できるくらいにコードを分割しましょうという話です。
こんなコードがつらい><
選択項目によってコンテンツが何パターンか変わるみたいなコード、Web制作でもありますよねぇ...
if (hoge === "aa" && !(piyo === "bb" || fuga === "aaaa")) {
/*
* 共通処理
*/
if (hige == "cc") {
//固有な処理A
}
} else if(hoge === "bb" && !(piyo === "aa" || fuga === "aa")) {
/*
* 共通処理
*/
if (piyo == "puyo") {
//固有な処理B
}
} else {
//なんでもなかった時
}
サンプルコードを考えるのもつらい
つらいポイント
つらポイ
- ifの条件が複雑で一発で理解できない
- 状態による分岐/分岐ごとの処理をまとめてやってしまっている
ふぇぇ、 こんな複雑なコード読めないよ>< - 分岐ごとの処理内では同じような処理を繰り返している
コピペ!コピペ!コピペ!
こうすると少し良いかも
長いけど我慢してください><
var status = 分岐判定();
switch (status) {
case 'パターンA':
パターンAの時の処理();
break;
case 'パターンB':
パターンBの時の処理();
break;
default:
alert('エラーだよ')
break;
}
function 分岐判定() {
var status;
/*
* 条件をDOMなり変数なりから分岐して判定
*/
// status = 'パターンA'; 分岐をかけてみたいな感じのものを入れる
// 戻す情報は一つ
return status;
}
function パターンAの時の処理(){
共通処理();
固有な処理A();
}
function パターンBの時の処理(){
共通処理();
固有な処理B();
}
function 共通処理() {
// ...
}
function 固有な処理A() {
// ...
}
function 固有な処理B() {
// ...
}
ポイント
それぞれの処理を分割した
関数やif文ごとに一つのことしかやらないようにしました。
というかifは分岐しかやらないのでswitchに化けました。チーン
分割してみると、一つ一つの処理は大抵簡単になります。
本当の処理自体は固有な処理A
,固有な処理B
に押し込めれらえていることがわかります。
それぞれのブロックが一体何をやっているのか分かりやすくなりました。
これは 単一責任の原則と呼びます。
実際にテスト実行してみて、バグが出た際に、バグが出た箇所さえ特定できれば 何が原因となっているのか
理解しやすいというメリットもあります。
まとめると
- 読みやすく
- 書きやすく
- テストしやすい
がメリットとなります。
共通化
繰り返しコピペが発生していた 共通処理 は一つの関数として独立し、
繰り返し呼び出されて利用されるようになりました。
もしこの処理へ変更が入った際も、一つの関数を修正すれば良いのでラクです。
一つ一つ再コピペなど、 しなくて良いのです。いいですかしなくて良いのです。 (大事なry
終わりに
改善されたコードは結構長いです。
扱うif文の複雑さにより、部分的に取り入れるなどのトレードオフをしても良いでしょう。
(Web制作とか、そんなに時間かけてられない時もありますからねぇ...)
早すぎる最適化は諸悪の根源であるみたいな格言もありますので、コードを見直した際に段階的に取り入っていっても良いでしょう。