以正确的方式分层 WCF 服务 [英] Layering a WCF Service the right way

查看:33
本文介绍了以正确的方式分层 WCF 服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题更多是架构性质的,较少涉及实际实现.

My question is more of an architectural nature, less involved with the actual implementation.

我已经基于 WCF 构建了一个 API,但无法真正决定如何将 PL 与 BL 分开.我已经使我的服务精简,因此它只包含最少的实现,例如:

I have build an API based on WCF, but can't really decide on how to separate the PL from the BL. I have made my service thin, so that it holds only a minimum of implementation, something like:

public TagItemResponse TagItem(TagItemRequest request)
{
   return (new ItemTagRequestProcessor()).GetResponse(request);
}

当然第一个问题出现了,RequestProcessors属于哪一层?我认为将它们称为外观是错误的,但同时,它们与演示无关.至于现在,我决定它们仍然属于 PL.处理器方法将我的 DTO(DataContracts)作为输入,验证请求消息(基类),验证(基类)并最终返回单个 DTO 响应,如下所示:

Than of course the first question arises, in what layer do the RequestProcessors belong? I think it would be wrong to call them a facade, but at the same time, they have nothing to do with presentation. As for now, i decided that they nevertheless belong in the PL. The processor methods take my DTO's (DataContracts) as input, validate the request message (base class), authenticate (base class) and eventually return a single DTO response, like so:

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 调用.

Now I ask myself, why do i need the facade classes 1:1 related to my business objects. For example i have a HostFacade that acts as a layer between the hostDAO and the processors. It, however, holds very little logic, it merely handles the DAO calls.

public static Host GetHost(HostDTO dto)
{
   return HostDAO.GetHostByCredentials(dto.Username, dto.Password);
}

问题:我不妨合并处理器和外墙,对吗?

Question: I might as well merge the processors and the facades, right?

我已经阅读了许多关于该主题的文章/书籍,但我仍然无法确定正确"的方法,并且每次遇到问题时都倾向于选择不同的方法.我想知道是否存在正确的方法.

I've read many articles/books on the subject, but i still can't settle on the 'right' way to go and tend to chose a different approach every time i face the issue. I wonder if a right approach even exists.

我找到了 f.ex.doFactory 示例,他们直接在服务实现中与 DAO 类进行对话.我不太喜欢那样,因为大多数 ServiceContract 方法共享一些逻辑,因此很适合与共享基类一起使用.

I've found f.ex. the doFactory example, where they talked to the DAO classes right from within the service implementation. I don't really like that, as most ServiceContract methods share some logic, and thus lend themselves well for use with shared base classes.

我还发现了其他示例,其中仅从服务内部调用外观,但这似乎仅适用于非常细粒度的消息.我的消息是胖"和复合的,以尽可能减少对服务的调用次数.我的额外处理层似乎是我真正的问题.

I've also found other examples where only the facades are called from within the services, but that seems to work well only for very fine-grained messages. My messages are 'fat' and composite in order to reduce the number of calls to the service as much as possible. My extra processing layer seems the be my real problem.

对于如何正确地对 WCF 服务进行分层,可能没有单一的答案,但希望你们中的一些人提出了符合我的直觉或为我对该主题提供新思路的意见.

Probably there is no single answer as to how to correctly layer a WCF service, but hopefully there are some of you out there with an opinion that will either conform my instincts or shed some new light on the subject for me.

谢谢!

杰弗里

推荐答案

首先,我假设 PL 是指表示层,而不是持久层?

First, I assume that by PL you mean presentation layer, not persistence layer?

在实现分层应用程序设计时,主要问题应该始终是:我是否可以在不影响上层实现的情况下替换下层的实现.

When implementing a layered application design, the main question should always be: can I replace the implementation of a lower layer without impacting the implementation of the layer(s) above.

这通常最好由持久层来说明.例如,如果您从 SQL Server 2008 切换到 MySQL,持久层会发生变化(当然).但是业务层的改变也是必要的吗?比如,业务层是否捕获了只有SqlClient抛出的SqlException实例?在一个好的设计中,业务层根本不需要改变.

This is usually best illustrated by the persistence layer. If you switch from SQL Server 2008 to MySQL for example, the persistence layer changes (of course). But are changes in the business layer also necessary? For example, does the business layer catch SqlException instances that are only thrown by SqlClient? In a good design, the business layer needs no changes at all.

同样的原则应该适用于业务层和表现层之间的分离.

The same principle should apply to the separation between business layer and presentation layer.

在您的示例中,我会说 ItemTagRequestProcessor 不应位于表示层中.首先,它与表示无关,其次,处理请求的实现不是表示层关心的.将其与 Web 应用程序进行比较,向客户端呈现 TagItemResponse 是 Web(表示)层的关注点.检索 TagItemResponse 的实例是表示层下面一层的关注点.

In your example, I would say that the ItemTagRequestProcessor should not be in the presentation layer. First, it has nothing to do with presentation, second, the implementation of processing a request is not a concern for the presentation layer. Compare it with a web application, presenting a TagItemResponse to a client is the concern of the web (presentation) layer. Retrieving an instance of TagItemResponse is the concern of a layer below the presentation layer.

决定是否在你的业务层和持久层之间有一个外观是很困难的.我通常不实现外观,因为它增加了一个额外的(通常是不必要的)间接层.此外,我认为直接从业务层方法调用持久层方法没有问题.如果只考虑相同的原则:您是否可以在不影响业务层实现的情况下更改持久层实现.

Deciding whether to have a facade between your business layer and persistence layer is difficult. I usually do not implement a facade because it adds an extra (usually unnecessary) layer of indirection. Besides, I do not see a problem in calling persistence layer methods directly from business layer methods. If only you take the same principle into account: can you change the persistence layer implementation without affecting the business layer implementation.

亲切的问候,

罗纳德·维尔登伯格

这篇关于以正确的方式分层 WCF 服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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