存储库是否应该引发域错误 [英] Should Repositories Throw Domain Errors

查看:15
本文介绍了存储库是否应该引发域错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个尝试遵守简洁架构的应用程序.我知道存储库旨在抽象出持久层并根据域语言返回实体.但是,这是否意味着它也应该在出现问题时检查并抛出域错误.让我们考虑一种情况,我想通过用户存储库添加用户.我可以执行以下操作:

I am building an application that tries to abide by clean architecture. I understand that the repository is meant to abstract away the persistence layer and return back entities in terms of the domain language. But, does that mean that it is also supposed to check and throw domain errors if something goes wrong. Let's consider a situation where I want to add a user via the user repository. I can do the following:

// in user repo
const add = (user: User): void => {
  try {
    // do some database stuff
  } catch() {
    throw new EmailAlreadyInUse(user.email);
  }
}

但是这种实现是否可取?我们现在依赖于使用正确的唯一键模式正确设置的数据库来强制执行域规则(没有两个用户可以使用同一个电子邮件注册).在我看来,这似乎是我们可能会将域规则溢出到持久层.

But is this implementation advisable? We are now relying upon the database to have been setup correctly with the correct unique key schema to enforce a domain rule (no two users can register with the same email). This seems to me like we are potentially spilling domain rules to the perisitence layer.

改为从用例层抛出这个异常是否更有意义.

Would it make more sense to throw this exception from the use case layer in stead.

const AddNewUserUseCase = (userRepository, email) => {
  const user = userRepository.findByEmail(email);
  if(user) {
    throw new EmailAlreadyInUseError(email)
  }
  else {
    const user = new User(email);
    userRepository.add(user);
  }
}

这有效并消除了持久层中的任何溢出.但我必须在每个我想要添加用户的地方都这样做.您推荐的模式是什么?你有其他鼓励的方法吗?你会在哪里做这些检查来抛出错误.

This works and removes any spillage from the persistance layer. but I'd have to do this every single place I'd want to add a user. What is the recommended pattern you would go for? Do you have another approach you'd encourage? Where would you do those checks to throw errors.

推荐答案

完全依赖数据库功能来执行业务规则是一种不好的做法.

Exclusively relying on database capabilities to enforce business rules is a bad practice.

也就是说,鉴于在某些业务验证检查之后引发域异常这一事实,您不应从代表您的数据库(存储库)的类内部引发域异常.

That said, given the fact that raising a domain exception follows some business validation check, you should not raise domain exceptions from inside the class representing your database (the repository).

域异常,顾名思义,应该在域(或应用程序)层内部使用.

Domain exceptions, as the name implies, should be used inside the domain (or application) layer.

因此,您的重复电子邮件验证应位于用例内部,然后是存储库操作(添加用户).对于代码重复,解决方案很简单:使用包含此两阶段逻辑(验证然后操作)的方法创建域服务,并在您喜欢的任何地方使用此服务.

Your duplicate-email validation should therefore be positioned inside use case, followed by the repository operation (add-user). As for code repetition the solution is simple: create a domain service with a method containing this two-phase logic (validation then operation) and use this service anywhere you'd like.

简洁架构的一个关键原则是形成一个稳定的域层,同时让基础设施细节可以交换.但是,当您将业务规则放入存储库(基础架构)时,请考虑如果您决定创建替代存储库会发生什么:您必须记住将业务规则复制到新存储库中.

A key principle of the clean architecture is to form a stabilized domain layer while letting infrastructural details be exchangeable. But, when you put a business rule inside a repository (infrastructure), consider what will happen if you decide to create an alternative repository: you have to remember to copy your business rule into the new repository.

这篇关于存储库是否应该引发域错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