はじめに
こんにちは。メルカリでエンジニアリングマネージャを担当しておりますkentanです。
メルカリのCustomer Reliability Engineeringチームでは、違反出品物などを機械学習やルールなどを用いて検出するためのModeration Systemと呼ばれるシステムを開発しています。Moderation Systemは、メルカリのmarket placeとシステム的に接続しつつ、違反を取り締まる業務を行うCustomer Support向けのWeb UIを備えているという特徴があります。フロントエンド、Backend、機械学習の技術要素を含んでおり、機能の複雑性も大きくなっております。
メルカリでは、歴史的にバックエンドエンジニアのチーム、フロントエンジニアのチーム、機械学習エンジニアのチームと職能ごとにチームを分けておりました。そのため、Moderation Systemの開発開始時点では、複数の職能チームでプロジェクトチームを構成し、連携して開発を行う必要がありました。
開始時点では、既存の4チームがModeration Systemの開発に参画することになりました。これは、それぞれのチームが担当している技術分野が、Moderation Systemに不可欠であったためです。
- Backend Aチーム
- Backend Bチーム
- 機械学習 Aチーム
- 機械学習 Bチーム
プロジェクト発足当初から、4チームが関わることによるコミュニケーションの難しさは容易に想像できました。そのため、プロジェクトの参画メンバがきちんと同じゴールを向けるように、チームを横断したマイルストーンを作成したり、チーム間コミュニケーションのフォーマットを整えたりしました。これらはとても効果的に機能したのですが、やはり本質的に開発している機能の大きさに対し関わるチームの数が多いという問題を無視できなくなってきました。また、メンバの離職などにより、1チームあたりのエンジニアも少なくなり、チーム構成の見直し自体も必要とされる状況でした。
また、メンバの異動や離職により、3チームすべてのProduct Ownerを一人のプロダクトマネージャ(PdM)が担当することになりました。一人のPdMが3チーム分のスクラムイベントに参加していたため、負荷の低減が必要とされていました。
チーム構成とマイクロサービスのオーナーシップ
問題の解決にあたっては、チーム構成の見直しと同時に、既存のチーム体制のままマイクロサービスのオーナーシップを見直す、というアプローチも検討しました。4チームがそのまま存続したとしても、Moderation Systemの開発に関わるマイクロサービスを3チーム、あるいは2チームに集約することによって問題が解決・軽減できると期待されたからです。
議論の結果、ひとまずオーナーシップの移管よりもチーム構成の見直しを先に行うことにしました。理由は主に2つありました。
- それぞれのチームが少人数であるため、これ以上マイクロサービスの開発を担当できない。
- 職能ごとに別れたチームであるために、スキルセットの違うチームのマイクロサービスを引き受けられない。(Backendチームが機械学習のチームのマイクロサービスを引き受けることはできない)
そのため、マイクロサービスのオーナーシップの整理はひとまず手を付けずに、チーム構成を見直すことにしました。
チームの構成の見直し
チーム構成の見直しは、まず単純に組み直しの効果が一番大きそうなところを手を付けることにしました。その結果、Backend Aチームと機械学習Aチームを一つにまとめることになりました。チーム選定の理由は概ね次のようなものになります。
- Backend Aチームは違反出品の検知に関するルールの登録・変更・適用などの機能を担当している。一方、機械学習 Bチームは違反出品物を特定するMLモデルの開発・運用を行っている。エンジニアリングの専門性に違いはあるが、ビジネスドメインとしては極めて近い分野を担当しており、チームの統合によるシナジー効果がとても大きいと期待される
- 機械学習 AチームのエンジニアがBackend領域に専門性を広げることに興味を持っていた。ソフトウェア開発は人材の能力・意欲がほぼ全てと言えるので、モチベーションを持っているのは効果的に働くと期待できる
- Backend Aチームと機械学習 AチームはPdMが同一人物であり、PdM業務観点でも統合の効果が高いことが期待される
どうやってチーム統合をすすめたのか
Phase 0. メンバのモチベーションの確認
統合にあたって、それぞれのメンバに意図を説明し、意向を伺ったところ、どのメンバも新しい領域にチャレンジできると言うことで、意欲的でした。機械学習エンジニアからすると、Backendの領域に専門性を広げられ、またBackendのエンジニアも機械学習に専門性を広げられます。
チームの統合はPhaseを4つに区切って行いました。
Phase 1. ドメイン知識の習得 EM編
統合されたチームのEngineering ManagerはBackend AチームのEMであった私が担当することになりました。私自身は、Backendを中心としたフルスタックエンジニアとしての経験しかなく、機械学習周りに関する業務経験は全くない状態でした。また、機械学習 Aチームの開発に関するドメイン知識もありませんでした。そのため、ここの知識の獲得が最優先でありました。
Goal
- EMが機械学習Aチームのプロジェクトを理解する.
- EMが機械学習Aチームの開発プロセス・スクラムプラクティスを理解する
- EMが機械学習Aチームのメンバのパーソナリティ、skill set、強み・弱み、モチベーションやキャリアプランなどを理解する
- EMがメンバと会話ができるように、機械学習の基礎を習得する。
Non-Goal
- メンバに関するゴールは設定しない
やったこと
- Sprint planningやRetrospectiveなどのスクラムイベントに参加した。
- MLエンジニアが所属するDivisionのEMミーティングに参加した。
- 過去のDesign docやPull Requestを読んだ。
- 過去1年くらいのSlackの会話を追いかけて、議論していたことの概要を掴んだ。
- 機械学習Aチームのオンボーディングドキュメントを読んだ。不足していたり、古くなっていたりしたので、必要に応じて作成・更新した。
- 機械学習Aチームが開発しているプロジェクトでPull Requestを作成した
- MLのモデルを新規作成・向上させるときに行ったExperimentに関するレポートを読んだ
- メンバとの1on1を通して、信頼関係の構築に努めた。
- その他、書籍やオンラインコースなどで機械学習の知識を習得した。
Phase 2. ドメイン知識の習得 メンバ編
続いて、それぞれのチームのメンバがドメイン知識を習得しました。
Goal
- Backendエンジニアが機械学習Aチームのプロジェクトを理解する
- Backendエンジニアが機械学習Aチームの開発プロセス・スクラムプラクティスを理解する。また、そこで使われている言語であるPythonを習得する。
- 機械学習エンジニアがBackendAチームのプロジェクトを理解する
- 機械学習エンジニアがBackendAチームの開発プロセス・スクラムプラクティスを理解する。また、そこで使われている言語であるGoを習得する。
Non-Goal
- 開発への貢献はゴールとしない。(知識の習得に集中してよい)
やったこと
- Slackにオープンチャネルを作って、機械学習・Backendに関する質問や勉強などを行えるようにした。
- 2チームで共同の勉強会を開いて、ドメイン知識を教授しあった。
- 機械学習チームのTech LeadがBackendチームのスクラムスプリントに参加して開発を行った。
Phase 3 スクラムの一本化
メンバがそれぞれのドメイン知識を得た後、スクラムプロセスを一本化することにしました。Sprint RefinementやPlanningを一つにするので、本格的に一つの開発チームらしくなっていきます。
Goal
- 2チームで別々に回していたスクラムプロセスを一つにする
- BackendエンジニアがMLプロジェクトの開発を行う
- 機械学習エンジニアがBackendのプロジェクトの開発を行う
Non-Goal
Backendエンジニアによる機械学習モデルの作成・向上
やったこと
- EMがScrum Masterとして、一本化したスクラムチームのスクラム運営をリードした。同時にメンバにScrum Masterのロールを引き継げるように、スクラムプロセスを定義していった。
- JIRAの開発チケットの背景を理解するための、勉強会を開催した。JIRAの開発チケットはどうしてもHigh Contextであるため、新しく入った人がそれ自体をみて全容を理解することが難しいです。それを補うために、その開発チケットの詳細や、なぜその開発が必要なのか、そしてその背景にある開発のビジネス的理由などの理解に努めた。
Phase 4 オンコールの一本化
そして最後にオンコールを一つにしました。メンバとしてはオンコールの担当の頻度が半分になるので、負担が劇的に減ります。また、オンコールに伴う手当などもだいたい半分になるので、会社としても開発費の効率の向上に繋がります。
Goal
- Backendメンバが機械学習チームのプロジェクトに対してオンコールを取れる
- 機械学習メンバがBackendチームのプロジェクトに対してオンコールを取れる
Non-Goal
- なし(Phase4が最後のphaseのため)
やったこと
- TLを中心に、全メンバが安心してオンコールを取れるために何が必要か議論を行った。そしてそのためにしなければいけないことについて議論を行い、Strategy documentを作成した。
- インシデントの発生を想定した予行練習を行った
- それぞれのマイクロサービスについてOncallのhandbookを作成した
今後の展望
新しく組成したFeature チームにてFrontendの開発を開始しています。Customer Supportの業務はとても複雑な機能群からなり、UIもリッチなものになっております。Moderation System開発に占めるFrontendの割合も大きく、必要な開発をすべてチームで行うというFeatureチームのコンセプトに照らし合わせるとぜひとも達成したいゴールです。
また、本格的にフロントエンド開発を行うためには、やはり、フロントエンドに強いエンジニアが必要となります。こちらは採用と平行して進めております。興味のある方はぜひご連絡ください。
終わりに
Backendエンジニアと機械学習エンジニアというスキルセットの全く異なる2つのチームを1チームにするのは、やはり簡単ではありませんでした。そのような中で、無事統合が成功できたのは、チームメンバが主体性を持って統合の実現に動いてくれたのが、一番の成功の理由であったように思えます。 Phase 4のオンコールの一本化に関しては具体的なプランニングから実行までテックリードが中心となって、ほぼEMの私の介入なく完了することができました。
また、一般的にはアンチパターンに分類されることもありますが、EMがスクラムマスターのロールを担ったことも効果的であったように思えます。日々のStandup meetingの進行の仕方やTicketの書き方など、乱暴に言ってしまえば、どちらの流儀でも大差が無いようなものに関しては、EMが意思決定をしていくのが一番波風が立たないやり方でありました。一旦、決めてしまって、運用を開始した後、スクラム開発を続ける上で実態に合わなくなってきたものは、その都度、Sprint retrospectiveで改善を議論しています。
課題としては、私を含めたBackendのバックグラウンドを持つエンジニアが機械学習の専門知識を完全には習得できておらず、機械学習のモデルを作成できる状態になっていないという点があります。現状は、機械学習プロジェクトのシステム部分・アプリケーション部分の開発を担当していますが、機械学習のモデルを作成できるようになるためにはさらなる仕掛けが必要でしょう。