とりわけプロダクト開発における 設計 の考え方をまとめようと思う。
荒削りであり、網羅性もないが、その中でも幹となる考え方をベースに、積み上げ式で整理をしていきたい。
これからこの文章は訂正され、洗練されていく。
「アーキテクト」というひと
アーキテクトとはなにか
(IT)アーキテクトと呼ばれるひとがいる。いわゆるシステム設計技術に長けた人物。
世の IT 企業の中にはアーキテクトとしての人材を募集しているところもある。 IPA には システムアーキテクト試験 というのもあって、アーキテクトの存在が明確に意識されている。この試験を受けたことも勉強したこともないけど。
アーキテクトは、必ずしも専任であるわけではない。というよりも、専任であるほうが珍しいくらいだろう。では兼任するものか、と言われれば、その言い方もしっくりこない。一人のエンジニアに「コーダーとしての人格」があるように「アーキテクトとしての人格」があるようなものに思う。
ここで重要なのは、 アーキテクト(と呼ばれる人格)は世にありふれており、それ故、アーキテクトが集まるコミュニティがある。そしてその周辺には、設計技術に対する体系的な世界が広がっている ということ。
つまり、システム設計に関して何か行き詰まりを感じるならば、このあたりから探ればよい。
アーキテクトになるには
いろんな言い方があるだろうが、少なくとも様々なアーキテクチャの 型 を学ぶことは、その必要条件としてあることを、きっと多くの人が賛同してくれるだろう。
ここで言う型とは例えば、 GoF(Gang of Four) に代表されるデザインパターン、またレイヤードアーキテクチャやイベント駆動アーキテクチャ、マイクロサービスアーキテクチャなどの有名なアーキテクチャのパターン、あるいは Dependency Injection, Clean Architecture, その他名前がついているわけではないがよく使われる設計手法、といったもの。なんとなく想像がつくだろうか。
型を学ぶことは必要条件なので、すなわち型を知っているだけでは不十分。それを使いこなせるようにならねばならない。
英語の学習が良い比喩となる。型を学ぶことが英語の文法を学ぶことであれば、文法を学ぶだけで英語が喋れるわけではないのは同様、型を知るだけでは不十分。英語を使いこなすために、実際にどのように活用されているかも知る必要がある。
さらに、英語学習に英会話による実践訓練もかかせない。アーキテクトとしても、実践を積む必要がある。
すなわち「抽象的な型を知る」「型の実際の活用事例を知る」「実践する」の 3 つに注目してそれぞれ具体的に述べるならば、以下のようになる:
抽象的な型を知る
これは教科書を見るのが一番よいと思う。一過性の情報を、ソフトウェアエンジニアリングの歴史とともにきちんと整理されていることが多い。特にオライリーの水色背表紙の本で、「ソフトウェアエンジニア」とか「アーキテクチャ」みたいな言葉がタイトルに含まれたやつを読むと良い。技術系の本はおよそ賞味期限があるので、特に特定のアプリケーションやフレームワークに関するやつは1年後には捨てるつもりで買うけれど、一方設計関連とかは多少古くても、コアとなるアイディアは不変であったりするので、買ってもあんまり後悔はしない。
以下に現時点のおすすめの本(というか僕が読んできた本)を並べておく。順番は気にしない:
- 進化的アーキテクチャ: 同じ著者の ソフトウェアアーキテクチャの基礎 もよい。だいたい同じことが書かれてある。進化的アーキテクチャのほうが本のサイズもコンパクトでよい。ソフトウェア・エンジニアリングについておよそ網羅的に書かれてる。
- リファクタリング: 古典。読んでおく。
- レガシーコード改善ガイド: 古典。読んでおく。
- UNIXという考え方: UNIXの設計思想について書かれた本。どの本を読んでもなんか既視感を覚えるのは、根本となる思想はここに大体書かれてるからとも思う。
- CODE COMPLETE: 古典。読んでおく。実際にコードをどう書くかについていろいろ書かれてある。
- Enterprise Integration Patterns: とりわけイベント駆動アーキテクチャに関する超詳細な専門書
-
Patterns of Enterprise Application Architecture
: これも古典
型の実際の活用事例を知る
これは OSS のコードを見るのが一番。これは必ずやる。
どういう OSS を選べばよいか。それは、自分が動作をよく知っているライブラリで、かつ有名なライブラリが良い。
動作をよく知っていないと、シンプルに実装を見たところでよく理解できないことと、良いと呼ばれる設計を学ぶのだから、多くの人に長く使われているもののほうがよい。
Python であれば以下とかあり:
- psf/requests: Python を使っていれば馴染みがあるし、シンプルでよく設計できてる。
- pytorch/pytorch: 機械学習してる人なら馴染みがあるだろうし、 pytorch はカスタムネットワークを組めたりするから、そういうのをどうやって実現してるんだろう?みたいな、アーキテクトぽい興味をそそるものでもある。
ちなみに、 OSS Insight もおすすめ。今どういう OSS が話題なんだろうか、ということを調べたいときはここから始めるとよい。今はやっぱり LLM が人気みたいね。
あるいは AWS のカンファレンスなどで、他の企業ではどういうアーキテクチャを組んでどういう問題を解決したかなどを見てみるのもよい。 Fortnite はサーバーの数何台か?どのように高頻度のリクエストをさばいているのか? Netflix はどうやって複数デバイスで再生時間の同期をとっているか?
こういうのは、カンファレンスの資料やテックブログなどに書いてある。
そして面白いことに、そこに書いてあることは、だいたい本の中に書いてあるなにかと符合する。
実践する
これはそのまま。自分で設計をしてみる。
数学でも、難しい問題を解いてみようとして、はじめて基礎のありがたみがわかる、という経験をする。今回もそれ。
理論を覚えたばかりにときに、それを思わず適用させたくなる症候群に罹ってしまいがちだけれども、それも含めてまずやってみて、適切なバランスを知る。
そして、具体的なアウトプットは 設計書 である。
アーキテクトとしての態度
この語り方が多く存在することは承知の上で、ここでは 3 つ述べる。
プロダクトを体現する設計をする
超当たり前なのだが、重要なので述べておく。
プロダクトとは、受託案件でも自社プロダクトであってもどちらでもよいけれども、抽象的な意味で「今から作るもの」。
ここではわかりやすく自社プロダクトを作ることを考える。
当然だけれども、アーキテクトは自社プロダクトを体現するために必要な設計をする。
ここを深ぼりたいので、プロダクトマネジメントについても話しておきたい。
以下は有名な プロダクトマネジメントのすべて の枠組みに沿って話す。プロダクトマネジメントについては色々な語り口があるが、この枠組みで説明されることが表現を変えて現れているようにも思う。
「プロダクトの提供価値」というとき、以下の Core, Why, What がセットで語られる。上から順に基礎となる。つまり、 Why は Core に依存しているし、 What は Why に依存している。
- Core ... ミッションとビジョン、世界観
- Why ... 「誰」を「どんな状態にしたいか」
- What ... それを「何で」解決するのか、解決策
Core とは、プロダクトの世界観。これがはっきりしていないと、例えばあなたが Apple 社員だとして「 iPhone に HDMI をつけてほしい」と言われたときに、明確にそれを否定することができない。
Why は、「誰」がどのような pain を抱えているのか、あるいは gain を必要としているのかを分析し、このプロダクトを介して「どんな状態にしたいか」を定義するもの。
What は具体的な解決策についての言及。
アーキテクトや開発の仕事は、 What にさらに依存した How の話。
- How ... 具体的な実現方法
つまり、アーキテクトの重要な仕事は 上段で定義されたプロダクトの提供価値を、具体的に形にする ことにある。
これはすなわち、アーキテクトは プロダクト提供価値について、明朗に語れなければならない ということ。
さらに、アーキテクトは設計段階で プロダクトの提供価値がたしかに実現できそうだ、という見込みを立てなければならない。
これは、アーキテクトの第一義の仕事であろう。
ロバストな設計をする
プロダクトは進化していく。プロダクトのビジョンも変わっていく。それに伴い、当然システムも変わっていく。しかも、その速度は速い。
ということで、システムが変化することを変更しにくい部分をなるべく小さくするような設計 を志向する。
変更しにくいとは何か。それは例えば、 ある部分を変更しようとすると連鎖的に見るべき場所が増えて、全体としてシステムの不安定さを感じてしまうこと 。
裏を返せば、変更しやすいとは、その変更を加えても変更箇所が小さく閉じること。つまりシステム全体として安定し続けること。
これをシステムのロバストネスと呼ぼう。
アーキテクトはロバストネスを志向する。
トレードオフを理解する
Laws of Software Architecture というものがある。アーキテクチャの法則、という意味だけど、ここには 2 つの法則がある。
1つ目が
ソフトウェアアーキテクチャにまつわるものすべて、トレードオフである。
これの Collorary として、
アーキテクトが、トレードオフではない何かを発見したとしたら、それは(トレードオフではないのではなく)単にトレードオフを見つけられてないだけ。
こういうのを法則と呼ぶのに、数学や物理に馴染んできた僕からは違和感を覚えるのだけども、 IT には、例えばコンウェイの法則とかムーアの法則とか、とりあえずこういうのを法則と呼ぶのりがあるので、それと同じものだと理解している。
前置きをしたけれども、この法則には経験的に賛同するところがある。トレードオフがあると感じる経験は体感で多い気がする。いわゆる銀の弾丸は無い、というやつ。システム設計の中で何かを選択したら、一方で何かを犠牲にしている、と思っていたほうがよい。
設計が全部トレードオフであるとするならば、僕らがやるべきは 私達が何を選択して、何を犠牲にしたかに、自覚的であること であろう。
では、そのトレードオフをどのように知るのか? -- 勉強する。故にアーキテクトは勉強し続けないと仕事にならない。
さて、ここで重要なのが「なぜその選択をしたか?」という観点。
ここに第2法則が刺さる。
Why は How よりも大事
ロバストネスの話に戻るけど、設計を変更しにくい理由の一つは「なぜその設計になっているか?」が全くわからなくなっていること。
一見重要そうな設計のパートが、実はえいやでてきとーで決められてた、ということもある。そんなしょうもない理由なら、と思うと、修正するハードルもぐんと減る。
この文脈のまま次へいこう。
設計書: アーキテクトのアウトプット
設計書 はアーキテクトのアウトプットのメインになるもの。設計書を書かない人はアーキテクトではない。
設計書には何が書かれるべきか?
それは上に述べたアーキテクトの態度として表現したものが入る:
- プロダクトの提供価値を実現する方法
- トレードオフや他のありうる選択肢を考慮して、なぜその設計に決めたのかの理由(Whyを書く)
1番めは当然設計書に含まれるべきことなので特に迷わないのだけど、特に2番めに注目したい。
設計を変更しようと思ったときにめちゃくちゃ困ることの一つは、なぜその設計になったかの理由が存在しないこと、であった。それがない場合、そもそもなんでこうなっているのか、これを変えることによって何が起きるのか、の調査をしなければならない。その調査を苦労してやっている途中で、当時を知る人が「あ、その設定はテキトーっす。変えちゃっていいっすよ」みたいなことを言って脱力する。
こういうことが起きないようにする。 設計書に Why が書かれることそのものが、ロバストネスなシステムを作ることに直接繋がっている.