前置き
業務Webアプリを作るためにはたくさんのことを決める必要があります。
この記事では、私が今思いつく業務Webアプリを作るための決め事を紹介しています。
業務Webアプリを作るにあたり、ここで紹介していることは、すべて、偉い人と相談したうえで決めて、メモレベルでもいいのでドキュメントとして残しておきましょう。
このくらい常識だろうと思うことでもしっかり説明や相談をするのがポイントです。
内容におかしいところがあれば指摘していただけると幸いです。
おかしいところだらけだと思いますが。。
排他制御
排他制御するのかを決める必要があります。
排他制御が必要な個所を洗い出す。(必要最小限にとどめよう)
楽観ロックなのか、悲観ロックなのかを決める。
楽観ロックでバージョン列を使用する場合、どのしょりで排他制御をするのかしっかり決めましょう。
必要最小限にしましょう!
削除フラグ
業務アプリといえば削除フラグ。
基本的に、削除フラグが必要な理由はトランザクションデータに表示されるマスタデータの情報を消したくないためです。たぶん、それ以外の用途はない。
よって、削除フラグはマスタデータにのみに設定します。
また、中間テーブルにはつけません。(主キーが他のテーブルのキーの組み合わせなので論理削除すると、同じキーのレコードを追加できなくなるので。回避方法があるかもですが、そもそもそんな必要性のないややこしいことをしたくない。)
ログ
ログの種類
・アクセスログ
・DBログ
・すべてのログ
ログに出してはいけないものの洗い出し
・パスワード
・個人情報
ログの書式
date{yyyy-MM-dd HH:mm:ss.SSS} [%-5le] [%t] %C.%M:%L - %m%n
←こんなの
プログラムに読みやすい形式(JSON)にしたり、
DBにログを出力したり、
いろいろあるみたい。
この辺は偉い人と相談しよう。
認証
ライブラリを使用するならライブラリの選定。
ライブラリを使わないなら自前で用意。
認証のライブラリは、使い方が難しいものが多いので、あらかじめ自分で使い方をマスターしておきたい。
プロジェクトが始まっていきなり調べて使うのは難易度が高い。
それと、パスワードはかならずハッシュ化しよう。
ORマッパー
使用するORマッパーの選定。
だいたい言語ごとにデファクトスタンダードなORマッパーがある、と思われる。
ORマッパーの機能をどこまで使うかは、チーム(と自分)のスキルレベルと相談。
ORマッパーを使ったことが無い場合、SQLでいいじゃんと思うかもしれないが、SQLの量が増えすぎて訳が分からなくなるので絶対にORマッパーを使った方が楽。
ただし、複雑なSQLは生SQLやビューで書いた方が楽。
静的型付け言語のORマッパーの場合、生SQLのSELECT結果を受け取る型(クラス)を作って、それをORマッパーに認識させる必要がある。その方法はどのORマッパーでも用意されているけど、調べるのが少し難しい。ChatGPTに聞こう。
あと、ChatGPTはSQLが得意なので、複雑なSQLを書くのに困っている場合はChatGPTに質問をするとよいと思う。
基本設計
API設計書と画面設計書のひな型を用意。
API設計書と画面設計書を作る。
DB設計書は基本設計の段階で作成しておく。(DBで表現するのに向いていない画面になるのを防ぎたい。DB設計を速めにやった方が楽。)
詳細設計
正直、基本設計と内容が重複することが多いので、いきなり実装でいいと思っている。(いた。)
ただ、設計しないまま実装すると、かなり行き当たりばったりな実装になってしまうので、詳細設計もした方がいいのかなーと考えを改めつつある。
詳細設計するとしても、丁寧にやらないと、ただの基本設計書のコピーになってしまう。
どれくらい時間を使うのか、何を詳細設計書に書いて、何を詳細設計書に書かないのか、しっかり研究する必要がある。。
API
使用するメソッドの選定。
ふつうどうするのか分からないけど、バックエンドが静的型付け言語で、かつ、フロント側のAPIにアクセスするライブラリがGETするときにリクエストボディを設定できなければPOSTオンリーでいい気がする。
特に制約が無いなら、POST、GET、PUT、DELETEでCRUDに対応させる感じかな。
※PATCHのAPIも実装しよう。フレームワークによっては簡単に作る仕組みが用意されてる。
レスポンスのルール決め
・HTTPステータスコード
・メッセージ
この2つはしっかり押さえておきたい。
バックエンドのフレームワークが生成するレスポンスも把握しておきたい。
この辺のルールを決めるのはかなり難しいうえに、影響範囲が広い。。
最近、自分が採用したのは、
レスポンスはすべてステータスコード200を返却
レスポンスボディは下記
{
ResponseCode: 1
Message : "あいうえお"
}
という感じのものだ。
ResponseCodeが0だったら成功とみなし、
そうでない場合は、処理を中断して、Messageに入っているメッセージを画面上部に出力する。
HTTPステータスコード400
バリエーションエラーの場合はフレームワークが勝手に400のレスポンスを生成するので、それを検出して、
{
ResponseCode: 2
Message : "Validation Error Message xxx"
}
みたい形に変換して、画面上部にメッセージを出す。
(基本的にバグが無ければ、クライアント側のバリデーションチェックに引っかかるので、サーバ側のバリデーションに引っかかるのはイレギュラーケースとしている。最低限、画面を使うユーザーからこんなのが画面に出てましたっていう報告をもらえるように配慮している。)
認証エラーもResponseCodeで表現する。
なので、200と400以外の場合はシステムエラー画面を表示するようにした。
この辺はAPIアクセス部品の共通処理とした。
何が正しいのか分からない。。
コードマスタ
コードマスタを使うか決める。
正規化してたらマスタが大量に増えるので使うのが無難なのかな。
使ってないプロジェクトで特に困ってなかったけど、最近のプロジェクトを思い返すと必須としか思えない。
わからん。
コードマスタのコードを保持するクラスを用意しよう。(判定処理で使う。)
ただ、コードマスタを用意して、SQLでセレクトするときに毎回ジョインしてっていうのは大変なので、Enumをうまく使ってコードを文字列に変換したほうがよいかも。
Enumがない動的型付け言語の場合はどうしてるんだろうか?
フロントエンドのフレームワーク選定
ReactとかVueとか。。
Blazorとか。。
そもそもバックエンドとフロントエンドを分割するのかも考えたほうがいいと思う。
基本的に、業務アプリにおいて、バックエンドとフロントエンドを分割するのは悪手になる。
(スマホアプリの場合は、しょうがない。)
理由
①フロントエンドの学習コストが高い
フロントエンドのデファクトスタンダードはReactだが、異様に学習コストが高い。
今まで簡単にできていたことが複雑な手順を踏まないとできないようになっている。
②フロントエンドとAPIを分離することで実装コストが増える
API設計書を書く必要がる。
わざわざAPIを介してDBアクセスするため、無駄な処理が増える。
・APIクライアントの呼び出し
・Controllerの作成
・リクエストの解析
・リクエストの入力チェック
・レスポンスの作成
・レスポンスの解析
バックエンドのフレームワーク選定
メンバーのスキルに応じて、メジャーなフレームワークを決めればいいと思う。
フロントエンドとバックエンドを分離しないフレームワーク
フロントエンドとAPIを分離しないフレームワークとしては
Blazor、Rails、SpringBootあたりがいいんじゃないかと思う。
業務アプリを作る業界だとJavaやC#を使える人が多いと思うので、BlazorかSpringBootかな。
例外ハンドリング
フロントエンド、バックエンドで例外が起きた時の挙動を決める。
・エラー画面に飛ばす
・エラーメッセージを画面上部に出す
・エラーメッセージをダイアログに出す
とかかな。。
DB設計書
A5SQLでER図を作る→ER図からDDLとDB設計書を出力
DB設計書からデータ型に対応するクラスを作るマクロを作る。
もしくは、スキャフォールディングがあるならそれを使ってDBアクセス部品を生成する。
「A5SQLでER図を作る→ER図からDDLとDB設計書を出力」という流れは鉄板だと思っているけど、なぜかあまり知られていない。デメリットは、地道にDB設計書やER図を作るプロジェクトに配属されたときにストレスを感じることだと思う。わりと馬鹿にできないデメリットではある。
※DBファーストと呼ばれる、スキャフォールディングでDBアクセス部品をDBのテーブルから作る方法はあまりよくないみたい。
コードファーストやマイグレーションといって、コードからテーブルを生成するほうがスタンダードらしい。確かに、いろんな記事を読んでもコードファーストについての説明が殆どだった。Railsチュートリアルもコードファーストだった。
自分も、直近のPJでは(偉い人に指摘されて)コードファーストを採用している。
なぜコードファーストにすべきなのか、ということも理解したい。。
DB設計
外部キー制約を使うかどうか
DBで表現するのが難しい画面が無いか
承認をDBでどう表現するか。複数人の承認が必要な処理とかは特に注意。
逆正規化をうまく使うとSQLがシンプルになったりする。
どういうクエリになるのか、考えると、いいテーブル設計が見えてくるのかも?
ステータス
業務フローを作成する際に、トランザクションデータのステータスの流れを整理する。
ページング
一覧画面の検索処理の時に、検索条件に合致するデータを全件取得するのか、そのページのデータだけ取得するのか。
UIフレームワーク、フロントエンド、バックエンドの相性次第なところがある。
たぶんフロントとバックを同じ言語にすればすんなりそのページのデータだけ取得する処理を作れる。
そうでない場合は地獄。フィルタ処理とか、ソート処理ごとに専用のロジックを組む必要がある。
庶民には厳しい修羅の道なので、検索するときに件数だけ取得して、一定件数を超えてたら条件を変えて再検索を促すメッセージを出すようにした方がいいと思う。ダサいけど現実的。
ビュー
ビューの乱立を防ぐためにビューをどういうところに使うのかのルールは決めたほうがいい。
一覧画面ごとに1つというルールでいいと思う。(詳細画面でも使えるし。)
ファイルアップロード
ファイルをbase64文字列に変換してリクエストボディにセットしてpostして、
API側でbase64文字列をバイト配列にしてって感じの方法を最近知った。
ファイル操作は結構考えることが多いし、深刻なバグを埋め込みやすい。
できればやりたくない。。
保存場所
S3
Webアプリから見えるフォルダ
DB?
ファイルサイズが小さいならDBに保存するのが楽かな。
ドキュメントのひな型
用意しておきたいひな型
業務フロー:業務の流れを定義する。シーケンス図っぽいのがいいのかなと思う。ExcelよりPlantUMLの方がよさそう。
方式設計書:排他制御とかファイルアップロードの方式を簡単にまとめた資料。Wordかテキストファイルでいい気がする。
基本設計書:画面イメージ、操作、入力チェック、呼び出すAPI、SQLなどを定義する。クライアントに見せる。
詳細設計書:具体的な処理の流れを記載する。基本設計書と詳細設計所は用意せず、画面設計書とAPI設計書を用意するほうがいい気がする。
基本設計書はクライアントに見せることと、実際にモノづくりしないひとがレビューすることから簡素になりがちだが、基本設計書に細かい仕様を記載しないと誰も仕様が分からないという事態に陥りやすい。なぜそういう仕様になっているのかもしっかり記載したい。
ファイルの命名規則
ダウンロードするファイルの命名規則
CSVとか帳票をダウンロードするときに、出力するファイルの命名規則。
帳票
帳票ライブラリの選定
バリデーション
メッセージの見せ方
あとがき
今まで平和に業務アプリを作ってたのに、いきなり1人でWebアプリを作れって言われたときに、何となく作り始めるのだけはやめましょう。私が思いつくだけでもこれだけのことを決めないといけないですし、ぶっちゃけ無理です。偉い人に、がんばって難しさを説明しましょう。できるだけ論理的に。
フレームワークに任せることで決め事を減らせそうですね。