リポジトリを使用した Laravel アプリケーションは意味がありません

PHPz
リリース: 2024-08-02 09:42:23
オリジナル
937 人が閲覧しました

Your Laravel application with Repository doesn

私は長年にわたり、多くの開発者が Laravel でリポジトリ パターンを使用し、クリーンなアーキテクチャの概念をアプリケーションに適用しようとしているのを見てきましたが、Laravel のようなフレームワークを使用する一般的な概念を誤解していることがよくありました。 .

始める前に、皆さんが私に投げてくるかもしれないいくつかの石を避けなければならない前に、はっきりさせておきます。これは、いくつかの言語、フレームワークを扱い、ソフトウェアをゼロから構築してきたソフトウェア エンジニアとしての私の意見です。古いレガシーコードベースを維持します。私の言葉は最終的なものではありません。いつものように、ソフトウェア エンジニアリングの質問に対する最も受け入れられる答えは、「問題を解決するために何を犠牲にするかによって決まります。」

それでは、早速本題に入りましょう。

クリーンアーキテクチャとは何ですか?

クリーン アーキテクチャは、保守、テスト、理解が容易なシステムを作成することを目的としたソフトウェア設計哲学です。これは、ある部分での変更が他の部分に悪影響を及ぼさないように、関心事の分離とシステムの異なる部分間の境界の作成を強調しています。このアーキテクチャは Robert C. Martin (Uncle Bob) によって広められ、ビジネス ルールや技術要件の変更に強い方法でコードを編成するためによく使用されます。

ボブが提案していることを簡単に言うと、アプリケーションを重要な原則に従うレイヤーに分割して、ビジネス ロジックを外部の依存関係から切り離し、それらに機動性と単一の責任コンテキストを与える必要があるということです。しかし、これはきれいなアーキテクチャの記事にはなりません。それについて私たちに同じ認識を持ってもらいたかっただけです。

Laravelとクリーンアーキテクチャはどうですか?

フレームワークに関して言えば、依存関係の密結合について話します。おそらく、Doctrine を使用するために Laravel を選んだわけではありません。おそらく Eloquent を使用するためにそれを選択したのでしょう。同じことが、どのフレームワーク機能にも当てはまります。開発速度と利便性のためにフレームワークを選択しているのです。

それで、私の質問は次のとおりです。単純であることを選択したものに、なぜ余分な複雑なレイヤーを追加するのでしょうか?

待って、こんなことを言って私を嫌いにならないでください。 Laravel ではクリーンなアーキテクチャを適応したり、使用したりすることもできますが、アーキテクチャ上の決定において最も重要な側面は、達成しようとしているものと、それらの選択の長所と短所を明確に理解することです。

これは難しい決断であり、実装の途中で気が変わることもあります。ソフトウェアは不変であってはなりませんよね?ソフトウェアの品質に関する記事全体でこのフラグを立てています。

とにかく、Laravel とクリーンなアーキテクチャに戻りましょう。私の謙虚な意見では、最も面倒なアプローチの 1 つは、Eloquent でのリポジトリ パターンの使用です。これが、私がこの記事を書く動機となったものです。

リポジトリパターン

リポジトリ パターンは、ドメイン レイヤーとデータ マッピング レイヤーの間を仲介する設計パターンであり、ドメイン オブジェクトのメモリ内コレクションとして機能します。ドメイン層とデータ マッピング層を分離することを目的としています。

つまり、リポジトリ定義はドメイン エンティティです。なぜ?それは、ドメインと対話し、インフラストラクチャがドメインと対話する方法を定義し、ドメインとアプリケーションのインフラストラクチャ層の間の契約として機能するためです。

Laravel のリポジトリ パターン

まず、Laravel アプリケーションでよく見かけるリポジトリ パターンの不適切な実装を示し、それを修正します。

// app/Repositories/UserRepositoryInterface.php
<?php

namespace App\Repositories;

interface UserRepositoryInterface
{
  // ...methods definitions
}
ログイン後にコピー
// app/Repositories/UserRepository.php
<?php

namespace App\Repositories;

class UserRepository implements UserRepositoryInterface
{
   // ...implementation
}
ログイン後にコピー

上記のコードからわかるように、ドメインとインフラストラクチャとの「契約」はドメイン内では定義されず、インフラストラクチャ自体の内部で定義されます。はい、App 名前空間はアプリケーション層の一部であり、ドメイン以外のすべてのものが含まれています。

さて、同じことをどのように実装するかを見てみましょう:

// domain/Repositories/UserRepositoryInterface.php
<?php

namespace Domain\Repositories;

interface UserRepositoryInterface
{
  // ...methods definitions
}
ログイン後にコピー
// app/Repositories/UserRepository.php
<?php

namespace App\Repositories;

use Domain\Repositories\UserRepositoryInterface;

