【问题标题】:Service layer in Architecture - DLL? [closed]架构中的服务层 - DLL? [关闭]
【发布时间】:2016-03-02 17:06:17
【问题描述】:

我们正处于 .Net 中的中型/大型应用程序的早期设计阶段,该系统具有三个不同的内部客户端(站点)(一个在单独的域中)连接,以及一个大量的外部服务。

我们现在专注于连接的内部站点,我提出了一个经典的分层应用程序,包括接口层、服务层、业务逻辑层和数据访问层。

在图像中,我们有一个连接到 MVC 应用程序的浏览器。控制器有一个对服务项目的引用(可能有每个“业务领域”的类。例如,“PersonService”)。 MVC 将直接引用此服务项目。在Service层,还会有一些WCF项目,将某些功能暴露给外部源、其他内部站点和服务等。

不过,WCF 项目将连接到主服务 DLL 以从中获取共享功能。

然后,Service 项目直接引用 Business 项目,包含所有业务逻辑。然后它引用了数据访问项目,该项目有一个/一些实体框架模型作为 SQL Server 数据库的 ORM。

SharedLib 只是一个所有层都引用的项目,包含任何共享逻辑,但主要用于 DTO(数据传输对象)。 EF 模型在数据层被转换为 DTO,因为没有其他层引用 EF 模型。

但是 MVC 应用程序,通过应用程序内的直接引用连接到服务层,以及将 WCF 服务暴露给外部源和跨域内部站点。

我们遇到的问题是在服务层上。我认为这应该是一个DLL,其他人说,如果没有WCF,那么表示应该直接连接到业务逻辑层。他们问,“为什么要在此处添加服务 DLL 的额外层和复杂性?”。

消除表示“可以”直接连接到逻辑的服务层是一种好习惯吗?我看到了服务层的好处,它增加了业务和表示的明确分离,并允许可扩展性。它看起来确实像一个通过 dll,但直接连接到 BL 似乎 - 奇怪。

是否有使用 DLL 的优点/缺点来证明保留/不保留它是合理的?

【问题讨论】:

  • 您好,当您说“我们遇到的问题是在服务层上。我认为这应该是一个 DLL”时,能否请您详细说明一下。您打算如何构建解决方案?在您的图中,共享库框是什么,您是指“共享项目”还是由不同 UI 实现共享的二进制文件?
  • 谢谢@LostBalloon。编辑了问题。
  • 如果我的回答太长,请随意跳过一些段落或一直到最后几段。希望我能帮上忙。
  • 谢谢@LostBalloon。无需跳过。喜欢阅读。谢谢。

标签: c# .net wcf dll architecture


【解决方案1】:

当我在图片中看到对 MVVM 模式的提示时,我会假设是这种情况,但它不应该对答案产生真正的影响。

我不会有完美的答案,但不要认为应该直接访问业务层。

我认为接口需要的任何功能都应该可以通过视图模型中的命令访问,这些命令使用可用的服务来执行它们的任务。

在我看来,业务层是业务规则,例如创建发票时的公式和预算映射。生成 P.O. 的另一个示例。号码。

另一方面,发票服务将负责应用您拥有的不同业务规则,以便生成、修改等(管理)您的发票。

当不需要把事情弄得太复杂时,我经常看到的情况是,业务层将隐式包含在服务层中。

将服务层编译为 DLL 的最大优势在于它们可以由应用程序的不同部分(例如前端和后端)共享。例如,如果您使用 ASP.net 构建前端,能够共享服务将是一个优势,但如果您使用 angular.js 之类的东西,那么显然它们将无法使用,从而使库更少可取的。

我还看到了 WebAPI 的提示,这是将客户端接口与基于服务器的后端分离的最新趋势。这种模式通常意味着客户端不了解您的业务逻辑或您的后端。发出 HTTP 请求以执行操作,API 会根据操作(GET 与 POST)以确认或数据进行响应。

至于WCF部分我不是太熟悉,我个人用的是RabbitMQ。

总而言之,我希望我的吐槽能给你一些思考并帮助你做出决定。

由于这是一个 C# .net 问题,我想我可以放心地假设您的解决方案将在 Visual Studio 中创建。就个人而言,如果有足够的目的将服务与业务逻辑分开,我会毫不犹豫地在我的解决方案中添加一个额外的库项目,并添加对需要它的项目的引用。它根本不会增加太多开销,因为其中大部分是由 Visual Studio 管理的(或者在自动化构建时在命令行中使用 msbuild)。

如上一段所述,我将在我的解决方案中创建库项目,因为管理它并不太复杂,而且它实际上会促进适当的命名空间管理,作为一个小小的好处。

