カーゴ・カルト・プログラミング

カーゴ・カルト・プログラミング。

実際の目的には役に立たないコードやプログラム構造を儀式的に含めておくプログラミングのスタイル

カーゴ・カルトという語句は、元々は第二次世界大戦後の南太平洋で見られた先住民の宗教に由来している。これらの人々は、戦時中素晴らしい積荷をもたらしてくれた神のような飛行機を呼び出そうと、一心不乱に精巧な飛行機の模型や滑走路を作り上げた

転じて、背景にある仕組みを理解せずに行動を過剰に(そしてその多くは無意味に)繰り返し実施すること

もっと平たくいうと、「○○するためのおまじない」などといって無秩序に放り込まれる (実際は無意味な) コピペコードだったり、誰かの勘違いから広まった不必要な処理を真似して増殖していったり。

/**
 * 引数の HogeDto の更新日時を書き換えて UPDATE 処理を行う
 * 
 * @param hogeDto 更新対象の DTO
 */
private updateHoge(HogeDto hogeDto) {
  // HogeDto の初期化
  HogeDto newHogeDto = new HogeDto();
  // 引数を取り込む
  newHogeDto = hogeDto;
  
  // 更新日時の変更
  newHogeDto.updated_at = new Date();
  // UPDATE する
  boolean updateResult = HogeDao.update(newHogeDto);
  
  return updateResult;
}

前職で見ていた泣きたくなるコードを真似してみた。こんな書き方をするなら、「HogeDto の初期化」で生成された new HogeDto() には何の意味があるのだ?


カーゴ・カルトなコードが生まれる現場では、カーゴ・カルトな設計書も生まれがちだ。大抵はプロジェクト全体に「無意味な慣習を守らせる宗教」が蔓延していることが、カーゴ・カルトの原因だからだ。

例えば、本当はある一部の条件下で、前後の文脈が揃って初めて必要になった対処法を、「全ての場面でやらないといけない初期処理」とみなして取り入れてしまったり。前述の new HogeDto() は、自分が実際にコードレビューで「初期化を必ずしてください」とツッコまれたものなのだが、恐らくレビュアーの知見の中では、それが必ず必要なものになってしまっているようである。以前に何か代入忘れなどでぬるぽでも引き起こしたのだろう。

しかしこうやって無意味な慣習が蔓延していると、「いやいや、次の行で同じ変数に代入してるし、最初の初期化いらんでしょ」という反論もする気がなくなる。もしくはその反論が理解されず「とにかくそうしろ!結果は正しく動いてるんだから!」と怒られたりする。こうなると「もうこの現場は適当でいいや」とモチベーションが下がる。

もしくは知識が少ないメンバであれば、その指摘をよく考えもせずただただ鵜呑みにして「どうやらそうするのが良いらしい、自分も守ろう、皆も守ろうね」と、新たな布教者になってしまうのだ。

厄介ごとを避けようという方針は困ったものだ。なぜなら、言語をマスターするにはその言語のすべてを知らなければならないし、恐れたり逃げたりすることは知識を得ることの妨げになるのだから

「知らないままでいいや」と思うことが間違いなのだ。どれだけ面倒でも情報量が多くても、全てを知らなくてはならないのだ。大体それで金もらってんだろ適当な働き方すんなボケ。


以下の記事では、「OJT とカーゴ・カルト」という視点でも検証している。

つまり、OJT により引き継がれる「現場の知識」とやらは、無意味なノウハウや間違ったやり方が多分に含まれているよ、ということ。教える側が既に体系的に学習した内容ではなく、現場の場当たり的な「実践知識」をベースにして話をするので、皆のインプットがそれだけだと、代を引き継ぐうちに知識はどんどん劣化していく。

この劣化のスピードは、少なくとも現場にいる当人にはなかなか認識しづらいゆっくりとしたもので、本人が常に危機意識を持っていないとなかなか変えることはできない。なにせ「その場では何とかなっている」からだ。そうこうしているうちに、効果のない呪文にまみれたコードの中で、さらに効果のない呪文を唱え続ける事態に遭う。

だからこそ、世界のオープンソースを見たりして勉強し続ける必要がある。

小さなステージで満足しないで、広い世界に目を向けていけ。

参考