免責事項: この記事は娯楽のみを目的として書かれています。職場で同じことを繰り返そうとしないでください。ただし、家では好きなことをしてください。
私たち開発者は定期的にバグに遭遇しますが、それは私たちの仕事の一部にすぎません。したがって、一見すると「故意にバグを作ることができますか?」という質問は起こりません。平凡に思えるかもしれません - 「はい、もちろん、バグを書くことはできます。」しかし、よく考えてみると、すべてがそれほど明白ではなくなっているように思えます。
実際のところ、バグは壊れたコードと同じではありません。バグとはエラーであり、一般的な機能の欠陥です。
動作するプログラム。
ソフトウェア問題の文脈における「バグ」という用語は、1947 年にハーバード大学 Mark II コンピュータに蛾が誤動作を引き起こしたときに始まりました。エンジニアたちは文字通り、リレーの 1 つに刺さっている蛾を発見し、これを「バグが実際に発見された最初のケース」と呼んでいました。
世界は数式によってよく記述されることが知られています。そして、その数式は実際にはアルゴリズムです。したがって、ある現象を数学的に説明できた場合、間違った結果が時々しか得られないように、結果の式を修正することは簡単な作業ではありません。それでも、絶望するときではありません。ここで境界条件が役に立つかもしれません。私たちは皆if index == 0 {…} else if index == n-1 {…}
ものを見たことがあるでしょう。境界線には常に何か問題があります🤷♀️。そこで、バグを作成するための最初のアイデアに注目してみましょう -エッジケースを無視します。
一般に、配列の反復処理は潜在的なバグの宝庫です。その中で最も一般的なのは、範囲外のインデックスです。このようなことに遭遇したことがない場合は、コーディングしたことがないことになります。残念ながら、このバグは非常に人気があるため、配列の安全なラッパーarray[safe: index]
など) を作成する人が増えています。したがって、今日では、これがなければ同僚はコードを承認することはほとんどありません。試すことはできますが、可能性は低いです…
よくあるバグには、スタック オーバーフローなどがあります。再帰的アルゴリズムは、終了条件がない場合、無限に繰り返すことができます。ここでは再帰はオプションのようです。 while true
書き込めば完了です。しかし、ここでもバグの人気が私たちに不利に働いています。開発者は無限ループの潜在的な問題をよく知っており、コードレビューでこのような問題に間違いなく注目します 👮
狡猾な計画を本番環境にプッシュするには、終了条件にグローバル変数を使用し、外部から静かに変更してみてください。
var coditionCounter = 0; class A { func foo() { while coditionCounter < 10 { coditionCounter++; B.boo(); } } } class B { func boo() { coditionCounter--; } }
バグを書くことに関しては、ChatGPT ですら手助けを拒否しているのは面白いことです。もしかしたら、プレミアム サブスクリプションが必要なだけかもしれません… 🤔
明るい面として、 AI は、バグのないコードの作成に貢献する一連の一般的なルールを提供します。つまり、少しずつコードを作成し、コーディング標準に従う、単体テストを作成する、そして、とにかく当たり障りのないコードです。逆のことを試みることもできます。つまり、スパゲッティ コードを作成し、SOLID のことは忘れてください。ただし、この方法では、作成するすべてのコードを制御できなくなります。エレガントなピンポイント兵器の代わりに、私たちのプログラムを征服する制御不可能な混乱が生じます。
バグの作成の問題を解決するときは、サブタスクを決定する価値があります。まず、まれな特殊なケースをいくつか考え出す必要があります。次に、コード レビューに合格できるように、バグを通常のコードとして偽装する必要があります。第三に、QA 部門の注意を鈍らせる必要があります。 4つ目は、すぐに捕まらないようにすることです。しかし、これはすでにオプションです。
私の一般的なアドバイスは次のとおりです (コメントで共有してください)。
アクセス レベルを操作します。元に戻すには、最も予期しない場所から重要なパラメータの値を変更します。 VPN であるかのように、いくつかのクラスを通じてこれを実行します。
子クラスに予期しないロジックを実装します。つまり、 SOLID の L 原則を破ります。
class A { func decrease() { x--; } } class B: A { override func decrease() { x++; } }
より大きな関数の潜伏性の変更を隠します。列は多ければ多いほど良いので、人混みに紛れてしまいましょう。
プル リクエストでも同じ原則を使用します。小規模な PR の方が注目される可能性は高くなります。
バグを複数の部分に分割し、それらを別のプル リクエストに入れるようにしてください。可能であれば、別の査読者にも。
QAの弱点を見つけて信頼を勝ち取りましょう。または、チェック中に会話で気を紛らわせます。
ところで、ハイゼンバグってご存知ですか?これは、調査/デバッグ中に消えたり動作が変化したりするバグです。シュレディンガーの猫みたいに。修正問題が自分に割り当てられない場合に最適です。
ハイゼンバグの一般的な例の 1 つは、プログラムが最適化コンパイラーでコンパイルされた場合に発生するが、同じプログラムを最適化なしでコンパイルした場合には発生しないバグです (デバッガーで検査する目的でよく行われます)。デバッグ中、最適化されたプログラムが通常レジスタに保持する値がメイン メモリにプッシュされることがよくあります。
自分を信じて!歴史上、非常に深刻な企業で本番環境にバグが認められた例が知られています。
アリアン 5 501 便:最も高価なソフトウェア バグの 1 つは 1996 年に発生し、クラスター ミッションを搭載したアリアン 5 ロケットが離陸後わずか 40 秒で爆発しました。失敗の原因は、ロケットの誘導システムのソフトウェアのバグに遡りました。
NASA の火星気候探査機: 1999 年、NASA はソフトウェア エラーにより火星気候探査機を失いました。ソフトウェアはメートル単位 (ニュートン秒) の代わりに帝国単位 (ポンド秒) を使用したため、宇宙船は火星の大気圏で燃え尽きました。
さらに、マリオの壁ジャンプやシヴィライゼーションにおけるマハトマ・ガンドの動作など、一部のバグは機能になる可能性があります…おそらく。
バグを開発するには、アルゴリズムを徹底的に検討し、起こり得る問題を徹底的に予測する能力が必要です。したがって、コードにバグを残す理由がない場合でも、検討する価値はあります。