- 2016年、React Nativeモバイルアプリの位置情報付き写真アップロード機能がAndroidベータ版でだけ失敗し、ローカルのAndroidとiOSでは再現しない問題を1週間追跡した
- Androidベータ版は画像アップロード失敗時にもエラーのフィードバックを返さず、Play Storeに新しいビルドを上げるたびに約1時間かかったため、仮説検証が遅くなった
- 組み込み、ハードウェア、化学、獣医学の事例と比べると、ソフトウェアのデバッグははるかに速く、観察可能性が高いことが分かる
- 実際の原因は画像のMIMEタイプを
"jpg"と書いた1文字の違いであり、ファイル拡張子は.jpgでもMIMEタイプは"jpeg"でなければならなかった
- ログ、リアルタイム観察、デバッガ、反復実験を低コストで使える開発環境は、他の職業のフィードバックループと比べると大きな特権に近い
Androidベータ版でだけ失敗した写真アップロード
- React Nativeモバイルアプリのgeolocated photos機能は、月曜日にはリリース準備が整ったように見えたが、Androidベータ配布後に画像がアップロードされなかった
- ローカルのAndroidテストとiOSベータ版では正常に動作し、失敗の原因はすぐには見えてこなかった
- エラー処理を改善したバージョンを再度上げても、アップロード失敗は依然としてフィードバックなしで発生した
- 新しい反復バージョンをPlay Storeに上げるのに約1時間かかり、次の仮説を準備しながらビルドが配布されるのを待たなければならなかった
他の職業における、より長いフィードバックループ
- 組み込みエンジニアは、遠隔機器にファームウェアアップデートを配布した後、ノードが応答しなくなる状況に遭遇する
- 原因を把握するには機器を回収して分析しなければならない
- 場合によっては、何が間違っていたのかを突き止めるのに数か月かかる
- ハードウェアエンジニアは、遠隔地に配布した新しいハードウェアがいくつもの季節を耐え抜いた後で、ようやく設計上の欠陥を露呈することがあると見る
- 古い機器を郵送で受け取り、次世代製品に修正を反映する
- 熱を下げようと通気口を追加したものの、その穴がスズメバチが巣を作れるほど大きく、さらに悪いバグになった事例がある
- 実験室でのテストは可能でも、最終的な検証は結局現場で行われる
失敗を受け入れる方法
- CEOは博士論文を準備していた化学者時代、高価な化学物質のための大きな研究費で実験を進めたが、数週間後の結果は実験ミスで失敗したように見えたと振り返る
- 何が間違っていたのかを突き止められず、同じミスを繰り返さないために何を変えるのかという質問にも答えられなかった
- それでも2度目の研究費を受け取り、この経験は失敗した人を再び立ち上がらせる共感的リーダーシップの事例となった
獣医学の事例が示した、より高いリスク
- 獣医の友人は、高齢で病気の犬を診察し、飼い主にX-rayを勧めたが、費用を理由に断られた
- X-rayなしでできる最善のことは、犬の腹を外側から触ってみることで、大きな物体が触知された
- 手術で取り除いたのはトウモロコシの芯だったが、X-rayがなかったため、それが問題のすべてだったのかは確信できなかった
- 翌日その犬は亡くなり、モバイルアプリのリリース問題とは異なり、他の職業の失敗には実際に生死がかかることがある
1文字のバグとデバッグツールという特権
- 金曜日の朝、Androidドキュメントとコードベースの間に不一致が見つかり、1週間にわたって問題を生んでいた原因はたった1文字だった
- 画像のMIMEタイプは
"jpg"に設定されていたが、実際には"jpeg"でなければならず、ファイルは.jpgとして保存されていた
- ソフトウェア開発者は、複雑なプロセスを深くのぞき込み、リアルタイムの動作を監視し、ログを残し、デバッガで実行を止めて調べることができる
- こうした能力は安価で高速であり、数回のクリックだけで1日に何度も実験を繰り返せる
- ソフトウェアも他の職業と同じくらい重要で影響力を持ち得るが、開発者は今手にしているデバッグツールに感謝できる環境で働いている
1件のコメント
Hacker Newsの意見
ソフトウェア工学が他の職業、冗談めかして言えば「本物の」職業とどう違うのかを示す、ほとんど寓話のような話
もっと短くて気の利いた版も好きだ。ソフトウェアエンジニア、ハードウェアエンジニア、部門長がスイスへ会議に向かう途中、険しい山道でブレーキが故障し、車がガードレールにぶつかりながら下っていって奇跡的に止まる
部門長は会議を開いてビジョンとミッション、目標を定め、継続的改善で核心的な問題を解決しようと言い、ハードウェアエンジニアはスイスアーミーナイフでブレーキを分解して直そうと言う
ソフトウェアエンジニアは「何かする前に、車をもう一度上まで押し戻して、再現するか見てみよう」と言う
同時に、ソフトウェア工学の大きな欠点も抽象化を扱う点にある。基礎まで全部動いてしまう
http://thecodelesscode.com/case/154
そういう能力があるからといって、ソフトウェアエンジニアが滑稽だったり非現実的だったりするという意味ではない
デジタル空間の工学は、物理分野では奇跡に近いデバッグ能力を与えてくれる。同じものを10個作って10通りの方法で試したければ、文字どおりCTRL+C、CTRL+Vでいい。整備士がそれをやるところを見てみたい
ソフトウェアエンジニアは「本物のエンジニア」ではなく、大規模な事前設計会議と膨大な計画をもっと増やせば解決する、という類いの不満には本当にうんざりしている
他の工学分野がそういうやり方をするのは、彼らが私たちよりずっと専門的だからでも、その方法がより優れているからでもなく、彼らにはその方法しかないからだ。ホテルを建て終えたあとに天井を6インチ高くすべきだったと気づいて、全部壊して建て直したりはしない
もし
ceilingHeight += 6を実行して「Rebuild」を押せばホテルが再建され、自動ユニットテストがアクセシビリティまで確認し、総費用が2.82ドルなら、彼らも当然そうしていただろう劣等感は捨てるべきだ。私たちは現実の土木・機械エンジニアが夢にも見られない道具で工学をしており、その結果としてプロセスが大きく違ってくるのは当然だ
もちろん、問題に十分なプロセスを適用できていないこともある。だがそれがプログラミングだけの問題だと思うなら、https://www.imdb.com/title/tt4788946/を数時間見る処方を出したい
優越感の話ではなく、あなたの基準のうち一つでも欠けていれば工学をしていることにはならない。私の経験上、ソフトウェア開発の大半はその四つがすべて欠けている。それが必ずしも悪いわけではないが、ソフトウェア開発の大半は工学ではない
開発より工学が優れているという意味はまったくない
粘土彫刻と大理石彫刻の違いのようなものだ。粘土で失敗したらすぐにまた手直しできるが、大理石で削ってはいけない部分を削ってしまったら、新しい大理石の塊を注文しなければならない
大理石彫刻のやり方を粘土の世界に持ち込めば、ひどい、あるいは少なくとも非常に非効率な粘土彫刻家になるだけだ
粘土と大理石のどちらの彫刻により価値があるかを競うのも、あまり意味がない。どちらも社会の中でそれぞれの居場所がある
ceilingHeight += 6に最も近い体験を与えてくれる点だ今日もある物をモデリングして出力したが、一部分が1mmほど厚いほうがいいと気づいた。30秒後にはバージョン2がプリンタへ送られていた
本当にすごい。こういうものが紙のプリンタ並みに普及するのを待ちきれない
https://www.youtube.com/watch?v=NPVT2lvMvOk
キャリアを通じて何度も、何かエラーが起きているのに完全に沈黙していて、全員が行き詰まったことがある。エラー出力も何もなかった
そういうケースのかなりは、低レベルのサードパーティライブラリが
catch (e) {}をしていたのが原因だった。初期に経験した最初の事例が良い教訓になり、今ではどんなエラーも当然のように見過ごさない。少なくともログは残す今作っているソフトウェアが5年後、まったく想像していなかった環境で使われるかもしれない
30年後:
/* X systems I modul body I 14.09.1990 */void xxvcda(int *addr, int sizeof)元の例外から新しい例外を発生させてスタックトレースの文脈を保つ言語機能も知らなかった。面白いものだ。少なくとも本業のコードではないが、本業にはまた本業なりの面白さがある
DRFが検証エラーを飲み込んで一般的なエラーだけを返すので手がかりがなく、結局自分で掘り下げながらロギングを追加して、何が起きているのか突き止める必要があった
物理学者の友人が、Rutherford の「すべての科学は物理学か切手収集のどちらかだ」という言葉をよく引用していた
その友人が言いたかったのは、物理学には数学やコンピューターサイエンスと違って、物理的現実によって検証される方法があるということだった
彼の分野は極限磁場で、巨大な銅コイルを作って溶けるほどの電流を流し、その後コイルの周囲で爆薬を爆発させ、ごく短い瞬間だけ中心の磁場を人類が作ったものの中で最強にし、数千度の液体銅が飛び散って装置全体が破壊される、というような実験だった
そういう作業環境では、ミスや計算違いは人が非常に速く、ひどい死に方をしかねないという意味になる。だから、セーターにチョークの粉が付くのが最大の被害である数学の博士課程の学生たちが自分たちを科学者と呼ぶと、彼は同意しなかった
つまり、対象のダイナミクスを理解しようとするものか、興味深い事実を集めて関心対象に名前を付けるだけにとどまるものか、という意味だ
スーパーヴィランとしてのキャリアに興味はあるが、どこから始めればいいかわからない人に言うと、本物の EMP はそうやって作る
[1] https://en.m.wikipedia.org/wiki/Explosively_pumped_flux_comp...
こういうことがあると、いつも上流での是正措置があってほしいと思う。適切なロギングとエラー報告があれば、直すのに1週間もかからなかったはずだ
間違った
image/jpgMIME タイプを受け取ったライブラリは、例外を投げるか、クラッシュするか、少なくとも大きくログを出すべきだった。元の筆者がそのライブラリにバグ報告を出したのか気になるサーバーに画像アップロードが実際に届いているかを確認、あるいは否定できるアクセス権限はあったのか? テスト環境ではアップロードできるのに、アプリのリリース版ではなぜできなかったのか? テスト環境は何が違っていたのか?
理論上、Shawn には、サーバーを自分で動かすにせよ、アップロードが黙って失敗する理由を診断できる人に助けを求めるにせよ、「アップロードは成功しているのになぜ表示されないのか」にかなり早く答えられる程度のアクセス権限があるべきだった
私の考えでは、「画像の MIME タイプが
jpgで、jpegであるべきだった」ことよりも、テストでは動いて本番では動かなかった理由のほうがはるかに重要な教訓だ。バグそのものより、環境がなぜバグを見つけにくくしたのかのほうが大きい私の場合、デスクトップアプリがひどく誤動作したのにエラーがログに残らなかった。数日後になってようやく、ファイルハンドルが枯渇していて、log4net もファイルハンドルを取得できなければログを残せないことがわかった。小さなバグ修正を1つ戻すという解決策は簡単だったが、本当の修正は、log4net がログファイルを常に開いたままにするようカスタマイズすることだった。そうすればアプリがファイルハンドルを使い切ってもエラーは記録される
沈黙が目標なのではない。あまりに多くの開発者が沈黙を目標だと考えているが、実際の目標は正確性だ。エラーがないなら静かであるべきだが、ユーザーに影響するエラーがあるなら大きな赤い警告ボックスがあるべきだ
開発者はエラーメッセージを好きになるべきだと思う。よく書かれたエラーメッセージは原因を素早く明らかにし、全員の時間を大きく節約してくれる
この開発者が今後、エラーメッセージをもっと頻繁に表示する方法を学んだのなら、とても良い結果だ
昔の同僚が「航空管制システムを作っているわけじゃないんだから」とよく言っていたのを思い出す。ミスしても命が懸かるわけではない、という意味だった
当時はゲームを作っていたが、私が書いたほぼすべての CRUD アプリにも当てはまる言葉だった
それとは別に、他のシニア技術リーダー、特に Director、VP、CTO に「あなたが犯した最も高くついたミスは何でしたか」とよく尋ねている。ジュニアエンジニアなら、いつか必ずやってみるといい
多くの上級技術リーダーは10万〜100万ドル規模の話を持っている。プロジェクトで数百万ドルを吹き飛ばして、そのまま昇進した人も見たことがある。なぜそんなことが可能で、さらになぜそれが良いことにすらなり得るのかを理解することが重要だ
バグのあるゲームによる苛立ちが、現実のあおり運転や怒鳴り合いにつながることもあり得る。コンピューターが誤った請求書を送ったことで自殺した人たちもいる。ソフトウェアが貴重なデータを失って潰れた会社もある
人々は些細に見えるソーシャルメディアアプリのせいで殺害されることもあったし、Twitter で虐殺の扇動を組織したこともあった。Pokemon Go が漏らした情報によってストーキングや暴行を受けた人もいる
ソフトウェアには現実の力がある。そうでなければソフトウェアを書く理由もない
大切なデータを失わせる可能性のあるソフトウェアを作ったことがあるし、今は誤動作すると浸水を引き起こし得るソフトウェアを作っている
自分の仕事にもう少し誇りを持つべきだ
ソフトウェアエンジニアとして、デバッグはかなり楽しんでいた。設計を作って実装するのとは違うスキルと考え方を使わせてくれたから
もちろん、デバッグにストレスがないという意味ではない。AT&Tの5ESS電話交換機ソフトウェアを開発していたときにデモがあったのだが、テストラボには私たちの機能用に設定された電話回線が1本しかなかった
何度試してもソフトウェアは動かず、ソフトウェア側は正しいと確信したまま、考えられるすべてを確認しながらストレスを感じていた。結局、ラボの技術者に回線を確認してもらったところ、唯一設定されていた回線がどういうわけか切り離されていた。愚かなハードウェアの問題だった
クラウド上の分散システムのデバッグは、すべてのサービスをローカルで立ち上げられる場合より指数関数的にひどいし、そのローカルな分散システムも、問題を1つのプログラム内でデバッグできる場合よりはるかに悪い
本物のデバッガもデバッグをずっとよいものにしてくれる。
printfデバッグと本物のデバッガのどちらか一方にこだわる人たちを理解したことがない。両方使えばものすごく得なのに。優れたトレース機能も、可能ならprintfデバッグよりずっと優れているので、ここで強調する価値があるプログラミングを始めたころは、「なぜこれが起きているのか分からない」という状態に不要な感情をたくさん結び付けていたが、次第に「ちょっと待て、なぜこうなる? 分からないな……あ、待てよ……うわ、これが動かなかった理由は本当に筋が通っている!」というループを受け入れるようになり、最後まで行けば気分がよいということも内面化した
今では、分からない状態そのものは、他人の期待や行動によってだけ台無しになり得る。時間が経つにつれ、このプロセスを簡単かつ速くするために、言語選択やアーキテクチャ選択などをかなり断固として管理しなければならないと学んだ
キャリアのこの時点では、AWS Lambdaが性能、総コスト、デバッグ容易性、開発速度の面でよくない選択だと事前に説得するほうが、後になって「なぜその問題を1つ直すのにそんなに時間がかかるのか」にはもっともな理由があると説得するより、ずっと簡単だ
最後で笑った。ちょうど昨日、会社で3年間悩まされていた問題を解決したのだが、私たちの場合は文字Aが原因だった
この3年間、誰かがデータを入れたり出したりする手作業の修正を続けていて、それが彼の業務の一部になっていた。定期的な整理のために、カレンダーに繰り返し予定まで入れていた。何百万もの顧客が、自分の携帯回線に正しいデータプランが適用されるよう、この1人に依存していた
彼が忘れたり休暇に行ったりしたら、どんな混乱が起きるか想像できる
結局、原因は
if $line->status == STATUS_ACTIVEで、一方はActive、もう一方はactiveだった。犬は傷つかなかったが、何年にもわたって計算不能な額のお金が消えていたその気の毒な人は、もう不可欠な存在ではなくなった。半分は冗談だ。ソフトウェアは仕事をより効率的にするものだが、人間の動機も見るようにしている
特にMacでHL7フィールドを埋めるときはひどく苦しんだ。Macのキーボードで入力した
’文字がHL7のすべてのバージョンと互換性がなかったか、HL7が渡された先と合っていなかったのだと思う古い記憶だが、
o’clockとo′clockのような単語の違いで放射線レポートの配布が壊れた。見つかるまで何年も続いていたHNは私が入力したものと違う形で
’を表示しているが、それでも同じ文字だ。デバッグ時に違いが見えなかったことが問題の半分だったので、かなり笑える話だSTATUS_ACTIVEが誤って定義されていたのだろうか?誰かが
HttpHeader::REFERRERのrefererという誤字を「親切にも」referrerに直してしまう危険は常にある。だがその誤字はHTTP標準に刻み込まれているので、そうするとソフトウェアは完全に壊れる。CERN時代のPhillip Hallam-Bakerの責任だスズメバチの巣の逸話が他人事とは思えない
うちのオフィスビルの貸主が、各フロントデスクに電話をかけてドアを開けてもらえるよう、建物の外にタッチスクリーンインターフェースを設置した。ドアを見られる受付担当者がいなかったためだ
その装置は6か月持ったあと、ひどく誤動作し始めた。原因は、実質的に大きな黒いAndroidタブレットであるインターフェースを、建物の東側に設置したことだった
春の半ばになると、毎日十分な日差しを受けて過熱し、タッチ電子部品と画面ハードウェアの一部が壊れた
私が作る種類のソフトウェアでは、熱負荷を心配することはない
鉄道会社はTwitterに「強い日差しによる発車問題のため、Lewishamを通る区間で深刻な混雑があった」と投稿した
低い冬の太陽が発車モニターを照らし、運転士が見られなくなったとも述べていた
「ついに解けた。文字『E』のせいだった」というメッセージが面白い
もっとも単純で小さなバグのほうが、かえって最も見つけにくいことが多い。今朝もオフバイワンエラーを見つけるのに1、2時間を無駄にした
リファクタリング時に変更し忘れた
index + 1が1つ原因だった