そのレビュー、バグ探しちゃダメですよ?
ども!海外の片隅で、今日も元気にC#をブン回しております、現役ITエンジニアです。
普段はクライアントアプリの開発がメインで、特にC#とWPF(Windows Presentation Foundation)を使った設計・開発をゴリゴリやっています。そう、あのWindowsのデスクトップアプリを作るやつですね。最近はWebだクラウドだと華やかな世界が目立ちますが、製造業の制御システム(HMI)とか、金融系のリッチなトレーディングツールとか、「絶対に落ちちゃいけない」「リッチなUIが必須」っていうニッチだけど超重要な分野で、WPFはまだまだ現役バリバリなんです。
さて、このブログは「これから海外でエンジニアとして働いてみたい!」と夢見る皆さんに向けて、僕がこっちで実際に体験した「リアルな気づき」や「知ってると得する(かもしれない)人生術」を発信しています。
技術力?もちろん大事です。C#の最新動向、.NETの進化、WPFのニッチなTIPS。それも大事。
でもね、海外で「ああ、こいつと一緒に仕事してよかったな」と思われるエンジニアになるために必要なのって、それだけじゃないんですよ。むしろ、技術力と同じくらい、いや、時と場合によってはそれ以上に**「文化的な柔軟性」や「アンラーニング(学びほぐし)のスキル」**がモノを言う世界なんです。
今日は、まさに僕が日本で叩き込まれた「常識」が、こっちでガラガラと音を立てて崩れ去った、ある金曜日の午後の話をしようと思います。
日本でWPFを使ってカッチリした設計をやってきた人ほど、「え、そんなのアリなの!?」って思うかもしれません。でも、この「定番のひねり(Unexpected Twist)」こそが、僕のエンジニア人生観を変え、海外でサバイブするための最強の武器になったんです。
日本時代の「完璧」という呪い
話の前提として、僕の日本時代の話を少しだけ。
僕は、自他共に認める「完璧主義」のエンジニアでした。特にWPF開発においては、その思想は宗教的ですらあったと思います。
WPFを使うなら、アーキテクチャは当然MVVM (Model-View-ViewModel)。これは絶対。
View(XAML)とViewModel(C#)は完全に分離。ViewがViewModelの存在を知っていても、ViewModelはViewの存在を一切知らない。コードビハインド(XAMLの裏にC#を書くこと)なんてもってのほか。見つけ次第、リファクタリング対象です。
DI (Dependency Injection) コンテナ(Prismとか)を使って依存関係をきっちり管理し、Interfaceを介してすべてを疎結合にする。ユニットテストのカバレッジは最低でも90%を目指す。
なぜなら、WPFは自由度が高すぎるから。XAMLでリッチな見た目を追求できる反面、油断するとすぐにViewとロジックが癒着し、あっという間に「スパゲッティ・コード」が出来上がる。だからこそ、強固な「設計(アーキテクチャ)」でガチガチに縛り上げ、変更容易性とテスト容易性を確保するんだ、と。
設計ドキュメント?当然です。
クラス図、シーケンス図、状態遷移図。コードを1行書く前に、まず設計図が「芸術品」レベルで完璧じゃないと気が済まない。この設計図さえあれば、誰が実装しても同じものができる。それが「プロの仕事」だと信じて疑っていませんでした。
当然、コードレビューも厳しかった。
「この命名規則、規約と違いますね」
「このLINQ、もっと効率的に書けます。IQueryableを意識してください」
「ここのエラーハンドリング、考慮漏れがあります」
レビューは「バグ」と「規約違反」を見つける場所。まさに「マサカリ」が飛び交う戦場でした。厳しく指摘し合うことこそが、品質を担保する唯一の道だと信じていたんです。
海外の現場と「普通」のレビュー
そんな僕が、期待と不安を胸に、今の海外のITチームにジョインしたわけです。
多国籍チーム。英語が飛び交う環境。
当然、こっちにもコードレビュー(PR: Pull Request)はあります。
最初の数週間は、もうビクビクでしたよ。
「(うわ、この設計思想、英語でうまく説明できなかったらどうしよう…)」
「”What’s this messy code?” (この汚いコード何?) とか言われたら泣くぞ…」
「WPFのこのXAMLの書き方、マニアックすぎるって怒られるかな…」
ところが、最初のレビューコメントは、意外なほどアッサリしたものでした。
LGTM (Looks Good To Me)
Approved!
Nice work! 👍
……あれ?
もっとこう…僕が日本でやっていたみたいに、設計思想の是非について熱く語り合ったり、パフォーマンスの限界について議論したり、命名規則の統一性についてツッコミを入れたりしないの?と。
もちろん、クリティカルなバグや、明らかな設計ミス(例えば、セキュリティホールになりかねない実装)には、ちゃんと指摘が入ります。それは世界共通。
でも、日本でやっていたような「重箱の隅をつつく」ような指摘は、驚くほど少ない。
日本が「100点満点からの減点法」だとしたら、こっちは「まずは動くものを作ってくれてありがとう」という「加点法」がベースにある感じ。
「ああ、海外ってこんなもんなのか。意外とユルいな」
「まぁ、スピード重視の文化ってことなのかな」
なんて、僕が少し「海外のやり方」に慣れてきた(とんだ勘違いだったわけですが)入社して数ヶ月が経った、ある金曜日の午後のことでした。
事件は、いつもの会議室で起きました。
「ムダコード大賞」の開幕
その日は、週の終わりにある「Weekly Tech Review」の日。
まぁ、よくある技術的な振り返り会とか、知見の共有会みたいなものですね。
ところが、会議室に入ると、シニアエンジニアのマーク(仮名・ビール腹が素敵な、いつも陽気なチームの兄貴分)が、プロジェクターの前でニヤニヤしながら立ってるんです。
「OK、Gents (野郎ども)! 今週もお疲れ! さて、今日のTech Reviewだけど、ちょっとルールを変更する!」
メンバーたちが「またかよ」「今度は何?」みたいな顔でザワザワしてる中、僕は「え、何が始まるの?」とキョトン。
マークが第一声、こう言い放ちました。
「今日のレビュー会は、**『バグ探し禁止』**だ! いいか? もし誰かの発表中に『それってバグじゃね?』とか『パフォーマンス最悪じゃん』とか、そういう『正しい』指摘をしたら、そいつは来週の金曜、全員分のビールを奢ることになるからな!」
えええ!?
レビュー会なのに、バグ探しちゃダメなの?
品質について議論しちゃダメなの?
意味が分からない。
マークは、得意げに続けます。
「今日のお題はこれだ!**『今週、最もクリエイティブだったけど、ボツになったコード』**を発表してくれ!」
「……は?」
「いかに『エレガントな無駄』を実装したか。いかに『本流から外れた』技術で遊んでみたか。それが審査基準だ! 優勝者には、俺からこの『ゴールデン・ラバーダック』(デスクに飾ってある金色の安っぽいアヒルのオモチャ)を授与する!」
ポカーン、ですよ。
頭が真っ白になりました。
これこそが、このチームに(というか、マークが勝手に始めた)謎の伝統、「Muda-code Award(ムダコード大賞)」だったんです。
まさに、ユーザーさんがくれたフックにあった「Ugly Sweater Contest(ダサいセーターコンテスト)」の「セーターがtoo nice(良すぎる)と減点」の、ITエンジニア版。
「コードが『マトモすぎる』と減点」
「『ボツになった(=失敗した)』コードこそが称賛される」
という、僕の常識とは真逆の価値観が支配する、奇妙な儀式の始まりでした。
「失敗」を大声で笑う同僚たち
僕はもう、パニックです。
「ボツになったコード?」「無駄?」
それって、エンジニアの「恥」じゃないですか。
日本で「完璧な設計図」を信奉していた僕にとって、「失敗した実装」なんていうのは、隠すべきものであって、ましてや人前で「どうだ!」と発表するなんて、ありえない。
その時、僕の頭をよぎったのは、まさに今週、僕が泣く泣くボツにしたWPFのコードでした。
あるカスタムコントロール(※WPFで使うオリジナルのUI部品)を作っていたんです。デザイナー(UI/UX担当)の無茶振りに応えるために、XAMLのAttached Propertyとか、Value Converterとか、Dependency Propertyとか、WPFの「マニアック」とされる機能をフル活用して、それはもう「芸術的」なXAMLコードを書き上げたんです。
結果、どうなったか。
「……ごめん、これ、コードが複雑になりすぎて、君以外誰もメンテナンスできないよ。それに、ちょっとやりすぎだ。もっとシンプルな実装に戻そう」
と、シニア(マークとは別の人)に却下されたばかりだったんです。
「うわ…あの『美しすぎるけどクソメンテしにくいコード』のことか…?」
「あれを発表しろってのか? 恥ずかしすぎる…」
僕が一人で冷や汗をダラダラかいている横で、同僚たちはやけに楽しそう。(※フックの「家族の反応」を「同僚の反応」に置き換え)
トップバッターは、ロシア出身のアンドレイ。
「俺、今週DBのパフォーマンスチューニングやってたんだけどさ。このSQL、見てくれよ。トランザクション分離レベルをあえていじり倒して、ダーティリード(※データの不整合を許容する、普通は危険とされる読み取り方)を使いまくって、理論上は最速のクエリを組んでみたんだ。もちろん、100回に1回はデータがバグるけどな!ガハハ!」
マークが「おー!クレイジー!でもその発想、特定のバッチ処理なら使えるかもな!」とか煽ってる。
次はインド出身のプリヤ。
「私は、社内ツールのローカライズ(多言語対応)を、新しく出たAIライブラリで自動化しようとしたの。でも、学習データが足りなくて、ドイツ語の『キャンセル』が『戦車(Panzer)』って翻訳されちゃって、ドイツ支社から『戦争でも始める気か!』ってクレームが来たわ(笑)」
チーム全員、大爆笑。
「ヤバい!」「そのAI、うちのチャットボットにも使おうぜ!絶対カオスになる!」
完璧主義者(僕)の葛藤
僕は、その光景を呆然と眺めていました。
彼らが語っているのは、どう考えても「失敗談」です。
プロダクトに採用されなかった「ゴミコード」のはずです。
顧客からクレームが来た「失態」のはずです。
なのに、誰も彼らを責めない。
それどころか、「その発想は面白い!」「その技術、別のとこで使えないか?」「その失敗、最高!」と、称賛し、爆笑し、そこから新しいアイデアを見つけようとしている。
僕が日本で信じていた「品質至上主義」とは、真逆の世界。
僕が日本で学んだ「失敗は悪」という価値観とは、180度違う世界。
「海外のエンジニアって、こんなに不真面目なのか?」
「こんなことしてて、プロジェクトは炎上しないのか?」
WPFで「完璧なMVVM」を追求し、「完璧な設計図」こそが正義だと信じてきた僕にとって、この「無駄の称賛」と「失敗の共有」は、カルチャーショックを通り越して、もはや恐怖ですらありました。
でもね。
この「一見ふざけた定番のひねり」こそが、実は海外でエンジニアとして(特に、僕のようにC#やWPFみたいなカッチリした技術を扱うエンジニアが)サバイブするための、超重要な「人生術」だったんです。
僕らが日本で学ぶ「完璧主義」が、いかにイノベーションの邪魔をし、個人のメンタルをすり減らしていたか。
この「ムダコード大賞」が、どうやって僕のガチガチだった「完璧主義」の呪いを解き、結果として(ふざけてるように見えるのに)チームの生産性を爆発的に上げることになったのか。
そして、これが(フックの予告通り)さらにヤバい、このチームの「最終伝統」へと繋がっていくのですが…それはまた別のお話。
次回(承)では、ついに僕が震える手で発表することになる「美しすぎるWPF(ボツ案)」と、それに対するマークの衝撃的なフィードバック、そして「完璧な設計図」を捨てる勇気について、ガッツリ語ろうと思います。
震える手で発表した「芸術的WPF」と、完璧主義の呪いが解けた瞬間
(「起」のつづき)
「ムダコード大賞」の会場は、同僚たちの「やらかし自慢」で、もはや爆笑の渦です。
ロシア人のアンドレイが「意図的にバグらせたSQL」を語り、インド人のプリヤが「AI翻訳で顧客を怒らせた話」を披露する。
みんな、自分が書いたコードが「ボツになった」こと、「失敗した」ことを、まるで武勇伝のように語っています。
僕は、その熱気にあてられて、クラクラしていました。
「(なんなんだ、この人たち…)」
僕の日本での常識では、「ボToolsになったコード」は「敗北」です。
費やした時間、リソース、すべてが無駄。エンジニアとしての評価が下がる、恥ずべき「負債」。
だから、失敗したら、バレないようにこっそり修正するか、あるいは「あれは最初から実験でしたから(キリッ)」と自分に言い訳して、フォルダの奥深くに封印する。それが「普通」だと思っていました。
でも、目の前の光景は真逆です。
彼らは「失敗」をオープンにし、それを「笑い」に変え、さらに「学び」のネタにしている。
僕が日本でやっていた「完璧な設計図」へのこだわり。
レビューでの「マサカリ」。
あれは一体、何を守るためだったんだろう?
「品質」? もちろんそうだ。
でも、その「完璧な品質」を追求するあまり、僕たちは「試してみること」を恐れていなかったか?
「恥ずかしいコード」を書くことを恐れるあまり、新しい挑戦を避けていなかったか?
僕の頭の中は、ぐるぐると疑問符で埋め尽くされていました。
その時です。
ニヤニヤしながら全員の発表を聞いていたマーク(主催者)が、ついに僕に目を向けました。
「OK、OK! みんな最高にクレイジーだ! ……さて、トリは我らがニューフェイス! ミスター『ジャパニーズ・クオリティ』!」
うわ、こっち見た。最悪だ。
「なぁ、君みたいな真面目なエンジニアが、今週どんな『エレガントな無駄』をやらかしたのか、俺は興味津々だよ。C#とWPFで、なんか『美しすぎるゴミ』は作らなかったのかい?」
会場の視線が一斉に僕に突き刺さります。
もう、逃げ場はありません。
僕は、PCの画面を切り替えながら、震える声で話し始めました。
「あー…えーっと。今週、デザイナーの無茶振りで、あるカスタムコントロールを作ってまして…」
それは、製造ラインの稼働状況を示す、ちょっと特殊なインジケーター(表示灯)でした。
デザイナーの要求はこうです。
「ステータスが『正常』『警告』『異常』『メンテナンス中』の4つあるんだけど、それぞれで色が変わるだけじゃなくて、デザインもちょっと変わって、さらに『異常』の時は、WPF特有の『グロー効果(ぼんやり光るやつ)』をアニメーションさせて点滅させて欲しい。あ、もちろん、その光る色も『異常』の種類によって変えたいから、データバインド(※)できるようにしといて」
(※WPFを知らない人向けに解説すると、「画面の見た目」と「裏側のデータ」を連動させる仕組みのことです)
この無茶振り。
日本時代の僕なら、まず「そんな複雑なことするより、シンプルにアイコンを4つ用意しませんか?」と交渉したでしょう。
でも、こっちのデザイナーは「技術的に可能なら、まずやってみようよ!」というスタム。
だから、僕はやったんです。
C#エンジニア、WPFエンジニアとしてのプライドにかけて。
「…で、僕はこれを、Prism(※MVVMフレームワーク)の流儀に則って、コードビハインド(※Viewの裏のコード)を一切使わずに、XAML(※見た目を定義する言語)だけで実現しようとしました」
僕は、プロジェクターにそのコードを映し出しました。
Attached Property(添付プロパティ)を駆使して、本来コントロールが持っていないはずの「光り方の状態」を外部から注入できるようにし、
DataTrigger(データトリガー)を何重にもネストさせて、ViewModelから飛んでくる「ステータス」と「異常種別」の組み合わせ(全12パターン)を分岐させ、
ValueConverter(値コンバータ)で、飛んできた「異常種別コード」を動的に「光る色(Brush)」に変換し、
VisualStateManager(VSM)とStoryboard(アニメーション定義)を使って、滑らかな点滅アニメーションをXAML内部に実装しました。
それはもう、自分でも「芸術品だ」と思えるほどのXAMLでした。
ロジックは一切XAMLにはなく、ViewModel側はただ「ステータス」を切り替えるだけ。
完璧な、完璧なMVVMアーキテクチャ。
「…というコードを、2日間かけて書き上げました」
僕は、ゴクリと唾を飲み込みました。
「でも、これ、アーキテクト(設計主任)に見せたら、『…君は天才か?』って呆れ顔で言われた後、『このXAML、君以外に誰がメンテナンスできるんだ? 悪いけど、やりすぎだ。オーバーエンジニアリング(過剰設計)だよ』って言われて、全部ボツになりました」
シーン…。
さっきまでの爆笑がウソのように、会議室が静まり返りました。
(あ、やばい。引かれた。完全に「イタい奴」だと思われた…)
「(結局、デザイナーの要求が強すぎたんで、最終的には『正常』『警告』『メンテ』はシンプルなSVG画像にして、『異常』の時だけ点滅するGIFアニメを表示する、っていう超絶ダサい実装に落ち着きました…)」
もう、恥ずかしくて死にそうでした。
日本での「完璧な設計」へのこだわりが、ここでは「過剰設計」と一刀両断された。
僕の2日間の努力は、完全に「無駄」になった。
僕は、ビールを奢る覚悟(バグじゃないけど、チームに迷惑をかけた的な意味で)を決めました。
すると、一番に口を開いたのは、意外にもロシア人のアンドレイでした。
「…おい。さっきのXAML、もう一回見せてくれ」
「え?」
「そのAttached Propertyの使い方…クレイジーだ。そんな方法でStoryboardを外からキックできるのか。俺、知らなかった」
続いて、プリヤも前のめりになって言いました。
「私も! そのValueConverterでBrush(色)を動的に生成してる部分、どうなってるの? 私、今やってる画面で、ステータスごとに背景色を変えたいんだけど、いつもCSSみたいに定義済みの色しか使えなくて困ってたのよ!」
え…?
僕が「失敗作」「恥ずかしいコード」として晒した、あの複雑怪奇なXAML(ゴミ)に、みんなが食いついてきたんです。
「あ、いや、ここはDependency Propertyで…」
「このConverterは、引数で渡ってきた文字列を…」
僕がタジタジになりながら解説すると、
「なるほど!」
「その手があったか!」
と、さっきまで僕を「哀れな奴」という目で見ていた(ように感じた)同僚たちが、目を輝かせてメモを取り始めたんです。
そして、最後に主催者のマークが、ポン、と僕の肩を叩きました。
「最高じゃないか」
「え?」
「最高だよ、その『美しすぎるボツコード』! それこそが、この『ムダコード大賞』の精神だ!」
マークは、プロジェクターの前に戻ると、全員に向かって言いました。
「いいか、みんな。今、彼がやったことこそが、俺たちがこの『バカげた会』をやってる理由だ」
「彼がこの『完璧すぎるWPF』を2日もかけて作ったこと。これは『無駄』か? プロダクトには入らなかったから、コスト的には『無駄』だ。でもな…」
マークは、プリヤを指差しました。
「プリヤは、彼のコードから『動的に色を変えるヒント』を得た」
次にアンドレイを指差します。
「アンドレイは『新しいアニメーションの起動方法』を知った」
「そして一番大事なのは、俺たちチーム全員が、『このレベルのXAMLは、やりすぎ(過剰設計)だ』という『共通の物差し』を手に入れたことだ」
「もし彼が、『失敗した』『恥ずかしい』って、このコードをこっそり捨ててたらどうだ? 彼の2日間の努力は、本当にただの『無駄』で終わってた。プリヤもアンドレイも何も学べず、俺たちも『どこまでが適切な設計か』を知る機会を失ってた」
「完璧主義は、バグを減らす。それは正しい」
マークは、僕の目をまっすぐ見て言いました。
「でもな、『完璧』を恐れるあまり、『挑戦』を隠す文化は、チームを殺すんだ」
「『失敗』は、隠したら『負債』になる。でも、こうやって全員で笑い飛ばして『共有』すれば、それはチーム全員の『資産』になるんだよ」
…僕は、頭をガツンと殴られたような衝撃を受けました。
日本で信じてきた「完璧であること」の正義。
失敗を隠す文化。
それが、いかにチーム全体の成長を阻害していたか。
「失敗を恐れるな」なんて言葉は、使い古された標語だと思っていました。
でも、このチームは、「失敗を安全に共有し、爆笑し、資産に変える」という、具体的な「仕組み(=ムダコード大賞)」を持っていたんです。
この日を境に、僕のエンジニアとしての価値観は、180度変わりました。
「完璧な設計図」を捨てる勇気。
「まず(雑でもいいから)動くものを作ってみて、そこから学ぶ」という考え方。
僕のWPF開発スタイルも、カッチリしたMVVM一辺倒から、「ここは保守性重視」「ここはパフォーマンス重視」「ここは(メンテを捨ててでも)リッチな表現を優先」といった、柔軟なアプローチに変わっていきました。
そして、この「失敗を資産に変える」という考え方が、実はこのチームのもう一つの、さらにヤバい「最終伝統」(フックの予告)に繋がっていくんですが…それは、また次のお話で。
リリースノートに「バグあり」!? 炎上させるための最終訓練
(「承」のつづき)
「ムダコード大賞」のあの日から、僕のエンジニア人生は変わりました。
あれだけ呪いのように憑りついていた「完璧主義」が、スッと軽くなったんです。
もちろん、品質を疎かにするようになったわけじゃありません。
C#でクリーンなコードを書くこと。WPFで保守性の高いMVVMを設計すること。その「理想」は今も持っています。
でも、前との決定的な違いは、「完璧じゃないことを恐れなくなった」こと。
レビューで「この書き方、ちょっと自信ないんだけどどう思う?」と素直に聞けるようになった。
「(うわ、ダサい実装だけど)とりあえず動くバージョンを先にPR(Pull Request)しちゃおう。フィードバックもらってからリファクタリングしよ」と、スピードを優先できるようになった。
僕が「失敗(という名の学習)」をオープンにするようになったら、不思議なことに、チームの仲間たちも僕に対して、よりオープンに技術的なディスカussionをしてくれるようになりました。
「なぁ、このWPFのXAML、君のあの『芸術的ボツコード』のテクニック、一部使ってみたんだけどさ…」
なんて、アンドレイ(ロシア人)が相談してきたり。
「失敗を共有すれば資産になる」
マークが言っていたあの言葉を、僕は「なるほど、いいこと言うなぁ」なんてレベルじゃなく、実体験として噛み締めていました。
そう、あの「ムダコード大賞」(=定番のひねり)は、僕にとって最高の「人生術」だったんです。
……と、僕がすっかりこのチームの「柔軟な」やり方に馴染み、C#のコードもWPFのXAMLも、肩の力を抜いて書けるようになってきた、数ヶ月後のこと。
その日は、四半期に一度の「メジャーリリース」を翌日に控えた、木曜日の午後でした。
海外のIT現場とはいえ、さすがにメジャーリリース前はピリつきます。
QAチームからのバグ報告がレッドアラートで飛び交い、僕ら開発陣も「マジかよ、こんなエッジケース!」と悲鳴を上げながら、必死でC#のコードを修正していました。
日本時代の「リリース前夜」の地獄絵図と、まぁ、これは万国共通です。
「完璧な状態でリリースするぞ!」と、チーム全員が最後の追い込みをかけていました。
僕は、割り当てられたクリティカルなバグを全て潰し、ふと、QAのバグ管理システム(JIRAとか)を眺めていました。
「よし、クリティカルとメジャー(重要)なバグは全部『Done』になったな。あとは…」
ん?
僕は、あるチケット(バグ報告)で手が止まりました。
ステータスは「Open(未対応)」。
優先度は「Minor(軽微)」。
内容はこうです。
「特定の条件下(OSがドイツ語設定、かつ特定の画面解像度)において、あの『製造ラインのインジケーター』のグロー効果(ぼんやり光るやつ)が、『異常』じゃない時も、うっすらと点灯し続けてしまう」
……あ。
これ、僕が数ヶ月前に「芸術的ボツコード」で実装しようとしていた、あの「グロー効果」の、簡易版の、バグだ。
(結局、あのアニメーションは簡易版が採用されていた)
「Minor(軽微)」とはいえ、バグはバグ。しかも画面(UI)のバグは目立つ。
リリース前に修正すべきです。
僕はすぐに、修正方法を頭に思い浮かべました。(WPFのVisualTreeを辿って、トリガーの条件式を一つ直せばいいだけだ)
「やれやれ、最後の最後に見落としか」
僕は、コーヒーを淹れ直そうと席を立ったマーク(あの「ムダコード大賞」の主催者)を呼び止めました。
「マーク! ちょっといいすか。JIRAに『Minor』で残ってるバグが一個あります。これ、僕がすぐ直せますよ。今夜対応しちゃいます」
「ああ?」
マークは、僕が指差すJIRAのチケット番号を見ると、一瞬キョトンとした顔をし、次の瞬間、ニヤァ…と、あの「ムダコード大賞」の時と同じ、意地の悪い笑みを浮かべました。
「あー、それ? それ、直さなくていいよ」
「……は?」
「いや、だから。そのバグは、修正しない。そのままリリースする」
僕は、耳を疑いました。
何を言ってるんだ、この人は。
「いや、でも、バグですよ? 軽微とはいえ、ドイツ支社の人から『なんかチカチカしてウザい』って報告が来てるじゃないですか。僕が今から1時間あれば直せます」
「だから、いいんだって」
「よくないですよ! リリースノートに『既知の不具合』として載せるんですか? カッコ悪いじゃないですか!」
僕の剣幕に、マークは「やれやれ」と肩をすくめました。
そして、僕を手招きし、会議室のホワイトボードの前に連れて行きました。
「なぁ」
と、マークはペンを取り、円を一つ書きました。
「君が日本でやってた『完璧なリリース』ってのは、これだ」
彼は、その円を指差します。
「バグがゼロ。QAのテストも100%パス。完璧なプロダクト。違うか?」
「…はい。それが理想です」
「じゃあ聞くが」とマークは続けます。
「もし、この『完璧なリリース』の直後に、誰も予期しなかった『超クリティカルなバグ』(例えば、サーバーが全停止するとか、顧客データが吹っ飛ぶとか)が見つかったら、どうする?」
「そりゃあ…」僕は答えに詰まります。
「緊急メンテナンスを入れて、大至急ロールバック(切り戻し)して、原因を特定して、ホットフィックス(緊急修正パッチ)を当てます…」
「その『ロールバック』の手順、本当に動くか、テストしたことあるか?」
「…それは、ステージング環境(本番そっくりなテスト環境)では…」
「本番でやったことあるか?」
マークの目が、鋭く光りました。
「いいか? 火災訓練(Fire Drill)ってのは、ベルを鳴らして『避難してください』って練習するだけじゃ、意味がねぇんだ」
「?」
「本当に火事が起きた時、パニックにならずに、スプリンクラー(監視アラート)がちゃんと作動して、防火扉(ロールバック手順)がちゃんと閉まって、消防隊(サポートチーム)が正しい場所に放水(顧客対応)できるか。それを確認するには…」
マークは、ホワイトボードに書いた「完璧な円」に、わざとペンで「黒い点(バグ)」を描き加えました。
「実際に、本番環境で『小さなボヤ』を起こしてみるしかねぇんだよ」
僕は、全身に鳥肌が立つのを感じました。
「まさか、そのドイツ語OSのバグって…」
「そう。それが今四半期の**『ゴールデン・バグ(意図的に残されたバグ)』**だ」
マークが明かした「最終伝統」。
それこそが、このチームが密かに行っている、最もクレイジーな訓練。
**「意図的障害(カオス)注入訓練」**通称「ファイヤー・ドリル」でした。
(※フックの「Ugly Sweater(ムダコード大賞)」が「内輪の失敗(開発)」の称賛だったのに対し、これは「本番環境(外部)」にまで『ひねり』を加えていた)
マークが説明します。
「俺たちは、四半期に一度、あえて『軽微』で『機能不全に陥らない』けど『必ず誰かが見つける』バグを一つ、意図的にリリースに混ぜ込む」
「もちろん、修正パッチはもう準備済みだ」と彼は自分のPCを指差します。
「そして、リリースと同時にタイマーをスタートさせる」
目的は3つ。
- 監視(モニタリング)が生きているか?「そのバグを、俺たち開発陣が『発見』するより先に、Datadog(監視ツール)が『異常』として検知できるか」
- サポート(顧客対応)が機能しているか?「顧客(今回はドイツ支社)からの問い合わせ(チケット)が、サポートチーム経由で、どれだけ早く、正確に開発チーム(俺たち)にエスカレーションされてくるか」
- 切り戻し(デプロイ)が迅速か?「『バグ発見』のトリガー(アラートか、顧客チケットか)が入ってから、俺たちが準備済みのホットフィックスを、どれだけ安全に、素早く本番環境に適用できるか」
「そんな…」僕は唖然とします。
「そんなの、サポートチームが可哀想じゃないですか! 顧客をダマすことになるんじゃ…」
「ダマす?」マークは首を横に振ります。
「逆だ。これは、俺たち開発チームから、サポートチームへの『挑戦状』であり、『最大の信頼』の証だ」
「『お前ら(サポート)がちゃんと機能してるか、試させてもらうぜ?』ってな。もちろん、サポートのマネージャーには話は通してある。『今週のリリース、何か一つ『ボヤ』を起こすから、準備しとけよ』ってな。だが、それが『何のバグか』は、彼らも知らない」
「だから、彼らも必死だ。俺たち開発陣の『ボヤ』を、誰よりも早く見つけて、『ほらよ、消しといたぜ!』ってドヤ顔で報告するために、リリース日は目を皿のようにしてる」
これが、僕が体験した「海外のIT現場」の、最も過激な「ひねり(Twist)」でした。
日本で僕が信じていた「完璧なリリース(=バグゼロ)」という「クラシック(古典)」。
それを、「あえてバグを仕込むことで、組織全体の『回復力(レジリエンス)』を鍛える」という、真逆の「ひねり」で上書きしていたんです。
「(『ムダコード大賞』で、失敗を『資産』に変えることを学んだ…)」
「(そしてこの『ファイヤー・ドリル』で、本番の『障害』すらも『訓練(資産)』に変えるのか…!)」
僕が「完璧な設計図」にこだわっていた頃には、想像もつかない世界でした。
WPFのコードがどうとか、C#の書き方がどうとか、そんなミクロな話じゃない。
チームが、組織が、「失敗」をどう扱うかという、根本的な「文化(カルチャー)」の違い。
僕は、ゴクリと唾を飲み込みました。
いよいよ明日、僕が数ヶ月前に関わった、あの「グロー効果」のバグが、意図的に世界中にリリースされる。
そして、このクレイジーな「最終伝統」は、僕にとんでもない「気づき」と、エンジニアとしての「次なるステージ」を突きつけることになるのですが…それは、この物語の「結び」で語ることにしましょう。
最強のエンジニアは「バグ」を恐れない。彼らは「回復力」を設計する
(「転」のつづき)
そして、運命のメジャーリリース日。
僕らの新しいコードは、全世界のクライアント(顧客)のマシンに向かってデプロイされていきました。
もちろん、あの「ドイツ語OSでのみ、うっすら光り続けるWPFコントロール」という「ゴールデン・バグ」と共に。
僕は、正直、生きた心地がしませんでした。
「(本当に大丈夫か…?)」
「(もし、このバグが『軽微』じゃなくて、何か別の重大な障害を引き起こしたら…?)」
「(これ、日本では『仕込みバグ』って言って、クビが飛ぶやつじゃ…)」
僕のそんな不安をよそに、シニアエンジニアのマーク(あの意地悪な笑顔の)は、いつも通りコーヒーを飲んでいます。
リリースから約2時間後。
ついに、その時は来ました。
Datadog(監視アラート)が鳴るより早く、サポートチーム専用のSlackチャンネルが発火しました。
ALERT [Support]: TICKET #4589 - German Office reports UI flickering on monitoring screen. (Severity: Medium)
(来た!)
僕の心臓が跳ね上がりました。
サポートチームが、顧客からの第一報をキャッチし、即座に「中優先度」として開発チームにエスカレーションしてきたんです。
マークが、ニヤリともせず、静かにSlackに返信します。
[Dev] Roger. Investigating. (承知。調査する)
そして、僕の方を向いて、一言。
「さあ、やれ。『訓練』だ」
僕は、この日のために準備されていた「ホットフィックス(緊急修正パッチ)」のブランチに切り替え、デプロイボタンを押す…
…寸前で、マークに手を止められました。
「待て」
「え?」
「まだだ。サポートチームに、もう一手間、仕事をさせてやれ」
マークはSlackにこう打ち込みました。
[Dev] @Support-Team, can you confirm the OS version and resolution? Need logs from the client. (OSのバージョンと解像度を教えて。クライアントのログも必要だ)
これは、「俺たち(開発)は、まだ原因が特定できていない」というフリです。
サポートチームは「ぐぬぬ…」とでも言いたげに、即座にドイツ支社と連携し、必要な情報を集めて返してきました。
[Support] Confirmed. German Win10, specific resolution. Logs attached. This seems to be the WPF glow effect bug we saw in staging. (確認した。ドイツ語Win10、特定の解像度だ。ログ添付。これ、テスト環境で見たWPFのグロー効果のバグじゃないか?)
(そうだよ! 当たりだよ!)と僕は心の中で叫びます。
サポートチームが「原因」にたどり着いた。
ここで初めて、マークが僕に頷きます。
「OK、Go」
僕は、ホットフィックスのデプロイボタンを押しました。
自動化されたCI/CDパイプラインが作動し、C#のコードがビルドされ、テストが走り、修正パッチが全世界に配信されていきます。
リリース(14:00)
↓
顧客がバグ発見、サポートに連絡(16:10)
↓
サポートが開発にエスカレーション(16:12)
↓
開発とサポートが連携(フリ)し、原因特定(16:25)
↓
ホットフィックス、デプロイ開始(16:26)
↓
全顧客に修正パッチ配信完了(16:40)
「バグ発生」の第一報から、わずか30分弱で「完全鎮火」です。
Slackに、マークが書き込みます。
[Dev] Fix #4590 deployed. Please ask German office to restart the app. (修正パッチ展開済み。ドイツ支社にアプリ再起動を促してくれ)
数分後。
[Support] Confirmed. Flicker is gone. Closing ticket. …Nice try, Dev-Team. Too easy. (確認した。点滅は消えた。チケットを閉じる。…やるじゃん開発チーム。まぁ、簡単すぎたけどな)
[Dev] Glad you were awake, Support. Next time, we'll make it harder ;) (起きててくれてよかったよ、サポート。次はもっと難しくするぜ)
僕は、この一連の「茶番」とも言えるやり取りを見て、全身の力が抜けると同時に、とんでもない「気づき」に打ちのめされていました。
「完璧な設計図」を捨てた日
日本で僕が信じていた「完璧主義」。
C#とWPFの「完璧なMVVMアーキテクチャ」。
「完璧なリリース」。
それらは全て、「失敗しないこと(Prevention)」をゴールにしていました。
バグをゼロにすること。
設計図通りに作ること。
それが「品質」だと信じていました。
でも、このチームは違った。
彼らが目指していたのは、「失敗しても、すぐに立ち直れること(Resilience=回復力)」だったんです。
考えてみてください。
この「ゴールデン・バグ」の訓練。
彼らは、バグをゼロにしようとはしなかった。
その代わり、
- 監視(Observability) を強化し、「いつ壊れたか」を誰よりも早く知る仕組みを作った。
- サポート(Human Pipeline) との連携を訓練し、「顧客への影響」を最速で把握する流れを作った。
- デプロイ(Deployability) を自動化し、「どれだけ安全に、早く」修正を届けられるか、その速度を追求した。
「ムダコード大賞」(承)で学んだのは、「失敗を共有すれば『資産』になる」ということ。
そして、この「ゴールデン・バグ」(転)で学んだのは、「障害は『訓練』であり、『回復力』こそが本当の品質である」ということ。
これこそが、僕がこのブログで、これから海外で働こうとする皆さんに一番伝えたかった「人生術」です。
これから海外で戦う君たちへ
もし君が、僕と同じように「完璧主義」の呪いにかかっているなら。
もし君が、C#のコードやWPFのXAMLを、誰にも文句を言わせない「芸術品」に仕上げることに心血を注いでいるなら。
少しだけ、立ち止まって考えてみてほしい。
君のその「完璧なコード」は、明日、君がチームを去った後、誰かが安全に「変更」できるだろうか?
君のその「完璧な設計図」は、予期せぬ「障害」が起きた時、チームの「回復」を助けてくれるだろうか?
海外の現場(特に流れの速いIT業界)で求められるのは、「間違えないエンジニア」ではありません。
そんな人間は存在しないからです。
求められるのは、「安全に失敗でき、その失敗から爆速で学び、システム全体を昨日より少しだけ強くできるエンジニア」です。
「バグを恐れるな」とは言いません。バグは怖いです。
でも、「バグが起きる」ことを前提に、システムを設計してください。
君が書くC#のコードに、適切なログ(監視の目)を仕込んでください。
君が作るWPFのアプリに、安全に切り戻しできる仕組み(回復の手段)を組み込んでください。
君の技術力(C# / WPF)は、そのための「道具」です。
完璧なアーキテクチャを作ることが「目的」じゃない。
変化に強く、回復力の高いシステムを作ること。
それこそが、僕らエンジニアの本当の仕事なんだと、僕はあのクレイジーな「最終伝統」から学びました。
君のその「完璧主義」、そろそろ捨ててみませんか?
「失敗」を笑い飛ばし、「障害」で訓練する、最高にエキサイティングな世界が、海の外で君を待っていますよ。

コメント