よく「コードがスパゲッティになってる」と言ったりします。麺が複雑に絡み合って、ほどけない状態ですね。ここで「麺」に例えられているものは、何なのでしょうか?


真っ先に思い浮かぶのは、「コードの実行の流れ」です。

でも、GOTO文しか無かった時代ならともかく、現代のプログラミング言語なら、コードの流れを追うのに苦労することは少ないかな?

コールバック、非同期処理、Promise、スレッド、golangのgoroutine、Clojureのcore.asyncなどは、そもそも生まれつき難解なので、スパゲッティの理由には当たりません。


では、麺の正体は何か?

答えは「変数のスコープ」だと思います。スコープとは、その変数を読み書きできる範囲のことです。

デバッグのためにプログラムを解読しているとしましょう。if文があり、変数aの値に応じて分岐しています。この変数に値をセットしている場所を遡って探しますよね。スコープが広い変数なら、すごく離れた場所で値が書き換えられているかもしれません。

スコープが広いということは、麺が長〜い、ということです。絡みやすいんですね。その一端をつまんだとき、もう片方の端がとんでもないところに飛び出てしまうんです。特に、グローバル変数やクラスのインスタンス変数は、関数間をまたげる飛び道具なので注意が必要です。


スコープと似て非なるものに、「変数の寿命」があります。

寿命が長い変数は、(たとえスコープが狭くても)やはり長い麺になる危険があります。例えば、クラス変数やC言語でstaticが付いた変数は、寿命が長いです。Webアプリで良く使う「セッション」も、(厳密には変数ではないけど)情報を長生きさせる便利なテクニックです。しかし寿命が長いだけに、「適切なタイミングで値を無効化する」というひと手間が必要だったりします。


さて、もうお分かりですね。コードがスパゲッティになるのを避けるには、どうすれば良いか?

麺を短くしましょう。

関数の引数やローカル変数はスコープが狭いです(寿命も短い)。でも、もちろん、その関数自体が長いと意味がありません。関数は、一息で読めるくらいの長さにしましょう。