デザイナーとエンジニアの両方やってると気づく共通点、モデルとモデリング
ソフトウェアデザイナー(以下、デザイナー)とソフトウェアエンジニア(以下、エンジニア)の両職能を行き来している人はもしかしたら共感してもらえるかもしれませんが、デザイナーがデザインをする上での思考とエンジニアが設計する際の思考は「具体的情報を集めて抽象化した情報をベースにさらに具体的情報を検証し、また抽象化した情報へフィードバックする」といういわゆるモデリングを踏まえるのはどちらも行うことです。
デザイナーは直感的でエンジニアは論理的という印象が強く一見すると交わらなそうな両職能ですが、意識的であっても無意識であっても実はモデリングをするということに関しては変わらないです。
これをデザイナーとエンジニアの両職能を自身でやるとより肌感として感じますし、モデリングを意識的にやっているからこそ両職能の行き来がシームレスにできるとさえ思います。
というわけで、今回はデザイナー・エンジニア(それ以外の職能もですけが)の共通点であるモデリングについて少し深掘りしてみようと思います。
モデルとは
目的に合わせて、
具体的な情報から共通する部分をみつけ、
また不要な情報を取り除くことで
注目すべき情報を抽象的に定義したもの。
とのこと。またこの抽象化の過程や抽象化後に具体的な情報と照らし合わせてモデルの再評価を行うことをモデリングといいます。
ここで気をつけたいのは「注目すべき情報」というところです。
なんでもかんでもただ共通点をまとめて抽象化することがモデリングではなく、何に注目すべきかで出来上がるモデルは変わってくるという点です。
そんなモデルがあることで人間は対象の情報から特徴を抜き出して単純化し物事の理解を早めます。
また、モデルを使うこと・モデリングの過程を共にすることで人々は認識を共有したり、そこから気づきを得ることがができます。
デザイナーのモデリング
では本題に立ち返ってまずはデザイナーにとってどうモデル・モデリングが活かされているのかいくつか例を挙げてみます。
ピクトグラム
デザイナーはピクトラグムを作るという仕事があります。
ピクトグラムは意味や概念を具体的な要素から抽象化してそれを視覚記号として表現するものです。
次の画像は障害馬術(Horse Jumping)という競技の実際の写真とそれをモデリングした東京オリンピックで使われた案内サイン(ピクトグラム)です。
上の写真は複数の具体的情報のある写真で以下の要素が共通点です。
- 馬が前脚を曲げてジャンプしている
- 馬がバーを飛び越えている
- 騎手は馬に乗っている
- 騎手はメットと競技用ジャケットを着ている
これらの要素の太字の部分を共通点や注目すべき点として抽象化しています。またそれ以外の写真に写る不要な要素は取り除いています。この過程を見るとこれはもうモデリングです。
オブジェクト指向UI
また、オブジェクト指向UI(OOUI)などはまさにモデリングを活用したUI設計の方法です。
例えば、宿泊予約ができるサービスのアプリケーションをOOUIで設計する場合、まずはユーザのユーザフロー(旅行を決めて宿泊するまでのフロー)を考えてみます。
- ユーザは、宿泊する日程を決める
- ユーザは、宿泊する旅先を決める
- ユーザは、宿泊する人数を決める
- ユーザは、宿泊の予算を決める
- ユーザは、条件(旅先・宿泊人数・予算) をきめて宿を探す
- ユーザは、条件にあった宿を選択する
- ユーザは、宿に自分の情報を記入して予約をする
- ユーザは、宿泊日当日に予約済みの宿を確認する
- ユーザは、都合により予約をキャンセルする
- ユーザは、予約をキャンセルしなかった場合、旅先へ向かい宿に宿泊する
この中で、太字になっている言葉はオブジェクトとして抽出できそうです。また単語の中で「〜する」といった動詞や修飾語は省きます。また、このオブジェクトを定義していきます。
オブジェクト | 定義 |
---|---|
ユーザ | このサービスを使って宿を予約する利用者本人のこと |
宿 | ユーザが条件をもとに探し、予約する施設のこと |
予約 | 宿を任意の泊数事前におさえること。 当日までにキャンセルができるが場合によってはキャンセル料が発生する |
オブジェクトを定義する際に、属性・振る舞いなどが見えてきます。ここまでの情報を使って例えばナビゲーションを考えます。
宿泊予約サービスのナビゲーション
-
宿
- 条件で探す
- 条件= 日程, 旅先, 宿泊人数, 予算
- 条件で探す
-
予約
- 確認する
- キャンセルする
-
ユーザ
- 設定する
オブジェクト指向UIでは、ユーザが普段からサービスや対象のコトについて持っているモデルに照らし合わせてUI設計をデザイナーが行います。このユーザのモデルを理解するためにモデリングを行い、サービスのアプリケーションにそれをそのまま反映します。
その他のデザイナーのモデリング
この様に、デザイナーが何かしらをデザインする時は必ずと言っていいほどモデリングを行い、他には次の様なものがあるでしょうか。そこで出来上がったモデルを成果物にしたり、設計の礎にしたりします。
- ペルソナ定義
- カスタマージャーニーマップ
- ユーザフロー
- コンポーネント設計
- などなど…
気づいたら色々モデリングしてますね👍
エンジニアのモデリング
エンジニアのモデリングは次のフェーズで行います。
- 要求仕様・要件定義
- 設計・アーキテクチャ
- 実装
ってモデリングしない時はないですね😅
要件定義ではリレーションシップ駆動要件分析(RDRA)とかの勉強会とかに出ると、まさにモデルでビジネスもシステムの関係性をわかりやすく整理しながら要件定義するフレームワークがあったりします。
設計についてもドメイン駆動設計もユビキタス言語を抽出し、そこから事業やサービスのドメイン(領域)についてモデリングしたモデルをコードで表現していき、ビジネスに関係することとアプリケーションに関係することと関心ごとを分離していきます。
データベース設計も同様にデータのオブジェクトをテーブルとして扱う際にモデリングを行います。
と言った様に、システムやアプリケーションの構築は複雑性との戦うためこれらのモデリングメソッドやフレームワークを活用しています。
実体(Entity)と値オブジェクト(Value Object)
エンジニアが設計や実装する際に実体(Entity) と 値オブジェクト(Value Object) というものを活用します。
実体(Entity) とは、一意な具体的情報です。
例えば、プラスチックでできたリンゴのおもちゃは工場にあるりんごの形をした型にプラスチックを流し込んで製造されます。この時に同じリンゴのおもちゃであっても製造されればそれぞれは別のりんごのおもちゃになります。要するに型から実体化されたわけです。この型はこれまでの話でいうモデルです。エンジニアの使う実体(Entity)とはこのモデルを実装することです。
この時にりんごのおもちゃはそれぞれに製造番号がふられ、またそれぞれに違う色にすることができるとします。製造番号と色には以下の制約があるとします。
属性名 | AttributeName | 説明 | 制約 |
---|---|---|---|
製造番号 | Serial Number |
りんごのおもちゃにふられる一意な識別子のこと |
APPLE_{製造年月日}{製造年月日に製造された際に付与される連番} という文字列の形式 |
色 | Color |
りんごのおもちゃに着色される色のこと | 赤, 青, 黄色の3種類から選ぶ |
これらの情報をもとに簡単に実装してみます。
class AppleToy {
// りんごのおもちゃの属性を定義
public serialNumber: string
public color: "red" | "blue" | "yellow"
// りんごのおもちゃを製造する際に製造番号と色を指定する
constructor({serialNumber, color}: Props) {
this.serialNumber = serialNumber
this.color = color
}
}
// りんごのおもちゃを製造する際に渡される情報の型
type Props = {
serialNumber: string,
color: "red" | "blue" | "yellow"
}
// 製造番号 APPLE_20211201_001,赤色のりんごのおもちゃを生成する
const appleToy = new AppleToy(
{
serialNumber: "APPLE_202112010001",
color: "red"
}
)
※コードはわかりやすくするために雑に書いてます。
りんごのおもちゃには製造番号と色という属性があります。
製造番号には形式があり、色には3色という種類が決められています。上のコードでは形式外でも3色以外でも指定ができます。そこで使うのが制約を定義した値です。それが「値オブジェクト(Value Object)」です。値オブジェクトは制約ルールを記述したモデルです。
class SerialNumber {
// 製造番号の値を定義
protected value?: string
constructor(value?: string) {
// 製造番号の形式に間違いがあるとエラーを返す
if(!this.validate(value)) new Error("製造番号に問題があります。")
this.value = value
}
// 製造番号の形式に間違いがないかチェック
private validate(value?: string) {
return value && value.match(/APPLE_(19[0-9]{2}|20[0-9]{2})([1-9]|1[0-2])([1-9]|[12][0-9]|3[01])([0-9]{4})/g)
}
// 製造番号を文字列として返す振る舞い
public parseString() {
return this.value
}
}
同じ様に色も Color
という値オブジェクトを定義したとして、これらを踏まえてAppleToyの実体(エンティティ)モデルを修正します。
class AppleToy {
public serialNumber: SerialNumber
public color: Color
// りんごのおもちゃを製造する際に製造番号と色を指定する
constructor({serialNumber, color}: Props) {
this.serialNumber = new SerialNumber(serialNumber)
this.color = new Color(color)
}
}
// りんごのおもちゃを製造する際に渡される情報の型
type Props = {
serialNumber: SerialNumber["value"],
color: Color["value"]
}
// 製造番号 APPLE_20211201_001,赤色のりんごのおもちゃを生成する
// ここで形式違いの製造番号などを渡すとエラーになります
const appleToy = new AppleToy(
{
serialNumber: "APPLE_202112010001",
color: "red"
}
)
という感じで実体や値オブジェクトを定義する際に具体的な値から制約ルールをみつけて抽象化したモデルを使い、生成する値が正しいものかを判別します。また、コードを読むことで対象のモデルがどういったものかを読みとることができます。まさにモデルを共通言語にしてエンジニア同士での会話で齟齬が減ります。
まとめ
…とこの様に、デザイナーの工程もエンジニアの工程もモデリングと作成されたモデルを活用しています。モデリングとそれによって作られるモデルは何かを作る時や誰かと何かを共有する時にその効果を発揮します。
またデザイナーとエンジニア両方のモデリングやモデルでの理解を行うことで以下の様なこともできるようになります。
- 両職能の知識をモデル化できるので、両職能の架け橋になれる
- エンジニアが扱うモデルを理解しているので設計・実装を考慮したデザインができる
- デザイナーが扱うモデルを理解しているのでユーザ分析や設計を踏まえた設計や実装ができる
- 両職能の知識をモデル化できるので、事業設計や計画にも大きく関連するので事業に対してオーナーシップをとれる
それにデザイナーもエンジニアもビジネスサイドも要件定義の部分は基本共有されるべき情報です。この部分がモデルになっていたり、そのモデリングの過程を一緒にやれば理解度はほぼ同じ状態でそれぞれが具体的な工程に踏み出せると思います。
ちなみに、この記事を書いているちょっと前に技術顧問的なことをやらせてもらっている会社さんでモデリングワークショップを2日間にわけて行いました。最初エンジニアだけという話だったのですが、お願いして特別にPdM・デザイナーの皆さんも混ざってのチームでワークショップしてもらいました。
これまではPdMを中心に要件定義を行い、デザイナーが画面設計をエンジニアはそれらを踏まえて設計と実装を行うよくあるスタイルだったのですが、要件定義でモデリングする際にデザイナーもエンジニアも参加していれば良さそうだという声が聞こえてきました。
実際、具体的な要件を共有するのは中々骨が折れるし、その要件を理解するために必要なメンタルモデルを持たないメンバーがPdMのドキュメントと口頭で理解していくのはできなくはないですがかなり大変です。理解が追いつかず齟齬が生まれたりもします。そういった意味でもモデリングやそれでできたモデルを活用するのは単純に色々捗ります。
デザイナーとエンジニアという二つの職能をこなす必要はその人のキャリアプランに合わせてどうするか考えればよいですが、モデルとモデリングを活用することでデザイナーとエンジニアを1人でやっているのとほぼ同じ様な思考をチームで行うことも可能だと思います。モデル・モデリングを積極的にチームに取り入れると色々捗るので是非意識的に取り組んではどうでしょうか。
Discussion