見出し画像

正しいシステム設計の始め方

いつもお読みいただきありがとうございます。
もしくは初めましての方はよろしくお願いします。ゼバ会です。
本日は、システムを新規設計するうえで最初の難関となる、アーキテクチャー設計について話したいと思います。

もちろん世の中の大部分のプログラマーは、改修を生業としていて、アーキテクチャーそのものの設計を新規に行うことはほとんどないと思います。
とはいえ、だからって何も知らなくていいかというと、そんなことはありませんよね。

とりわけ小さなチーム/プロジェクトでは、新規システムの設計がエイヤで適当に行われていることも多く、そのせいでメンバーがその後何年にもわたってしなくていい苦労をし続けてしまうケースも見受けられます。
そういや最近テレビCMに「エイヤ大事ですよね」ってセリフありましたけど、あのCMには個人的に「いやもうおまえマジふっざっけんな」って言いたいです。
あとから辻褄合わせする人の気持ちも考えて。

極端な場合、たとえばモノの試しに若い子主導で始まったようなプロジェクトだと、「もう開発がスタートしてるのに決まっているのはフレームワークだけ」なんてこともありそうです。
(ありそうです、ってか、過去に実際ありましたしね、、、)

そんなプロジェクトにうっかり入ってしまった場合、ベテランとしては足りないところを追加提案とかしなきゃいけないわけであり、アーキテクチャー設計の知識は一通り持っておいた方がよさそうです。
まぁ、なんというか、自分自身の身を守るという意味でね。

個人的に、最低限やった方がいいと思うステップはこんな感じです。

STEP1. サービス内容の確約
  1.1. サービスフローを固める
  1.2. 必要機能の一覧を起こす
STEP2. インフラの構築
  2.1. インフラ/リソースとして何が必要かを確定
  2.2. 現在すでにあるリソース/ないリソースの列挙
  2.3. ユースケースとインフラからアーキテクチャーを確定する
  2.4. もっとも適した環境を選択(言語/フレームワーク/他)
  2.5. デプロイプランを作る
STEP3. チームビルディングの開始
  3.2. 足りないリソースの調達を開始する
  3.3. 開発環境の構築手順書を書く
  3.4. 開発フローの作成

ざっくりまとめると「1. どんなサービスを?」⇒「2. どこのインフラに?」⇒「3. どうやって?」の順って感じでしょうかね。

ちなみにもしかすると、上記リストのサービスフローを固めるの部分について、エンジニアの仕事じゃないように感じた人もいるかもしれません。
ですが残念ながら、このサービスフローを作る作業は、エンジニアでないとできない仕事です。
もちろんプロジェクトの総責任者と二人三脚で考えることが前提ではあるのですが、このサービスフローは「お客さんをどうしたいのか」と「コンピューターがどんな動きをするか」の両方が分かっていないと作ることはできないからです。

なおかつ、これが出来上がっていないことには、とりあえず環境だけ作れって言われても無理なものは無理です。
なのでプロジェクトに入ったとき、サービス内容の確約をクライアントが求めているならエンジニアが請け負う必要があるし、あるいはそうでないのなら、ちゃんと確約するようリーダーに要求することがエンジニアの仕事になります。

STEP1 機能の一覧の前に、まずサービスフローありき

大切なことなので、ここでサービスフローなるものについて、もう少し詳しく説明します。
ただしこのサービスフローという呼び方は実は我流の言い方でして、世の中的には、、、、なんて言うんでしょうね?
サービスの基礎設計者はなら必ずみんな作ってるはずなんですが、なんでか、デファクトスタンダードになる言葉がないのです。
作るのがあまりに当たり前すぎるから、、??
だから個人的に勝手にサービスフローと呼んでいます。
(この段落を書くために PIMBOK の本を読み返してみたけど、それっぽいのはやっぱなかったっス、、、)

マーケティング用語だと「カスタマージャーニー」とか「パーセプションフロー」なんて言葉もあるんですけど、イメージとしてはそれらが近いでしょうか。
要は、お客さんが、どんなことをどんな順番でやるのかの手順書です。
もしくは立場を逆に「お客さんにやってもらうことリスト」、「お客さんが満足するまでの工程」なんて言い方でもいいと思います。

たとえばWebを使ったゲームのサービスの場合、「アカウント登録 ⇒ ログイン ⇒ キャラクター作成 ⇒ チュートリアル ⇒ ミッション ⇒ クリア報酬の精算 ⇒ 追加要素の各種管理」といったところでしょうか。
ゲームのサービスはお客さんに楽しいと感じてもらうためのサービスなわけですから、お客さんが楽しいと感じるまでの手順書が必要になるのですね。
同じようにビジネス業務アプリの場合は、お客さんが「ひと仕事終わったぜイエイ♪」と感じるまでの手順書になります。

言うまでもなく、この世のありとあらゆるサービスは、このフローが存在することがありきです。
この世の全てのプロジェクトは、お客さんに喜んでもらうために存在しているので、よって喜んでいる状態にどういう順番で達するかの設計は必須のはずなのです。

なのに大部分のシステムプロジェクトは、このフローが(最高責任者の頭の中にしか)ないのにいきなり画面一覧表とか作りだしちゃうケースもあって、そのせいで出来上がってきた画面に、最高責任者が望む機能が搭載されていないなんてトラブルもしばしあります。

まぁ、要は、システムの設計者であれば、大なり小なりそういうものを頭の中で作ってから製造を開始しているはずです。
私が言いたいのは、それを1度設計書に起こしてみませんか? ってこと。

良いモノづくりのためには絶対あった方がいいので、次に機会に一度作ってみるといいと思います。
もしくは現時点で携わっているシステムにそのような設計図がないのであれば、作ってみてください。
総合テストがめっちゃくちゃやりやすくなります。

少し考えたらすぐ気づいてもらえると思うんですが、一般に必要機能の一覧と呼ばれるものは、まずサービスフロー(に該当する何か)を作ってから、そこから「お客さんがこういう動きをするのなら」「システムはこうあるべき」という作り方をします。
てゆーか、そういうじゃなきゃ作れないはずです。

ですがサービスフローをドキュメントに残さない現場も多いため、開発段階に入ってから「なんでこんな機能が必要なんですか?」という問い合わせが設計者のところに頻繁に飛ぶことになるわけです。

STEP2 インフラ/リソースの確定

インフラエンジニアの方であれば、必要インフラのリストアップが不得意な人はなかなかいないと思いますが、アーキテクチャー設計を始める段階で、設計作業に必要な情報が十分そろっていないケースは多いです。
(メールサーバーを搭載するかどうか決めなきゃいけないのに、メール発信機能を付けるかどうかが決定していない、とかね)

そういうときは本人の過去の経験から「多分必要だろう」くらいの予想でリストを作ると思います。
が、そのようなケースで、なおかつ開発部と営業部が完全に分断していて互いに意思疎通がない、といった会社は要注意です。

そういう会社に長く居すぎたエンジニアは、プロジェクトリーダーの要求仕様を満たしているかだけでアーキテクチャー設計をしてしまう傾向もあり、そのうちの一部の人はそれが正常じゃないことに気づいていません。

インフラやリソースというものは、お客さんを喜ばすために必要なことが全部できるように取りそろえるものです。
言うまでもなく、システムというのは組めればそれでいいわけではないし、中には後からでは追加できないインフラなんてものもあるのですから、アーキテクチャー設計を担当する人はやはりクライアントの要求仕様を直接見聞きすべきです。
そのためにはキックオフミーティングに最初からエンジニアリーダーが入るのが理想的ではありますが、仮にミーティングの場に参加できなくてもサービスフローがあればある程度の予想はしやすくなるはずです。
特に出来上がってからのクライアントからの戻りが多いと感じることが多いチームの方は、サービスフローを作った方がいいでしょう。

「カスタマージャーニーの作り方」みたいな系統の本にやり方が書いてあるので、1度くらいはそういう本を読んでみてもいいと思います。
お客さんがやりたいことの一覧が用意できれば、そこから「ユースケース1つあたりの複雑さの予想」とか「モジュール設計図」なんてものも作りやすくなるはずです。

次に、開発段階に入ってから発見されがちなアーキテクチャー設計でもっとも典型的なトラブルは、処理内容が複雑なのに、その複雑さを吸収できるだけの十分なディレクトリーがないというケースでしょう。
ビジネスロジックが複雑なシステムは、そのディレクトリー構造も整理しやすくなっていなければいけません。
ですが通常世の中の多くのフレームワークでは、ビジネスロジックを入れる専用のディレクトリーは特に用意されていないので、本来はシステムロジックが入るはずだったディレクトリーに、ビジネスロジックがバラバラに混ざった状態で入っているケースは多いです。

そのような初期状態の環境を末端のエンジニアに投げつけたら、ビジネスロジックとモデルが両方とも全て、スパゲッティのままコントローラーに直接書かれる、なんてことにもなってしまうかもしれません。
そんなことになったら、それを後からメンテナンスする人はとても大変です。
もしくはさらに複雑なシステムになると、ビジネス層やモデル層を2つに分けなきゃだったり、モデル層にアウトプット先ごとの異なるドライバーが必要だったり、あるいはそこそこ凝ったモジュール設計が必要なことだってあるかもしれません。

それらがバラバラに混ざってしまわないよう、「ビジネスロジック」「モデル処理」等々、そういう系統のものをそれぞれどう格納するかは、アーキテクチャーの設計担当者が自分で決めなければいけないのです。

で、そこまで資料がそろえれば、「このような構造を一番作りやすいフレームワークは?」と発想するのは多くの人には自然なことでしょう。
まかり間違っても「俺が好きな最新型だから」なんて理由でフレームワークを選ぶことはなくなるはずです。

STEP2.5. デプロイプラン

それからインフラ設計を進めていくうえで最後に絶対にすべきなのは、デプロイプランを作ることです。
通常多くのチームでは、デプロイプランは「一般的な構成だから完成間近になってからでいい」と判断されがちです。
ですが、これは非常に危険です。

たとえサーバー構成が一般的であったとしても、たとえば以下のように両立できない問題が発生することだってあります。

・ミッションクリティカルなシステムなので、停止はできない
・ミッションクリティカルなシステムなので、DB定義変更とプログラムリリースは常に同時でなければならない

仮に上記の要件が両方とも発生してしまった場合、本番サーバーが1台構成だと解決はもう絶対に解決不可能です。

上記の例の場合、リリース専用のタンデム構造(いわゆるブルー/グリーンデプロイ構造)なんてのを用意することで解決可能ではあります。
ですが、そのような環境をあとから準備するのは純粋に予算増であり、クライアントに追加予算を要求するという、おそらくこの世で最も胃の痛い話題が登場してしまいます。
上記に加え、さらにシステム全体がクラスター化されていてローリングデプロイが必要なんてことにでもなれば、その追加予算額が幾らになるのやら、考えたくもありません。

つまりデプロイプランを作ることとは、自分達がやろうとしてることが実現可能かどうかをテストするのと同じことなのです。
ですので、これは絶対に計画初期段階で作るべきです。

STEP3. 最優先事項の意思統一

アーキテクチャー設計の最後に、開発前の段階における最重要事項の決定をします。
もしプロジェクトリーダーがエンジニアリングに疎い場合、アーキテクチャー設計者がクライアントと直接交渉しなければいけません。
それくらい大事なことです。

それは、以下の4つのうちどれが一番大事かを決めることです。

1. システムの安定性
2. 開発期日
3. 予算
4. 要件の網羅性

「全部大事」はありえません。
この4つの要素は絶対に並立させることはできません。
もし本気でそんなことをいうクライアントなら、即刻プロジェクトを中止して取引を打ち切るべきです。
それはパワハラだからです。

もしくは「全部そこそこ大事」くらいの口調なら、それはクライアントが優柔不断なケースですので、必ずどれか1つに絞る必要があることを教えてあげるべきでしょう。

たとえば銀行システムのような安定性ありきなシステムでは、「要件を網羅して期日も予算もちゃんと守る」のはとても難しいでしょう。
ですが中小企業向けの社内システムであれば、安定性にはある程度目をつぶれることだってあるかもしれません。

あるいは、開催期日の決まっているイベントの管理システムは期日ありきとなりますので、安定性・要件・予算のうちどれかが必ず犠牲になります。
もしくは予算ありきなシステムであれば、ない袖振ってもお金は湧いては来ませんので、安定性・要件・期日のいずれかを犠牲にするしかどうしようもありません。

それから、たまにあるのが、他の何を差し置いても要件を網羅していることが一番大事というパターンです。これは通常ありえません。クライアントが優柔不断か、でなければよっぽどの自信家なのか、あるいは両方か。
なぜなら、社内情勢・社会情勢は常に変化するものだからです。

最初に「要件の網羅がありき」を謳ってくるようなクライアントはまず間違いなく後から言うことをコロコロ変えてくるので、そのような顧客からは早々に手を引いた方がいいでしょう。

ポイントは、4つのうちもっとも大事にしたいことを1つ決めて、「この優先順で判断しますがいいですね?」という確約をもらうことです。
必要なら正式な契約書にその旨も織り込んでもいいかもしれません。

〇 まとめと次回予告

さて、ここまで決まれば、晴れて開発をスタートさせることができると思います。
メンバーとなる開発人員が入ってきて、複数名で開発することだってあるでしょう。

自分以外のメンバーが開発する環境になると、1人で開発していたときとは違い、他人の作ったコードに責任を持つ必要が出てきます。
そしてその責任を持つための方法論の1つとして、「コードルールを作って守らせる」という手法は昔ながらのよくあるものでしょう。
が、この「コードルールを作る」という方法論には1つ大きな欠点があり、それは「ルールの作り手に観点不足があるとトラブルが防げず、ただメンバーの手間が増えただけになる」ということです。

コードルールは、「防ぎたいトラブル」をあらかじめ網羅したうえで作る必要があります。
そのための重要観点はもちろんいくつもあるし、状況によっても変化はするのですが、次回は、その中でもっとも見過ごされがちなものについてお話したいと思います。
メチャクチャ重要なことなのに、これを防ぐためのルールがある現場はほとんど見たことがない、という話。
「バウンダリー違反」について。

プログラムには踏み越えちゃいけないラインがあって、それを超えるとバグが出やすくなるよ、って感じの話題です。

この記事が気に入ったらサポートをしてみませんか?