やっと「依存性の逆転(Dependency Inversion)」がわかった
オブジェクト指向設計において、依存性逆転の原則、または依存関係逆転の原則[1](dependency inversion principle) とはソフトウエアモジュールを疎結合に保つための特定の形式を指す用語。この原則に従うとソフトウェアの振る舞いを定義する上位レベルのモジュールから下位レベルモジュールへの従来の依存関係は逆転し、結果として下位レベルモジュールの実装の詳細から上位レベルモジュールを独立に保つことができるようになる。この原則で述べられていることは以下の2つである:[2]
A. 上位レベルのモジュールは下位レベルのモジュールに依存すべきではない。両方とも抽象(abstractions)に依存すべきである。
B. 抽象は詳細に依存してはならない。詳細が抽象に依存すべきである。
正直こういうのを見てもいまいちわかってなかった。
しかし、ようやく理解した。
だめな例
<?php
namespace App\Domain\User;
use App\Infrastructure\DBConnection;
class UserRepository {
public function __construct(DBConnection $conn) {
$this->conn = $conn;
}
public function save(User $user): void {
$this->conn->table('users')->save($user->toArray());
}
}
<?php
namespace App\Infrastructure;
class DBConnection {
/* ... */
}
この作り方だと、 UserRepository
がいるパッケージ App\Domain\User
は、 App\Infrastructure
パッケージを知っている(=use
する)必要がある。
しかし、 UserRepository
が担う責務は「User
に関する状態を永続化したり取得したりすること」だとすれば、 App\Infrastructure
パッケージは知る必要がない。つまり、具体的にどうやって永続化するかを知る必要がない。 UserRepository
= ビジネスロジックはその状態がDBに保存されようがメモリに保存されようが関係ない のである。
だから、ここで「依存性の逆転」を利用する。
良い例
<?php
namespace App\Domain\User;
interface IUserRepository {
public function save(User $user): void;
}
<?php
namespace App\Infrastructure\Domain\User;
use App\Domain\IUserRepository;
class DBConnection {
/* ... */
}
class DBUserRepository implements IUserRepository {
public function __construct(DBConnection $conn) {
$this->conn = $conn;
}
public function save(User $user): void {
$this->conn->table('users')->save($user->toArray());
}
}
これで App\Domain
パッケージは App\Infrastructure
パッケージを知る必要がなくなった。
代わりに、 App\Infrastructure
パッケージが App\Domain
パッケージを知り、そのパッケージが必要な実装(例えば DBUserRepository
)を行う。
このように依存性(use)の逆転を行うことで、 パッケージごとの責務 を適切に分離出来るようになる。この 「パッケージごとの責務」 という部分が重要だということに気づいた。
DDD というより、「パッケージごとの責務分離」を正しく担うことがオブジェクト指向プログラミングのかなり重要なポイントだった。
そして、 interface を用いてパッケージ分離された宣言と実装は、主に DI コンテナ(IoC コンテナ)を使って紐づけられる。 そのための DI コンテナだった 。
このサンプルは slimphp/Slim-Skeleton を参考にしている。
このため、 Active Record 型の Laravel Eloquent などは App\Infrastructure
層以下に class User extends Model
のようなクラスを生やすべきだし、ビジネスロジックは...分離するのが難しい。これが Active Record 型の弱点である。 Doctrine など POPO(Plain Old PHP Object) を使える Data Mapper 型の O/R Mapper なら分離出来るだろう。
Author And Source
この問題について(やっと「依存性の逆転(Dependency Inversion)」がわかった), 我々は、より多くの情報をここで見つけました https://qiita.com/il-m-yamagishi/items/c058d35f022cfa34e595著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .