ZOZOTOWNのアーキテクティングで大切にしている4つのこと


株式会社ZOZOでアーキテクトをしている @OkaHiromasa です。
この記事は ZOZOのAdvent Calendar 2021のカレンダー 5 の最終回(25日目)です。

ZOZOTOWNのアーキテクティングって?

ZOZOTOWNは約2年前より大規模なリプレイスに着手しており、常時いくつかのリプレイス案件が進行しています。
たとえばTECHBLOGに掲載されている ZOZOTOWN カート決済機能リプレイス Phase1 〜 キャパシティコントロールの実現 では、オンプレ上のIISとSQL Serverで実装されていた機能にAWS上に構築したキューイング機構を拡張する形で実現しています。このような、組織として未知のアーキテクチャを考案し実現性を検証し、採用の意思決定を行うプロセスをアーキテクティングと呼んでいます。

ZOZOTOWNのリプレイス案件で新規アーキテクチャを構築することになる(だいたい組織横断の混成チームになる)と、アーキテクトチームからアーキテクトが参画することになります。参画したアーキテクトは、チームに伴走する形でプロジェクトが安全な空域に到達するまで寄り添います。伴走中に特に大切にしている4つのことについて本記事で書いてみたいと思います。

抽象度を高く、解像度も高く

アーキテクチャ設計プロセスは、基本的に ADD : Attribute Driven Design のサイクルで回しています。雑に言うと「ざっくり描いたアーキテクチャを具体的な事象をあてはめて検証しながら整えていく」プロセスです(もしご要望が多ければ ADD について別途記事にしてもいいかなと思ってます。フィードバックください)

私も含めてエンジニアは、誰しも自分が詳しい分野もあればあまり自信のない分野もあります。新しいアーキテクチャを考えるとき、どうしても詳しい分野は詳細かつ具体的になるし、あやしい分野はもやもやっとした記述になってしまいがちです(←自分のことだ)。

なので、いつも私は最初は思いっきり抽象度の高い図をPPTやGoogle Slidesで描くところから始めるようにしています。「カート投入リクエストがカートDBに飛ぶ図」とか「ブラウザがWebサーバにHTTPリクエストを投げる図」とかのレベルです。そこに仕様や制約やセキュリティの仕組みやらを入れ込んで登場人物が増えていくうちに、どうもあやしい、となるわけです。

そうなったら他の有識者と一緒に叩いて補整する。これを高い抽象度のまま進めるところがポイントです。

注意すべきは「抽象度が高い = 解像度が低い」ではないところです。「高い抽象度」の正しい姿は、解像度はあくまで高く、本質には関係ない部分を省略/抽象化された状態です。初期のアーキテクチャ設計における本質とは、他のモジュールとのインタラクションと、それぞれのモジュールの責務、この2点に尽きます。それ以外を省略/抽象化し、本質的な構造と振る舞いのみ可視化させることで、意味のある議論に集中することができます(詳細の不必要な議論を発生させない、とも言う)。

人間の脳は良く出来ていて、抽象度の高い図を見ながら解像度の高い議論をすることができる。これができる人たちでチームを組むことができると、めちゃめちゃ生産的な設計セッションが生まれます。

「我々がいなくなった後」を意識する

アーキテクチャ設計のキモは、抽象度の行き来によって全体の整合性とバランスを整えてアーキテクチャ全体を通して設計思想(≠技術)の一貫性を持たせることです。

そもそも、なぜ一貫性が必要なのでしょうか。

私はよく「我々がいなくなった後」というフレーズを使います。たとえばドメイン要素を基盤に一部取り込むという例外的判断をしようとした場合、今ここで議論している仲間たちであれば、たとえ一貫していなくても説明すれば分かってくれるし、意図を理解してうまく作りうまく運用しうまくメンテナンスすることができます。
しかし世代が変わり残されたのはコードだけ、という状態でその意図は期待できません。一貫性がない部分に違和感を覚え、「ここ、なんでこんな設計にしてるんだろ。誰か知ってる人いない?」であったり、さらに「ここにこう書いていいんなら他もやっていいよね」と基盤のコードにドメイン要素が続々と持ち込まれる未来が容易に想像できます。

