要件定義とWebアプリケーション設計について体系的に学びました。

Posted date at 2024-11-02

Design

TypeScript

joanna-kosinska-bF2vsubyHcQ-unsplash.jpg

 Udemyでアプリケーション設計について学びましたので、知識のアウトプットを兼ねて以下2点を共有します。

  1.学んだこと

  2.AP課日報のバックエンドの1つに取り入れた結果


🚀Udemy講座と学んだこと

 講座名:リバーシで学ぶアプリケーション設計入門〜仕様の整理からTypeScriptでの実装まで〜

 講師:大嶋 勇樹 さん

 動画再生時間:9.5時間(林がかけた時間:40)

説明文

 リバーシ(オセロ)のWebアプリケーションの開発を題材として、要件定義からクラス設計、アプリケーションの実装、リファクタリング(改修)までを行いました。

 要件定義と仕様整理ではアウトプット(資料)の作成方法を学びました。

 設計と実装においては、「3層アーキテクチャ」、「サービスクラス」、「ドメインモデル」と呼ばれる典型的なデザインパターン(オブジェクト指向設計)を学びました。

 以下、私の感想を載せておきます。

review.png


 

🚀要件定義と仕様整理

  具体的に仕様を決めるまでに、いくつかの図や文書を作成します。図の作成には、講座ではDrawIoをVSCodeの拡張機能で使用しました。こちらではそれぞれの資料の役割を説明します。

🐡コンテキスト図

  登場人物を整理した図になります。開発する対象のシステムと、関わる人や他のシステムを整理します。

context-diagram.png


🐡ユースケース図

 登場人物がシステムで何をするかを整理した図です。粒度の設定に留意する必要があります。

 (個人的には、この図については担当課と詳細に詰めたほうがいいのではと考えています。この図がビジネスにおいて、アプリケーションが行うこと(範囲)を決定づけるものだと考えられるためです)。

 

use-case.png


🐡クラス図(概念モデル)

 クラス図を使って概念を整理したものです。データベースの設計やアプリケーションの設計の際に立ち戻って確認する図になります。概念(後でクラスになりそうなもの)の役割がある程度決まります。

 (講師も概念モデルの設計はじっくり時間をかけて行っているとおっしゃっていましたが、後述する小さなアプリでこの作業をした際に、私はこれが一番難しいと感じました)。

conceptual-model.png


🐡機能一覧

 ユースケース図を見て、ユースケースごとに機能を書いていきます。階層的に詳細を書いていきます。

(個人的には、実装の工数をある程度想定するためにも、自分の中で関数やロジック(難易度)がイメージできそうな解像度で書くのが良いかなと思っています。)

# 機能一覧 ## ユースケースごとの機能一覧 - 「対戦する」ユースケース - 対戦を開始する - 盤面を見る - 石を打つ - 勝敗を確認する - 「過去の対戦結果を確認する」ユースケース - 自分の対戦結果を表示する ## 石を打つ機能について - 内部には以下の処理がありそう - 選ばれた位置に石は打てるのかチェックする - 石を打つ - ひっくり返す - 次はどちらの番か判断する - ※打てない場合は自動でスキップする - (勝敗が決まったら)対戦を終了する ## プレイヤーについて - プレイヤーの登録機能は設けない - このアプリケーションは自分の PC で立ち上げて、自分一人だけ遊べることにする

🐡画面イメージ

 実務ではFigmaを使用して、フォントやカラーの統一的なデザイン、画面遷移なども制作するようです。

ui.png


🚀設計(技術選定・API設計・DB設計)

 要件定義と仕様が固まったら、設計に入ります。まず、アプリケーションで使用する技術選定をした後、バックエンドの場合、API設計、DB設計を行います。

🐡技術選定

 要件定義に基づき最適な技術選定を行います。

個人的に、ここで普段どれだけ技術に触れているか、学習しているかの差が出ると思っています)。

 〇Webアプリケーションの場合

 フロントエンド:フレームワーク(React、Vue、Svelete等)、ライブラリの選定

 バックエンド:使用する言語(Ruby、Node、PHP等)、フレームワーク(Express、Rails、NestJS等)の選定

 データベース:RDBとNoSQL、DMBMSの選定(MySQL、PostgreSQL、Firebase、Superbase等)

 インフラ:オンプレとクラウド、使用するクラウドサービスの選定


🐡API設計

 機能一覧を見ながら、APIの機能を記述していきます。完成したらOpenAPIを記述してhtmlとして後で確認できるようにします。

#API 設計メモ ## 「対戦する」ユースケース ## 対戦を開始する 「対戦」を登録する POST /api/games ## 盤面を見る 現在の盤面を表示する ⇒ 指定したターン数の「ターン」を取得する GET /api/games/latest/turns/{turnCount} レスポンスボディ json { "turnCount": 1, "board": [ [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 2, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 2, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0] ], "nextDisc": 1, "winnerDisc": 1 }

openapi.png


🐡DB設計

概念モデルとAPI設計メモを見ながらテーブルを設計します。(講師はAPIとDB設計のどちらが先でも良いとおっしゃっていましたが、個人的にはDBが先の方が良いと思います。理由は改修コストが大きいDB基準で設計を考えたいからです)。アウトプットはER図で作成します。

er.png