我认为你们不应该害怕拥有更多的 dll(同样取决于项目的规模)。如果你仔细想想,每次你在项目中添加一个 nuget 包时,你实际上是在依赖另一个 dll。

【讨论】:

  • 谢谢! MVVM 确实在这里展示了它的自我。它更像是 MVC,但由于 MVC 使用“视图模型”,我认为它基本上是 MVVM。我需要了解更多。你的答案是我的想法。我喜欢逻辑和表示之间的分离,允许定义“从我这里获取所有服务”类型的想法。与“一些来自逻辑 DLL,一些来自服务”相反。命名空间是一个好点!这给了我更多的弹药。 :) 我得到的阻力是维护 DLL 的额外工作的开销。但是..这只是一个传递,真的,对我来说,开销非常低。谢谢!
【解决方案2】:

我不打算解决服务交付层之上的任何问题;在服务层的设计中,如何将服务结果传递给浏览器应该是中立的。我们目前使用 AngularJS 的完全客户端 UI,它运行得非常好。

对我来说,拥有层的目的主要是允许抽象并允许用其他东西替换层,或者在不重写所有内容的情况下修改层的实现方式。所以在我的设计中,层层叠叠;所以Service层应该只使用repository,repository是唯一引用领域模型/核心业务逻辑的地方。

在过去的 4 年里,我一直在研究一个相当大的系统。我们开始使用 Windows Worfklow、WCF 和 MVC.Net。在第一次修订后(大约 6 个月),我们停止使用 Workflow 和 WCF - WCF 只增加了编码的复杂性和单调乏味。一旦我们弄清楚如何正确实施它,工作流仍然在我们的重新包含列表中。我们在每个 DLL 中使用我的Emesary 消息传递系统,并使用 EmesaryMSMQ 桥接器来允许多台机器提供服务。 Emesary 允许您在项目中拥有基于接口的通知系统 - 并且桥允许您将某些通知(可靠地通过 MSMQ)桥接到其他进程。无论您使用哪种方法,正确设计您的协议都非常重要。

我们有自己的私有 nuget 存储库 - 我希望我们以这种方式开始,因为它真正专注于设计过程并确保可替换性。目前,我们有一个由 IUnitOfWorkManager 提供的 IUnitOfWork 和一个提供基于 Reference Monitor 的对象级安全性的 IAuthorisationMediator。我花了一天左右的时间才习惯使用 NuGet,但这是一笔不错的投资。

最后,我建议不要使用 EF。尽管我建议使用 dataobjects.net 需要额外的费用(除了作为一个非常快乐的用户之外,我没有任何关联)。 最初我们选择了 dataobjects.net,因为它是代码优先。我在 2012 年重新评估了 EF(代码优先)、NHibernate 和其他一些 ORM——我们继续使用 dataobjects.net,因为它是最容易编码并且性能最好的(对我们来说)。我不想在 ORM 的主题上跑题太多,所以我会说我们最近将 EF 用于另一个项目 - 我们都希望我们没有使用它。


1我们当时确实意识到它部分是由 dataobjects.net 的创建者宣传的,但我们的测试结果在很大程度上与他们的一致。

【讨论】:

  • 出于好奇,EmesaryMSMQ 与 RabbitMQ 相比如何?它是否还具有重试、错误处理以及允许您将消息重新提交回队列以进行处理的接口?
  • 至于 EF,我在最近的一个项目中使用了 EF6,它做得很好(虽然我有一个有趣的学习曲线..) github 上正在开发的 EF7 应该是更好,并且还将支持(更容易)拥有多个数据源(这是我使用 EF6 时遇到的最大问题)。我不得不说我的项目是数据库优先的。
  • EF 的主要问题(可能已经解决)。当您插入/修改更多记录时,保存更改的速度会呈指数级增长。我发现大约 300 是最佳值。在保存更改之前不分配 ID(当自动生成键时)。延迟加载太懒了,需要包含。在不同上下文中混合对象时缺少异常。数据库迁移很难正确进行。当两个相同的实体与上下文分开加载时出现问题。 EF 有很多困难,它不像我预期的那样工作。
  • EmesaryMSMQ 是比 RabbitMQ 低得多的协议;它更接近 ZeroMQ。基本上,您通过发送器发送消息,然后通过 MSMQ 可靠地传递。这就是它所做的一切。一旦收到消息,就由接收者来处理任何额外的逻辑。通常,收件人会发回一条消息以指示状态。由您来设计协议。优雅在于简约;发起对象不需要知道通知是否正在路由,只需以与本地处理消息相同的方式发送。
猜你喜欢
  • 2017-06-09
  • 2021-04-09
  • 1970-01-01
  • 2021-02-16
  • 2014-02-05
  • 2018-01-27
  • 1970-01-01
  • 2012-02-12
  • 2014-04-13
相关资源
最近更新 更多