こんにちは、リファクタリングが大好きなミノ駆動です。
この記事は READYFORアドベントカレンダー2022 、10日目の記事です。
これはなに?
ろくに設計せずにシステム開発を進めると技術的負債が蓄積し、変更が難しくなってしまいます。
しかし設計を推進しようにも、周囲が設計is何を知らないと、なかなか理解を得られません。特にビジネス側や経営側はプログラムの内部構造を知らないわけですから、輪をかけて説得が困難です。
この記事は、ビジネス側や経営側など、非エンジニアサイドに対して技術的負債や設計を分かりやすく説明するための例えや手法をまとめたものです。
私が非エンジニアサイドへ説明するとき実際に活用しているもので、聞き手からも「分かりやすい」と好評を得ております。
この記事のゴール
以下を知ることがこの記事のゴールです。
- 技術的負債や設計について、非エンジニアサイドに理解を促すノウハウ
- ユビキタス言語の重要性について、ドメインエキスパートに理解を促すノウハウ
状況と課題の整理
手法を説明する前に、まず状況を整理します。
例えばスタートアップ時は、ローンチして軌道に乗るまでとにかくイケイケドンドンでサービスの機能開発が進みます。この段階ではサービスはさして大きくもなく、技術的負債はあまり目立ちません。開発速度にも問題はありません。
ところがローンチして数年経過し、軌道に乗ってきた段階になると話は変わってきます。サービスの巨大化に伴い、いよいよ技術的負債が無視できないレベルにまで蓄積していきます。
開発速度が鈍化する他、不具合が目立ち始めます。
「最近なかなか新機能をリリースできないな。不具合も多い。エンジニアの連中、サボってるんじゃないか?」
そんな幻聴()が聞こえてきそうです。怖いですね。
この状況を打開するには、機能開発一辺倒のコスト配分から、設計にもコストをかけるよう予算と計画の見直しが必要になります。
設計にはコスト……すなわち時間やお金が取られます。
機能開発以外に時間を取られることに、ビジネス側は神経質になります。
また、お金がかかることに経営側は神経質になります。
したがって 設計を推進するには、ただ開発側だけでやればいいという話ではなく、非エンジニアサイドの方々に対して設計することの意義や効果を説明し、説得しなければならないのです。
ところで技術的負債や設計を説明して、非エンジニアサイドはすぐに理解できるものでしょうか?
技術的負債とは、開発速度を貶める粗悪な構造のことを指します。
具体的には、変更容易性の低い構造です。変更容易性とは、なるべくバグを埋め込まず、素早く正確に変更できる度合いを示すソフトウェア品質特性です。
変更容易性の良し悪しを判断するには、「変更容易性の高い理想的な構造がどういうものなのか」を知る必要があります。
つまり、 変更容易性の高いあるべき構造を知って、そのギャップとして初めて技術的負債を知覚できるようになるのです。 変更容易性の知識がなければ、開発に携わるプログラマですら負債は認知できません。 ソースコードの読解スキルと技術的負債の認知スキルは全く別物です。
こうした幾重にもハードルがある状況で、一体どうやって非エンジニアサイドに設計の意義を説明すればいいのでしょうか。
プログラミングや設計の知識を非エンジニアサイドの方々に身に着けてもらえばいいのでしょうか。しかしそれは非現実的です。人はそれぞれ専門性をもって仕事をしており、分業の観点からもナンセンスです。
ではどうするかというと、彼らに目線を合わせ、彼らの分かる言葉に置き換えて説明する必要があります。
伝え方
では非エンジニアサイドに説明するときに好んで用いている表現、伝え方を解説します。
まず設計が解決する課題やメリットを伝える
設計が何であるかを伝える前に、まずは設計が解決する課題やメリットを伝えましょう。具体的には以下です。
なお、ここから先、 非エンジニアサイドに説明する内容は下記のように引用で表現 しますので、注意して読み進めて下さい。
長年に渡る機能追加や改修により、システム構造がいびつになってきています。
そのため開発速度を出そうにも出せず、全体的に鈍化してきています。
開発速度の鈍化は、すなわち開発コストの高騰です。バケツに穴が空いた状態です。 継続的に利益が減衰してしまいます(ココ重要)。
この設計は、開発速度の継続的な向上に寄与します。
顧客が喜ぶ新機能を素早く開発できるようになります。
なぜ設計が必要なのか
ではここからが設計の必要性についての説明です。
変更容易性を高めるには、関心事や責務ごとの単位でモジュール、クラスを分割することが肝要です。しかしモジュールやクラスと言っても非エンジニアサイドには通じません。代わりにこれを、 収納 という比喩を用いて私は説明します。
次に示すのが私の説明例です。
キャビネットといった収納を想像してみてください。
本、文房具、オモチャ……それぞれの収納場所が決められていて、整理して正しく収納されていれば、例えばオモチャを取り出したいといった場合にすぐに取り出せますね。
また、「文房具の収納を改善したい」といった場合にも、楽に整理できるでしょう。
ところが、こんなぐちゃぐちゃで整理されていなかったらどうでしょうか?
文房具を取り出したくても探すのが大変ですし、取り出そうにもぶつかってオモチャが壊れてしまうかも知れません。また、ハサミが紛れ込んでいようものなら、探している最中にうっかり手を切ってしまうかも知れません。システムの内部構造は、今このように散らかった状態なのです。
新機能を新しいオモチャに例えると、散らかった棚に新しいオモチャを上手く収納できるでしょうか?
難しいことが容易に想像できるでしょう。
無理に押し込めるとオモチャが壊れる……つまりシステムが壊れてしまうのです。今まで以上に、より安全により素早く機能追加、機能改善するには、システム内部の構造を整理する必要があります。上手く整理できるように構造を考えるのが設計です。
……以上のようなたとえで私は説明しており、いつも「分かりやすい」と反応をいただいております。
ユビキタス言語の策定活動に繋げる
技術的負債をたとえる比喩として、他にはジェンガやハウルの動く城などが有名です。「汚い構造を表現するなら、別にジェンガとかでもいいのでは?収納を比喩に持ち出したからと言って、今さら何か特別すごいとは思えないんだけど」と感じる方もいるかもしれません。
しかし収納を用いた比喩は、 ユビキタス言語の策定をする上で大変便利です。
ユビキタス言語とはドメイン駆動設計に登場する考え方で、意図や目的を共有するための言葉です。ドメインモデルや境界付けられたコンテキストの設計に深く関わります。
変更容易性を大幅に高めるには、特にコンテキスト(文脈)の違いからくる目的の違いを正確に見分けて、目的が違う、すなわち似て非なる概念をそれぞれ別々のドメインモデルとして設計する必要があります。この設計をする上で、ユビキタス言語は超重要な役割を果たします。
例えばECサイトにおける「商品」は、文脈によって目的が全然異なります。
目的が違うものを無理にひとつの「商品モデル」としてまとめてしまうと、変更容易性だけでなく機能性にも支障をきたします(次に示す動画とスライドを参照)。
クソコード動画「一枚岩モデル」 #AWSDevDay pic.twitter.com/NwfOmXWy6F
— ミノ駆動 (@MinoDriven) November 9, 2022
つまり、 似て非なるものを見分け、それぞれ別の箱に収納する必要があるのです。
サービスの事業領域について深い知識を持っている人をドメインエキスパートと呼びます。ドメインエキスパートと協力してユビキタス言語を策定し、ドメインモデルを作り上げる必要がある、という教えがドメイン駆動設計にはあります。
ドメインエキスパートと協力してユビキタス言語を策定する際、上で記した収納の比喩に加え、私はさらに次に示す説明をします。
(上記収納話の続き)
ではどうやったら上手く整理できるのでしょうか?
例えば「おどうぐばこ」とだけ書かれた箱がたったひとつだけあるとします。
このたったひとつの箱だけで、様々な種類の道具を上手く整理して収納できるでしょうか?
ぐちゃぐちゃになりそうですね……
一方、道具の種類ごとに引き出しが分かれていて、しかもちゃんと名前が付いていれば、収納整理が簡単ですね。
さて、ここまで収納と道具で例えてきましたが、収納対象となる道具は、我々の事業で取り扱う物事や概念です。例えばECサイトであれば、以下のようなものです。
- 商品
- 注文
- 在庫
- 予約
- 配送
ただし、ここでひとつ大きな問題があります。
我々エンジニア側は、ビジネス側の方が扱っている物事や概念について熟知しているとは言えません。
登場概念を知らなければ、収納するための引き出しも作られないですし、どこに整理していいかも分からなくなってしまうのです。 そしてぐちゃぐちゃな構造になり、機能の追加や整理の効率が悪化してしまうのです。それだけではありません。
例えばECサイトでは「発注金額」という概念があります。
一見、「顧客が商品を購入する際の発注金額」のように思えるかもしれません。
しかし「販売側が商品を仕入れる際の発注金額」を意味しているケースがあります。
このように、文脈によって言葉が意図するところが全然異なるケースが沢山あります。「発注金額」と書かれた箱をひとつしか用意せず、そこに意図の違うものを収納すると混乱しますよね。 同じように見えるものでも、意図や目的が違うものはそれぞれ別の箱に分けて収納しなければならないのです。
ここまでのことを一旦まとめると、システム構造の整理には以下が必要です。
- 事業で取り扱う物事や概念を把握すること
- 文脈によって意図の異なる言葉を区別すること
このように、皆さんが普段お仕事で扱っている概念をより正しく理解することで、我々エンジニアは素早く機能追加や改善ができるようになります。ご協力をお願いいたします。
……以上のように説明すると、理解促進が容易になるでしょう。
ここから先は余談です。
【余談1】調理器具と便所掃除道具を一緒にするのかあああ!?!??
もっと激しい比喩としては、私は以下を用いたりします。
例えば、「おどうぐばこ」と書かれた箱がひとつだけあるとする。
そして調理器具と便所掃除道具がある……。「調理器具も便所掃除道具も同じ道具だから一緒の箱に入れちゃお☆」となるのか!?
どう考えてもヤバいだろ!?
ミソクソ一緒にしちゃダメだろ!?!?
収納は別々にしないと絶対マズいだろうがああああああ!!!!!
【余談2】実はアーキテクトとしての仕事をしてるんだよ
書籍 『Design It! - プログラマーのためのアーキテクティング入門』 では、ソフトウェアアーキテクトの仕事は以下のように定義されています。
- エンジニアリングの観点から問題を定義する
- 利害関係者と協力し、ソフトウェアのビジネス目標と要求を定義する
- システムを分割し、責務を割り当てる
- 広い視野を持って全体に目を向け続ける
- 品質特性間のトレードオフを決定する
- 技術的負債を管理する
- チームのアーキテクチャスキルを高める
(『Design It! - プログラマーのためのアーキテクティング入門』著:Michael Keeling、訳:島田浩二、2019年刊行、オライリージャパン、p.4-7より引用)
「品質特性間のトレードオフを決定する」とは、変更容易性を含むさまざまなソフトウェア品質特性のトレードオフを決定することです。つまり、 非エンジニアサイドへの説明や説得は、まさにアーキテクトとしての仕事なのです。 書籍 『Clean Architecture』 でも、「ビジネスマネージャーなどのステークホルダに対して、機能の緊急性よりアーキテクチャの重要性を伝える責務がアーキテクトにはある」といった旨の解説がなされております。
アーキテクトを目指している方は、ぜひ説明力を向上させていきましょう。