使用 DDD 为用户域模型生成 ID 和散列密码的最佳方法
Best approach for Id generation and password hashing using DDD for User Domain model
我是 DDD 的新手,现在我正在实施用户注册。
基本上流程是:
- 控制器收到请求
- 将从客户端接收到的数据映射到用户域模型。
- 将用户域模型映射到 EF 核心实体模型。
- 使用 EF-Core 将用户添加到数据库。
我对 IdGeneratorService
class 和 BCryptService
class 的位置有一些疑问。目前它们在域层都有一个接口:src/Domain/Model/Services
。它们的实现驻留在我的基础设施层中:src/Infrastructure/Services
。它们也在用户域模型中被调用:
public class User
{
private User(
long id,
string name,
string lastName,
string contactPhone,
string contactEmail,
string userName,
string password)
{
Id = id;
Name = name;
LastName = lastName;
ContactPhone = contactPhone;
ContactEmail = contactEmail;
UserName = userName;
Password = password;
}
public IEnumerable<Role> Type { get; set; }
public static async Task<User> ConstructAsync(
string name, string lastName,
string contactPhone, string contactEmail,
string userName, string password,
IIdGeneratorService<long> idGeneratorService, IBCryptService bCryptService)
{
var id = await idGeneratorService.GenerateAsync();
password = bCryptService.HashPassword(password);
return new User(id, name, lastName, contactPhone, contactEmail, userName, password);
}
这是由我的控制器调用的:
[HttpPost("[Action]")]
public async Task<IActionResult> Create([FromBody] UserModel userModel)
{
var user =
await DomainUser.ConstructAsync(
userModel.Name, userModel.LastName,
userModel.ContactPhone, userModel.ContactEmail,
userModel.UserName, userModel.Password,
_idGeneratorService, _bCryptService);
await _userRepository.AddAsync(user);
return sampleResponse;
}
我觉得在域模型中调用 IdGenerator 和 BCrypt 是一种不好的做法,因为据我所知,域层无法了解基础结构层,所以我不太确定我该怎么做。非常感谢任何其他 help/suggestions 关于基于您在此处理解的内容的其他实现。
在控制器和域层之间引入一个中间 "Application Service" 层是一个很好的做法。
App Service 将负责调用(注入的)基础设施服务,调用域层以及 persisting/loading 必要的数据。控制器的职责只是收集请求参数,确保身份验证(如果需要),然后调用应用程序服务方法。
应用服务是领域模型的直接客户,充当协调外部世界和领域层之间的中介。他们负责处理基础设施问题,例如 ID 生成、事务管理、加密等。这些职责也不是控制器层的问题。
应用程序服务通常还会在 API 秒内进行任务协调(每个 API 一个服务方法)。使用 ACID 数据库时,相同的服务还控制事务,确保模型状态转换以原子方式持久化。
在您的具体示例中,应用服务将负责调用 IdGeneratorService 和 BCryptService,获取输出并将它们作为参数发送到域层。就域层而言,它确实需要知道 ID 或密码是如何生成的——这些与域无关。所以它很高兴地忽略了这些基础设施方面,只为用户行为的任务增加了负担。
我是 DDD 的新手,现在我正在实施用户注册。
基本上流程是:
- 控制器收到请求
- 将从客户端接收到的数据映射到用户域模型。
- 将用户域模型映射到 EF 核心实体模型。
- 使用 EF-Core 将用户添加到数据库。
我对 IdGeneratorService
class 和 BCryptService
class 的位置有一些疑问。目前它们在域层都有一个接口:src/Domain/Model/Services
。它们的实现驻留在我的基础设施层中:src/Infrastructure/Services
。它们也在用户域模型中被调用:
public class User
{
private User(
long id,
string name,
string lastName,
string contactPhone,
string contactEmail,
string userName,
string password)
{
Id = id;
Name = name;
LastName = lastName;
ContactPhone = contactPhone;
ContactEmail = contactEmail;
UserName = userName;
Password = password;
}
public IEnumerable<Role> Type { get; set; }
public static async Task<User> ConstructAsync(
string name, string lastName,
string contactPhone, string contactEmail,
string userName, string password,
IIdGeneratorService<long> idGeneratorService, IBCryptService bCryptService)
{
var id = await idGeneratorService.GenerateAsync();
password = bCryptService.HashPassword(password);
return new User(id, name, lastName, contactPhone, contactEmail, userName, password);
}
这是由我的控制器调用的:
[HttpPost("[Action]")]
public async Task<IActionResult> Create([FromBody] UserModel userModel)
{
var user =
await DomainUser.ConstructAsync(
userModel.Name, userModel.LastName,
userModel.ContactPhone, userModel.ContactEmail,
userModel.UserName, userModel.Password,
_idGeneratorService, _bCryptService);
await _userRepository.AddAsync(user);
return sampleResponse;
}
我觉得在域模型中调用 IdGenerator 和 BCrypt 是一种不好的做法,因为据我所知,域层无法了解基础结构层,所以我不太确定我该怎么做。非常感谢任何其他 help/suggestions 关于基于您在此处理解的内容的其他实现。
在控制器和域层之间引入一个中间 "Application Service" 层是一个很好的做法。
App Service 将负责调用(注入的)基础设施服务,调用域层以及 persisting/loading 必要的数据。控制器的职责只是收集请求参数,确保身份验证(如果需要),然后调用应用程序服务方法。
应用服务是领域模型的直接客户,充当协调外部世界和领域层之间的中介。他们负责处理基础设施问题,例如 ID 生成、事务管理、加密等。这些职责也不是控制器层的问题。
应用程序服务通常还会在 API 秒内进行任务协调(每个 API 一个服务方法)。使用 ACID 数据库时,相同的服务还控制事务,确保模型状态转换以原子方式持久化。
在您的具体示例中,应用服务将负责调用 IdGeneratorService 和 BCryptService,获取输出并将它们作为参数发送到域层。就域层而言,它确实需要知道 ID 或密码是如何生成的——这些与域无关。所以它很高兴地忽略了这些基础设施方面,只为用户行为的任务增加了负担。