境界線による分割と分担は実装コスト運用コストは上昇しますが、シンプルさが維持されるため保守性は高いまま推移させることができます。それはサービスというドメイン要素間の横方向の組織的分離だけでなく、ドメイン要素と非ドメイン要素(メカニズム)の縦方向の組織的分離、自サービスと外部サービスの分離、APIの外側と内側の分離、自コードと外部コードの分離、そしてオンプレとクラウドの分離といった、縦横無尽に境界線が引かれています。
たとえばAPIが分かりやすいと思いますが、この境界線の引き方(と、またぎ方)に一貫性を持たせること、欲を言えば簡単に境界線を越えられないような仕組みや境界線が維持されるための仕組みもあわせて提供することが、将来にわたってシンプルさが維持され、高い運用性・保守性を維持することにつながっていくと考えています。

「腹落ち感」を大切にする

冒頭で紹介したTECHBLOGの記事にあるアーキテクチャを実現するために、サーバサイドチームを中心に、オンプレ側のSRE、クラウド側のSREが協業して設計・実装を進めました。

複数チームのメンバーが集まることで決めづらい、と思うかもしれません。でも逆なんです。

一般的には組織横断で新規のアーキテクチャを模索しながら構築を進める場合、チーム毎の関与度合いの差やチーム間の前提知識の差により、想定外のXX(XXのはずだったのに、XXは知らなかった)が発生しがちです。

異なる立場・異なる観点の経験を積んできたメンバーたちの目で1つの事象を検討することで、たとえポンチ絵をつかった机上の議論であってもかなり網羅性の高い検証が可能です。

それを現場では「腹落ち感」と呼んだり「筋がよさそう」と言ったりしています。

特に、ポンチ絵の上で解像度の高い議論ができるメンバーで叩いたアーキテクチャは、みっちりRobustness分析を行うよりも効果的かつ効率的だと感じています。
その理由は、静的なその場に出ている要件だけでなく、運用開始後に起こるであろう例外処理やセキュリティ面の懸念事項、将来発生するはずの仕様変更や機能追加、さらにはチーム間のやりとりのオーバーヘッドまで視野に入れたシナリオを各自動かしているので、結果的に多層的かつ多面的な検証が行われていることになります。抽象度高・解像度高の議論の結果皆が腹落ちしている状況は、実は相当ロバストなんです。暗黙知は我々の強い武器です。

非機能要求の置き方を工夫する

見落としがちですが、CloudNative技術を使ったアーキテクチャ設計では、非機能要求の"置き方"がキモになります。

たとえばダウンタイム3分以内、のようなレガシーな置き方ではレガシーな設計を導くことになりますし、24時間ダウンタイムゼロといった非現実的な要求を置いても具体的な設計を導くことはできません。

皆さんご存じの通り、CloudNative技術は新陳代謝が早く、その時点の旬の技術を適切なタイミングで取り込み続けることが勝ち筋になります。
勝ち筋に乗ることができれば、サービスの健全性は高く維持され、費用もトイルも下げ続けることができます。

「じゃあどんな置き方がちょうどいいんだ。例を挙げろ」という声が聞こえてきそうですが、それはお正月休みに皆さんで考えてみてください。機会があればご紹介したいと思います。

ヒントというか個人的な感覚ですが、運用性、保守性を最大化するために Resiliency(回復性)と Disposability(廃棄容易性)を設計時にうまく入れ込むことができれば、弾力性があり手の入れやすいアーキテクチャに近づくように感じています。

まとめ

書き終わって読み直してみると、改めて”楽しいことやらせてもらってるなぁ”、という感想とともに、今の環境でご一緒させていただいている皆さんに感謝の念しかありません。いつもありがとうございます。

社内の人も社外の人も、この記事を読んだみなさんとゼロイチの醍醐味の詰まったアーキテクティングの感覚を共有できれば幸いです。

2021年のZOZOアドベントカレンダー5もこれで終了です。
みなさま、素敵な休暇をお過ごし下さい。