我的问题更多的是建筑性质,与实际实施的关系较少。
我已经基于WCF构建了一个API,但是无法真正决定如何将PL与BL分开。我已经使我的服务变薄了,所以它只保留了最少的实现,如:
public TagItemResponse TagItem(TagItemRequest request)
{
return (new ItemTagRequestProcessor()).GetResponse(request);
}
当然第一个问题出现了,RequestProcessors属于哪一层?我认为将它们称为外观是错误的,但与此同时,它们与演示无关。至于现在,我认为它们属于PL。处理器方法将我的DTO(DataContracts)作为输入,验证请求消息(基类),验证(基类)并最终返回单个DTO响应,如下所示:
protected override void Process(TagItemRequest request, TagItemResponse response, Host host)
{
var profile = ProfileFacade.GetProfile(host, request.Profile);
var item = ItemFacade.GetItemId(host, request.Item);
var tags = new List<Tag>();
foreach (var name in request.Tags)
{
var tag = TagFacade.GetTag(profile, name);
ItemFacade.TagItem(item, tag);
tags.Add(tag);
}
ItemFacade.UntagItem(item, tags);
}
现在我问自己,为什么我需要与我的业务对象相关的门面类1:1。例如,我有一个HostFacade,充当hostDAO和处理器之间的层。然而,它只保留很少的逻辑,它只是处理DAO调用。
public static Host GetHost(HostDTO dto)
{
return HostDAO.GetHostByCredentials(dto.Username, dto.Password);
}
问题:我不妨合并处理器和外墙,对吧?
我已经阅读了很多关于这个主题的文章/书籍,但我仍然不能满足于'正确'的方式,并且每当我面对这个问题时都倾向于选择不同的方法。我想知道是否存在正确的方法。
我发现了f.ex. doFactory示例,他们在服务实现中直接与DAO类进行了交谈。我并不喜欢这样,因为大多数ServiceContract方法共享一些逻辑,因此很适合与共享基类一起使用。
我还发现了其他只从服务中调用外墙的例子,但这似乎只适用于非常细粒度的消息。我的消息是“胖”和复合的,以便尽可能减少对服务的调用次数。我的额外处理层似乎是我真正的问题。
对于如何正确分层WCF服务,可能没有单一的答案,但希望你们中的一些人有一个意见,要么符合我的直觉,要么为我提供一些新的主题。
感谢名单!
杰弗里
答案 0 :(得分:3)
首先,我假设PL表示表示层,而不是持久层?
实现分层应用程序设计时,主要问题应该是:我可以替换较低层的实现,而不会影响上面层的实现。
这通常由持久层最好地说明。例如,如果从SQL Server 2008切换到MySQL,则持久层会发生变化(当然)。但业务层的变化是否也必要?例如,业务层是否捕获仅由SqlClient抛出的SqlException实例?在良好的设计中,业务层根本不需要进行任何更改。
同样的原则应该适用于业务层和表示层之间的分离。
在您的示例中,我会说ItemTagRequestProcessor
不应该在表示层中。首先,它与表示无关,其次,处理请求的实现不是表示层的关注点。将其与Web应用程序进行比较,向客户端呈现TagItemResponse
是Web(表示)层的关注点。检索TagItemResponse
的实例是表示层下面的图层的关注点。
确定在业务层和持久层之间是否有外观是很困难的。我通常不实现外观,因为它增加了一个额外的(通常是不必要的)间接层。此外,我没有看到直接从业务层方法调用持久层方法的问题。如果只考虑相同的原则:是否可以在不影响业务层实现的情况下更改持久层实现。
亲切的问候,
罗纳德威尔登伯格