時差14時間、それでもコードが壊れない理由:海外エンジニアが語る「安定」を生む標準化のリアル

悪夢の始まりは、いつも「ちょっとした違い」だった

どうも!皆さん、こんにちは。海外のとある国で、主にC#とWPFを使ってデスクトップアプリの設計開発をしている、しがないITエンジニアです。

「海外で働くエンジニア」って聞くと、どんなイメージですかね?

なんかこう、最新のMacBook片手に、ビーチサイドのカフェでカタカタ…みたいな?(笑)

まあ、そういう側面もゼロじゃないかもしれないけど、現実はもっと泥臭いです。特に僕らC#er、WindowsとVisual Studioと(時には)にらめっこする日々。それは日本にいても、海外にいても、あんまり変わらない。

でも、決定的に違うことがある。

それは、**「時差」と「物理的な距離」**が生む、とんでもない「ズレ」です。

今日は、僕が海外のグローバルチームで文字通り「痛い目」にあって学んだ、「標準化」っていう、一見お堅いトピックについて、実体験ベースで語らせてください。

「標準化?なにそれ、Linterとかコーディング規約でしょ?堅苦しいな」

って思った、そこのあなた。

わかります。僕も昔はガチガチのルールが大嫌いでした。「動けばいいじゃん」「俺の芸術的なコードにケチつけるな」って。

でも、もしあなたが将来、タイムゾーンの違うメンバーと働くことになったら、この「標準化」こそが、あなたの睡眠時間を守り、チームの精神を安定させる「最強の武器」になるってことを、先に伝えておきます。


あれは、僕がこのチームに参加してまだ間もない頃。

こっちは夜。ようやく今日のタスクを終えて、自信満々でコードをプッシュ。「よし、WPFのこの部分のロジック、我ながらキレイに書けたわ」なんて思いながらPCを閉じ、ビールを開けた、その30分後。

Slackの通知音が、けたたましく鳴り響きました。

メンション。相手は、地球の裏側(時差14時間)にいる、リードエンジニアのマーク。

「Hey. The build pipeline is completely RED. Looks like your last commit broke… everything?」(やあ。ビルドパイプラインが真っ赤だ。君の最後のコミットが…全部壊したっぽい?)

血の気が引きました。

慌ててPCを開き、CI/CD(継続的インテグレーション/デリバリー)のダッシュボードを見る。

そこには、無慈悲な「Failed」の赤いバツ印が、ズラッと並んでいました。

「え、なんで!?俺のローカル(自分のPC)では完璧に動いてたのに!」

これ、エンジニアなら一度は言ったことある(そして言われたことがある)セリフですよね。

でも、これがグローバルチームだと、冗談じゃ済まない。

僕が寝ている間に、地球の裏側ではマークたちが障害対応に追われることになる。逆に、彼らが寝ている間に僕らが困ることもある。

「ちょっとそこの席のAさん、これどうなってます?」が、できない。

Slackでメンションを飛ばしても、返事が来るのは早くて半日後。

その時の原因は、今思えば本当にくだらないことでした。

僕が使っていたC#のライブラリのバージョンと、ビルドサーバーが参照していたバージョンが、微妙に(・・・・・)違っていたんです。

でも、その「微妙な違い」に気づけなかった。なぜか?

チーム内に、「どれが正解か」を示す「唯一無二の真実(Single Source of Truth)」がなかったからです。


この「俺の環境では動いてた」問題。

根っこは、技術的な問題というより、「文化」と「暗黙の前提」の問題だったりします。

例えば、環境変数。

アプリを動かすための「鍵」みたいなものですね。データベースの接続文字列とか、APIキーとか。

僕がプロジェクトに参加した時、まずこの「鍵」を見つけるのに3日かかりました。

  1. まず、公式のドキュメント(Confluence)を見る。→書いてある設定情報が、半年前のもので古い。動かない。
  2. メンターのBさん(同じタイムゾーン)に聞く。→「ああ、それね。俺のローカルの .env ファイルあげるよ。これで動くから」→もらったファイルで試す。…動かない。
  3. リードのマーク(時差14時間)に聞く。→(半日後)「Hey, Bさんのファイルじゃダメだ。開発環境のシークレットは、こっちのシークレットマネージャー(別のツール)で管理してるから、このドキュメント見てアクセス権申請して」→申請する。…承認されるのに、また半日。

