はじめに
アンチパターンは、名前だけ妙にかっこいい。
溶岩流、神オブジェクト、手品師。
「やらかし」の名前のクセに。
アンチパターンとは、広く行われているのに望ましくない結果を招く実践を、原因・兆候・悪影響・対処法までセットで整理した形式のこと。
この記事では、名前がカッコいいアンチパターンを独断と偏見で6つ選んだ。
各項目に アカンポイント(アカポ) を箇条書きでつけて、何がどうアカンのかをまとめた。
溶岩流(Lava Flow)
定義
最適とは言えない状況で書かれたコードが、未完成のまま本番に流れ込み、そのまま育ってしまう状態。
冷えて固まった溶岩が除去しづらいのと同じで、後から依存が絡みつき、不完全な元設計との互換を保ち続けるはめになる。
締切で暫定対応が恒久化し、ドキュメントが無く、テストが無く、人が入れ替わって知識が消える——この4つが揃うと発生する。
アカポ
- 誰も触れない・消せないコードが、地層になって固まる
- 元の設計が未完成のまま本番に流れ込み、後方互換の維持に縛られる
- テストが無いと、人は不安なコードを「消さずに避ける」
例
新人が legacy_utils.rb を開く。
中ほどに # TODO: あとで消す(2019/03) というコメント。git blame すると、書いた人はとっくに退職済み。
「いらなそうだな」と思って消してみると、関係なさそうなテストが3つ落ちる。テストの中身を読んでも、なぜこれが必要なのか書いていない。
新人はそっとファイルを閉じ、自分のコードをその隣に書く。半年後、別の新人が同じコメントを見て、まったく同じことをする。
# TODO: あとで消す の「あとで」は、永遠に来ない。
対処法
- リファクタリングを開発ライフサイクルに組み込む
- 自動テストで「触っても壊れない」状態を作る
神オブジェクト(God Object)
定義
やたら多くの型を参照し、無関係なメソッドを大量に抱えた「全知」のオブジェクト。
本来は問題を小さく割って各オブジェクトに自分のことだけやらせるべきところを、全機能を1個に集約してしまう。他のオブジェクトは自前で動かず、何でもこの神に伺いを立てる。結果として神は周辺と密結合し、変更の影響が読めなくなる。
アカポ
- 1クラスが全部を知り、全部を握り、周辺と密結合する
- 単一責任の原則の真逆で、片方の都合の変更が無関係な処理に波及する
例
UserService というクラスがある。最初はユーザー登録だけだった。
ある日「ログイン履歴もここで持たせよう」。次の週「通知の送信もついでに」。
気づけばメール送信、決済、CSVエクスポート、管理画面用の集計まで担っている。
新機能のたびに UserService に1メソッド足すのが一番速いから、みんなそうする。
こうして UserService は3000行になる。ある日、表示名の修正を入れたら、なぜか決済が止まる。
もう誰も、このクラスに触りたくない。
対処法
- 単一責任の原則で、責務ごとにクラスを割る
- 「このクラスは何を知らなくていいか」を問う
マジックストリング(Magic String)
定義
開発者が「こんな入力、偶然打つわけない」と思い込んで仕込んだ、隠し機能を起動する特定文字列。
問題の核は「この値は来ない」という思い込みのほうで、思い込みは検証の代わりにならない。
「来ないはず」という前提が崩れる事例は実際に複数ある。
-
NOPLATE:
California DMV で、希望ナンバーの第3候補に「NO PLATE」(候補なしの意味のつもり)と書いた男性に、文字どおりNO PLATEのプレートが交付された。
警官がプレート無し車両の違反切符に「NO PLATE」と記入する運用だったため、全州の「プレート無し」違反が彼宛てに集まった(Snopes, 1979年)。
NOTAGで200枚超の切符を受け取った同種の例もある(Fox News)。 -
Hotmail の
eh:
1999年8月、パスワード欄にehと打つだけでどのHotmailアカウントにもログインできた。当時「Web史上もっとも広範なセキュリティ事故」と呼ばれた(CNN, 1999/8/30)。 -
Null さん問題:
苗字がNullの人が、システムに「値なし」と誤認され、ビザ申請や航空券の購入で姓欄が空欄扱いされ弾かれ続けている(Slashdot(BBC報道経由))。
背景は Patrick McKenzie の Falsehoods Programmers Believe About Names が詳しい。
アカポ
- 「絶対に外から来ない」と信じた入力は、信じただけ
- 検証スキップなどの隠し機能を、消し忘れたまま本番に出す
- 入力バリデーションの「例外扱い」が抜け穴になる
例
決済画面のテスト中、毎回ダミーのクレカ番号を打つのが面倒で、「0000 を入れたら検証スキップ」というショートカットを仕込む。便利。テストが捗る。
リリース前、その分岐を消すのを忘れる。
半年後、あるユーザーが入力欄で「とりあえず仮で」と 0000 を打つ。決済が、検証ゼロで、すんなり通る。
仕込んだ本人はもう、その分岐の存在すら忘れている。
対処法
- 入力の「例外扱い」を本番コードに残さない(テスト用フラグは環境で分離する)
- チートコードのように意図的に残すなら、その旨を明示し検証する。境界は「意図的かどうか」
手品師(Smoke and Mirrors)
定義
誤解を招く情報で実態をごまかすことを指す。
語源はマジックの古典で、隠したプロジェクタの光を鏡で反射させ煙に散乱させて、空中に像が浮かんで見えるトリック。
ソフトウェアだと、未実装だということを隠して機能をデモ用にそれっぽく動かして見せること。
アカポ
- 動いているように「見える」だけで、中身は実装されていない
- デモ後に「本物を作る義務」が残る
- 誤解を招く見せ方で、判断材料を歪める
例
投資家向けデモの前夜。「リアルタイムAI分析」の機能が間に合わない。
エンジニアは腹をくくり、グラフが乱数を足して2秒おきに動くだけのモックを作る。それっぽい。すごくそれっぽい。
当日、ボタンを押すとグラフがぬるぬる動き、投資家が唸る。資金調達は決まる。
翌朝、Slackに一言。「で、あのAI、いつ作るんですか」。
煙が晴れたあとに残るのは、約束した本物を作る義務だけだ。
対処法
- デモが「実装済み」か「見せかけ」かを、見る側に必ず明示する
- モックを作るなら、本物のコストと納期をセットで見積もる
カーゴ・カルト・プログラミング(Cargo Cult Programming)
定義
実際には不要なコードや構造を、儀式的に含めてしまう悪習。
経験の浅い人が、よそのコードを「仕組みも必要性も分からないまま」コピーしてくると発生する。語源のカーゴ・カルトは、本質を理解せず表層だけ模倣する行為を指す言葉だ。
AIエージェントに「いい感じに直して」と投げて差分を読まずにマージするのも、構造としては同じだと思う。
アカポ
- 意味を理解せず、儀式としてコードを唱える
- 仕組みも必要性も分からないままコピーしてくる
- 「動くから残す」で、なぜ動くか誰も説明できなくなる
例
表示が崩れるバグに詰まって、Stack Overflow で見つけた setTimeout(() => { ... }, 0) を貼ってみる。直った。なぜ直ったかは分からない。でも直ったので残す。
次に別の表示バグに当たったとき、また同じ setTimeout(fn, 0) を試す。今度は効かない。でも「おまじない」だと思っているので、念のため残しておく。
数ヶ月後、コードベースには意味不明な setTimeout(fn, 0) が点々と散らばっている。レビューで「これ何のため?」と聞かれて、全員が黙る。
誰も唱えた呪文の意味を知らないのに、怖くて消せない。
対処法
- レビューで「それ何のため?」に答えられないコードを炙り出す
- 判断基準を「動くから残す」から「なぜ動くか説明できるから残す」に移す
偶発的な複雑性(Accidental Complexity)
定義
Fred Brooks の "No Silver Bullet"(1986)が下敷き。複雑性には2種類ある。
- 本質的複雑性 : 解こうとする問題(仕様)そのものが持つ難しさ
- 偶発的複雑性 : エンジニアが自分で作り、自分で直せる難しさ
アンチパターンとして問題なのは、本質に切り込まず偶発的な部分ばかり磨くこと。
Brooks によると、偶発的複雑性をゼロにしても本質的複雑性を削らない限り桁違いの改善は来ない、という。
アカポ
- 本質の難しさに手を付けず、自分で増やした難しさばかりいじる
- 偶発的複雑性をゼロにしても、桁違いの改善は来ない
- 流行りのツール追いが、本質からの逃避になりうる
例
「開発が遅いのはツールが古いからだ」と、チームでビルドツールを乗り換える。設定に2週間かかったが、ビルドは速くなった。
半年後、また遅い気がしてくる。今度は状態管理ライブラリを最新のものに移行する。3週間かかった。
その間、肝心の「仕様が複雑すぎて誰も全体を理解していない」という問題には、誰も手を付けていない。半年後、チームはまた「次は何に乗り換えよう」と話している。
本当の難しさだけが、最初の場所でずっと待っている。
対処法
- 「いま削ろうとしている複雑性は、本質的か偶発的か」を先に切り分ける
- ツール乗り換えの前に、問題そのものの構造を理解する地味な作業に時間を割く
おわりに
名前のかっこよさと中身のヤバさのギャップが、アンチパターンの面白さだと思う。そして大事なのは、これらが他人事じゃないこと。溶岩流もカーゴ・カルトも、締切とプレッシャーの前では誰でも踏む。
失敗に名前がつくと、踏みかけたときに「これ溶岩流だ」と気づける。
気づければ対処できる。
それが名前をつける効用だと思う。
出典
- 溶岩流: Lava flow (programming)
- 神オブジェクト: God object
- マジックストリング: Magic string
- 手品師: Smoke and mirrors
- カーゴ・カルト・プログラミング: カーゴ・カルト・プログラミング
- 偶発的な複雑性: No Silver Bullet(Fred Brooks, 1986)
- アンチパターン全般: アンチパターン
- NOPLATE: Snopes / Fox News(NOTAG)
- Hotmail
eh: CNN, 1999/8/30 - Null さん問題: Slashdot / Falsehoods Programmers Believe About Names





