Architecture 在检查DTO';s id有效,或者如果其中一个dto';s属性为空?

Architecture 在检查DTO';s id有效,或者如果其中一个dto';s属性为空?,architecture,domain-driven-design,tdd,Architecture,Domain Driven Design,Tdd,我的应用程序服务中有验证逻辑,可以确定请求的操作是否成功,如果不成功,原因是什么。我怀疑这是否是一种代码味道,因为它在应用程序服务中,而不是域服务中,它围绕着检查域模型是否存在,dto中的属性是否可以为空,等等。代码如下: public async Task<ResultDTO> CreateEvent(string userId, CreateEventDTO createEventDTO) { var user = await _userManag

我的应用程序服务中有验证逻辑,可以确定请求的操作是否成功,如果不成功,原因是什么。我怀疑这是否是一种代码味道,因为它在应用程序服务中,而不是域服务中,它围绕着检查域模型是否存在,dto中的属性是否可以为空,等等。代码如下:

    public async Task<ResultDTO> CreateEvent(string userId, CreateEventDTO createEventDTO)
    {
        var user = await _userManager.FindByIdAsync(userId);
        var claims = await _userManager.GetClaimsAsync(user);
        var projectId = Convert.ToInt32(claims.FirstOrDefault(c => c.Type == "Project").Value);
        var eventType = _eventTypeDataAccess.GetEventType(createEventDTO.EventTypeId);

        if (eventType == null)
        {
            return new ResultDTO
            {
                Succeeded = false,
                Errors = { "Event type doesn't exist" }
            };
        }

        if (_eventDataAccess.Exists(projectId, createEventDTO.Name))
        {
            return new ResultDTO
            {
                Succeeded = false,
                Errors = { "An event with this name already exists" }
            };
        }

        var result = new ResultDTO();

        if (string.IsNullOrEmpty(createEventDTO.Name))
        {
            result.Succeeded = false;
            result.Errors.Add("A name must be provided for the event");
        }

        if (string.IsNullOrEmpty(createEventDTO.Description))
        {
            result.Succeeded = false;
            result.Errors.Add("A description must be provided for the event");
        }

        if (result.Errors.Count > 0)
        {
            return result;
        }

        var newEvent = new Event(Guid.NewGuid(),
            createEventDTO.Name,
            createEventDTO.Description,
            new Guid(createEventDTO.EventTypeId),
            createEventDTO.StartDate,
            createEventDTO.EndDate,
            true);

        _eventDataAccess.Add(newEvent);
        result.Succeeded = true;
        return result;
    }
public async Task CreateEvent(字符串userId,CreateEventDTO CreateEventDTO)
{
var user=await\u userManager.FindByIdAsync(userId);
var claims=await_userManager.GetClaimsAsync(用户);
var projectId=Convert.ToInt32(claims.FirstOrDefault(c=>c.Type==“Project”).Value);
var eventType=\u eventTypeDataAccess.GetEventType(createEventDTO.EventTypeId);
if(eventType==null)
{
将新结果返回到
{
成功=错误,
错误={“事件类型不存在”}
};
}
if(_eventDataAccess.Exists(projectId,createEventDTO.Name))
{
将新结果返回到
{
成功=错误,
错误={“具有此名称的事件已存在”}
};
}
var result=new ResultDTO();
if(string.IsNullOrEmpty(createEventDTO.Name))
{
result.successed=false;
result.Errors.Add(“必须为事件提供名称”);
}
if(string.IsNullOrEmpty(createEventDTO.Description))
{
result.successed=false;
结果.错误.添加(“必须为事件提供说明”);
}
如果(result.Errors.Count>0)
{
返回结果;
}
var newEvent=新事件(Guid.NewGuid(),
createEventDTO.Name,
createEventDTO.Description,
新Guid(createEventDTO.EventTypeId),
createEventDTO.StartDate,
createEventDTO.EndDate,
正确的);
_eventDataAccess.Add(newEvent);
result.successed=true;
返回结果;
}

我在域模型中进行验证,例如在创建新事件()时进行验证。构造函数对其传递的值进行基本验证,例如名称不能为null或空。但是,当谈到为此编写测试时,我开始质疑验证逻辑是否应该位于可以单独测试以进行验证的域服务中。然后可以测试此方法,以确保所有依赖项都被正确调用。这让我怀疑这是域泄漏到应用层,还是被认为是应用层逻辑。但同时,域不负责进行DTO并验证值,对吗?

尽管对于将验证放在哪一层有不同的看法,但我个人认为只有业务规则应该在域层中进行检查。将每个验证放在域层会导致域层走错方向。域层是为业务规则而设计的。检查不为空的属性是业务规则吗?如果没有,最好在应用程序服务层检查它


从中可以看出,这是一个Microsoft示例项目,这种验证是在应用程序层实现的。在本示例中,
CreateOrderCommand
类似于DTO。它是用在它。由于单一责任原则,我建议您使用此工具将验证过程与方法分离,并使测试更容易。

我通常会问这样一个问题:用户可能做错了什么,还是开发人员针对API实施的可能做错了什么?。对于后者,我的意思是,针对API实现的开发人员首先不应该允许用户发送一些不完整的请求

如果API严格定义必须设置属性(即强制设置)我已经在API或应用层验证了这一点。无需将其传递到域层。因此,如果针对API实现的开发人员(例如,在前端代码中)忘记确保发送的数据符合规范,则在接收和处理来自REST调用、队列消息或使用的任何其他通信协议的数据时,应该已经引发错误。当然,我所说的不变量与此级别的业务逻辑无关

当然,这并不意味着在某些情况下也会在域层中检查类似的内容。域模型类不允许使用无效数据构造,因此在接收到无效属性时引发错误也是域层的责任

将其移交给域层之前检查是否存在明显错误也符合
fail fast
原则,并且可以避免不必要的操作,例如在调用域模型操作时从数据库加载聚合失败,而域模型操作将失败,因为没有正确地传递参数不管怎么说,请求还是被拒绝了

也考虑一下,如果这种情况发生一次,可能没有太多的含义,但是考虑到客户端代码中存在一些错误,如果有很多无效的调用,您确实可以节省大量的资源。 在检查DTO的id是否有效或DTO的某个属性是否为空的应用程序服务中进行验证是否是一种不良做法

因此,如果您不是针对业务不变量进行检查,而是针对无效的API规范进行检查,我认为这甚至是一种好的做法