控制器逻辑与服务/业务层逻辑

问题描述:

我正在研究应用程序,并且正在使用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,AuthorServicePremiumService。那么你的控制器对ContentManager只有一个依赖关系。当控制器想要显示书籍列表时,它会调用ContentManager.getBooks并传递一些用户详细信息,以便确定该用户是否已订阅。然后ContentManager确定用户是否可以查看书籍,获取书籍的详细信息,获取书籍的作者详细信息等。

虽然ContentManager最终在它的子服务中有很多东西在它的下面,但它仍然是一个非常简单的类,因为它唯一的工作就是针对给定操作调用适当的子服务方法。

不可否认,这并不是一个很大的改进,因为您没有大量的依赖关系,但是如果您发现自己处于需要控制器的情况下,说八个依赖关系,那么您可以将这些依赖关系拆分为外观。如果其中五项服务用于一套高级业务规则(例如您的图书馆/发布商管理),其中三项服务用于另一组高级业务规则(例如计费),那么您会有一个门面有五个依赖关系,另一个门面有三个依赖关系。