🚀アーキテクチャ

 アプリケーションの設計を行います。この分野はアプリケーションアーキテクチャと呼ばれます。

🐡そもそもアーキテクチャとは

 ソフトウェア開発と関連する範囲では、以下のように様々な分野があります。

 〇コンピュータアーキテクチャ(CPUアーキテクチャ)   ⇒パソコンのこと(例:ノイマン型コンピュータ)  〇アプリケーションアーキテクチャ⇐今回取り扱っているもの   ⇒アプリケーション自体をどのように構成するか(例:3層アーキテクチャ)  〇インテグレーションアーキテクチャ   ⇒システム間連携をどのようにするかという部分(例:kitnoneとスプレッドシートをBizteXConnectで連携)  〇インフラアーキテクチャ   ⇒サーバやネットワークの構成をどうするのかという分野(例:GoogleCloudのVPCとComputeEngineを使用する)

🐡アプリケーション設計の基本(3層アーキテクチャ)

 3層アーキテクチャという言葉の指す分野は2つあります。1つめは以下のものです。(こちらは私も知っていましたし、皆さんもご存じかと思います)。

three_layer_1.png

 今回学んだのはこちらです。アプリケーション内部(実装)における3層アーキテクチャです。

thee_layer_2.png

🐡各層の役割

 〇プレゼンテーション層

  ユーザまたは、API呼び出し元との直接的なやり取りを行うもの。ユーザまたはAPI呼び出し元からのデータに対するバリデーションチェックやビジネスロジック層が必要な形式への変換や、ユーザまたははAPI呼び出し元への最終的なレスポンスの返却を行います。

 〇ビジネスロジック層(アプリケーション層+ドメイン層)

  リバーシで言うと、石を置く、石をひっくり返す、勝敗を判定するなどのアプリケーションで解決したい課  題を解決するための処理を担当します。

  さらに、処理の流れを担当するアプリケーション(ユースケースとも呼ばれる)と処理そのものを担当するドメインに分割して設計します(例:石を置く、石をひっくり返す、勝敗を判定する処理⇒ドメイン。各ドメインを呼び出すもの⇒サービス)。

 〇データアクセス層(インフラストラクチャ層)

  DBとのやり取りを行うもの。SQLやORマッパーを記述します。

  

🚀設計(アプリケーション)

 3層の役割を意識して各層のクラスの構成を図にします。RouterやService、Modelなどには、具体的な名前を付けます。リバーシのターン情報を扱うクラスの場合は、「TurnRouter」、「Turn」、「TurnRepositrory」、「TurnRecord」、「TurnGateway」としています。

architecture2.png

🐡実装段階のクラス図の作成

 次に各クラスの依存関係、メンバやメソッドについて記述します。クラス図を書き終えたら実装に移ります。

 なお、AがBに依存しているというのは、AがBを呼び出している、TypeScriptで言うとAがBをImportしていると言い換えることができます。

domain-model.png

🐡実装で気を付けること

 各層の役割を超えた機能を実装していないか。(例:ビジネスロジック層のクラスにSQLを書いていないか)

 クラスの機能分担が適切か。(例:getterを必要以上に呼び出している⇒メンバやメソッドを依存元クラスに持たせた方がいいのでは?)

🐡目指すべき設計

 クラスの依存関係がドメイン層にあつまる設計が良い設計となります。(個人的にはまずは3層を意識するところから始めようと思います)

bestpractice.png

 上記の構成を反映した3層アーキテクチャです。矢印が真ん中に向かっています。

query-service.png


🚀AP課日報アプリでの実践

 AP課日報の小さなバックエンドで練習しました。

 1日に1回前日に追加された日報データを対象として、kintoneとFirestoreで同期をとるアプリケーションです。

 あまりしっくりした感覚はないですが、コードの見通しは良くなりました。以下に、要件定義と設計資料を示します。

🐡コンテキスト図

context-diagram.png

🐡ユースケース図

use-case.png

🐡概念モデル

conceptual-model.png

🐡機能一覧

# 機能一覧 ## ユースケースごとの機能一覧 - 「日報データを取得する」ユースケース - kintone から前日に作成された日報データを取得する - firestore から前日に作成された日報データを取得する - 「日報データを更新する」ユースケース - 追加・更新・削除を判断する - kintone のデータで firestore を更新する ## 追加・更新・削除を判断する機能について - キーについて  - キーは kintone のレコード番号とする - 追加 - kintone に存在し、firestore に存在しない場合 - 削除 - kintone に存在せず、firestore に存在する場合 - 更新 - kintone と firestore の両方に存在する場合 ## スケジューラについて - 0:00 に実行するようにする - GoogleCloud の CloudScheduler で実行する

🐡アーキテクチャ

architecture.png

🐡クラス図(ビジネスロジック層)

domain-model2.png


🚀まとめ

 要件定義、仕様検討に関しては図を使用することで業務担当者との打合せがしやすくなるのではと思っています。次に開発するアプリケーションから取り入れたいと思います。

 オブジェクト指向については、役割分担(何をクラスにして、どのクラスで処理をさせるか)が難しいと感じます。こちらは、デザインパターンについて内化(学習)をしつつ、いただいた仕事の中でも実践していこうと思います。

 次は有名なデザインパターンを学習したいと思います。

 

←ホームに戻る