カオスですよね。

誰が悪いわけでもない。Bさんは親切で教えてくれたし、マークも正しい手順を教えてくれた。

ただ、「今、現在の、正しい設定は、どこにあるのか」という「Single Source of Truth」が、チーム内で共有されていなかった。

これがもし、本番環境の障害対応中だったら?

「正しい設定ファイルどこだっけ?」なんて探してる間に、サービスは死んだままです。ゾッとしますよね。


もう一つ、僕らを苦しめたのが、「良いコードとは何か」という定義のズレです。

C#エンジニア、特にWPF(XAML)を書いてると、コードの書き方って結構「流派」が出ません?

MVVMパターンの実装一つとっても、

「ViewModelはインターフェースを実装すべきだ」派

「いや、Prismみたいなフレームワークに全部乗っかれ」派

「XAMLのコードビハインド(.xaml.cs)は一行たりとも書くな」派

「いや、UIに閉じたロジックなら書いてもいい」派…

これに加えて、C#の言語機能。

僕は比較的新しい構文が好きで、<code>global using</code> とか <code>record struct</code> とか、トップレベルステートメントとか、書けるところはモダンに書きたいタイプ。

ある日、僕がレビューに出したコード。

自分では「C# 10の機能使って、超スッキリ書けたわ」と思ってました。

そしたら、シニアエンジニアのDさん(別の国)からのレビューコメント。

「This expression is unfamiliar. Please rewrite with traditional class and explicit using statements. It’s more readable.」(この式は見慣れない。従来のclassと明示的なusing文で書き直してくれ。そっちの方が読みやすい)

カチン、と来ました。(笑)

「いやいや、こっちの方がモダンだし、コード量も減るでしょ!」

「読みやすいって、それはDさんが見慣れてないだけでしょ!」

って、反論のコメントを書きそうになりました。

でも、一呼吸置いて考えた。

このやり取り、非同期(チャット)でやってるんです。僕が反論して、Dさんがそれを見るのは半日後。また反論が返ってくるのは…って、このコードレビュー、いつ終わるんだ?と。

問題は、どっちの書き方が「絶対的に正しいか」じゃない。

問題は、「僕らのチームにとっての『良いコード』とは何か」という共通認識(Shared Understanding)が、確立されていなかったことです。

Dさんの言う「読みやすさ」も、チームの安定性を考えたら正義なんです。新しいメンバーがすぐに読めるコード、という観点では。

僕の言う「モダンさ」も、生産性や将来性を考えたら正義。

でも、この「正義」がタイムゾーンを超えてぶつかり合うと、ただの消耗戦にしかならない。

あるモジュールはモダン記法、あるモジュールはレガシー記法…みたいな「コードのサイロ化」が始まり、あっという間に「技術的負債」が積み上がっていく。


どうです?

「標準化」って、ただ開発者を縛り付ける堅苦しいルールだと思ってませんでしたか?

時差と文化の壁があるグローバルチームにおいて、「標準化」は、

「朝起きたらビルドが壊れてる」という悪夢を防ぐためのセーフティネットであり、

「この設定、どれが最新?」という無駄な時間を使わないための道しるべであり、

「どっちの書き方が正しいんだ」という宗教戦争を終わらせるための共通言語なんです。

つまり、**チームが安定して開発を続けるための「土台」**そのもの。

じゃあ、僕のチームは、このカオスな状況をどうやって乗り越えたのか?

ただLinterのルールを厳しくしただけ?

いやいや、それだけじゃ「なんで俺がこんなルールに従わなきゃいけないんだ」って、反発が起きるだけです。

大事なのは、ツール(技術)と、それを使う人間(文化)の両輪。

