.NET应用程序体系结构-哪个是此类的最佳程序集?

.NET应用程序体系结构-哪个是此类的最佳程序集?,.net,oop,architecture,n-tier-architecture,.net,Oop,Architecture,N Tier Architecture,我已经接管了一个.NETWeb应用程序,它在过去遭受了所有业务逻辑都在页面后面的代码中的痛苦,并且与UI紧密相连 我花了一些时间进行重构,特别是将数据访问代码移动到专用的数据访问项目“Company.DataAccess”(例如)中。代码的其他逻辑部分也有自己的程序集 我不喜欢的是需要在部件之间共享的对象的放置: 例如,在我的项目“Company.ClientDataImport”中,我有一些类包含用于导入客户机数据的业务逻辑 包含此代码的一项特定功能是,客户机导入格式可以映射到我们的默认导入格

我已经接管了一个.NETWeb应用程序,它在过去遭受了所有业务逻辑都在页面后面的代码中的痛苦,并且与UI紧密相连

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

我不喜欢的是需要在部件之间共享的对象的放置:

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

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

public class DataImportFieldMappingInfo {

    int CompanyFieldName
    {
        get;
        set;
    }

    int ClientFieldName
    {
        get;
        set;
    }
}
这些映射存储在数据库中,因此在某个时候,我需要用该对象的实例填充集合

一个架构目标是,所有数据库IO都应该由“Company.DataAccess”处理

我希望“Company.DataAccess”知道类dataimportfiedmappinginfo,这样它就可以像存储此类数据那样使用该类,但这意味着“Company.DataAccess”和“Company.ClientDataImport”都需要知道dataimportfiedmappinginfo,以便它们可以使用相同的类进行通信

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

我不喜欢的是DataImportFieldMappingInfo是一个数据导入问题,因此我认为它应该位于该名称空间中,因此位于“Company.ClientDataImport”项目中。然而,循环引用限制阻止了这一点,因此我不得不使用“Company.DomainEntities”项目作为中间人


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

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


另一种方法(并非前所未闻)是简单地说“所有这些程序集都没有做任何额外的事情”,并使用名称空间来划分代码。如果您不需要只使用dll的一个子集运行,为什么不使用一个dll呢?与此相对应的是,您有多个不同的UI/服务,它们都使用相同的dll(或dll的不同子集)。

我倾向于同意Marc;但你可能会考虑其他一些事情:

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

另一种观点是,所有数据存储库(包括特定于您的应用程序的数据库以及所有外部数据源,如外部数据库、文件或系统)都被平等对待,并通过一个而不是一个具体的实现来访问。在这种情况下,所有数据都是以业务逻辑/以域为中心的方式指定的,而不是数据访问/存储库特定的方式。在本例中,您还需要在公共程序集中定义应用程序使用的所有公共数据结构

编辑:

简言之,接口允许您抽象出与讨厌的东西相关联的复杂性和依赖性,而这些东西是您不愿意密切(永久)联系在一起的

使用接口背后的原则是(DI)。(关于这方面的信息并不缺乏——事实上,你可能会发现信息太多了)。DI一直在帮助构建能够很好地使用的系统

其思想是,与其让您的业务逻辑(assembly/s)依赖于数据访问,不如让它们都依赖于接口;然后,您可以随时交换实现。您可能有一个针对SQL的“真实”数据访问组件和一个直接从代码返回虚拟测试数据的“虚拟”组件

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

代码结构

  • 公共程序集(MyBusiness.Common)-包含用于在层之间交换数据的任何数据结构(例如:
    MyBusiness.Common.Info.OutstandingAccount
    MyBusiness.Common.Info.OutstandingAccountCollection
    类)
  • 接口程序集:您可能有几个这样的程序集。如果您所有的数据访问都是通过一个系统(比如SQL)进行的,那么您可能只有一个系统(MyBusiness.Interfaces.DataAccessProvider),但是如果您要与不同的系统进行接口,您可能希望将它们分开。MyBusiness.Interfaces.DataAccessProvider引用公共程序集,因为它将包含“info”类型