多年来,我看到许多开发人员在 Laravel 中使用存储库模式,试图将干净的架构概念应用于他们的应用程序,但经常误解使用像 Laravel 这样的框架的一般概念。
在我开始并必须躲避一些我知道你们可能会扔给我的石头之前,让我澄清一下:这是我作为一名软件工程师的观点,他曾使用过多种语言、框架,从头开始构建软件并维护旧版本遗留代码库。我的话不是最终的,一如既往,我相信对任何软件工程问题最容易接受的答案是:“这取决于你愿意牺牲什么来解决你的问题。”
那么,话不多说,让我们进入正题吧。
清洁架构是一种软件设计理念,旨在创建易于维护、测试和理解的系统。它强调关注点的分离以及系统不同部分之间边界的创建,以确保一个部分的更改不会对其他部分产生不利影响。这种架构由 Robert C. Martin(Bob 叔叔)推广,通常用于指导代码组织,以适应业务规则或技术要求的变化。
简而言之,Bob 的建议是,您的应用程序应该分为遵循关键原则的层,以允许您的业务逻辑与任何外部依赖项解耦,从而为它们提供移动性和单一职责上下文。但这不会是一篇干净的架构文章;我只是想让我们在这件事上达成共识。
说到框架,我们谈论的是依赖关系的紧耦合。您可能没有选择 Laravel 来使用 Doctrine;您可能选择使用 Eloquent。这同样适用于您可能找到的任何框架功能 - 您选择框架是为了开发速度和便利性。
所以,我的问题是:为什么要在你选择简单的东西上添加额外的复杂层?
等等,不要因为我这么说而恨我。您仍然可以在 Laravel 中适应甚至使用干净的架构,但任何架构决策中最重要的方面是清楚地了解您想要实现的目标以及这些选择的优缺点。
这是一个艰难的决定,您可以在实施过程中改变主意。软件不应该是一成不变的,对吧?我有一篇关于软件质量的整篇文章,我在其中举起了这个旗帜。
无论如何,回到 Laravel 和干净的架构。以我的拙见,最烦人的方法之一是将存储库模式与 Eloquent 结合使用,这就是我写这篇文章的动机。
存储库模式是一种在域和数据映射层之间进行调解的设计模式,充当域对象的内存集合。它的目的是解耦领域和数据映射层。
因此,Repository 定义是一个领域实体。为什么?因为它与域交互并定义基础设施如何与域交互,充当域和我们应用程序的基础设施层之间的契约。
首先,让我向您展示我在 Laravel 应用程序中经常看到的存储库模式的一个糟糕实现,然后为您修复它:
正如您在上面的代码中所看到的,域和基础设施的“契约”不是在域内部定义的,而是在基础设施本身内部定义的。是的,App命名空间是应用程序层的一部分,它包含所有非域的东西。
现在,让我们看看如何实现同样的事情:
请注意,现在我们有了适当的领域层和应用程序层。是不是很简单就可以得到呢?
现在,让我们想一下。由于存储库接口现在是域的一部分,这意味着我们不能简单地将其他层的依赖项注入其中。这是一个不好的例子来解释它:
还不清楚吗?让我把它移动到领域层:
看到问题了吗?我们正在将作为基础设施层一部分的 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로그인 후 복사
// domain/Entities/User.php로그인 후 복사
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 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.
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.
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!