次回の「承」では、僕らが「安定性」を勝ち取るために導入した、超具体的なツール(pre-commitフックやCI/CDパイプライン)の話と、それを導入する時に起きた「人間くさい衝突」や、「共通認識」をどうやって作っていったのか、そのリアルなプロセスについて、詳しくお話ししようと思います。

カオスとの戦い。「ルール」を「文化」に変えた僕らの武器

「起」で話した通り、僕のチームは「時差」と「暗黙の前提」によって、かなりカオスな状況に陥ってました。

ビルドは毎朝のように壊れ、設定ファイルは「秘伝のタレ」みたいになってるし、「どんなコードが良いコードか」っていう基準もバラバラ。

「このままじゃ、時差のせいでまともに開発できねえ!」

「マーク(地球の裏側のリード)が寝てる間に、こっちで全部火消しとか無理ゲーだろ!」

そんな悲鳴が、僕だけじゃなく、同じタイムゾーンの同僚からも上がり始めました。

そこで、僕らはついに重い腰を上げたんです。

「標準化」、この一見つまらない作業に、本気で取り組むことにしました。

今日は、僕らが具体的に「何をしたか」を紹介します。

これは、ただツールを導入したって話じゃありません。ツールを使って、どうやって「共通認識」っていう文化を作っていったかの、泥臭い戦いの記録です。


武器その1:「真実の在処」を一つに絞る(Single Source of Truth)

まず、あの悪夢の「環境設定ファイルどこだっけ?」問題。

これを撲滅することから始めました。

やったこと:『Azure Key Vault』の導入と、CI/CDパイプラインからの参照徹底

最初はね、「Wiki(Confluence)に最新版をちゃんと書こうよ」って話も出たんです。

でも、人間が手で更新するドキュメントは、絶対に腐る。これはIT業界の真理です。

そこで、僕らは「設定情報やシークレット(APIキーとか)は、プログラム(CI/CDパイプライン)以外からは触れない場所」を「唯一の正義」とすることに決めました。

それが、僕らの場合は『Azure Key Vault』(Azure版のシークレット管理ツール)でした。(AWSならSecrets Manager、GCPならSecret Managerとかですね)

もう、メンターのBさんが「俺のローカルの .env ファイルあげるよ」は、禁止。

個人のPCに、本番環境や開発環境の「生」の接続文字列を持つのも、禁止。

じゃあ、どうやって開発するのか?

開発用の環境変数は、Key Vaultから「開発環境用」として払い出されたものを、自分のローカルPCの「ユーザーシークレット」(.NETの機能ですね)に設定する。

そして、その「設定の仕方」だけをWikiに書く。

こうすれば、Wikiが古くなっても、「設定値そのもの」はKey Vaultにあるので、問題ない。

CI/CDパイプライン(僕らはAzure Pipelines)も、ビルドやデプロイの時に、必ずKey Vaultの「本番用」の値を参照しに行くように設定しました。

これ、副次的な効果がデカかった。

「設定値の変更」が、めちゃくちゃ慎重になったんです。

今までは、誰かが「あ、ここの設定変えといたわ」ってローカルで変えて、それがコミットされて、ビルドが壊れてた。

でも今は、Key Vaultの値を変更するっていうのは、「インフラチームへの正式な変更依頼」が必要な「イベント」になった。

結果、設定ファイルの不一致によるビルド破壊は、マジでゼロになりました。

これはC# WPFのデスクトップアプリでも同じ。

例えば、アプリが参照するAPIのエンドポイントとか、ライセンスキーとか、そういう「環境によって変わる値」を、昔は App.config にベタ書きしてた。

それを全部、ビルドプロセスでCI/CDがKey Vaultから取ってきた値で「差し替える」ようにしたんです。

これで、「俺のローカルでは動いてたのに、リリース版だとAPIに繋がらない」みたいな事故が、無くなりました。

地味だけど、最強の安定化策です。


武器その2:「良いコード」を定義する(Linterルールの先へ)

次に着手したのが、あの「モダン記法 vs 読みやすさ」の宗教戦争です。

やったこと:『コーディングスタンダードギルド』の発足と、.editorconfig の全社適用

これも最初は、「Linter(.NET AnalyzersとかStyleCop)を導入しよう」って話だけでした。

でも、Dさん(レガシー派)と僕(モダン派)の意見が割れたように、どのルールを有効にするかで揉めるのがオチ。

そこで、僕らは「ツール」の話の前に、「文化」の話をすることにしました。

「コーディングスタンダードギルド」なんて大層な名前を付けましたけど、要は週に1回、各タイムゾーンのエンジニア代表が数人集まって、「僕らのチームの『良いコード』って何?」を話し合う、ただのミーティングです。

最初の議題は、もちろん僕とDさんが揉めた「C# 10のモダン記法、使っていいのか?」問題。

僕:「<code>global using</code> とかトップレベルステートメントは、コードがスッキリするし、生産性が上がる」

Dさん:「いや、それは君が見慣れてるだけだ。新しいメンバー(特にジュニア)が入ってきた時、<code>class Program</code> も <code>Main</code> メソッドもないコードを見たら混乱する。『読みやすさ』が最優先だ」

これ、どっちも正しい。

この議論、Slack(チャット)でやってたら、多分お互いイライラして終わってた。

でも、ビデオ通話で、顔を見て、時差を超えて議論したことで、落とし所が見つかったんです。

結論:「使ってもいい。ただし、チーム内で『これが我々の標準だ』と合意が取れたものだけ」

そして、合意した内容は、全部 .editorconfig ファイルに落とし込みました。

.NET(Visual Studio)は、この .editorconfig ファイルをリポジトリに置いておくと、それに違反するコードを書いた瞬間に「警告」や「エラー」を出してくれます。

例えば、「<code>global using</code> は使わない」と合意したら、それを禁止するルールを .editorconfig に書く。

そうすれば、僕がうっかり使おうとしても、Visual Studioが「ダメだよ」ってリアルタイムで怒ってくれる。

Dさんがレビューで指摘する必要がなくなるわけです。

この「ギルド」、めちゃくちゃ効果ありました。

WPFのMVVMパターンについても、「ViewModelからViewを直接触っちゃダメ、絶対」とか、「この処理はModelに書くべきか、ViewModelに書くべきか」みたいな、設計思想の根本的な部分を、ちゃんと時間を取ってすり合わせることができた。

「コードの書き方」でレビューが荒れることが、劇的に減りましたね。


武器その3:人間を信用しない。「自動化」という名の門番

さて、「設定ファイルのSsoT」もできた。「良いコードの定義」もできた。

でも、人間は忘れる生き物です。

「あ、ごめん、Linter(コード整形)かけるの忘れてコミットしちゃった」

「ローカルでテスト(<code>dotnet test</code>)回すの忘れてた…」

これが起きると、結局CI/CDパイプラインが赤くなる。マーク(リード)が叩き起こされる。

やったこと:『pre-commitフック』と『CI/CDパイプライン(PRビルド)』の強制

僕らは、人間の「うっかり」を、技術で殴り倒すことにしました。

1. pre-commitフック(ローカルの門番)

これは、「<code>git commit</code>」ってコマンドを叩いた「瞬間」に、あらかじめ決められたスクリプトを「強制的に」実行する仕組みです。

僕らはここに、

  1. <code>dotnet format</code> (コードが .editorconfig に準拠してるか自動チェック&修正)
  2. <code>dotnet build</code> (そもそもビルドが通るかチェック)
  3. <code>dotnet test</code> (単体テストが全部通るかチェック)を仕込みました。

これ、最高ですよ。

自分のPCでコードを書いて、「よし、コミットするぞ!」ってやると、PCが「待て。お前のコード、スタイルが汚いぞ。テストもコケてる。直すまでコミットさせん」って止めてくれる。

もう、CI/CDパイプラインに「汚いコード」や「壊れたコード」をプッシュすること自体ができなくなったんです。

2. CI/CDパイプライン(本流の門番)

とはいえ、pre-commitフックは、上級者なら「<code>–no-verify</code>」みたいなコマンドで(こっそり)回避できちゃう。

だから、GitHubやAzure Reposで「プルリクエスト(PR)」が作られた時に、「必ずCIビルドが成功しないと、メインのブランチにマージさせない」というブランチポリシーを設定しました。

これが「最後の門番」です。

このパイプラインは、pre-commitフックよりも厳格に、全プロジェクトのビルド、全テスト、全コード解析を実行します。

これが通らない限り、僕のコードは絶対に製品コード(mainブランチ)に入らない。


さあ、どうでしょう。

僕らはこうして、「設定」「コーディング規約」「ビルド&テスト」という3つの側面から、「標準化」の土台を固めました。

「唯一の真実(SsoT)」としてのKey Vault。

「共通認識」としての .editorconfig とギルド。

「強制力」としてのpre-commitフックとCI/CDパイプライン。

この「安定化の三種の神器」を手に入れたことで、僕のチームのビルド失敗率は、体感で9割以上減りました。

僕も、夜中にマークから叩き起こされることはなくなったし、マークも、僕がプッシュしたコードに怯えなくて済むようになった(笑)

まさに「Standardizing for Stability(安定性のための標準化)」です。

これを知ってるだけで、グローバルチームで働く時のストレス、マジで激減しますよ。

…と、ここまで聞くと、「なんだ、ガチガチにルールで固めただけじゃん」「窮屈そう」って思いますよね?

そう、この話、ここで終わりじゃないんです。

この「最強の安定化」を手に入れた僕らを、次に待ち受けていた「新たな壁」。

それは、**「標準化」が行き過ぎたことによる「副作用」**でした。

次回の「転」では、この「安定」が引き起こした、予想外の「停滞」と、僕らがどうそれに立ち向かったかについて、お話ししたいと思います。

安定という名の「牢獄」。ルールが僕らの首を絞め始めた日

「承」で紹介した「三種の神器」(Key Vault、ギルドと.editorconfig、CI/CDとpre-commit)のおかげで、僕らのチームは劇的に変わりました。

ビルドは常に「Green」。夜中の叩き起こしコールは消滅。

「俺の環境では動いてた」という、あの不毛なセリフも、もう誰も言わなくなりました。

平和。そう、平和そのものだったんです。最初の数ヶ月は。

みんながルールを守り、標準化されたプロセスの上で、淡々とタスクをこなしていく。

時差なんて関係ない。地球の裏側のマークが書いたコードも、僕が書いたコードも、まるで一人の人間が書いたかのように、均一で「読みやすい」ものになっていきました。

完璧だ。僕らはついに「グローバルチームの理想郷」にたどり着いたんだ。

…そう、本気で思ってました。

あの「事件」が起きるまでは。


その日、僕は新しいタスクに取り組んでいました。

「WPFアプリの、とある一覧画面の表示速度がめちゃくちゃ遅い。改善してくれ」

よくあるパフォーマンスチューニングのタスクです。

僕はC#erとして、WPFの内部(UIの仮想化とか)をあれこれいじくり回すより、もっと根本的な解決策を探していました。

そこで、ある新しいNuGetパッケージを見つけたんです。

それは、データバインディングの仕組みに手を入れて、従来の INotifyPropertyChanged よりも劇的に高速にUIを更新できる、という触れ込みのライブラリでした。

「これだ!これを使えば、コードもシンプルになるし、爆速になるぞ!」

僕は興奮しました。こういう新しい技術を試して、問題をスマートに解決する瞬間こそ、エンジニアの醍醐味ですよね。

早速、僕はそのNuGetパッケージをプロジェクトに追加し、リファクタリング(コードの改善)を始めました。

ローカルでのテストは完璧。

「よっしゃ、これでPR(プルリクエスト)出すぞ!」

自信満々でコードをプッシュ。

…その5分後。CI/CDパイプラインから通知が。

「Failed」

無慈悲な赤いバツ印。

「え、なんで!?」

僕は慌ててログを見ました。

そこに書かれていたエラーメッセージは、僕が予想もしないものでした。

「Error: Disallowed NuGet Package ‘XXXX.YY.ZZ’. This package is not in the approved list. Please submit a request to the ‘Coding Standard Guild’ for approval.」

(エラー:許可されていないNuGetパッケージ ‘XXXX.YY.ZZ’。このパッケージは承認済みリストにありません。「コーディングスタンダードギルド」に承認リクエストを提出してください)

…は?

そう。僕らは「安定」を求めるあまり、「使っていいNuGetパッケージ」すらも、「ギルド」の承認制にしていたんです。

忘れてました。いや、正確には、「安定」の裏返しとして、そういうルールが自動的に運用されていたんです。

まあ、ルールなら仕方ない。

僕は早速、次の「ギルド」のミーティング(週に1回、タイムゾーンをまたいで開催される)に、議題として申請しました。

「このイケてるライブラリ、使わせてくれ」と。

そして、ミーティング当日。

僕は、このライブラリがいかに素晴らしいか、パフォーマンスがどれだけ上がるかを力説しました。

しかし、他の国のシニアエンジニアたちの反応は、驚くほど冷ややかでした。

「うーん、でも、これを入れると、チーム全員がこのライブラリの『お作法』を新しく学ばないといけないよね?」

「作者は信頼できるの?メンテナンスが止まったらどうする?」

「今のやり方(<code>INotifyPropertyChanged</code>)でも、遅いとはいえ『動いては』いるんだろう?」

「これを許可すると、似たような『俺が使いたいライブラリ』の申請が殺到して、標準化が崩れるんじゃないか?」

時差14時間のマーク(リード)も、ビデオ越しに渋い顔。

「気持ちはわかる。でも、安定性を考えると、新しい依存関係を増やすのは慎重になるべきだ…」

結局、このライブラリの採用は「保留」。

「まずは、既存のコードの範囲内で、地道なチューニングを試みること」

それが「ギルド」の結論でした。

僕は、その一覧画面を、新しいライブラリなしで、小手先のテクニックでなんとか「ちょっとだけ」速くしました。

ユーザーは、たぶん違いに気づかないレベルです。

僕のモチベーションは、地の底まで落ちました。

「なんのための標準化だよ…」


この「事件」をきっかけに、チームの「淀み」が目に見えるようになってきました。

「安定」は、いつしか「停滞」に変わっていたんです。

僕らがあれほど苦労して作った「標準化」の仕組みが、今度は僕らを縛る「牢獄」になっていた。

例えば、C#の新しい言語機能。

C# 11やC# 12で、もっと簡潔に書ける構文(例えば <code>required</code> プロパティとか、コレクション式とか)が出てきても、

「いや、.editorconfig で『C# 10準拠』って決めたから」

「Dさん(レガシー派)がまだその構文に慣れてないから、チームの『読みやすさ』を優先しよう」

と、ギルドで却下される。

新しい設計パターンを試そうとしても、

「それは、我々の『標準MVVMパターン』と異なる。混乱を招くからやめてくれ」

と、PRレビューで弾かれる。

pre-commitフックとCI/CDパイプラインは、もはや「品質を守る門番」ではなく、「新しいことを許さない監視官」のようになっていました。

チームの雰囲気は、明らかに悪くなりました。

特に、僕みたいに新しい技術が好きなエンジニアは、どんどん「どうせ言っても無駄」という「あきらめ」の空気をまとうようになった。

誰も、新しいライブラリや新しい設計を提案しなくなったんです。

開発スピードも、目に見えて落ちました。

だってそうでしょう?

「ちょっとこの書き方、どうかな?」

「この方が効率的じゃない?」

という、日々の小さな「カイゼン」が、すべて「ギルドの承認待ち」か「レビューでの差し戻し」になるんです。

エンジニアは、一番面白くて、一番価値のある「どう作るか」という思考を放棄し、ただ「ルールに違反しないこと」だけを考える、つまらない作業者になっていました。

皮肉な話です。

カオスを脱するために「標準化」を導入したら、今度は「標準化」によってチームが窒息しかけている。

ビルドは、相変わらず「Green」でした。

でも、僕らの顔色は「Red」だった。

このままじゃダメだ。

この「安定という名の停滞」を、どう打ち破るか?

かといって、せっかく手に入れた「安定」を捨てて、またあのカオスな時代に戻るのも絶対に嫌だ。

「安定」と「進化」。

この、一見、相反する二つを、僕らのチームは両立させなきゃいけなくなった。

僕らの「標準化」は、第二章に入ったんです。

次回の「結」では、この「硬直化したルール」という新たな敵と、僕らがどう戦ったのか。

「安定」を土台にしつつ、「変化」や「進化」を恐れないチームになるために、僕らが見つけ出した「答え」について、お話ししようと思います。

僕らが見つけた「生きた標準化」。安定の土台の上で、踊り続ける方法

「転」でお話しした通り、僕らは「安定」を手に入れた代償に、「進化」を失いかけていました。

ガチガチに固めたルールは、チームをカオスから守る「鎧」であると同時に、新しい動きを封じ込める「ギプス」にもなっていたんです。

CI/CDパイプラインは毎日「Green」。

でも、チームの雰囲気は「Red」。

新しい技術にワクワクするエンジニアの目は、いつしか「どうせ却下される」という、あきらめの色に変わっていました。

「安定」は手に入れた。でも、このままじゃ、このチームはゆっくりと死んでいく。

僕らは、この「安定という名の牢獄」から、どうやって脱出すべきか、再び議論を始めました。


議論は、もちろん、あの「コーディングスタンダードギルド」で行われました。

皮肉なことに、僕らの首を絞めていた「ルール」を作っていた、まさにその場所で。

僕:「あの…パフォーマンス改善の件で提案したNuGetパッケージ、結局『保留』になりましたけど、納得いってません」

思い切って、切り出しました。

僕:「ルールを守るのは大事です。ビルドが壊れなくなったのは、本当に感謝してる。でも、今のやり方じゃ、僕らは『より良い方法』を探すこと自体をやめてしまいます。それって、エンジニアとして、チームとして、ヤバくないですか?」

ビデオ会議の画面越しに、時差の違う国のメンバーたちが、難しい顔をしているのがわかりました。

シニアエンジニアのDさん(レガシー派)が、重い口を開きました。

「…君の言いたいことはわかる。だが、あのカオスな日々に戻りたいか?誰もが勝手なライブラリを入れ、勝手な書き方を始めたら、また時差のせいでビルドが壊れ、地球の裏側で誰かが泣きを見るんだ」

その通り。

「安定」を捨てて「進化」を取る?ダメだ。

「進化」を捨てて「安定」を取る?それもダメだ。

じゃあ、どうする?

その時、ずっと黙って聞いていたリードのマーク(時差14時間)が、ふっと息を吐いて言いました。

「…俺たちは、勘違いをしていたのかもしれないな」

「『標準化』の目的は、変化を『止める』ことじゃない。『標準化』の本当の目的は、『安全に』変化し続けるための『土台』を作ることだったはずだ」

…安全に、変化し続ける、土台。

「今のギルドは、『変化の門番』になってしまっている。そうじゃない。ギルドの仕事は、『変化の交通整理』であるべきなんだ」

このマークの一言で、僕らの「標準化」は、第二章の幕を開けました。


僕らが見つけ出した答え。

それは、**「ルールを『聖書』にするな、『辞書』にしろ」**ということでした。

聖書は、絶対の教え。変えてはいけないもの。

辞書は、今の時点での「正しい」意味が書いてある。でも、言葉の意味が変われば、辞書も改訂される。

僕らの .editorconfig や「承認済みNuGetリスト」は、いつの間にか「聖書」になっていた。

これを、**「生きた辞書(Living Document)」**として、安全に、継続的に更新していくプロセスを導入したんです。

具体的に、何を変えたか?

「コーディングスタンダードギルド」の役割を、根本から変えました。

【Before】ギルド = 承認機関(ブロッカー)

「新しいことはダメ」

「標準と違うから却下」

【After】ギルド = 実験の推進機関(イネーブラー)

