· 9分で読了

僕が開発チームの効率を改善した方法

この記事は中国語から自動翻訳されたものです。翻訳によりニュアンスが失われている場合があります。

ここ数ヶ月はちょうど大型機能のリリース時期だった。次のプロジェクトに移るまではそれほど大きな開発はなく、主に細かなバグ修正や既存機能の改善を行っていた。開発スケジュールがそこまで過密ではなかったこともあり、今期はプロセスの改善により多くの時間を割くことができた。

背景

まずは開発時に直面していた状況について話そう。チームや組織によって置かれている状況は異なるため、背景と解決したい課題を理解することは極めて重要だ。今回の開発で明らかに問題となっていた状況がいくつかある。

組織内で関わる人員が多い

僕が現在携わっているのは金融関連の開発で、現時点でもFX(外国為替)、株式、投資信託などのプロダクトがある。比較的大規模な機能は切り離して個別に処理されるものの(例えばFXは別途アプリを開発するなど)、大半の機能は同一のWebサイト配下に実装され、各プロジェクトを担当する開発チームによって処理されている。これによって以下の問題が生じていた。

  • 共通モジュールに手を入れるたびに複数のチームを巻き込む必要があり、認知負荷が高い。コードを変更したことで壊れるのを恐れ、問題と真正面から向き合うのではなくワークアラウンド(対症療法)に偏りがちになる。
  • 複数のプロジェクトが並行開発される際にコンフリクトが発生しやすい。例えば、プロジェクトAでデスクトップ版を実装したが、同時に進めているプロジェクトBではまだ対応していないような場合、2つのプロジェクトをマージする際にコンフリクトが起きやすい。

チームですべてのリソースをコントロールできない

例えば、僕たちがQAを行う際はすべてのプロジェクトのスケジュールに合わせる必要があるが、QAのリソースには限りがあるため、機能自体はずっと前に完成しているのに、QAを受けるために1〜2ヶ月待たなければならないという状況が発生することがある。このコストは非常に大きい。

  • 開発者は1〜2ヶ月も経つと実装の詳細をとっくに忘れており、思い出すのに時間がかかる。
  • QAから指摘を受けて修正する頃には、イテレーション全体のサイクルが非常に長くなってしまう。
  • 一部のAPIや実装は他チームの修正を待つ必要があり、相手のスケジュールをコントロールできないため、結果としてチームの開発進捗がブロックされてしまう。

QA環境が煩雑

理想を言えば、QA環境は1つだけであるべきだ。

しかし、プロジェクトの並行開発、テスト環境の不足、テスト環境の追加コストの高さ(アーキテクチャの制約)といった状況下では、QAが2つの環境で同時に行われる可能性が十分にある。テスト環境が足りない状況では、開発とQAが同一の環境を共有することもあり、これがいくつかの問題を引き起こしていた。

  • QAで問題が発生した際、それが本当のバグなのか、それとも開発側が新機能をテストしている最中なのかが判断できない。
  • QA環境の不足によるコミュニケーションコストが非常に大きい。チーム規模が大きいため、連絡を取るべきチャンネルも非常に多い。
  • テストアカウントの準備プロセスが煩雑なため、各環境に不完全で使えないアカウントが散乱している。

不完全なスプリント

現在チームはスクラムを採用して開発を進めているが、前のプロジェクトを離れて以来、スクラムがかなりスムーズにいかなくなっていることに気づいた。推測される原因は以下の通りだ。

  • チーム内の一部のエンジニアが異なるプロジェクトを掛け持ちしており、スプリントゴールが形骸化している。
  • アサインできるQAリソースがなく、テストが進められない。
  • 進捗管理が徹底されておらず、優先度がAなのに同僚がBのタスクを進めているといった事態が頻繁に起こる。
  • 明確な目標とイテレーションが存在しない。

以上の状況から見ると、おそらくチーム自体が理想的なスプリントに必要な条件を満たしていなかったのだろう。多くのリソースが他の場所に制約されている状況では、スプリントが必ずしも最適な選択肢ではないのかもしれない。

改善プロセス

大半の問題は開発側だけで完結できるものではないが、開発環境に関してはある程度の対処ができると考えた。

改善を進めるにあたっては、まず動機と達成したい目的を考える必要がある。そこで第一歩として、現在直面している問題と実行可能な解決策をまとめたドキュメントを準備した。

主な目的は以下の通りだ。

  • 開発チームが異なるブランチのコードを自由に切り替えられるようにすること。これは非常に重要で、僕たちの開発チームは担当するプロジェクトが異なり、同時に複数のプロジェクトが進行するため、「ちょっと環境を貸して、テストが終わったら返すから」といった事態が時に発生していた。
  • QAと開発チームが同じ環境を共有しないようにすること。これにより、問題が発生した際に原因が特定できなくなる状況を防ぐことができる。

このドキュメントを作成した上で、チーム内でのディスカッションを始めた。この議論には主にいくつかの目的があった。

  • 全員が同様の問題意識を持っているかを確認し、お互いが想定している状況が一致しているかを擦り合わせること。
  • 同僚たちそれぞれが持つ異なる懸念点を確認すること。これらの懸念点は、その後の改善がスムーズに進むかどうかの鍵を握る。
  • 知恵を出し合うこと。僕の考えに欠陥があるかもしれず、お互いのアイデアを集約することでより良い解決策が見つかるかもしれない。

今回は実装そのものよりも改善のプロセス全体に焦点を当てたいが、ここでも僕のアプローチを簡単に説明しておこう。

  • フロントエンドはSPAで動いているため、ビルドしたJavaScriptをうまくアップロードできさえすれば、異なるブランチのコードを自由に切り替えることができる。そうすれば開発がQAと環境を共有する必要がなくなり、異なる開発チームも自由に環境を切り替えられるようになる。
  • クエリパラメータによって異なる環境を切り替えるアプローチ。ただし、クエリパラメータを保持し続けるのも面倒であり、特にアプリ内にはリダイレクト処理(決済完了後のリダイレクトなど)が存在する。
  • Deploy Preview(Netlifyなど)のような機能を実装し、PRを作成するたびに開発チームがURLをクリックしてデモを確認できるようにする。

検討を重ねた結果、これらの手法にはいくつか問題があることが分かった。

  • デプロイ時、フロントエンドには簡易的な認証サーバー兼便利なAPIを提供するサーバーとしてNode.jsサーバーも別途実装されている。そのため純粋なフロントエンドだけではなく、ファイルアップロードのアプローチは誤解を招きやすく、変更すべきコードベースも大きくなるため反発を生みやすい。
  • Deploy Previewには動的DNSのサポートが必要になることが多いが、社内ではプライベートクラウドを使用しており、それを実現できるAPIがあるか不明だった。また、ログイン機能などはSSOのために他ページへリダイレクトされるが、実装上でドメインの制限があり、Deploy Previewで生成されたドメイン名が拒否されてログインに失敗してしまう。ログインが不要な機能であれば確かに機能するが、費用対効果が悪く中途半端だった。

そんな中、別のエンジニアも同様の問題意識を感じており、今回の改善プロセスに自発的に加わってくれた(最初は孤軍奮闘することになると思っていた)。そして一緒に問題を整理し始めた。まず僕が彼にDeploy Previewの概念を説明したところ、理解してくれた上で既存の案に対して新しいアイデアを出してくれた。

「DNSを動的に調整するコストが高いなら、nginxでルーティングするのはどうだろう?」

つまり、現在のデプロイ方法に従ってマシンを新たに1台立ち上げ(社内プライベートクラウドで数クリックするだけで可能)、既存のマシン内のnginxにリダイレクトのロジックを追加するというものだ。

特定のCookie値が含まれていれば開発用のマシンにルーティングし、含まれていなければ従来通りにする。これなら既存のコードベースには1行も手を加える必要がなく(せいぜいJenkinsスクリプトとAnsibleスクリプトを少し修正する程度)、既存のデプロイフローも再利用できるため、開発コストを大幅に削減できる。

こうして方針を決定した後、他のチームにも意見を聞いてみたところ、基本的に全員が前向きで肯定的な姿勢を示してくれ、最終的にSREチームに確認しても問題ないとのことだった。こうして実装は無事に一段落した。

改善後

正直なところ、机上の空論やドキュメントだけでは実感が湧きにくく、デモを見たとしても同様だ。実際に使ってみて初めてその価値を実感できるものだ。みんなが新しい環境切り替えの仕組みを使い始めると大好評で、プロセスを本当に改善できたと実感した。

振り返り

この改善プロセスにはトータルで3ヶ月強ほどかかった。関わるチームが多かったこともあり、それなりに時間がかかった形だ。最初は焦ってはいけない。焦るとチームの理解を得られなくなってしまう。今回のプロセスを通じて、僕も多くのことを学んだ。

1. まずドキュメントを書く

ドキュメントを書くことは、チームの合意形成における第一歩だ。ドキュメントを書く際は、実装方法に過度に焦点を当てるのではなく、どのように問題を解決するのか、どのような解決策が考えられるのかに注力し、チーム内でより良いアイデアを引き出せるようにすることが重要だ。こうすることには、この取り組みが自分一人のものではなく、チーム全体で議論して決めたものだと感じてもらえるというメリットもある。

2. 個人ではなく全体を起点にする

今回の改善が高い評価を得られた理由の一つは、これが僕個人のためだけでなく、チーム内の多くの人が同様のペインを抱えていたからだ。改善を行うときは、「この方が書きやすいから」「この技術に慣れているから」といった個人的な理由を出発点にしてはならない。その改善が本当に全体に利益をもたらすかどうかを考えるべきだ。そうして初めて周囲に納得してもらえ、味方になってくれる人が現れる。

3. 技術に過度に執着しない

正直に言って、今回の取り組みでは技術的に高度なことは何も使っておらず、単に条件分岐を1つ加えただけだ。しかし、全体にもたらした効果は非常に高かった。多くのエンジニアは技術そのものに執着しがちだが、解決すべき問題を見失ってしまうことが少なくない。技術は本来、人間の役に立つための手段であり、その事実を見落としてしまえば、技術自体の意味も失われてしまう。

4. 他のチームを恐れない

他チームの協力を仰ぐ改善は、心理的ハードルが高くなりがちだ。面倒なことに関わりたくない、自分の担当業務だけをこなしていればいいと考える人も多いからだ。しかし、問題を正確に説明し、相手のペインポイントを突いた解決策を提示できれば、多くの場合は味方になってくれる。相手の懸念事項が一見すると邪魔立てのように聞こえることもあるかもしれないが、過剰に勘ぐる必要はない。

5. 志を同じくする仲間を見つける

この取り組みが成功した大きな要因の一つは、当時この問題に関心を持ってくれたもう一人のエンジニアがいたことだと思う。彼がたまたまバックエンドエンジニアでアーキテクチャ面に詳しかったからこそ、後のnginxによる解決策が生まれた。ただ、志を同じくする仲間は求めようとして簡単に見つかるものではない。出会えたときは大切にするべきだ。

関連記事

他のトピックを探索