論理的にシステム設計するためのガイドライン
Design Guidelines
経験や勘だけに頼らず論理的に設計するためのガイドラインを示します。
設計者の使命
システムを設計するエンジニア(設計者)は、その設計の上で開発するエンジニア(実装者)と同じエンジニアが担うことも多いため、両者の区別は曖昧になりやすいかもしれません。
しかし、システム設計における設計者と実装者の関係は、UI デザインにおけるデザイナーとユーザーの関係と同じです。
UI デザインの思考は、システム管理画面はもとより、API や内部オブジェクトのインターフェース、あるいは運用手順の設計等にも適用できる。これらはインターフェースデザインというひとつのジャンルと言えるかもしれない。つまり異なる二項のモデルを透過的にする、中間項モデルのデザインである。
— Manabu Ueno (@manabuueno) December 21, 2022
特に「デザイナーはユーザーよりメタな俯瞰視点を持っている」という関係性は共通して重要です。
問題の本質を見極めてその核心に対してアプローチするには、デザイナーはユーザーに同化するのではなく、ユーザーとその状況をプロの視点から解釈し、「ユーザーが理解していることを理解する」必要があるのです。これを「二次的理解」と言います。
設計者の使命は、将来のすべてのエンジニアが自分なりの方法でアイデアを実現できる(=開発しやすい)システム(=インターフェース)を設計することです。
エンジニアがこの使命を果たすには、実装者としての自分から意識的に抜け出し、エンジニアの置かれる状況(仕様、アーキテクチャ、エンジニア自身)を客観視する「設計者の視点」を持つ必要があります。
設計原則
「設計者の視点」を体現する具体的なアクションを示します。
アーキテクチャを図解する
生態心理学において、人間をはじめとする動物は、環境のさまざまな要素から価値や意味(アフォーダンス)を受け取り、その環境に適合した行動をとるとされています。
これに従うと、エンジニアはシステムの構造や構成要素(名詞)を把握することで、さまざまな行動(動詞)の可能性を直感し、例えばコードを理解したりアイデアの実現方法を模索したりといった、状況に適合した行動をとれるようになるといえます。
システムの構造や構成要素を把握する=メンタルモデルを構築するには、図を見るのが効果的です。
プレゼンでは、言葉だけで伝えるのが難しい時に絵を使う、のではない。逆である。
— Manabu Ueno (@manabuueno) November 14, 2021
アーキテクチャとは、エンジニアが使命を果たすために操作(追加、更新、削除)する対象、すなわちシステムの構造や構成要素のことです。
エンジニアがメンタルモデルを構築したり共有したりできるように、アーキテクチャを構成する「名詞」同士の関係が視覚的に理解できる図を作成します。
図に含むべきか迷う要素がある場合は、新入りのメンバーに対する初めての説明に含まれていた方が自然か、理解が促進されるか混乱させてしまうかなどを基準に考えてください。
メンタルモデルと一致させる
変更が容易だとか拡張性だとかは(コードについては)ナンセンスな視点で、メンタルモデルと正しく一致するモデルにできているかが重要。変更や拡張のアイデアはメンタルモデルから生まれる。一致していれば無理のない変更で実現できる。アイデアをすぐ実現できない設計は、メンタルモデルと齟齬がある
— KOBA789 (@KOBA789) December 22, 2022
これは「アーキテクチャを前面に出す」とも言い換えられます。
アーキテクチャ図に現れる要素や存在が自明な要素は上位階層に露出すべきです。逆に、アーキテクチャ図に現れない要素や存在が自明でない要素は下位階層に隠蔽すべきです。
例えば、アーキテクチャ図を見て自然に理解できる事項はすべて main 関数上で確認できるように実装すべきですが、実際に実装してみて初めて気付くような事項は別の関数に切り出して実装すべきです。
また、コードの行数が大きくなってきたことを理由に処理を別の関数に切り出したり、コードの形状が似ていることを理由に共通化したりするような安直な行動は、隠蔽すべきでない要素を隠蔽してメンタルモデルと齟齬を生む可能性があるため不適切です。仕様の複雑性は仕様を変更しない限り取り除けません。どうしても仕様が複雑ならその複雑性は正直に前面に出してメンタルモデルと一致させるべきです。
コードの書き方以外にも、関数やファイルの分割基準、ディレクトリ構造など、あらゆる観点でメンタルモデルと一致した状態を目指します。
Discussion