Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

改めて整理するアプリケーション設計の基本

os1ma
October 20, 2022

 改めて整理するアプリケーション設計の基本

●発表のアーカイブ動画はこちら:https://youtu.be/4rgGkoyUaZw

●発表の中で紹介しているUdemy講座:https://www.nextskill.co.jp/courses

===

プログラミングの基礎を学び、アプリケーション開発に実践的に関わり始めると、「MVC」「サービスクラス」「ドメインモデル」「クリーンアーキテクチャ」といった、よく分からない単語に遭遇します。

これはいわゆる「アプリケーションアーキテクチャ」という分野の話で、アプリケーション開発に関わり始めると、誰もが突き当たる壁の一つです。

今回はアプリケーションアーキテクチャを学ぶ最初の一歩として、「MVC」や「3 層アーキテクチャ」などの、基本的な用語の意味や関係性を整理します。

発表者が過去に書いた以下の記事を中心に、+α の内容を加えた発表になります。

・「ビジネスロジック」とは何か、どう実装するのか (いいね1700+)
https://qiita.com/os1ma/items/25725edfe3c2af93d735
・MVC、3 層アーキテクチャから設計を学び始めるための基礎知識 (いいね400+)
https://qiita.com/os1ma/items/7a229585ebdd8b7d86c2

os1ma

October 20, 2022
Tweet

More Decks by os1ma

Other Decks in Programming

Transcript

  1. 自己紹介 • 名前:大嶋勇樹(Twitter:@oshima_123) ◦ 最近はよく「しま」と呼ばれています • キャリア ◦ 都内の某 IT

    企業 -> フリーランスエンジニア -> 会社設立 ◦ “ ” 現在は 実務につき始めたエンジニアのスキルアップをサポート ◦ 研修・勉強会の開催・Udemy 講座の作成など • 関連分野で過去に執筆した記事 ◦ 「ビジネスロジック」とは何か、どう実装するのか(いいね 1700+) ◦ MVC、3 層アーキテクチャから設計を学び始めるための基礎知識(いいね 400+)
  2. Udemy 講座の紹介 Linuxとネットワークの基礎から学ぶDocker入門 Linux とネットワークの基礎知識から Docker を使った開発環境構築まで、 手を動かしながら学習する講座 JavaScriptで学ぶWebアプリ開発の必須知識 〜Node.js・Web

    API・Ajax・async/await〜 「なんとなく」Web アプリ開発に入門で壁になる、Web アプリの仕組みと JavaScript の重要知識を、実際にコードを書きながら学習する講座 リバーシで学ぶアプリケーション設計入門 〜仕様の整理からTypeScriptでの実装まで〜 「MVC」「3 層アーキテクチャ」「サービスクラス」「ドメインモデル」など アプリケーション設計の基本を学ぶ講座 今日の発表は、こちらからも抜粋 先日リリース
  3. 今日のテーマ • ここからは、アプリケーションアーキテクチャの中でも、まとまって 動作するコードの構成をどのように整理するかがテーマです • この分野には、以下のようなキーワードがあります ◦ MVC、MVVM、MVP、... ◦ トランザクションスクリプト、ドメインモデル、...

    ◦ リポジトリ、アクティブレコード、... ◦ 3 層アーキテクチャ、レイヤードアーキテクチャ、クリーンアーキテクチャ、... フロントエンド サーバサイド データベース この中をどのように整理するか
  4. Web アプリケーションの 3 層構造 • Web アプリケーションの基本構成は、Web サーバ・アプリケーション・DB の 3

    つから成り立つ 3 層構造です • この 3 層構造を「3 層アーキテクチャ」と呼ぶことがあります Web サーバ アプリケーション DB 固定の HTML・CSS・JS などを返し、 プログラムによる処理が必要な場合は アプリケーションに依頼する プログラムで HTML や JSON などを 生成して返す
  5. アプリケーション内部の 3 層アーキテクチャ • 一方で、アプリケーションの内部を 3 層に分けて整理することがあります • これも「3 層アーキテクチャ」と呼ぶことがあります

    Web サーバ アプリケーション DB プレゼン テーション層 ビジネス ロジック層 データ アクセス層 内部のコードを層に分けて整理 ここからは、アプリケーションの内部を 3 層に分けた、 こちらの 3 層アーキテクチャについて話します
  6. 3 層アーキテクチャの役割分担 • ここで、3 層アーキテクチャの各層の役割を整理してみます プレゼン テーション層 ビジネス ロジック層 データ

    アクセス層 アプリケーションの利用者 (人間や別のプログラム) とやりとりする DB やファイルなどの データの保存先 とやりとりする 「ビジネスロジック」 を実装する 「ビジネスロジック」の意味はあとでしっかり説明するので、まずは プレゼンテーション層とデータアクセス層の役割をおさえましょう
  7. データアクセス層 • データアクセス層の役割は、ファイルや DB などのデータの保存先に対して データを読み書きすることです • ビジネスロジックをデータアクセスと切り離すというのは、保存先がファイ ルだろうと、RDB だろうと、その他の

    DB だろうと、ビジネスロジックはそ れを気にかけないように記述するということです • よく見かける実装方式は、データベースのテーブルと対応した読み書き用の クラスを作成する「Table Data Gateway (DAO)」パターンです データ アクセス層 ビジネス ロジック層 プレゼン テーション層
  8. プレゼンテーション層と MVC • プレゼンテーション層のアーキテクチャとして有名なのが「MVC」です • MVC と 3 層アーキテクチャを対応させると、以下の図のようになります プレゼンテーション層

    ビジネスロジック層 データアクセス層 Controller View Model 入力の受け付け UI データ アクセス層 ビジネス ロジック層 プレゼン テーション層
  9. プレゼンテーション層 • プレゼンテーション層は、そのアプリケーションの利用者(人間や別のプロ グラム)とやりとりする層です • 例えば、以下のようなものがプレゼンテーション層に属します ◦ HTML を返す Web

    アプリケーションの場合 ➢ リクエストの受け取り (Controller ) や UI (View) ◦ JSON などを返す Web アプリケーション (Web API) の場合 ➢ API の出入り口 (Controller) や・リクエストやレスポンスの型 ◦ CLI アプリケーションの場合 ➢ ユーザからの入力受付・処理結果の出力 データ アクセス層 ビジネス ロジック層 プレゼン テーション層
  10. (補足)プレゼンテーション層とフロントエンドの違い Web サーバ アプリケーション DB プレゼン テーション層 ビジネス ロジック層 データ

    アクセス層 内部のコードを層に分けて整理 サーバサイド (サーバ上で処理される) HTML CSS JS ※ Rails で ERB、Laravel で Blade、Spring で Thymeleaf などを使い、サーバサイドで   HTML を生成する方式の場合は、プレゼンテーション層はフロントエンドになります フロントエンド (ブラウザなど、ユーザの手元で処理される)
  11. 改めて整理すると... • 3 層アーキテクチャでは、以下のような分担で層分けします プレゼン テーション層 ビジネス ロジック層 データ アクセス層

    アプリケーションの利用者 (人間や別のプログラム) とやりとりする DB やファイルなどの データの保存先 とやりとりする 「ビジネスロジック」 を実装する
  12. 典型的な 3 層アーキテクチャの構成例 • 以下のような構成が、3 層アーキテクチャ (+ MVC) の典型例です ※

    クラス名の付け方は色々あります プレゼンテーション層 ビジネスロジック層 データアクセス層 Controller View Output (DTO) Gateway (DAO) Record (Entity) Service 利用者とやりとり UI Service の戻り値 DB とやりとり データの入れ物 ビジネスロジック
  13. アプリケーションの役割を 3 層で整理 プレゼン テーション層 ビジネス ロジック層 データ アクセス層 アプリケーションの利用者

    (人間や別のプログラム) とやりとりする DB やファイルなどの データの保存先 とやりとりする 「システムのコア」や 「システムの目的の処理を するところ」と言われる まずは、「とっかかりとして」プレゼンテーションでも データアクセスでもない部分がビジネスロジックと考えてみましょう この説明は、 意味を分かってからはしっくりくるが、 最初はあまりにも難しい...
  14. 例えば、リバーシを考えてみましょう • リバーシで石を打つときの処理は、例えばこんな流れになります ◦ プレイヤーの入力(石をどこに打つか)を受け付ける ◦ データアクセス層を使って、盤面の状態を取得する ◦ 盤面に置けるかチェック ◦

    石を置く ◦ ひっくり返す ◦ データアクセス層を使って、盤面の状態を保存する ◦ 画面に新しい状態の盤面を表示する これがビジネスロジックの例であり、 ビジネスロジック層に書くべきコードです ここがビジネスロジック!! 見ての通り、 • 利用者とのやりとりの方法 • 保存先の DB の種類 などは関係ない
  15. これはビジネスロジック?(2/4) • リクエストの形式チェックはビジネスロジック? ◦ リクエストの必須パラメータは足りているか ◦ リクエストのデータサイズは決められた範囲内か • 以下のような理由で、これらは「プレゼンテーション層」でチェックすべき 内容だと考えています

    ◦ 利用者とのインタフェースでの約束事に関するチェックであること ◦ 不正なデータはできるだけ早く検知し、以後のプログラムに進ませないようにしたいこと ◦ DB とのやりとりが不要なため、簡単に実装できること
  16. これはビジネスロジック?(3/4) • リクエストの形式より少しだけ複雑な条件チェックはビジネスロジック? ◦ SNS で、自分には「イイね」できないようにする ◦ TODO 管理アプリで、過去日の TODO

    は登録できないようにする • 私は以下の 2 つの理由でこれは「ビジネスロジックである」と考えています ◦ プレゼンテーション層は見た目などの UI に直接関わることだけを知っているべきであり、こ のような知識を持つべきではないこと ◦ ユーザインタフェースが GUI か API か CLI かといった、プレゼンテーション層の違いによら ず、共通したチェックであると想定されること
  17. これはビジネスロジック?(4/4) • DB のデータとの整合性チェックはビジネスロジック? ◦ リバーシで、現在の盤面を踏まえ、指定された場所に石を置くことができるか判定する ◦ EC サイトで購入リクエストした商品が購入可能なものか判定する •

    これは「まさにビジネスロジックである」と考えています • リバーシの場合、石をひっくり返す計算処理もまさにビジネスロジックです アプリケーションが従うべきルールのチェックであったり、 ルールを適用する計算処理が、まさにビジネスロジックの中心です
  18. ドメインロジックとユースケース • ビジネスロジック層の処理は、「ドメインロジック」と「ユースケース」の2 種類に分類すると整理しやすいです • リバーシで石を打つときの処理の流れの例だと... ◦ データアクセス層を使って、盤面の状態を取得する ◦ 盤面に置けるかチェック

    ◦ 石を置く ◦ ひっくり返す ◦ データアクセス層を使って、盤面の状態を保存する 「システム都合ではない、コアなルール」 ・ドメインロジック ・エンタープライズビジネスルール と呼ばれることも 「処理の流れを実現すること」 ・ユースケース ・アプリケーションビジネスルール と呼ばれることも
  19. ドメインロジックの例 • リバーシ ◦ 盤面に置けるかチェック ◦ はさまれた石をひっくり返す • ホテルの予約 ◦

    指定された部屋に、宿泊できる人数の予約かチェック ◦ 何日前のキャンセルなので、キャンセル料はいくらか算出 システムなしで、現実世界で同じことをやろうとしたときにも 登場するルールは、ドメインロジックの分かりやすい例です 電話予約や対面での予約など、 システムなしで人間が対応するときにも 登場するルール
  20. ここから、ビジネスロジックの実装について見ていきます • リバーシで石を打つときの処理の流れの例だと... ◦ プレイヤーの入力(石をどこに打つか)を受け付ける ◦ データアクセス層を使って、盤面の状態を取得する ◦ 盤面に置けるかチェック ◦

    石を置く ◦ ひっくり返す ◦ データアクセス層を使って、盤面の状態を保存する ◦ 画面に新しい状態の盤面を表示する ビジネスロジックの実装方法は、「トランザクションスクリプト」と 「ドメインモデル」の 2 種類があります ビジネスロジックはここ 単純化すると... ・データの取得の呼び出し ・チェックや計算処理 ・データの保存の呼び出し
  21. トランザクションスクリプトとドメインモデル トランザクションスクリプト パターン ドメインモデル パターン ビジネスロジック層 DTO (Model…?) Service データの入れ物

    ドメインロジック ユースケース ビジネスロジック層 Domain Model Service データの入れ物 ドメインロジック ユースケース ・データの取得の呼び出し ・チェックや計算処理 ・データの保存の呼び出し の全てを Service に実装 ドメインロジック (チェックや計算処理)を データの入れ物となる クラスに一緒に持たせる
  22. トランザクションスクリプトとドメインモデル トランザクションスクリプト パターン ドメインモデル パターン 概要 • データの入れ物と処理を分離する • 手続き型プログラミング

    • Service がドメインロジックと ユースケースを担当 メリット • 学習コストが低い デメリット • Service クラスが肥大化しやすい • 同じロジックが Service クラス間 に分散しやすく、変更に弱い 概要 • データの入れ物に処理も持たせる • オブジェクト指向プログラミング • Model はドメインロジックを担当 • Service はユースケースを担当 メリット • Service クラスが肥大化しにくい • 同じロジックが分散しにくく、変 更に強くなりやすい デメリット • 学習コストが高い
  23. ドメインモデルを使う構成例 • 例えば、アプリケーション層とドメイン層を分離した 4 層の構成があります • 以下のような構成を「レイヤードアーキテクチャ」と呼びます プレゼンテーション層 アプリケーション層 データアクセス層

    (インフラ層) Controller View 利用者とやりとり UI Service (UseCase) ユースケース Record データの入れ物 ドメイン層 Domain Model ドメインロジック Output (DTO) Service の戻り値 Gateway (DAO) DB とやりとり ※ 実際には、次の Repository パターンも使う例をレイヤードアーキテクチャと呼ぶことが多いと思われます
  24. Repository パターン • 以下は、DB のテーブル都合ではなく、ドメインモデルの都合でデータを 読み書きする「Repository パターン」を導入した構成です プレゼンテーション層 アプリケーション層 データアクセス層

    (インフラ層) Controller View 利用者とやりとり UI Service (UseCase) ユースケース Record データの入れ物 ドメイン層 Domain Model ドメインロジック Output (DTO) Service の戻り値 Gateway (DAO) DB とやりとり ※ Repository の実装に Table Data Gateway を使うのはあくまで一例で、実装はどんな方法でも構いません Repository
  25. アーキテクチャの組み合わせ例 • レイヤード + MVC + ドメインモデル + Repository •

    Repository の内部実装は Table Data Gateway プレゼンテーション層 アプリケーション層 データアクセス層 (インフラ層) Controller View 利用者とやりとり UI Service (UseCase) ユースケース Record データの入れ物 ドメイン層 Domain Model ドメインロジック Output (DTO) Service の戻り値 Gateway (DAO) DB とやりとり Repository
  26. アプリケーション設計の学習のポイント • アプリケーション設計には、以下のように異なる観点があります ◦ どのように層を分けるか ▪ 3 層・レイヤード・ヘキサゴナル・オニオン... ◦ 各層をどのように実装するか

    ▪ MVC・MVVM・MVP... ▪ トランザクションスクリプト・ドメインモデル... ▪ Table Data Gateway・Repository… ◦ ドメインモデルをどう設計・実装するか アプリケーション設計に関する書籍を読んだりするときは、 どの観点の話なのか注意してみると理解しやすくなることがあります
  27. 例 1 • ノンフレームワーク・Express などの軽量なフレームワークで、Controller に SQL まで書かれている場合... プレゼンテーション層 ビジネスロジック層

    データアクセス層 Controller View Record 利用者とやりとり UI ユースケース ドメインロジック データの入れ物 DB とやりとり
  28. 例 2 • 今度は Rails や Laravel などで ActiveRecord 系

    OR マッパーを使う例です • よくある苦しくなりやすい構成は、以下のような役割分担です プレゼンテーション層 ビジネスロジック層 データアクセス層 Controller View Model 利用者とやりとり UI ユースケース ドメインロジック DB とやりとり データの入れ物
  29. 本来のアクティブレコードパターン • アクティブレコードパターンは、「DB のレコードと対応するクラスを作成 し、データアクセスのメソッドと、ドメインロジックを持たせる」ものです • つまり、アクティブレコードのモデルの役割は、本来は以下の 3 つです ◦

    データベースのレコードと対応するデータを持つ ◦ データアクセスのメソッドを持つ ◦ ドメインロジックを持つ アクティブレコード系 OR マッパーを使うと、ドメインロジックが DB に強く依存する代わりに、実装量が非常に少なくなります
  30. ユースケースの分離 • もし Controller からユースケースを分離したい場合は、Service ( または UseCase) クラスを設ける手法を使うことができます プレゼンテーション層

    ビジネスロジック層 データアクセス層 Controller View Model (ActiveRecord) 利用者とやりとり UI ドメインロジック DB とやりとり データの入れ物 Service (UseCase) ユースケース
  31. ActiveRecord による Repository の実装 • ActiveRecord や Eloquent で Repository

    の実装も可能ですが、ActiveRecord のメリットは非常に弱くなります(あまりおすすめしません) プレゼンテーション層 ビジネスロジック層 データアクセス層 Controller View ドメインモデル 利用者とやりとり UI ドメインロジック Service (UseCase) ユースケース ActiveRecord DB とやりとり データの入れ物 Repository 呼び出し ActiveRecord とは関係ない ドメインロジックのためのモデル
  32. フレームワークなどの特性を活かす • MVC + ActiveRecord 系 OR マッパーで、少ないコードで実装できることが魅 力のフレームワークであれば、その特性を活かした構成が良いと思います プレゼンテーション層

    ビジネスロジック層 データアクセス層 Controller View Model (ActiveRecord) 利用者とやりとり UI ユースケース ドメインロジック DB とやりとり データの入れ物
  33. 参考文献 • 『エンタープライズアプリケーションアーキテクチャパターン』 ◦ マーチン・ファウラー (著), 株式会社テクノロジックアート (翻訳), 長瀬嘉秀 (翻訳,

    監修), 2005, 翔泳社 • 『エリック・エヴァンスのドメイン駆動設計』 ◦ エリック・エヴァンス (著), 今関 剛 (監修), 和智 右桂 (翻訳), 牧野 祐子 (翻訳), 2011, 翔泳社 • 『実践ドメイン駆動設計』 ◦ ヴォーン・ヴァーノン (著), 髙木 正弘 (翻訳), 2015, 翔泳社 • 『Clean Architecture 達人に学ぶソフトウェアの構造と設計』 ◦ Robert C.Martin (著), 角 征典 (翻訳), 高木 正弘 (翻訳), 2018, KADOKAWA •   『.NETのエンタープライズアプリケーションアーキテクチャ 第2版』 ◦ Dino Esposito (著), Andrea Saltarello (著), 日本マイクロソフト (監訳), クイープ (翻訳), 2015, 日経BP • 『現場で役立つシステム設計の原則 ~変更を楽で安全にするオブジェクト指向の実践技法』 ◦ 増田 亨 (著), 2017, 技術評論社
  34. ドメイン層を中心にした構成例(1/2) • 依存性逆転の原則を適用することで、ドメイン層を中心にできます プレゼンテーション層 アプリケーション層 データアクセス層 (インフラ層) Controller View 利用者とやりとり

    UI Service (UseCase) ユースケース ドメイン層 Domain Model ドメインロジック Output (DTO) Service の戻り値 Repository DB とやりとり << interface >> Repository 実装クラス