年の瀬ご多端の折、皆様におかれましては本年も大変お世話になりました。crowdworks.jpの開発をしているプロダクト開発部部長兼VPoEの@hihats です。 本記事はクラウドワークスAdvent Calendar 2022 24日目の記事です。
我々の組織ではこれまでも技術的負債解消に取り組んできていましたが、今期(10月)よりさらに人と時間をそこに集中しています。これまでこのブログでも紹介されてきたようにRuby on Railsのモノリスとなっているcrowdworks.jpにおいて、フロントエンドのVue.jsへの移行は今年に入ってから着々と進む中、バックエンドのほうは保守性の低下からどう脱却していくかが手付かずに近い状態でした。
この本丸を攻略するにあたって、闇雲にリファクタリングしていくぞ!では到底うまくいきそうにない。まず「何故やるのか、何をゴールとするのか」の意識あわせから始まり、戦い方を探求していっています。まだその道半ばではありますが、方針を決めていっている最中での気づきをまとめ、そこで個人的に得ることができた新たな考え方を記しておきます。 (ここからは冗長さを除くため「である調」になります)
技術的負債という課題
技術的負債とは
具体の話に入る前にまず「技術的負債」という用語についての定義を揃えておくと、原義はWard Cunninghamが「開発の進行過程での気付きに対処しないと借金の利子が膨らんでいく」と隠喩で説明したことだが、それが歴史的経緯を経て拡大解釈されていったり、頻出用語として扱うならそもそもレトリックを使わず直叙的に表すべきだとか諸論ある。一旦それらは脇において、我々の中では「現状放置しておくと開発速度の低下を招き、やがてプロダクトの競争力を失わせる技術的要因」を指し示している。なので本記事における「技術的負債」はその意味で使っていることを大目に見ていただきたい。
課題
大きい粒度では3点
- Railsバックエンドに関しては、過去にもリファクタリングに挑んだことがあり、そのときどきのレイヤーが残って地層となっている状態だった。コードリーディングに際して、残っているドキュメントと現在の構造を頭の中で整合させながら読むという、新たにジョインしたエンジニアにとっては非常に難読な課題(私もその一人)。
- 新たに機能追加するにおいても、どの地層に合わせた構造にするべきなのかが決まっておらず、最終的に個々の判断に委ねられるため、さらに統一性が失われるという課題もあった。
- ユーザーの多様なニーズに対応するため行ってきたこれまでの機能追加が、ドメインの複雑性を認知の限界まで引き上げている。
その他、開発現場で見られる、より詳細な事象に目を向けると
- コミュニケーションの中で使われる用語の解釈の調整があちこちで起きている(ユビキタス言語がない)
- コード上のコンテキストが実装技術に依拠した分かれ方をしている(実装上のコンテキストがビジネスの実態と一致していない)
これらの課題を見る限り、複雑化したドメイン、すなわちユーザの活動や状態のモデルをうまく扱う必要がある。となるとまず最初にドメイン駆動設計(以下DDD)が浮かび上がってくるが、現状はメンバーのDDDに対する認知やバックグラウンドにバラツキがあったり、そもそもDDDを採用すれば解決する問題のようにもあまり思えなかった。
その大きな理由としては、過去にも同様のチャレンジがあった中、結果的に頓挫となっている要因とその後も技術的負債が生まれてくる要因が、設計スキルや開発プロセスよりも手前にありそうという仮説があったためである。他にもRuby on RailsとDDDの戦術的設計の相性が悪いという問題もあるが、これは根本的理由ではないと位置づけた。
負債を生む構造の問題
基本的には、技術的負債を借りたくて借りているエンジニアはそういないはずである。どれだけ早く市場に価値を提供したくとも、借り入れをせずに済むならそのほうがよい。借り入れせざるを得ない何らかの要因があるわけで、ビジネス的な速度の要求以外でよくある話としては「個別の機能の局所最適化が全体戦略との接合点を欠いている」といった文脈である。
機能開発に限らず、既製品を組み込んだりすること自体は(ユーザーのニーズに素早く対応するためには)間違った意思決定ではない。しかし「そのコンポーネントが今現在も要求を満たしているのか」や「よりよい代替製品が生まれてきてないか」「他のコンポーネントとの関連性に変化はないか」といった、全体から見た価値の変化を継続的に観察していないことは言い訳にしてはいけない。それを許すと理屈上は全てがビルドトラップの温床になる。何を作るにしてもプロダクト運用する上での原則にすべきことである。
このような現象は、一定数以上ユーザーに使ってもらえるようになったプロダクトの組織においては珍しい話ではない。この現象に対して「では全体戦略を決めましょう」と言うだけでは何も変わらないという個人的経験もあった。
つまり「全体戦略だけではない現場感に即した方針設計=技術的負債解消にとどまらない持続的なアーキテクチャへの道程」が必要で、そういったトップダウンとボトムアップ双方からのアプローチとなるフレームワークみたいなものがあれば、自分たちに活用できそうだなと考えていた。
Architecture for Flow with Wardley Mapping, DDD, and Team Topologies
ここからが本題。そういった状況の中で今年5月、たまたまInfoQのQCon Plus May 2022でSusanne Kaiser氏によるArchitecture for Flow with Wardley Mapping, DDD, and Team Topologies というセッションを視聴し、この内容が考えていたことと部分的にリンクした。この考え方は日本ではまだ馴染みがないと思うので紹介していく。
簡単に言うと、
Wardley Mapping、DDD、およびチームトポロジーは、それぞれ異なる分野で用いられるものだが、それらを組み合わせることで、より良いプロダクトを構築するための強力なツールセットになり、変化の速い流れに適応するアーキテクチャを構築できる
という内容。個別に少しずつ紹介していく。
Wardley Mapping
英国の研究者Simon Wardleyによって考案された戦略フレームワークで、状況認識と戦略サイクルに沿った動きに基づいてビジネス戦略を設計し、プロダクトを進化させるのに役立つもの。
自分も名前だけは聞いたことあるレベルだったが、このセッションのあとに公式サイトや以前のInfoQ Conの動画を鑑賞した。
バリューストリームを縦軸、製品開発のステージを横軸としたマップとなっていて、自分たちの製品のコンポーネントがどこに位置していて、市場環境から見てどうなっているかを俯瞰して見れるようになる。 https://www.kaiser-consulting.net/conferences/slides/usi-2022.pdf
DDD(ドメイン駆動設計)
システムの核となるビジネスドメイン(領域)を中心にソフトウェア設計を行うアプローチ。ベースはEric Evansによる書籍エリック・エヴァンスのドメイン駆動設計(通称Evans本)
Team Topologies
時間とともに変化していくコンテキストに対応するために技術戦略と組織戦略を結びつける実践的モデル。 概略はTeam Topologies(by Manuel Pais)のキーポイントに昨年書いた。アトラクタの御三方による翻訳の書籍も出ている。
これらを組み合わせると何が嬉しいのか
Wardley MappingとDDD
まずはDDD(というかEvans本出版時)の時代背景として、エンタープライズアプリケーション1の開発者が主流な時勢であったことを頭に入れておく必要がある。crowdworks.jpのようにLarge set of unknown usersに使用されるWebアプリケーションのことは想定して書かれていなかった。つまり現在のソフトウェア開発者は2003年当時より不確実性が高く、当時よりユーザーのことを知らない2状況でのプロダクトづくりをしているということである。
Wardley Mappingのサイクルではまず「なぜ作るのか」の再確認から入り、自分たちが置かれた複雑な地形(Landscape)を理解し、原則(Doctrine)として「ユーザーを知る」ことがある。「その後にDomain Driven Designの出番が来る」とKaiser氏は(おそらく)言っていた。Evans本でも「ユーザーのためにドメインに没頭せよ」とは言っているが、その前段としてまず「ユーザーを知る」ことが強調されているとは読みとれない3。
要するに、現在の我々の開発においては必要なステップが足りていない。上述の「DDDだけでは不十分では」と感じた大きな要素の一つである。
次に既製品の導入にどう対処していくかの課題について。Evans本ではGenericサブドメインとして「既製品を導入するか、自社で実装するか」などいくつか選択肢を提示してくれているが、現在はSaaSやクラウドのマネージドサービスのように既製品の安定化や進化のスピードが当時とは桁違いで、そこの想定が大きく異なっている。
Wardley Mappingでは、各コンポーネントがバリューチェーン(縦軸上)でどうなっているかを確認できることにより、それらをアジャイルにカスタムビルドするか、リーンで対応するかの選択肢が逐次迫られる。
一言で言ってしまえばBizDevOpsっぽい話ではあるが、フレームワーク的に組み込まれることが嬉しい。
Team TopologiesとDDD
チームトポロジーとは大胆に言い切ってしまうと チームの認知負荷とコンウェイの法則の話である。ただこのいかにもシンプルなポイントもDDDでカバーしていないエリアを補ってくれる。
どういうことかを説明する前にDDDの基本からおさらいすると、Eric EvansはDDDを駆動している原則は基本的に3つだけとしている。
例えばユーザーが特定の顧客である業務アプリケーションであれば、ドメインモデル ↔ コードの往復は多くてもせいぜい顧客との定例Mtgと同頻度だった。先述のように、Volatilityの高い現代においては変化に対応するために日常的 & 継続的に行っていく必要性が高くなる。日常的に行われるとなるとおそらく多くの人がコミュニケーションの労力が高いと感じる。
だがそれはモデルを成熟させるために必要なコミュニケーションであるので、労力の高さに対する忌避感を取り除く仕組みが必要である。イコール「認知負荷の問題にどう対処するか」であり、チームトポロジーはそれにどう立ち向かっていくかの話である。
また、フローとインタラクション4を整備することによって動作中のシステムからのフィードバックをチームが受けることができるよう最適化するアプローチ でもあるので、DDDのイテレーティブな設計を支援することもできる。
まとめ
Kaiser氏のセッションの内容はもっと具体的なケーススタディを含んでおり、例えばWardley Mapを自分たちのプロダクト用に作成することも可能である。私も手書きのラフで作ってみたものがあるので、またの機会に公開できればと思う。
またこのセッションの内容は、おそらくもっと大規模な(それこそ社会システムに近い)ソフトウェアシステムでも適応できると言っていると思われるので、そういった開発者の人たちにも注目してもらいたい。我々も会社のミッションとして「インフラ」を掲げている以上、よりスケールしていった場合の解法の一つとして携えておきたいと思うものだった。
個人的所感としては、この3つの個別のアプローチを組み合わせなくとも、DDDだけで技術的負債を解消していく試みはおそらく不可能ではない。ただそれぞれの現場で、同様の技術的負債の課題を抱えているように見えてコンテキストが大きく異なるのは確かだと思われるので、One size fit allと考えるよりは、より広範な選択肢としてフレームワークがあることは理論的にも有用なはずである。(※もちろんフレームワークに功罪あることはご承知かと思う)
最後に最も大事なのは、設計や手法どうこうの前に
- 「私たちは問題を理解し、その共通の認識を持つことができたか?」
- 「我々のソリューションはユーザーのニーズにどれだけ合致しているか?」
- 「顧客のために価値を創造しているか?」
であるということで、絶え間ない変化の中でもその3つが常にフィードバックされる仕組みになっていれば、具体的なアプローチは二の次という元も子もない結論でこちらからは以上です。メリークリスマス!
追記(We are hiring!)
大事なことを忘れてました。この記事を読んで興味をもった方はこちらからエンジニア募集しております。それ以外のチームのエンジニア一覧からもどうぞ。