class UserRepository implements UserRepositoryInterface
{
   // ...implementation
}
ログイン後にコピー

これで、適切なドメイン層とアプリケーション層ができたことに注目してください。入手は非常に簡単ですよね?

Eloquent を使用したリポジトリ パターン

さて、少し考えてみましょう。リポジトリ インターフェイスはドメインの一部になっているため、他のレイヤーから依存関係を単純に注入することはできません。それを説明する悪い例を次に示します:

// app/Repositories/UserRepositoryInterface.php
<?php

namespace App\Repositories;

use App\Models\User;

interface UserRepositoryInterface
{
  public function find(int $id): User|null;
  // ...other methods
}
ログイン後にコピー

まだ明確ではありませんか?これをドメイン層に移動させましょう:

// domain/Repositories/UserRepositoryInterface.php
<?php

namespace Domain\Repositories;

use App\Models\User;

interface UserRepositoryInterface
{
  public function find(int $id): User|null;
  // ...other methods
}
ログイン後にコピー

問題がわかりましたか?インフラストラクチャ層の一部である Eloquent モデルをドメインに挿入しています。これにより、私たちのドメインが Eloquent に緊密に結合され、リポジトリ パターンの目的が無効になります。

But how do we solve it? Well, it is not as hard as you might think. You probably already heard about Entities, right? So, let’s fix it:

// domain/Repositories/UserRepositoryInterface.php
<?php

namespace Domain\Repositories;

use Domain\Entities\User;

interface UserRepositoryInterface
{
  public function find(int $id): User|null;
  // ...other methods
}
ログイン後にコピー
// domain/Entities/User.php
<?php

namespace Domain\Entities;

class User
{
  public function __construct(
    public int $id;
    public string $name;
    public string $email;
  ) {}
  // ...other properties and methods
}
ログイン後にコピー

Our domain layer is now clean from external dependencies, and if we want to move the whole domain to another framework, we can do it.

Now, how do we implement our Repository in our Laravel application? Let me show you:

// app/Repositories/EloquentUserRepository.php
<?php

namespace App\Repositories;

use Domain\Repositories\UserRepositoryInterface;
use Domain\Entities\User;
use App\Models\User as EloquentUser;

class EloquentUserRepository implements UserRepositoryInterface
{
    public function find(int $id): ?User {
        $eloquentUser = EloquentUser::find($id);
        return $eloquentUser ? $this->toDomain($eloquentUser): null;
    }

    private function toDomain(EloquentUser $eloquentUser): User
    {
        return new User(
          $eloquentUser->id, 
          $eloquentUser->name, 
          $eloquentUser->email
        );
    }
}
ログイン後にコピー

Now we have a proper implementation of the Repository pattern in Laravel using Eloquent. You can create any other Repository implementation, such as PDOUserRepository.php, DoctrineUserRepository.php, and many others without injecting any dependency into your Domain layer.

Do You Really Need to Use Repository?

Back to what I said in the subject of this article, I’ll complement that, in my humble opinion, using the Repository Pattern with Laravel is just overengineering, and you need a really good reason to do it.

You are adding an extra layer of complexity to your application that you may not need at all, or even worse, it will not guarantee that your business logic is actually isolated into the Domain layer.

What are you trying to achieve here? Think about it. You might end up missing out on many nice functionalities from Laravel or at least making their usage overly complicated.

Are you not sure if Laravel is the best framework for your application and you might move your application to Symfony in the future? Sure, go for the Domain and the Repository. Do you need to replace your SQL database with a NoSQL database later? Maybe it is a good justification. But do you really need it, or is it just charm?

One common argument is that the Repository helps to put some business logic into a separate layer. This normally gives me the creeps because there are better approaches for splitting your logic. Repositories are just for acting as a middle layer to connect the data layer and domain, nothing else. If you want to split your business logic, you should make use of something else — but this is another subject.

Conclusion

In conclusion, while the Repository pattern and clean architecture principles offer significant benefits in terms of maintainability and separation of concerns, their application in a Laravel context often introduces unnecessary complexity. Laravel is designed for simplicity and rapid development, and adding layers of abstraction can complicate this process.

Before implementing the Repository pattern, it is essential to evaluate your project’s specific needs. If decoupling your domain logic from Laravel’s infrastructure is a genuine necessity due to future migrations or a need for flexibility, then the complexity might be warranted. However, for many Laravel applications, leveraging Eloquent directly aligns better with the framework’s strengths and keeps the codebase simpler and more maintainable.

Ultimately, the decision should be driven by a clear understanding of your project’s requirements, balancing the trade-offs involved. Overengineering can lead to more problems than it solves, so aim to keep your solutions as straightforward as possible while still achieving your design goals. The primary objective of any architecture is to solve problems, not to create new ones.

以上がリポジトリを使用した Laravel アプリケーションは意味がありませんの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート