これはフェンリル デザインとテクノロジー Advent Calendar2024 25日目の記事です。
こんにちは、インフラ・バックエンド担当の森井です。
アドベントカレンダーのテーマに沿った話を書きたいなといろいろ思い悩んだ結果、技術におけるデザイン(設計)についてなら書けるかもしれないと思い立ちました。 今回は良いシステムを設計するための考え方をまとめてみたいと思います。
システムを設計するということ
根本に立ち返って、デザイン(設計)がどういう行為なのかを確認します。
デザイン(英語: design、中: 設計[1])は目的設定・計画策定・仕様表現からなる一連のプロセスである[2][3]。すなわち人・ユーザー・社会にとって価値ある目的を見出し、それを達成できるモノゴトを計画し、他者が理解できる仕様として表現する、この一連の行為をデザインという[4][5][6][7]。 どのように決めるのか
どうやら太字の部分が重要そうです。
ウォーターフォール型のシステム開発に置き換えて考えると、「価値のある目的を見出し」は企画で、「それを達成できるモノゴトを計画」は要件定義と設計となるでしょうか。
要件定義では機能要件と非機能要件を定義します。 機能要件はシステムに求められる機能を定義するもので、例えば、「ログイン機能を提供すること」「管理者画面ではExcel形式の帳票がダウンロードできること」などです。 非機能要件は機能以外に求められる様々なシステムの特性を定義します。
機能要件に比べて、非機能要件がイメージしづらいのですが、 例えばIPAが提供している非機能要求グレードでは、下記のようなことを定めます。
- 可用性
- 性能拡張性
- 運用保守性
- 移行性
- セキュリティ
- システム環境・エコロジー
このような機能要件・非機能要件を達成できるシステムを計画し、ドキュメントに記載するということが、設計という行為だと言えそうです。
そうやって設計されたシステムは要件を満たしているわけですから十分ではあるでしょう。 では、十分以上を実現するにはどうしたら良いのでしょうか。 この十分以上を実現できていることが「良い」システムを設計することだと定義して考えてみます。
「良い」システムを設計するということ
なぜ十分以上を狙う余地があるかというと、要件定義で定義する内容は必要条件であって理想形ではないことが多いからです。
理想形を定義するのが難しいのは、どんな技術もメリット・デメリットがあることに原因があるような気がします。
メリットがない技術というのは淘汰され市場から消えていきます。 技術Aに対してあらゆる特性が上回る技術Bが出てくれば、技術Aは次第に技術Bに置き換えられ、目にしなくなっていきます。 新しいシステムを設計するときにWindows 95で開発する意味はないし、PHP5を使う意味もないわけです。 そうすると、テーブルの上に乗っている選択肢には常にメリット・デメリットが両方あるわけですから、作り方が決まっていない要件定義の段階では最低限になりがちなのだと思います。
簡単な例としては、「VMを選択すればカスタマイズ性を得られるが運用コストが高い、サーバーレスを選択すればカスタマイズ性は下がるが運用コストが低い」ということなどがあるでしょうか。
良いシステムを設計するには、あっちを立てればこっちが立たずという選択に対し、システムを構成する部分についてもシステム全体としても「ちょうど良い」ものを選びとることが重要な気がします。
そして、「ちょうど良い」を選び取るためには、どこにメリット・デメリットがあるのかを認識する必要がありそうです。
冒頭に記載したIPAの非機能要求グレードや、SQuaREの品質特性、AWSのWell-Architected フレームワーク、The Twelve-Factor Appなどを活用していくことで解像度を高めることができるかもしれません。
また、純粋に技術の課題解決力も必要でしょう。 例えば、Netflix社は1台のサーバーで800Gb/sの配信を実現していますが、開発コストをかけることで配信パフォーマンスを劇的に高めることができるとは私のレベルからすると思いもよらないわけです。
ユーザーのニーズや文化、開発チーム、システムの将来像についても理解しなければなりません。どのような観点を重視するのかが変わってきます。
体験することの価値
観点が一つなら良いですが、複数の軸が複雑に絡み合っていることが多いです。 この状況で「ちょうど良い」を選び出すことは極めて難しい作業のような気がします。
もっと普通の人が「ちょうど良い」を見つけることはできないだろうかと考えていたら、先日参加したAWS re:Invent 2024で、Dr.Werner Vogelsの講演を思い出しました。
この講演でWernerは、システムにSimplicity(シンプルさ)を保つことが重要であるという前提のもと、このような例え話をしていました。
- 一輪車は最もシンプルな形で、部品の数が少ない。その場で方向転換もできる。しかし乗るのが難しい。
- 三輪車はコーナーを曲がるのが難しく、柔軟性がない。
- 二輪車は部品の数は多いが柔軟性を得ることができる。全体的な観点から見ると最もシンプルな形である。
- 複雑さというのは、部品の数ではない。複雑さを示すのは全体的な体験である。
車輪の数は2つがシンプルさという観点においては最も「ちょうど良い」ということであり、それは全体的な体験によって示されると解釈できます。 この講演はシンプルさのみに焦点をあてたものですが、設計における多くの「ちょうど良い」は対象を体験することで認識できるのかもしれません。
先のVMの例に照らせば、実際に体験してみることで次のように様々な観点のメリット・デメリットを認識できるかもしれません。
「VMは経験者も多いしチームで使いやすいな、でも多くのパッケージやプロセスが含まれているし、セキュリティ製品を入れる必要があるだろうか。セキュリティ製品はどこまでの保護を担保できるだろう。パッケージのアップデートはどれくらいの頻度でおこなえばよいのだろう。設定変更を管理するためにIaCが必要だろうか。サーバーレスは初期設定が簡単だけど、コールドスタートが発生してしまった。これは許容できるのだろうか。特定のサーバービスへの依存度が高くなってしまったが、コンテナを使えば軽減できるだろうか。サーバーレス固有の知識が必要になりそうだが、チームに引き継ぎできるだろうか。」
体験をもとにチームで議論を重ねていくことで、少しは「ちょうど良い」設計には近づいている気がします。
まとめ
要件定義において理想系を定義することは難しいため、設計によって十分以上を狙う余地があることが多いです。 メリット・デメリットを認識し「ちょうど良い」を選びとるために活用できるリソースは様々ありますが、体験することが一つの解決策かもしれません。