控制器逻辑与服务/业务层逻辑
我正在研究应用程序,并且正在使用REST API的Repository-Service-Controller方法。控制器逻辑与服务/业务层逻辑
我发现自己在控制器逻辑与服务逻辑之间辩论。服务逻辑处理业务逻辑,例如计算书价,控制器逻辑应处理演示细节。
- 如果什么 应用程序的业务逻辑的一部分是检查出版商订阅到的
PremiumService
,以确定是否这本书是编辑? 这将在业务逻辑或控制器逻辑? - 如果在控制器中,如果发布商未在
PremiumService
中订阅,我想隐藏正在呈现的图书?那么PremiumService
会被PublisherController
检查出版者的订阅PremiumService
?
我可以看到如何在BookService上创建过多的依赖关系可以变成意大利面代码。
这是一个带有伪代码的界面,可以帮助回答我的问题。
class Publisher
{
public function getId(): int;
public function getName(): string;
public function getBooks(): Book[];
}
class Book
{
public function getId(): int;
public function getName(): string;
public function getPublisher(): Publisher;
public function getAuthors(): Author[];
}
class Author
{
public function getId(): int;
public function getName(): string;
public function getBooks(): Book[];
}
// Simple CRUD repository.
class BookRepository
{
public function find($id);
public function findAll($criteria);
public function create($book);
public function edit($book);
public function remove($book);
}
class BookService
{
public function __construct(
BookRepository $book_repository,
AuthorService $author_service,
PremiumService $subscription_service
);
public function get($id);
public function getAll($criteria);
// Book is editable if the publisher of the book is subscribed to the PremiumService
public function edit(Book $book);
// Book is removable if the publisher of the book is subscribed to the PremiumService
public function remove(Book $book);
// Can only add an author if the publisher of the book is subscribed to the PremiumService.
public function addAuthor(Author $author, Book $book);
}
class PublisherController
{
public function __construct(BookService $book_service);
// Can only view a book if the publisher of the book is subscribed to the PremiumService
public function getBook(Request $request);
// Can only view books if the publisher of the book is subscribed to the PremiumService
public function getBooks(Request $request);
}
如果服务依赖于其他服务的过多依赖关系,那么这里常用或推荐的方法是什么?服务是否应该像存储库一样愚蠢?
回答您的问题:
1)你有种说:“如果有什么应用程序的业务逻辑的一部分是......”既然是商业逻辑,把它放在回答了你自己的问题业务逻辑层(即服务)。
2)如果发布者没有订阅订阅服务,隐藏书籍听起来像是您的业务逻辑的一部分(您的业务规则是如果用户不支付它们,则无法阅读图书),所以这将在服务中。然后是的,该服务必须是您的控制器的依赖。
我经常发现自己处于与您的情况类似的状态,其中单个业务规则需要依赖大量业务服务才能完成其工作。在保持每项服务简单的同时,避免在服务中存在大量依赖性的一种好方法是,一旦开始获得服务的四个或五个依赖关系,就可以使用门面服务服务。门面是处理协调下层服务的更高级服务。
例如,您可以使用ContentManager
服务,该服务取决于BookService
,AuthorService
和PremiumService
。那么你的控制器对ContentManager
只有一个依赖关系。当控制器想要显示书籍列表时,它会调用ContentManager.getBooks
并传递一些用户详细信息,以便确定该用户是否已订阅。然后ContentManager
确定用户是否可以查看书籍,获取书籍的详细信息,获取书籍的作者详细信息等。
虽然ContentManager
最终在它的子服务中有很多东西在它的下面,但它仍然是一个非常简单的类,因为它唯一的工作就是针对给定操作调用适当的子服务方法。
不可否认,这并不是一个很大的改进,因为您没有大量的依赖关系,但是如果您发现自己处于需要控制器的情况下,说八个依赖关系,那么您可以将这些依赖关系拆分为外观。如果其中五项服务用于一套高级业务规则(例如您的图书馆/发布商管理),其中三项服务用于另一组高级业务规则(例如计费),那么您会有一个门面有五个依赖关系,另一个门面有三个依赖关系。