diff --git "a/source/_posts/2025/20251031a_\347\247\213\343\201\256\343\203\226\343\203\255\343\202\260\351\200\261\351\226\2232025_.md" "b/source/_posts/2025/20251031a_\347\247\213\343\201\256\343\203\226\343\203\255\343\202\260\351\200\261\351\226\2232025_.md" index 3c5c2011e4a..66a795b050c 100644 --- "a/source/_posts/2025/20251031a_\347\247\213\343\201\256\343\203\226\343\203\255\343\202\260\351\200\261\351\226\2232025_.md" +++ "b/source/_posts/2025/20251031a_\347\247\213\343\201\256\343\203\226\343\203\255\343\202\260\351\200\261\351\226\2232025_.md" @@ -32,8 +32,9 @@ lede: "秋のブログ週間とは2020年から始まったブログリレーの | 11/4 火 | 内堀 航輝 | [新卒1年目で勉強してた時に感じたこと](/articles/20251104a/) | | 11/5 水 | 大前七奈 | [AI-ReadyのためのAI駆動のデータモデリング](/articles/20251105a/) | | 11/6 木 | 澁川 喜規 | [データベースと向き合う決意をしてから3年たった](/articles/20251106a/) | -| 11/7 金 | 小橋 昌明 | TBD | +| 11/7 金 | 真野 隼記 | [なぜアーキチームは設計や実装のパターンを絞りたいか?](/articles/20251107a/) | | 3週目 | 🍬 | - | | 11/10 月 | 清水 雄一郎 | 書評 | +| 11/11 火 | 小橋 昌明 | TBD | いつもはコードが本文に書かれていることも多いフューチャー技術ブログですが、この連載はスマホ片手で読めるような記事成分を高めたいと思います。約2週間、どうぞお付き合いください。 diff --git "a/source/_posts/2025/20251107a_\343\201\252\343\201\234\343\202\242\343\203\274\343\202\255\343\203\201\343\203\274\343\203\240\343\201\257\350\250\255\350\250\210\343\202\204\345\256\237\350\243\205\343\201\256\343\203\221\343\202\277\343\203\274\343\203\263\343\202\222\347\265\236\343\202\212\343\201\237\343\201\204\343\201\213\357\274\237_\350\203\214\346\231\257\343\201\253\343\201\202\343\202\213\346\200\235\350\200\203\343\201\250\346\212\200\350\241\223\351\201\270\345\256\232\343\201\256\343\202\270\343\203\254\343\203\263\343\203\236.md" "b/source/_posts/2025/20251107a_\343\201\252\343\201\234\343\202\242\343\203\274\343\202\255\343\203\201\343\203\274\343\203\240\343\201\257\350\250\255\350\250\210\343\202\204\345\256\237\350\243\205\343\201\256\343\203\221\343\202\277\343\203\274\343\203\263\343\202\222\347\265\236\343\202\212\343\201\237\343\201\204\343\201\213\357\274\237_\350\203\214\346\231\257\343\201\253\343\201\202\343\202\213\346\200\235\350\200\203\343\201\250\346\212\200\350\241\223\351\201\270\345\256\232\343\201\256\343\202\270\343\203\254\343\203\263\343\203\236.md" new file mode 100644 index 00000000000..6caaa19a765 --- /dev/null +++ "b/source/_posts/2025/20251107a_\343\201\252\343\201\234\343\202\242\343\203\274\343\202\255\343\203\201\343\203\274\343\203\240\343\201\257\350\250\255\350\250\210\343\202\204\345\256\237\350\243\205\343\201\256\343\203\221\343\202\277\343\203\274\343\203\263\343\202\222\347\265\236\343\202\212\343\201\237\343\201\204\343\201\213\357\274\237_\350\203\214\346\231\257\343\201\253\343\201\202\343\202\213\346\200\235\350\200\203\343\201\250\346\212\200\350\241\223\351\201\270\345\256\232\343\201\256\343\202\270\343\203\254\343\203\263\343\203\236.md" @@ -0,0 +1,189 @@ +--- +title: "なぜアーキチームは設計や実装のパターンを絞りたいか? 背景にある思考と技術選定のジレンマ" +date: 2025/11/07 00:00:00 +postid: a +tag: + - アーキテクチャ + - 設計 +category: + - Programming +thumbnail: /images/2025/20251107a/thumbnail.jpg +author: 真野隼記 +lede: "アーキチーム(アーキテクト)やテックリードなどからの設計/開発のレビューで、こんな経験はありませんか?「その実装は、この機能ID BL310 の実装パターンでお願いします」" +--- + + +[秋のブログ週間](/articles/20251031a/)の7本目です。TIG 真野です。 + +アーキチーム(アーキテクト)やテックリードなどからの設計/開発のレビューで、こんな経験はありませんか? + +- 「その実装は、この機能ID "BL310" の実装パターンでお願いします」 +- 「そのライブラリの採用は見送りでお願いします」 +- 「そのミドル(DB)のその機能の利用は原則禁止です。え? はい、あー、、ガイドラインには...確かに今、書いていないですね。後出しで申し訳ないのですが利用はしない方向でお願いします。開発規約には私がこれから追記しますね。え? あ、はい。そうですね、今度タイ料理でも食べに行きましょう」 + +難しい要件・厳しい期限・不確実性・そして必ずしも満足とは言い難い体制の中、こっちはベストを尽くしていて、ましてより直感的で意図が明確な設計や実装だと思っていて、ていうか品質やスケジュールで遅延が生じた際に結局、矢面に立つのは自分なのに、否定されてかつやり直す合理性がどこにあるの? 仮に指摘事項が"正"だとしても、それをやるのって今なの? 今って割とけっこう瀬戸際なんだけどと、感覚が鈍ってるんじゃないの?...とモヤったことがある人は多いのでないでしょうか。 + +私は最近の比率で言うとモヤッとさせている側です。すいません。そしてメンバーから「なんでダメなんでしたっけ?」と言われ説明することもしばしばです。秋の夜長を楽しむという秋のブログ週間にあやかって、どういう思考でそういう発言をしているのか説明します。 + +# 実装/設計パターンを絞りたい理由は全体最適と局所最適 + +導入で触れた「モヤッと」の多くは、レビュイーが見ている「局所最適(目の前のタスクの最速完了)」と、レビュワーが見ている「全体最適(プロジェクト全体の長期的な健全性)」の視点の違いで、大まかに説明できる気がします。 + +開発言語・フレームワーク・マネージドサービス、バージョンアップのたびに、次々と便利な機能が追加されます。若手開発者目線ではそういった新機能を享受したいのはキャリア観点でもタスク遂行の観点でごもっともです。それでも新しいパターンを増やしたくない場合、私は以下の考えが多いです。 + +- **コードベース全体の一貫性を保ち、認知負荷を小さくする。予測可能性を保ちたい** + - 新しいメンバーが参画して来たときの学習コスト(引き継ぎコスト)を下げたい + - 将来的に横断的な修正作業が発生した時に、調査漏れするリスクを軽減したい +- **各開発者への設計余地を減らし均質化したい** + - 同じこと(例えばHTTPアクセスなど)をするのに、手法Aと手法Bが存在すると、開発者がどちらを使うべきか迷います。空気を読んで選んでねと言いたいところですが、レビューの場でひっくり返されるとお互い嫌です。何かしら指針を開発ガイドラインへ追記が必要です。そうすると、既存のコードがその開発指針に従っているか確認し、従っていない場合は修正しないと矛盾が生じます。そこまでしてやること? + - より良い手法を編み出せる開発者は良いのですが、チームメンバーの成熟度によっては必ずしも正しい選択ができるメンバーばかりとは限りません。手法Bを本来使うべきでないところに、手法Bを導入してしまう場合もしばしば見受けられます。選択肢が増えるとできる開発者は嬉しいですが、そうでない場合、開発難易度が上がるということでもあります。難しい案件であればあるほど、プロジェクトの遅延リスクとなる要因は、万難を排しておきたい気持ちの場合があります +- **ライブラリや利用サービスの追加による管理コストを下げたい** + - ライブラリやクラウドサービスは便利なのでどんどん新しく使用したくなります。システム構成図や技術スタック図にアイコンが沢山並んでいると、なんかイケているPJに所属している感じが嬉しいです。しかし、それぞれ学習コストが発生しますし、バージョンアップコストや脆弱性対応など追加作業が発生します。引き継ぎ先にそのサービスやライブラリを使ったことがないので、詳しい使い方を伝授して欲しいと言われる可能性もあります。ドキュメント作成の手間を増やしてでも本当にやるべきだったのでしょうか + +つまり、各機能単位でより良い実装方法が存在したとしても、システム全体でパターンを増やすデメリットを上回るメリットが存在するのかを考えています。特に保守運用時の観点は重要です。プロジェクトのライフサイクルによっては、今の熟練メンバーがいなくなりよりジュニアなメンバーで運用する場面が存在するかもしれません。その時に、難しい調査・改修が難しいコードベースになっていないか、引き継ぎしやすい構成になっているかは、軽視したくありません。 + +# 象牙の塔 + +もちろん、統制が常に正解と思い込み、現場の状況を無視した開発規約を強制するといった「象牙の塔」的なアンチパターンも世の中にはあると聞いたことがあります。統制を強めること自体にも当然デメリットがあります。 + +| メリット | デメリット | +| :--- | :--- | +| ✅ 品質の担保 | 🚫 モチベーション低下(特に若手) | +| ✅ 認知負荷の低減 | 🚫 開発速度の低下 | +| ✅ 保守性の向上 | 🚫 変化への対応の遅れ | + +統制と裁量の最も良いバランスの、スイートスポットは常に状況で変化します。現場をよく観察した上で考え続けて柔軟に意思決定していく必要があります。そのため、フェーズの前半と後半で、「あ、自分違うことを言っているな」と思う時があります。その場合は何かしらの前提が変わったことから、比重を変えたくなったということですので、疑問に思ったら「なんの要因で方針が変化したの?」と聞いてみると良いと思います。アーキテクト的にも自分の考えを言語化できてきっと嬉しいでしょう。 + +私の経験上では、プロジェクト初期は不確実性が高く、開発を軌道に載せて魅力的な機能実装をスピーディに行うことでユーザー獲得を目指すフェーズでは自由度を高めていました。その後、ユーザーが増え安定性を求められるようになってきた段階で、保守運用を見据えてレビューで細かく処理方式を指摘するようになった、ということがあります。 + +# 自律と統制のバランス。開発速度が最優先の場合 + +先程の象牙の塔の話のように、必ずしも、アーキチームは統制を強めたいわけではなく、状況によります。 + +例えば、新規事業のプロダクト開発を行う場合は、今目の前で市場(顧客)が求める機能を提供しないと、プロジェクトが即終了するとか、開発したものが来週には不要になることもザラという、痺れる状況もあります。 + +この様な場合は、開発速度が最優先のため、さきほどいった実装/設計パターンを絞るという方向にはならないでしょう。必ず守るべき、セキュリティやコンプライアンス対応のみしっかりチェックし、あとは腕利きの開発者のセンスに任せることが最適解になります。 + +ある案件ではメチャクチャ自由度高く任せてくれたアーキテクトが、別の案件ではめちゃくちゃ細かいところまで口出しするようになったというのは、プロジェクト特性の差がおそらく理由の大きな部分を占めます。 + +# 開発ガイドラインの功罪 + +導入の例(「ガイドラインには...確かに今、書いていないですね」)で触れられている、レビュワー側の「後出し」問題について言及します。基本的にガイドライン整備は後手に回ります。いや、最初から書いておけよってのは分かるのですが、そこまで工数を割けないこともありますし、その他の理由もあります。 + +- ガイドラインをしっかり書いても、どうせ読まれない問題 + - 一番読んで欲しい人ほど、読まないものです。費用対効果を考えるとここばかりに注力が難しい +- 書けば書くほど、読まれなくなる + - 量が多いと、必然的に読むのが難しくなりますし覚えきれません +- 最小限のルールセットで運用したい + - 記載量が多いと、メンテナンスも大変です + +緻密で厳格すぎると実効性がなくなるため、実際にレビューの場などで出てきた現場感が強い内容のみにガイドライン内容を記載したいという気持ちになります。 + +一方でルールに従う立場からすると、後出しジャンケン的になるのが難しいところです。もちろん、最初から重厚にガイドラインを書く場合もあります。例えば、プロジェクトの特性上、後出しジャンケンを繰り返すとチームの信頼関係が著しく悪化すると想定できる場合などは、初期コストをかけてでもルールを明文化することを選択します。 + +# 静的解析・AIレビュー + +開発ガイドラインは実効性が低いので、フォーマッターやリンターの整備は必須です。カスタムルールを適用するツールを開発することも多々あります。 + +AIレビューをそれなりの規模で実践導入した経験が私にはないのですが、開発ガイドラインに記載した内容は全てAIレビューでもチェックさせるべきでしょう。もし、精度が高いのであれば、さきほど書いたガイドラインにあまり書きすぎない方が良い、という前提は覆り、バンバン追加していきましょうに変化すると思います。 + +# どこから、いつから、統制を強めるのか + +基本的には、大規模になればなるほど、例外を許さず一貫性のある設計や実装を求めたくなります。各開発者の選択肢をできる限り減らし、設計の揺れを無くし均質化する戦略を指します。メンバー数が多いと、正しくない設計を選択される確率が高まるためです。また、誤った場合に手戻りを許容できる余地が無いことも多く、防御的にならざるを得ません(小規模であれば1人が2,3時間の修正で済んだとしても、20人いればかなりの工数です)。 +一方で、小規模・準委任・アジャイルなどの案件だとむしろ開発者の能力を最大限に引き出すアプローチを取ります。 + +具体的にどのあたりでこの感覚が変わるのか考えてみます。 + +### チーム規模 + +小規模なチーム(例: 5人程度)であれば、全員が顔見知りで、阿吽の呼吸で進められます。10-15名を超えてくると統制が必要だなと感じます。 + +ここで目安となるのが、人類学的な「**ダンバー数**」という概念があります。これは、人間が安定的な社会関係を維持できる人数の認知的な上限を示すものです。 + +- **〜15人:** お互いを知れるので、暗黙知で統制可能です。ルールは最小限でOK。業界的には、2ピザチーム(5〜10人程度)の方が通りは良いと思います +- **15〜50人:** それなりに専門家をアサインした統制が必要 +- **50〜150人:** 立ち話などでは情報が行き渡らなくなる。強いトップダウンのルールが不可欠 + +なんとなく、「規模」をX軸、「統制レベル」をY軸とすると、なだらかな直線ではなく、特定のダンバー数の閾値を超えるあたりでS字カーブ的に統制を強めるイメージがあります。 + +scurbe.drawio.png + +理由を何となく説明すると、以下の2点のバランスがあるためです。 + +1. 人が増えれば増えるほど、バラツキを補正するコストは指数関数的に増えるため、ルールを強めるメリットがある +2. ルールを維持するコストは、初期は作る方も守る方も、大変ですが一度作れば比較的安定する。開発量が少なければ学習コストが見合わない + +### 開発チームや引き継ぎ先の技術レベル + +小規模チームでも、ジュニアメンバーが多ければ統制は強めるべきと判断する場合があります。規模とスキルで無理やり4象限に分類してみます。 + +| | ジュニア中心 | 熟練メンバー多い | +| :--- | :--- | :--- | +| 小規模 | ② 指導・規範 | ①お任せ or 見守りモード | +| 大規模 | ④ 統制を強める | ③幻想(維持困難) | + +- ①それなりのシニアが揃った小さなメンバーで完結できるのあれば、基本ドキュメントを書いてもらうなどのルールを設けて、見守りモードに移行しましょう +- ②小規模でもジュニアが多い場合は、迷わず開発を進められるような、サンプルプログラムや開発ルールに投資します。特に新規参画者へのケア・運用・引き継ぎ・別案件へ移籍時に困らないか?という視点は所属メンバーが見落としがちです +- ③は存在しません。万が一、熟練者を揃えていても、大規模であればメンバー入れ替わりは必ず発生するためジュニア・ミドルの参画は必然です +- ④問答無用でベストを尽くすべき + +注意として、運用時(引き継ぎがあればその時の体制)は、一般的にピーク時より体制は薄くなります。その最も弱い状態を見据えての技術選定を意識する必要があります。 + +# シニアがやるべきこと + +アーキテクト視点では、アーキテクトロールが必要になる規模感の時点で、枯れた技術を採用しがちというジレンマがあります。社名に「フューチャー」が入っていることもあり、例えば10年経ったとしても色褪せない設計思想と、最新の技術で最高の価値を提供したいと思うものです。とはいえそれ以外にも、アーキテクトとして成長の楽しみの見出し方は様々です。 + +- プロジェクトライフサイクル全体で、継続的に開発が継続できるような、仕組み化を作ることに価値を見出す + - コード生成、静的解析などチェックの自動化 + - 採用技術、パッケージ構成と、開発方針、教育などの実施スキルを上げる +- 開発生産性の部分の技術セットを習得する + - CI/CDパイプラインをがんばる、Git開発フローを整備、開発ツールを作るなど + +施策の結果が出るのはしばらく時間がかかります。長期的な視点で、実施内容がどう効果を上げるか、施政者的な視点で観察できるのはとても楽しく、学びも別格だと思います。 + +もちろん、枯れた技術ばかりを入れようと推奨しているわけではありません。大規模になるほどリスクを潰し込める技術を採用したいというだけで、リスクを受け入れてでも利便性を享受したほうがトータルでメリットがあるプロジェクト規模や特性があれば、どんどんモダンな技術にチャレンジします。実績を詰めば大規模案件でも採用しやすくなります。大規模プロジェクトで導入され磨かれ洗練されたノウハウは、当然ながら小・中規模のプロジェクトにも還流するため、相互にメリットがあります。 + +# 判断基準を言語化する。理由を伝える + +レビュイーをモヤっとさせないために、特に棄却した場合は判断基準や理由を伝える必要があります。それを怠ると、レビュイーからは「象牙の塔からの押し付け」に思われてしまいます。まぁ普通に嫌われますよね。一般的なレビューという行為に共通する原則ですが、指摘とその理由(Why)をセットで伝えます。 + +- ❌️「このライブラリは使用しないでください」 +- ✅️「そのライブラリの採用は見送ってください。理由: 将来の脆弱性対応コストを考慮し、類似機能を持つ既存ライブラリAに統一する方針だからです」 + +この辺は、[コードレビューガイドライン](https://future-architect.github.io/arch-guidelines/documents/forCodeReview/code_review.html#%E3%83%AC%E3%83%92%E3%82%99%E3%83%A5%E3%82%A2%E3%83%BC%E3%81%AE%E6%8E%A8%E5%A5%A8%E8%A1%8C%E5%8B%95)に詳しく書いていますので、気になる方はぜひ。 + +また、ADR (Architecture Decision Records) で設計・開発上の重要な決定(「なぜこのDB機能を使わないのか」「なぜこのパターンに統一するのか」)は、ADRのような軽量なドキュメントに残していくと良いです。...と言いながら、実は私はADRを使ったことがなく、開発ガイドラインのようなドキュメントにまとめていくことが多いです。重要なのは、レビュー時に理由を説明するのと、詳細はこちらの開発ガイドラインの章(リンク)を参照ください」と伝えられる状況をできる限り多く作ることです。 + +導入の例のように「後出し」になってしまった場合は、まずそれを率直に謝罪します。その上で、「なぜ今このルールが必要になったか」の背景(例:チームが5人から15人に増えたから、ジュニアメンバーの参画が決まったから)を説明し、理解を求めることが重要です。 + +納得感は重要です。また、もちろん一貫した振る舞いも信頼関係の構築には不可欠です。信頼関係を欠いて良いものを作ることはできません。 + +# 統制する側にも視座がある + +ここまで、主にプロジェクト内での全体最適について話してきましたが、視座の高さも存在します。 + +1. プロジェクト視点 + - 所属するプロジェクトを円滑に推進することに注力する視点です + - 隣のプロジェクトではモダンな技術を使えるが、こっちがダメな理由も、速度優先のPoCや、安定性が重要な基幹系といった特性の違いで説明できます +2. 複数プロジェクト/部門視点 + - 同じ事業部などで、複数のプロジェクトが並行して動いている場合の視点です + - 部門内でノウハウを共有したり、メンバーの流動性を高めるため(いざという時にヘルプ的なアサインも可能にするよう)に、非差別化領域はなるべく標準パターンを寄せたいというインセンティブが働きます +3. 全社視点 + - 全社レベルで標準化することで、知見を集約しセキュリティやコンプライアンス要件を満たしやすくし、人材育成コストを最適化していきたいといった視点です + - 技術広報・採用広報といったことと連動し、ビジネス計画に沿った人材ポートフォリオも考えていく必要がでてきます + +私の感覚では、この「全社視点」または「部門視点」で特に揃えておきたいのが、Webアプリケーションフレームワークや、DBアクセスライブラリ系(ORマッパーなど)、ログライブラリなど利用頻度が高いライブラリ群は揃えておきたいと思います。ちょっとした実装の違いではあるのですが、各プロジェクトがバラバラであればレビュー時も混乱しますし、先述した脆弱性の横断対応など何かと不都合の方が大きいです。とは言え、この論法では技術の新陳代謝が働かなくなるので、プロジェクトの技術選定のたびに、「部分的」にその時点で最も良いと判断できるものを取り入れていくといった戦法を取ることが多いです。チャレンジ要素をどこまで盛り込むかは、これまで述べたプロジェクト特性やメンバースキルセットにも依存します。プロジェクト視点で「なぜこのライブラリや開発方針を採用するんだ?」と思っても答えが出ない場合は、こうした視座が違うということで説明できるかもしれません。 + +だれしもがプロジェクト最適の視点(保守運用や引き継ぎまで見据えたプロジェクトライフサイクル全体)で考えるところから始めます。アーキテクトとして成長してくると、複数プロジェクトの管理を任されることも多いでしょう。最終的には全社の技術方針について、関与・責任の一端を担うようになってきます。もちろん、視座を高く持てば持つほど現場との距離は乖離するため、あくまで現場に適用できるかは常に脳内で検証すべきです。そのため、全社レベルでの視点から、今このプロジェクトがどれくらい整合があるか、あるいは乖離しているかは常に念頭に置いておく必要があります。もし、こういった視点を欠いてプロジェクト最適な行動を取りすぎると、大きな仕事は任されにくくなってしまいます。アーキテクチャに個性は必要無く、妥当で良いのです。目新しい技術を目玉に掲げる必要は時としてありますが、それは自分のキャリアの彩りのためになってはなりません。 + +全社レベルの技術標準は、よほど社歴が長いメンバーを除き、腹落ちレベルの理解はしていないと思うべきです。少なくともドキュメント化しておきアクセスしやすい状況にしておくとよいでしょう。公式ではないですが、フューチャーでは社内有志で設計ガイドラインを作っていたりします。これもその1つの方法です。 + +- https://future-architect.github.io/arch-guidelines/ + +また、レビューで「モヤッと」する指摘を受けた時、その背景にはプロジェクト・部門・全社のどのレベルの最適化を目指した判断なのかを(タイ料理でも食べながら)聞いてみると、その統制の意図がより深く理解できるかもしれません。基本的にプロジェクト視点と全社視点は短期的には利益相反することが多いですが、長期的には分かりあえると思うので、双方心を開く方向で話し合うと良いと思います。 + +# まとめ + +アーキテクトの役割を持つと、短期的な「開発速度」と長期的な「引き継ぎコスト」というジレンマの中で、いい感じの最適解で統制・裁量のバランスを取ろうとします。パターンを減らして長期的なコストを減らすか、自由度を増やして開発速度を上げるかの調整ゲームです。スイートスポットは、チームの規模や技術力にも依存します。 + +何か新しい技術や実装方法を導入したい場合、全体を見通して(場合によっては既存を修正して、開発規約を修正して、稼働済みシステムであればリリースして)までして行うべきなのかという視点を持っておくと、話がスムーズに進むかもしれません。現場の現実を無くして規則を正しく作ることはできませんが、全体最適の視点を無くして個別の話はできないため、両者の立場を尊重しつつ、建設的な議論をしていければと思います。 diff --git a/source/images/2025/20251107a/scurbe.drawio.png b/source/images/2025/20251107a/scurbe.drawio.png new file mode 100644 index 00000000000..9430a2d0b68 Binary files /dev/null and b/source/images/2025/20251107a/scurbe.drawio.png differ diff --git a/source/images/2025/20251107a/thumbnail.jpg b/source/images/2025/20251107a/thumbnail.jpg new file mode 100644 index 00000000000..1bf8ce98396 Binary files /dev/null and b/source/images/2025/20251107a/thumbnail.jpg differ diff --git a/source/images/2025/20251107a/unnamed.jpg b/source/images/2025/20251107a/unnamed.jpg new file mode 100644 index 00000000000..b6ef312e1dd Binary files /dev/null and b/source/images/2025/20251107a/unnamed.jpg differ