スパゲティプログラム

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動先: 案内検索

テンプレート:複数の問題 スパゲティプログラムまたはスパゲティコードとは、制作したプログラマ以外にとって解読困難である事を表す俗語。

ファイル:Computerplatine Wire-wrap backplane detail Z80 Doppel-Europa-Format 1977.jpg
プログラミングがワイヤラッピングで行われていた時代のスパゲティコード(1977年)

概要

ファイル:Spaghetti.jpg
スパゲッティ

実務において、特にクライアントからの受注や業務委託に求められるコーディングは他者が解読可能な形態、すなわちコードの整序やリファクタリングされたプログラムコードを求められる。しかしコード共有範囲の狭いプロジェクトや趣味で行うプログラミングの場合、第三者に対する可読性を追求しない場合がある。

プログラムのテストを行う際、プログラムの実行順序をトレース(追跡)するのに苦労する。それゆえ、バグが発生してもなかなか原因を見つけ出せなくなる。

スパゲティプログラムは保守・機能追加を妨げる為、修正されることが望ましい。しかし「動作しているプログラムは修正しない」ことを習慣とする文化では、修正は避けられる傾向にあった。これは見通しの悪いスパゲッティ状態のプログラムを変更することにより、予期せぬバグを追加してしまったり、「寝たバグを起こす」可能性が高かったからである。時間や予算・人材が許す場合でもこの傾向は見られた。

後にテストファーストの方法論が確立され、プログラム本体の完成と同時期に、テストプログラムも作成されるようになると、プログラム変更の危険性は相対的に低くなり、このような状態のプログラムは積極的に修正することが奨励されるようになった(リファクタリング)。

なお近年jQueryなどのJavascriptライブラリで可読性を欠くコードが配布されているが、ダウンロード高速化を目的とした圧縮によるため一般的なスパゲティプログラムとは経緯が異なる。

スパゲティプログラムの特徴

goto文の濫用

スパゲッティプログラムを作りだす原因としてよく挙げられるのが、goto文の濫用である。BASICなどの言語にあるgoto文は、無条件に指定したラベルの位置までジャンプする。これは関数ループなどの制御構文を利用した制御に比べ、処理の流れを追いにくく、ソースコード可読性およびメンテナンス性を低下させてしまう。近代的なプログラミング言語では、例外処理や多重ループを抜けるための制御文が用意されているため、ほとんどgoto文は使われない。

しかしgoto文や分岐先の直接指定が適切、または行わざるを得ない場合もある。

  • マシン語などによる制御系プログラミング
  • 1980年代のBASICにおけるgoto文にはラベル機能が無く、行番号しか指定できない。
  • C言語等でエラーを処理する場合、goto文を使うことでエラー処理を書きやすくなることがある。

多重継承の濫用

オブジェクト指向を取り入れたプログラミング言語において、多重継承を機能追加のためにむやみに濫用し、クラス間の関係が複雑になりすぎてしまうことでスパゲティ化が起こることがある。このため(メンバの名前の衝突や菱形継承を避けるなどの目的もあり)、DelphiJavaC#などの言語では多重継承が禁止され、機能の追加にはオブジェクトコンポジションを利用することが推奨されている。

スコープの拡大

グローバル変数の濫用によりスコープが拡大され、可読性が悪くなることがある。プログラミング言語によってはグローバル変数が言語仕様に無いものも存在する。

技術不足

コーディング技術の不足による要因もある。同一関数内に処理を延々と書き連ねたり、一貫性のない記述を繰り返したりすることにより可読性が悪くなることがある。

スパゲティプログラムの奨励事例

通常スパゲティプログラムが奨励される事は無い。しかし過去に雑誌MSX・FANの投稿プログラムコーナー『ファンダム』で事実上のスパゲティプログラム奨励が行われていた。特に「1画面プログラム」すなわち行番号を含めた40×24文字のショートプログラムを多数採用・掲載しており、可読性よりソースの圧縮性を評価していた。

よく行われていた可読性の逸脱行為には以下がある。

  • 1行の文字数を40の倍数以内に近い数に収める
  • コメント、コメント行、(アポストロフィのみの)空行を書かない
  • 空白文字やタブを書かない (MSX-BASICが逐次解釈である事を利用している)
  • 行内の分岐に関わるIF文の使用は極力避ける (if文を終了するには行を終了するしか方法が無かった為)
  • NEXTの対象変数を書かない

例として、BASICにおけるトリガー入力待機ルーチンは通常「10 IF STRIG(0)=0 THEN GOTO 10」と記述するのに対し、1画面プログラム採用作品では「10 FORI=0TO1:I=-STRIG(0):NEXT」という記述が用いられていた。

中には「マシン語ソースをアスキーコード制御文字列を含まない範囲の8ビット値にシフトさせ、そのキャラクターコード群とデコーダのみ記述する」という可読性が全く無いプログラムが採用される事もあった。

脚注

テンプレート:脚注ヘルプ テンプレート:Reflist

関連項目