繁体   English   中英

.NET应用程序体系结构-此类的最佳组合?

[英].NET Application Architecture - Which is the optimal assembly for this class?

我已经接管了一个.net Web应用程序,该应用程序过去曾遭受所有业务逻辑的困扰,这些逻辑在页面后方的代码中并与UI紧密相关。

我花了一些时间进行重构,尤其是将数据访问代码移动到专用的数据访问项目“ Company.DataAccess”中(例如)。 代码的其他逻辑部分也具有自己的程序集。

我不满意的是需要在程序集之间共享的对象的放置:

例如-在我的项目“ Company.ClientDataImport”中,我有一些类,这些类包含用于导入客户数据的业务逻辑。

包含此代码的一项特殊功能是,可以将客户端导入格式映射为我们的默认导入格式。 因此,我在“ Company.ClientDataImport”程序集中有一个类“ DataImportFieldMappingInfo”:

public class DataImportFieldMappingInfo {

    int CompanyFieldName
    {
        get;
        set;
    }

    int ClientFieldName
    {
        get;
        set;
    }
}

这些映射存储在数据库中,因此在某些时候,我需要使用此对象的实例填充集合。

一种体系结构目标是所有数据库IO应由“ Company.DataAccess”处理。

我希望“ Company.DataAccess”了解类DataImportFieldMappingInfo,以便它可以按预期的方式使用用于存储此类数据的类,但这意味着“ Company.DataAccess”和“ Company.ClientDataImport”都需要了解DataImportFieldMappingInfo,以便他们可以使用相同的类进行通信。

到目前为止,我对这个常见问题的解决方案是使用另一个名为“ Company.DomainEntities”的库,该库包含应用程序中其他程序集之间共享的对象的类。 这很好用,并且所有程序集都可以根据相同的对象进行通信。 这些类实际上只包含属性,因此它们只是数据容器,而不是包含应用程序逻辑。

我对此不满意的是DataImportFieldMappingInfo是一个数据导入问题,因此我认为它应该在该命名空间中,因此应该在“ Company.ClientDataImport”项目中。 但是,循环引用限制阻止了这种情况,因此我必须以“ Company.DomainEntities”项目为中间人。

我的体系结构是否有问题,还是这种情况下的常见做法?

在那种情况下,将共享类型/接口分解为单独的程序集是很正常的。

另一种方法(并非闻所未闻)是简单地说:“所有这些程序集都没有做任何额外的事情”,而只是使用命名空间来分隔代码。 如果不需要只运行一部分dll,为什么不只拥有一个 dll? 对此的经典对策是,您有多个使用同一个dll(或dll的不同子集)的不同UI /服务。

我倾向于同意马克的观点。 但您可能还要考虑其他几件事:

什么是“业务逻辑”与“数据访问”代码与您的应用“了解”的简单数据结构? 乍一看,DataImportFieldMappingInfo看起来可能与数据访问相关,但我认为它们实际上只是通用结构(并且更面向业务),因此将它们放在一个通用程序集中就很有意义-假设您使用它们在不同层之间交换数据/ assembilies。

可以采取的另一种观点是, 所有数据存储库(包括特定于您的应用程序的数据库以及所有外部数据源(如外部数据库,文件或系统))均被同等对待,并通过接口 (而不是通过单个具体实现)进行访问。 在这种情况下,所有数据都是以业务逻辑/域为中心的方式指定的,而不是以数据访问/存储库特定的方式指定的。 在这种情况下,您还将定义应用程序在通用程序集中使用的所有通用数据结构。

编辑:

简而言之,接口使您可以抽象出与讨厌的东西相关联的复杂性和依赖性,而这些东西是您不希望与其紧密(永久)相关联的。

使用接口背后的原理是依赖反转 (DI)。 (有关此方面的信息并不缺乏-实际上,您可能会发现太多了)。 DI一直在帮助构建符合“ 稳定依赖原则”的系统

这样的想法是,让您的业务逻辑(程序集)不依赖于数据访问,而是让它们都依赖于接口; 然后,您可以随时替换实施。 您可能有一个针对SQL的“真实”数据访问组件和一个“虚拟”组件,该组件直接从您的代码返回虚拟测试数据。

在设计接口时,其想法是从业务逻辑/领域的角度进行设计的,而不是从技术角度; 尽管在某些情况下这是适当的。 实现的工作(即:实现接口的数据访问类)是在面向业务的接口与它要处理的任何奇怪数据源之间进行转换。 例如,您平均的基于SQL的数据提供程序可能会通过DataReader吸收数据,然后转换为MyBusiness.Common.Info.OutstandingAccountsCollection

代码结构

  • 通用程序集(MyBusiness.Common)-包含用于在各层之间交换数据的任何数据结构(例如: MyBusiness.Common.Info.OutstandingAccountMyBusiness.Common.Info.OutstandingAccountCollection类)。
  • 接口组件:您可能有几个。 如果所有数据访问都是通过一个系统(例如SQL)进行的,则可能只有一个系统(MyBusiness.Interfaces.DataAccessProvider),但是如果要使用各种系统进行交互,则希望将它们分开。 MyBusiness.Interfaces.DataAccessProvider引用Common程序集,因为它将在其合同中包括“信息”类型。
  • 具体的数据访问程序集:(MyBusiness.DataAccess.SQLDataAccessProvider)。 这引用了Common和Interface程序集。
  • 您的业​​务逻辑(MyBusiness.BusinessLogic)引用了Common和Interface程序集。

有关更多信息(和图表),请查看以下内容(自我提升警报): 5层体系结构

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM