メリークリスマス!ChatWork Advent Calendarもついにラストとなりました。 本日の記事はChatWork CTOの山本が担当です。
ChatWorkでは約3年半前に、PHPの独自フレームワークでつくられた大規模システムを、Scalaを使ってゼロベースでつくりなおすという決断をしました。
当時の記事:チャットワークの新しい開発言語とフレームワークを決める開発合宿を開催!その全貌を丸公開します。
その決断をした時に在籍していたScalaエンジニアは0人。まずブログで宣言してからスタートするという、なんとも無謀なプロジェクト進行ではあったのですが、当時の自分たちとしてはマジメも大マジメ、ここでなんとかしないとサービスが将来的に死ぬと背水の陣で挑んだプロジェクトでした。
あれから3年半。途中で大きく開発が頓挫しチームが絶望に包まれた時もありましたが、どうにかこうにか立て直しに成功し、昨年度末に基幹となるシステムをリリース。今年にかけて中規模なサブシステムが2つほどScalaで新規に稼働するなど、まだまだPHPの部分が大きく残っているものの順調に切り替えが進んでいます。
ちょくちょく他社のCTOやエンジニアさんからアーキテクチャ刷新に関するアドバイスを求められることも増えており、一旦区切りとしても良いタイミングなので、このブログ記事でCTOとしての目線で振り返りと考え方をまとめてみたいと思います。
僕らの事例はキレイに成功したわけでもなく、またあくまで一例には過ぎないのですが、あまりここまで大規模なアーキテクチャ刷新の事例は少ないとも思いますので、少しでも参考になれば幸いです。
アーキテクチャ刷新を考える時
みなさんが開発しているサービスでは技術的負債はありますか?
全然ないよ!という人はほとんどいないと思いますが、技術的負債が少なすぎるのはそれはそれで問題で、サービス成長に必要なスピードを犠牲にしているということになります。秀吉の一夜城をイメージしてもらえばわかりやすいと思いますが、まずは必須となる機能を最速でつくりあげ、走りながら品質を上げていかなければ、この競合がどんどこファイナンスしてブーストかけて迫ってくるスタートアップ時代で生き残っていけません。
というわけで技術的負債とは適度なお付き合いをするのが健全ではあるのですが、しばらくするとあーもうムリ!となってしまうタイミングがやってきます。それが、「アーキテクチャの限界」というやつです。
一夜城ではとりあえず目の前の一戦をやらかすのにはベストなのですが、じゃあその戦いに勝って平定したあと周囲からの侵略に長期的に備えたり、各種統治を行うのに最適というわけではないですよね。ロクな基礎工事もできてないでしょうから、当然拡張には限界があります。
Webサービスの会社のCTOを十数年やってきた経験上ですが、大体3年ぐらい、開発チームが1サービスで15〜20人を越えてきたぐらいのタイミングで限界を感じはじめることが多いように思います。3年たつと当時採用した最新のミドルウェアは軒並み見劣りするようになりますし、データベースのスキーマも場当たり的なALTERが積み重なってイビツになり、コードベースも現在のサービス規模に見合った品質になっていないところが目立つようになります。
その頃には現場エンジニアのヘイトがMAXになりつつあり、特に後から開発にジョインしたメンバーから「なんだこのクソコードは!」と突き上げを食らいまくって初期メンバーが肩身の狭い思いをすることになります(つらい)
まあ、おっしゃる通りなんですが、じゃあ一夜城じゃなく本格的な城をのんびり建ててたら一戦目で勝ててるはずもなく、そもそも自分たちの給料を稼いでるのは現行コードなわけです。このあたり、「レガシーコードは叩くのが正義」というのがなんとなくエンジニアカルチャーとしてあるのが原因だとは思うのですが、同じチーム内でマサカリ投げつけたところで萎縮や反発を生むだけで何もプラスはなく、「レガシーコードは"敬意を持って"叩く」というスタンスが良いかと思います(笑)
アーキテクチャ刷新を決断する時
さて、アーキテクチャの限界は見えてきた。じゃあこれからどうする?ということですが、「言語レベルで書き直す」「フレームワークレベルで組み替える」「マイクロサービスに切り出していく」「リファクタリングめっちゃがんばる」など濃淡あわせてたくさんの選択肢があります。
ここをどうするかにはっきりとした正解はなく、どちらかというと技術的なPros/Consの比較というよりも経営的にどう判断するかということが重要になってきます。
どの選択を取るにせよ最低半年以上は新規開発をストップすることになるでしょうし、それをビジネス的に許容できるプロダクトの先行優位の大きさ、資金的な体力、開発体制があるかが問われることになります。ここはCTO(に相当する技術トップ)が経営の意思を示していく必要があります。
ChatWorkの場合は、大きく2つの経営課題への解決策としてアーキテクチャの刷新を決断しました。「多発するサービス障害の抜本的解決」と「開発プロジェクトの慢性的な遅れの解決」です。
このあたり、ある程度定量的なファクトは当然揃えつつも、最後はもはやロジックではなく経営の意思なので、わかりやすく状況を説明しつつも、責任は自分がとるからやらせてくれ!と言うしかないかもしれません。(自分がビジネス側の役員だったら、詳しく説明されてもなかなか納得はできないものだと自分でも思います)
幸い、自分の場合はChatWorkを企画して立ち上げた本人ということと、当時はChatWork全体の事業長も担当していたので、ビジネスを理解しての提案だと理解してもらいやすかったようにも思います。 (CTOが事業責任を負うのは良し悪しだと思いますが)
※このあたりにご興味あればこちらを参考に:サービスをつくりなおす決断をするとき
アーキテクチャ刷新を成し遂げるために必要なこと
決断したのなら、あとは実行のフェーズ。やりきるしかありません。
3年半の中で、たくさんの失敗や挫折を繰り返してはきたのですが、まがりなりにもなんとか先が見えてきたいまだから思うに、必要な要素は以下の3つなんじゃないかと思っています。
- 目指すアーキテクチャを実際つくれるエンジニアを揃えること
- 大規模プロジェクトを回せるプロジェクトマネージャーをたてること
- あきらめない心
それぞれ、説明していきます。
1. 目指すアーキテクチャを実際つくれるエンジニアを揃えること
まあ、当たり前の話ではあるんですが、一戸建てばかりを専門につくってきた建築会社が、いきなり高層ビルを建てられるはずがありませんよねという話です。社内を見渡して、高層ビルを建てたことがあるエンジニアが1人もいないのであれば、外から採用してくるしかありません。
ChatWorkの場合はもともと技術的にトガった会社は志向しておらず、どちらかというと企画、マーケティング、開発のバランスで複数の事業ポートフォリオを回して勝負する会社だったので、この規模のアーキテクチャ刷新をやれる(やったことがある)メンバーはいませんでした。
外から採用するにしてもそんなに都合よく入社してくれそうな知り合いがいるわけでもなく、人材紹介会社を使うにしてもそのクラスのエンジニアはほぼほぼ紹介会社を使いません。そこでとった採用戦略は、「課題感の大きさで勝負する」ということでした。平たくいうと「ほんと困ってるんで助けてください!」と大声で叫ぶという事です(笑)
その最初が冒頭の技術合宿のブログでもあるのですが、その後も引き続き自分が率先して記事を書いたり、他社さんとコラボして勉強会をしたり、登壇するなりして積極的に認知をとれるよう努力しました。このあたりのアクションで「ChatWorkがScalaやるんだ」みたいな話を目にした方も多いのではないでしょうか。Scalaというエッジがたった人が好む言語を採用したのは、技術的な理由はもちろん採用の観点も大きくありました。
そんなブログを見て、なんの接点もなかったChatWork社にScalaとDDDの第一人者であるかとじゅん(@j5ik2o)さんがエントリーし、テックリードとして早々に入社してくれたのは幸運だったとしか言いようがありません。かとじゅんさんが入社したことをきっかけに、Scalaをはじめとした技術コミュニティでも知られるようになり、続々と強力なエンジニアが入社してくれるようになりました。
2. 大規模プロジェクトを回せるプロジェクトマネージャーをたてること
これに気づかず、大きな失敗をしてしまいました。
前述の通り、幸いにして強力なエンジニアチームを揃えることはできました。これだけ凄いエンジニアが揃ってれば、多少プロジェクトの遅れはあるにせよ成功したようなもんでしょと、甘く見てしまっていた部分が正直ありました。
結果起きたのは、度重なるプロジェクトの遅延。アジャイルでSCRUMっぽく開発を進めていたのですが、当初のリリース期日が来ても全然完成が見えない。2ヶ月伸ばして開発を延長し、2ヶ月たつとまた2ヶ月延長される。それを延々と繰り返してしまっていました。さすがに見過ごせない状況となり、ウォーターフォールに切り替えて、絶対にここで出すぞという期日を決めてスコープをギリギリまで絞り込みながら必死の進行で実装を完了させました。
やっと終わったか、、、とほっとしながらリリース作業を見守っていましたが、結果は惨憺たるものでした。ロジックとして動作はするものの、パフォーマンスが十分出ず、なんとかするには抜本的な改修や莫大なインフラコストがかかるということが、リリースのタイミングで発覚しました。いままで膨大な時間をかけて実装してきたコードがほぼ無駄になるとわかり、目の前が真っ暗になったことをいまでも鮮明に覚えています。
転機となったのは、そのタイミングで開発本部長として入社してくれた春日さんでした。入社早々いきなり鉄火場につっこまれることになり本当に申し訳なかったのですが、彼と一緒に必死になってどう立て直すかを議論していきました。
振り返って思うことは、アーキテクチャ刷新のプロジェクトは SoE (System of Engagement) よりも SoR (System of Record) な性格が強いプロジェクトだったんだなと思っています。(※参考 https://furien.jp/columns/156/ )
利用者の満足度を重要視するSoEでは、新規サービスの立ち上げや試行しながらUXを改善するといういわゆるWebサービス企業の開発スタイルが向いています。一方、SoRはシステムの安定性や信頼性を重要視するシステムで、要件をカッチリ固めて納期と品質が絶対なSI案件に近いスタイルが向いています。
チャットワーク自身はコミュニケーションサービスという典型的なSoEシステムではあるのですが、「アーキテクチャ刷新のプロジェクト」は決まっている既存機能や仕様を満たすシステムをつくるという、要件がカッチリ決まっており、かつ同じ動作をすることという信頼性が強く求められるSoRにとても近いプロジェクトなのだったと。つまり、いわゆるWeb系企業の開発スタイルではなく、SIerの開発スタイルで進めるのが正解のプロジェクトだったのではないかと思っています。
元大手SIer出身でWeb系企業の文脈もわかる春日さんがプロジェクトに大鉈を入れた仕切り直しを行ってくれ、スコープを切り直し、中間にしっかりとPoC (Proof of Concept)のフェーズを入れて技術的検証を行いながら進め、NTTデータさんにコンサルティングを依頼し技術協力を仰ぐなど、プロジェクトリスクをしっかりとコントロールしながらのプロジェクト管理ができるようになりました。
結果としてはただScalaの導入というだけではなく、Akkaで分散コンピューティングさせながらCQRS構成でKafkaとHBaseを使い分け、Kubernetesで大量のコンテナを管理するという超難度の案件となりましたが(いずれの技術も社内での運用実績はゼロ)、無事カットオーバーさせ安定した運用に乗せることができています。(※技術面の詳細を知りたい方はこちらを:ChatWork の新メッセージングシステムを支える技術)
この観点、Web系どっぷりな会社がクラウドベンダのマネージドサービスに乗っかって順調に成長し、スケールの限界に来たところでイキナリ熟練SIerじゃないとやれないような課題に直面して痛い目にあうというのは非常にハマりやすい落とし穴だと思うので、急成長しているサービスを運営している場合や、アーキテクチャ刷新を検討する際に意識するとよいのではと思います。
3. あきらめない心
これ、簡単なことではないです。
結果論としては、強力なエンジニアチームとプロジェクトマネージャーがいてなんとかなったんでしょ、という話に見えなくもないですが、実際はいつメンバーの心が折れてチームが総崩れになってもおかしくないようなシーンも何度かありました。
その中で、ひとつとても印象深い話があるのでご紹介しておきます。
今回のメインプロジェクトの開発コードは「Falcon」というのですが、その由来は下記のかとじゅんさんの発言でした。
探査機はやぶさかー、なんか難航したプロジェクトだったはずだから不安だなーと聞いた時は思っていたんですが、まさにその予感は的中することとなりました (苦笑)
プロジェクトが一番どん底だった、リリースに失敗しこれからどうしようと途方にくれていた後の全社での合宿で、全社員に向けて下記のようなプレゼンをしました。
“いま、Falconは故障して地球に帰ってこれない状態になってる。みんなでFalconを地球に帰還させよう。”
それがみんなの合言葉になったから、長い長いトンネルを走り続けられたのかもしれません。プロジェクトにストーリーがある、ということも困難なプロジェクトでは大事なことなんだと思います。
プロジェクトのカットオーバー後、全社員に向けてこんなプレゼンをしました。
本当に、みんな頑張ってくれました・・・!!
最後に
もうちょっとスマートにやれなかったのかと反省することはたくさんありますが、大きな失敗をしたからこそ学んだことや得たこともいっぱいあります。これからチームみんなで取り返していけるように走り続けていきたいと思います。
ChatWorkのScala化大丈夫なの?と心配いただいていたみなさま、ご心配おかけしました。大きな機能追加ができない、ご要望にお応えしきれないジリジリとした日々が長く続いてしまいましたが、今年はお待たせしていたAPIのOAuth対応やWebhookもリリースされ(バックエンドはScalaです)、どんどんとChatWorkならではの進化をしていきますのでご期待いただければと思います!
それでは良いクリスマス&年末を!
// お約束ですが・・ ChatWorkではアーキテクチャ刷新を一緒にチャレンジしてくれるエンジニアを積極募集中です!
※社内プレゼンでの探査機はやぶさの写真については、下記の記事より引用させていただきました。ありがとうございます。
http://monoist.atmarkit.co.jp/mn/articles/1205/14/news004.html
https://news.mynavi.jp/photo/article/20150204-hayabusa2/images/004l.jpg