「いいね、それ。じゃあ、『安全な場所』で試してみよう

そう。僕らは「サンドボックス(砂場)戦略」を導入したんです。


新しいライブラリ、新しいC#の構文、新しい設計パターン…

「試したい」という提案が上がってきたら、ギルドはもう「ダメ」とは言いません。

代わりに、こう言うんです。

「OK。じゃあ、影響範囲を限定して、まずはその新しいやり方で実装してみてくれ」

「影響範囲を限定」っていうのがミソです。

例えば、僕が提案したあの高速化NuGetパッケージ。

「アプリ全体にいきなり入れるのはリスクが高すぎる」

「だから、まずはあの『パフォーマンスが遅い一覧画面』だけに使ってみよう」

と、ギルドが「お墨付き」の「実験場」を与えてくれるんです。

他のモジュールには、まだ古い標準(<code>INotifyPropertyChanged</code>)を使い続けます。

CI/CDパイプラインも、「このモジュールだけは、例外的にあのNuGetパッケージの使用を許可する」という一時的なルールを追加します。

そして、その「実験」が終わったら、僕はギルドに**「結果」を報告する義務**を負います。

「実験」して終わり、じゃない。

「導入した結果、パフォーマンスはマジで30%上がった」

「でも、学習コストがこれくらいかかった」

「こういうバグの懸念が見つかった」

という、生々しい「成果」と「コスト」を、チーム全体に共有するんです。

その結果を見て、ギルドが再び判断します。

「なるほど。メリットがデカいな。じゃあ、これを『次の標準』にしよう」

「このライブラリを、正式に『承認済みリスト』に追加する。全員、次のタスクからこれを使っていこう」

「そのために、君が作ったドキュメントを、チームのWikiに貼ってくれ」

こうして、僕らの「辞書(.editorconfigとか)」が、安全に改訂される。

これが、僕らが見つけた「安定」と「進化」を両立させる道でした。


この「サンドボックス戦略」が回り始めてから、チームは劇的に変わりました。

「どうせダメ」という「停滞」の空気は消え、「次は俺が実験してやる」という「健全な挑戦」の空気が生まれました。

エンジニアは、「ルールに従う作業者」から、**「ルールを進化させる当事者」**に変わったんです。

シニアのDさんも、今では「C# 12のこの新機能、ちょっと局所的に試してみないか?」なんて言い出すくらい(笑)

僕らを縛っていた、あの「三種の神器」も、役割が変わりました。

  • CI/CDとpre-commitフック:「変化を許さない監視官」ではなく、「実験場所以外に『変化』が漏れ出さないことを保証する防波堤」になった。
  • コーディングギルド:「門番」ではなく、「次の標準を作るための、安全な実験の交通整理役」になった。

これこそが、「Standardizing for Stability(安定のための標準化)」の、本当の意味だったんです。

「安定」とは、止まることじゃない。

「安定」とは、**転ばないように、安全に歩き方(=標準)を改善し続ける「プロセス」**そのものだったんです。


読者の皆さんへ。今日、持って帰ってほしいこと

もし、あなたがこれから海外で働く、あるいはすでにグローバルチームで消耗しているなら、今日の話を思い出してください。

時差や文化の壁を乗り越えるために、「標準化」は絶対に必要です。カオスを防ぐために、ルールは作らなきゃいけない。

でも、**ルールは作った瞬間に「古くなり始める」**ということを、絶対に忘れないでください。

大事なのは、「完璧なルール」を作ることじゃありません。

大事なのは、**「不完璧なルールを、チーム全員で安全に改善し続ける『仕組み』」**を作ることです。

あなたのチームの「標準」は、ガチガチの「聖書」になってませんか?

それとも、未来のために改訂され続ける、生きた「辞書」になっていますか?

「安定」の土台の上で、「進化」というダンスを踊り続ける。

それが、時差14時間の壁を越えて、僕らがようやくたどり着いた「人生術」であり、最強の「チーム術」です。

最後まで読んでくれて、ありがとうございました!

コメント

タイトルとURLをコピーしました