LoginSignup
7

More than 3 years have passed since last update.

インフラストラクチャ層のモジュール設計について

Last updated at Posted at 2020-12-17

この記事はLaravel Advent Calendar 2020の18日目です。

はじめに

ドメイン駆動設計で開発していてインフラストラクチャ層がとっ散らかりがちになるのが悩みの種でした。
実践ドメイン駆動設計』の第9章にモジュールを使ってクラスを整理する方法が書かれていますが、ドメイン層のモジュールについての話がほとんどで、インフラストラクチャ層のモジュールについては書かれていません。

そんな折に見つけた『Domain-Driven Design in PHP』という本に、いいなと思うインフラストラクチャ層のモジュール設計が書かれていたので紹介したいと思います。

『Domain-Driven Design in PHP』で推奨されているインフラストラクチャ層のモジュール設計

この本ではインフラストラクチャ層にドメイン層と同じ構成のモジュールを作ることを推奨しています。

|-- Domain
|   `-- Model
`-- Infrastructure
    `-- Domain
        `-- Model

ドメイン層のインターフェースをインフラストラクチャ層で実装するときは、対応するモジュールに配置します。

|-- Domain
|   `-- Model
|       `-- Bill
|           `-- BillRepositoryInterface.php
`-- Infrastructure
    `-- Domain
        `-- Model
            `-- Bill
                `-- EloquentBillRepository.php

私がこの設計をいいなと思った理由は、インターフェースの実装がどこにあるのかわかりやすくなる点と、インフラストラクチャ層のモジュール名にもユビキタス言語が使われるようになる点です。

ORMなどドメイン層に対応しないものは、その技術に関連したモジュールに配置します。

Infrastructure
|-- Domain
`-- Persistence
    `-- Eloquent
        `-- Models
            `-- Bill.php

本には書かれていませんでしたが、アプリケーション層のインターフェースをインフラストラクチャ層で実装するときもドメイン層のときと同じようにするのがいいと思います。

|-- Application
|   `-- DataTransformer
|       `-- Bill
|           `-- BillDataTransformerInterface.php
`-- Infrastructure
    `-- Application
        `-- DataTransformer
            `-- Bill
                `-- BillLaravelPaginatorDataTransformer.php

Webアプリケーションフレームワークとの付き合い方

この本にはWebアプリケーションフレームワークとの付き合い方についても書かれています。
Webアプリケーションフレームワークを使う場合は、インフラストラクチャ層にデリバリーメカニズム(Web、API、コンソールなど)ごとのモジュールを作り、さらにその中にフレームワークごとのモジュールを作ることを推奨しています。

Infrastructure
|-- Delivery
|   |-- Api
|   |   `-- Laravel
|   |-- Console
|   |   `-- Symfony
|   `-- Web
|       `-- Silex
`-- Domain

上記の例ではAPIにLaravelを使い、コンソールにSymfonyを使い、WebにSilexを使っています。

ユーザーインターフェイス(コントローラやビューのことだと思います)に関しては、各フレームワークのモジュールに配置することを推奨しています。

本では各フレームワークのモジュール内部については特に書かれていませんでしたが、

Frameworks should obey you, and not the other way around. (フレームワークがあなたに従うべきであり、その逆ではない。)

との言葉があったので、各フレームワークのモジュール内部はフレームワークの規約に縛られることなく自由に設計していいということだと思います。

Laravelの例

以下は本に書かれていることではないですが、本を読んでみてLaravelを使う場合どうするか自分なりに考えてみました。

Laravelモジュールの中に自分のアプリケーションで使うLaravel関連のファイルを好きなように配置します。

Infrastructure
`-- Delivery
    `-- Web
        `-- Laravel
            |-- Controllers
            |-- Middleware
            |-- Providers
            |-- Requests
            |-- resources
            |   |-- fonts
            |   |-- js
            |   |-- lang
            |   |-- less
            |   `-- views
            `-- routes

これらのファイルをLaravelに使わせるには設定ファイルを書き換えることになります。

また、設定ファイルを書き換える以外の方法として、パッケージ機能を使ってLaravelに公開することもできると思います。
この方法であれば設定ファイルを書き換えることすら不要になるので、Laravelをほとんど素のままで使うことができるはずです。

Laravelのドキュメントには書かれていませんが、ミドルウェアやイベントもパッケージとして公開できます。

ミドルウェアはIlluminate\Support\ServiceProviderを継承したサービスプロバイダーを作って、bootメソッドの中でLaravelのAPIを使うことで登録できます。

ミドルウェアの登録
public function boot()
{
    $this->app['router']->aliasMiddleware('my_middleware', MyMiddleware::class);
}

イベントもIlluminate\Foundation\Support\Providers\EventServiceProviderを継承したサービスプロバイダーを作れば、あとは普通にイベントを登録するときと同じように登録できます。

イベントの登録
protected $listen = [
    // ...
];

おわりに

『Domain-Driven Design in PHP』に書かれていたインフラストラクチャ層のモジュール設計について紹介しました。
また、Laravelを使う場合どうするか自分なりに考えてみました。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7