はじめに
WEBアプリ開発の設計について、学習する機会があったのでまとめてみます。
たまに設計書の修正やら、簡単な詳細設計をする機会はあるけど、全然勉強してこなかった人のチラシの裏です。
[読んだ本]
はじめての設計をやり抜くための本 第2版
忘れてはいけないこと
設計することは情報共有が目的であると知るべし
設計する時、必ず設計書・仕様書と名前のついたドキュメントを残していると思います。これはなんのために残すのでしょう?
言い方はいろいろあるかと思いますが、参考書では情報共有のためと表現されていました。当たり前すぎて、忘れがちなところです。
何も知らない誰かが見た時でも、ある程度把握できるよう、情報に不足がないことが大事なのです(戒め)。
設計の種類と目的
設計は大きく分けて、外部設計と内部設計に分かれます。設計の前に「要件定義」という工程もあったりしますが、あれは「開発工数を見積もるために、ステークホルダーに応じたシステムの機能を決定する」のだそうです。機能要件や非機能要件というのはこの辺で決まってきます。機能要件=システム利用者に提供される具体的な価値・ユースケースで定義される機能、非機能要件=それ以外の補助的な機能になります。
外部設計:要件定義で決まっていない外部仕様を決定する
≒基本設計・機能設計・概要設計
PJ関係者内での情報共有のために実施する側面もあるようです。これを見れば、どんなものかがだいたいわかるという設計書になります。
内部設計:実際にシステムでどう実現するかを決定する。
≒詳細設計・プログラム設計
プログラミングに進むために実施します。これを見れば実装できる、という設計書です。
設計書には、メンテナンスのための設計という観点もあります。開発が終わったあと、保守で必要になってきます。保守の時にも資料は必要ですね。
外部設計と内部設計の違い
外部設計は「システムがユーザーや外部システムに対して提供する機能やインターフェースの設計」です。なので、ここで明確にするべきは入力と出力になります。
内部設計はいわゆるプログラムの部分の設計です。外部設計で入力と出力が決まるので、内部は入力と出力の間で行われることを設計していきます。
外部設計ですること
参考書では下記の作業を外部設計の範囲で説明していました。
・ユースケース分析
・概念モデリング
・非機能要件定義
・画面設計
・外部システムIF設計
・バッチ設計
・帳票設計
・DB論理設計
ユースケース分析や概念モデルは知識的に必要ということで、著者曰く要件定義の段階に含めるところも多いとのことです。私の現場でも、上3つくらいは要件定義のあたりでやっているようです。
開発者的には、画面設計ぐらいからがよく関わる部分だと思うので、そのあたりから見ていきます。帳票設計はあんまり書いてなかったので、まとめは割愛します。
ユースケース分析や概念モデルについては、参考に読んだページを貼っておきます。
画面設計
やることは書いて字の如しです。画面設計で作成するものは以下の通りです。
UI設計ポリシー | 個々の画面に統一感のあるユーザビリティを実現するもの。画面のレイアウトパターンや機能パターン、項目数を決めたもの。 |
画面遷移図 | ユースケースのシナリオを実現するには、どんな画面が必要か。また、それらの画面がどう関連しているかを表現した図。 |
画面一覧 | 画面遷移図に登場した画面を一覧化して整理したもの。画面IDを採番すると良いとか。 |
画面モックアップ | 画面項目を明確にして、項目の配置や、実装前の画面イメージを確認するもの。画面遷移なども併せて確認する。htmlで実際に遷移の確認などができるようにしておくのが良い。 |
画面入力チェック仕様書 | 入力フォーマットやデフォルト値、必須か任意か、文字列や数値の最小値、最小文字数、最大値、最大文字数、利用可能文字などをまとめたもの。 |
これまで見てきた画面設計書では、対象機能の画面一覧、レイアウト、入力チェック仕様が書かれていることが多かったです。だいたい大きなシステムの時に、画面設計書を見る機会が多かったからかもしれません。大きなシステムでは、機能ごとに設計書も分かれています。その場合は、UIポリシーなどは全体に関わるため、別にしているでしょうし、モックアップもすべて作るというよりは一部だけ作成して、あとはレイアウトとして残すという感じになるのでしょう。画面仕様と別に外部仕様書などがある場合、入力チェックがそちらに細かく書かれていて、画面設計には落とし込まれてない、ということも間々ありました。二重メンテになるのを嫌って、どれかに書かれていればOKとするか、画面仕様書さえ見れば入力チェックがわかるようにしておくか、というのは難しい問題だなと思っています。現場や人によって、どこを重視するかが違うので一概に何が正解とも言えない気がしますが、個人的には、画面仕様書に統一するか、できないなら両方に書いとけば良いんじゃない?と思います。画面遷移図は今のところ見る機会はありませんが、時間がある時にでも探してみたいと思います。
外部システムIF設計
ネットワークやファイル交換などで、外部のシステムとデータを交換する部分についての設計になります。開発しようとしているシステムから、別のシステム(自社の基幹システムなり、他者のシステムなり)に個別の方法で連携するときに必要になります。
参考書曰く、接続先、プロトコル・手段、タイミング、インターフェース項目仕様、認証・セキュリティ、例外処理、が主な検討項目のようです。開発者視点でも重要な情報ですね。
外部システムとの連携は、相手方のシステムがうまく取り込んでくれるか、または自分がデータを処理するために相手方がどんな風にデータを渡してくるか、が大事です。なので、開発中同士のシステムの場合はこまめに確認が必要ですね。
バッチ設計
夜間バッチなどのイメージですね。ある時間になったら手動でキックされるプログラムです。これらの設計では、実行タイミング、実行制御・ジョブ制御、トランザクション、リカバリーについて検討せよ、とのことです。
実行タイミングや実行制御・ジョブ制御は、前後のバッチとの関連性を検討するということでしょう。トランザクションは、バッチ=だいたい大量データを処理する係なので、何件単位でコミットするか、パフォーマンスとのバランスを検討する必要がある、ということのようです。
DB論理設計
外部設計の段階のDB設計では、概念モデルをベースに、テーブルやカラム、キーの設計を行い、ER図を作成します。概念モデルをRDBで扱えるようにすることが目的ということです。論理ER図を作成して、テーブルを正規化します。Aが決まるとBが決まり、Bが決まるとCが決まる、というような従属関係でテーブルを整理していくわけです。
論理ER図の作成では、以下に注意します。
・主キーを決める
└データが一意であることを示すキーを決めます。テーブルに1個なのでよくIDが使われますね。
・関連を外部キーにする
└他のテーブルの主キーで、自テーブルから参照するために使われるキーを作ります。
・N対Nの関連を関連テーブルにする
└テーブルA.FKとテーブルB.FKだけを持ったテーブルを作るということですね。
・概念モデルの継承をリレーショナルで実現する
一番最後は、概念モデルを自分で作成した経験がないこともあり、ちょっと実感がわかずです。いずれわかるようになったら、説明文を追記します。
内部設計ですること
参考書では、下記の作業を内部設計の範囲で説明していました。
・画面プログラム設計
・ビジネスロジックプログラム設計
・データベースプログラム設計
・データベース設計
正直なところ、これまで見てきた画面プログラム設計等は、保守業務の時に役立った記憶がありません。唯一、データベース設計(DB定義書)はよく使います。
さて、これらが成果物となるからには、何か作成しておくべき理由があるはずです。理想的にはどんなことを目的に作られているのか、順繰りに見ていきたいと思います。
なお、参考書ではSpringBootを利用した開発を想定していました。ただ、MVCモデルのフレームワークであれば、気にするべきところは共通しそうでしたので、SpringBoot固有っぽい部分を省いてまとめていきます。
画面プログラム設計
画面プログラム設計としてやることは、Controller一覧、Controller設計書、画面共通部品設計書を作成することです。
Controller一覧
画面遷移図から洗い出します。静的なHTMLへの画面遷移以外は、Controllerが呼び出されます。それを一覧化します。
Controller設計
Controllerが実施する処理は以下とされています。
・リクエストパラメータのバリデーション
・リクエストパラメータの取得
・ビジネスロジックの呼び出し
・レスポンスへのデータ設定
・画面遷移
Controller設計はUML図を使って記述すると良いそうです。場合によっては、図の中にメモで文章を残すのも良いそうです。
UML図については、以下がわかりやすかったです。
役立った記憶のなかったController設計ですが、なぜ役に立たないと思ったのでしょうか。Controllerが実施する処理として記載された内容は、開発者的には決まっていると助かる内容です。それに、参考ページの図も見るだけでなんとなくやりたい事がわかるようになっています。原因を振り返ってみます。
1.クラス図、パッケージ図、シーケンス図のすべてが、そっくりそのままプログラム名の通りに書かれている。
これはおそらく、プログラムから逆起こししたことが原因でしょう。本来、事前に作成するものですから、プログラム名やメソッド名などは設計時点では不明なはずです。なので、日本語で処理内容を書いてあり、後から見てもどんなことをしたいのかがわかる、というのが理想でしょう。逆起こししなくてはならないシーンでも、人が見てわかる図を書くように努めたいものです。
2.図の使い分けがされていない。
基本的には1で書いたことがすべてな気がしますが、加えて処理内容について書いた図のほとんどがシーケンス図で、図の使い分けがされていなようでした。別にシーケンス図が悪いという話ではありません。例えば実体験として、登録されているデータに応じて表示画面が変わる処理で、分岐条件がどこにも書かれておらず、手間取ったことがありました。残っていたのはシーケンス図がほとんどだったので、もしかしたら分岐をどう書くべきか悩んで書けなかったのかもしれません。わかりやすさのためには、図を使い分けることも大事ですね。
プログラムをひたすら読み解くタイプの現場にばかりいましたが、実はちゃんと伝えるための設計書になっていれば、残すことにも意義があるようです。
画面共通部品設計/HTTP Sessionの設計
画面共通部品については、参考書はSpringBootを想定しているため、Tymeleafで書くよ、という感じでした。
あまり参考になるページも見当たらなかったのですが、ざっくり総合すると
・画面設計で設計したUIポリシーと画面項目を元に、ファイルを作ってしまう
・作ったファイルのファイル名と、どこに使われるかを一覧にまとめておく
ぐらいの感じでしょうか。
ここはもう少し経験値が溜まって、説明できるようになったら追記します。
HTTP Sessionの設計では、以下に気を付けます。
・どこで(いつ)生成するか
・どこで(いつ)破棄するか
・セッション情報として何を持たせるか
└大きすぎる場合はDBに持たせる等、手段も検討
ロードバランサなどで冗長性を持たせるようなシステムの場合は、セッションの共有についても考慮が必要なようです。
ビジネスロジックプログラム設計
ビジネスロジックはその名の通り、実際の業務に関する処理の部分です。この設計には、どんなアーキテクチャパターンで組むのかが重要です。利用するアーキテクチャパターンによって、ビジネスロジックをどこに持たせるかが変わってきます。
参考書では、ドキュメントとして書き起こす部分なのかどうかまで言及されていないようでした。なので、ここからは完全にイメージですが、どこにビジネスロジックを持たせたいのか、どんな思想(パターン)でプログラム化したいのか、が共有できると良いのかもしれません。また、一番処理の内容を書ける部分のはずなので、処理フローなどを記載しておくのがいいかもしれません。
おまけ
アーキテクチャパターンという言葉よりデザインパターンという言葉を先に知っていたのですが、別物なのでしょうか…。参考書では、アーキテクチャパターンで設計を進めつつ、必要に応じてデザインパターンを取り入れる、とされていたので、使いどころがそもそも違いそうです。
これもいつか説明できるようになったら追記します。
DBプログラム設計
DB論理設計では、概念モデルを元にテーブルやカラムなどを決めました。DBプログラム設計でも、概念モデルを元にエンティティクラス図を作成していきます。Javaで言うとgetter/setterが書いてあるやつ(雑)を作るイメージでしょう。この時に、概念モデルで日本語になっているクラス名や属性名を英語に直し、クラス間の参照を矢印で表現します。エンティティができたら、DAOクラス図を作成していきます。中身としてはCRUD+findメソッドを作っておきます。この辺りは、初めは必要最低限だけを作成しておいて、ビジネスロジックの処理の設計に応じて追記していくのが良いようです。
この他に、トランザクションについてもここで決定していきます。トランザクションの設計は次の2点に注意して行います。
・トランザクションスコープ
・トランザクションアイソレーションレベル(分離レベルとも)
トランザクションスコープは、データの整合性が取れるように、処理のどこからどこまでを1トランザクションとして扱うかを検討します。トランザクションアイソレーションレベルは「トランザクション間でコミットの有無によってデータがどのように見えるかを指定する」ものです。プログラムはスレッドなど、並行で処理を行うことができますが、DBの同じテーブルに対して操作を行う場合もあります。こういった時、コミットしていないデータを見られるのか見られないのかなどを検討します。基本的にはRead comittedとのことです。
アイソレーションレベルについては下記なども参考になります。
なお、トランザクションスコープを考える必要があるため、発行するSQLはこのあたりか、ビジネスロジック設計あたり、もしくは後続の物理設計のパフォーマンス設計と並行、なんていうこともあるようです。データ量が多いテーブルが対象の場合、パフォーマンスにも影響するので、その辺りも検討対象でしょう。
そのほか、データベースのロックについても検討します。集計処理などで、テーブルをロックするのか、行をロックするのか、処理に応じて決定する必要があります。
この辺りは、まず1番大事なのはデータの不整合を発生させないことを重視して考えるのが良さそうです。
また、コネクションプールについても考えていきます。いちいち取得すると時間がかかるので、使いまわすための仕組みですね。
初期コネクション数、最大数、などを検討します。最近、まさにこのあたりの設定をさんざん見る機会があり、コネクションのクローズ漏れがあると枯渇云々が発生するので開発時には要注意と学びました。
DB物理設計
物理設計では論理設計の方で作成した論理ER図から物理ER図の作成と、テーブル定義書の作成を実施します。
日本語のままでは使えないので、各テーブル名、列名を英語表記にするのと、型やサイズを決定します。型やサイズは、入力チェック仕様などを踏まえて決めていきます。
また、パフォーマンス設計もここで実施します。パフォーマンス設計で大事なことは
・I/Oを減らす
・インデックスでデータを見つけやすくする
・結合を簡単にできるようにする
・処理はまとめて行う
だそうです。取得するデータは(項目も行数も)必要な分だけとか、Prepared Statementを使うとか、そのようなことが対処法になってくるようです。インデックスもここで検討します。
そして、それらを元にテーブル定義書を作成していきます。記載事項はだいたいこの辺りとのことです。
・テーブル名
・スキーマ名
・論理列名
・物理列名
・データ型
・長さ
・精度(有効桁数)
・必須
・デフォルト
・主キー
・外部キー
・インデックス
これまで見てきたDB定義書だと、Null許容とかも記載されていました。あと、これは経験上の話ですが、保存するデータがコード値の場合は、コード値の詳細か詳細の参照先を書いておいてあげると親切かもしれません。
おわりに
ただの感想です。
一人で全部やる機会はないと思いますが、外部設計から内部設計までの一連の流れをさらっていきました。
どうやら、私はきれいに作られた設計書を見たことがなかったようです。今の現場は比較的ドキュメントがしっかり残っている方だと思っていましたが、ほどほどだったようです。いや、実はまだ見ぬドキュメントにいろいろあるのかもしれませんし、もしかしたら、どこでもそんなものかもしれません。
とは言え、自分の手元に設計書が流れてくるまでの間に、本来どんなことが検討されているべきなのかがわかると、設計書の見方や、修正時の情報の残し方が少しわかるようになってきます。
ドキュメントはわかりやすく、5年後の私が見てもわかるように書くをモットーにしていきたいと思いました。