关于构造域驱动设计命名空间的一些问题

时间:2010-12-04 18:52:29

标签: c# api design-patterns namespaces domain-driven-design

我对框架设计有一些一般性问题。

我正在为C#.NET(框架3.5)中的iPhone应用程序构建API,& SQL 2008(使用LINQ)。我遵循了Domain-Driven-Design模式(在一本书中)和 具有以下文件夹结构:

Core
- DataAccess
--Impl
-Domain
-Impl

Core是我的核心API库 - 我的DLL。 DataAccess包含数据访问接口 DataAccess.Impl包含存储库(DBQ的LINQ) 域包含我的大多数数据类型和属性。 Impl包含我的服务(即AccountService.cs,EmailService.cs)

现在,作为练习,我已经为此项目添加了Windows服务 并尝试从此服务中的DLL调用功能。 我的问题是,我应该向其他应用程序公开哪一层 什么应该隐藏?

  • Impl文件夹中的服务类应该是程序员看到的吗?
  • 或者来自DataAccess.Impl的存储库?
  • 或者,我应该全力以赴让程序员看到吗?看起来如此 现在,这似乎有点令人困惑。

当我开始阅读关于DDD时,我假设存储库是 隐藏和服务类访问,但我发现我需要打电话 来自我的客户端的功能。我设计错了吗?

我的另一个问题是命名空间命名。当Windows服务 从我的核心库调用功能,我必须做我的包括:

using Company.Product.ProductCore.Core.DataAccess.Impl 
using Company.Product.ProductCore.Core.Domain 
using Company.Product.ProductCore.Core.Impl

这似乎很罗嗦。看看微软的DLL,它们似乎与两层保持一致 约定 - (System.Linq,System.Text等)。拥有Company.Product.ProductCore.Core.Impl 看起来很乱,并没有真正告诉程序员这个命名空间做了什么(但它 是我读过的例子所建议的)。这里有最好的做法吗?

您的建议(和任何示例)都非常感谢。

感谢。

3 个答案:

答案 0 :(得分:7)

在我看来,域名绝对不是您所需要的,也不是您的数据访问层。

根据我的拙见,如果我们考虑外观设计模式,暴露你的库子系统的特性和功能,那么必须暴露的内容还不存在,即静态类。 >

alt text

Façade设计模式解释:

  1. Façade Design-Pattern - (Gang of Four);
  2. Facade pattern (Wikipedia)
  3. 所以最后,你的代码应该做什么?只要揭示您应该知道的必要内容,因为您是唯一了解您正在开发的系统的人。

    简而言之,我经常使用Façade模式,这样我就可以在幕墙的引擎下隔离我的类,实现和几个相关的子系统。让我们考虑一下我们是一个全新的汽车经销商。这个外观将是伟大的窗户,让您看到在展示厅暴露的汽车。你必须想到这个外观所暴露的东西。它只暴露汽车吗?

    在我看来,这个外观暴露了你可以购买的汽车,借钱购买,修理汽车,购买其他相关配件等等。然后配件被曝光,但只有什么需要。与汽车等其他项目相同。也就是说,您可能只希望公开一个接口,并为自己保留实现,这样当您需要返回ICarIAccessory时,必须通过façade实例化它们。你的实现对象类,然后通过你的façade返回接口实例。也就是说,用户不需要知道引擎盖下发生了什么,但只有当他想要一辆车时,他必须通过你的外墙订购它。就像你不会去梅赛德斯奔驰购买马自达3。你会使用正确的外观。然后,不同的汽车经销商可能只是子系统,因此是某种工厂。然后你向外墙询问有这个和那个规格的汽车,并且外观应该知道返回什么ICar实例以换取你要求它提供给你的东西。

    希望无论如何都有帮助! =)

答案 1 :(得分:7)

如果我没弄错的话,你会问两个问题:

  1. 如何构建DDD应用程序?
  2. 那些长命名空间名称怎么样?
  3. 我的答案相当冗长 - 我冒昧地把它分成两个小圆。

    这是第二个问题的答案:

    <强> 2。那些长命名空间名称

    怎么样?

    我认为长名称空间名称不一定是混乱的。 恕我直言,你的名字看起来很乱:

    • 重复单词“Product”和“Core”
    • 使用通用术语“Impl”

    第一个改进可能是:

    // The Domain objects go here;
    MyCompany.MyProduct.Core.Domain;  
    // DataAccess interfaces go here:
    MyCompany.MyProduct.Core.DataAccess;
    // a Linq implementation of the DataAcces interfaces go here:
    MyCompany.MyProduct.Core.DataAccess.LinqImpl; 
    // The Core service go here:
    MyCompany.MyProduct.Core.Services;
    // Some general purpose infrastructure goes here (e.g. emailing code)
    Mycompany.MyProduct.Infra;
    

    此外,我发现在代码结构中使用商业产品名称(例如MyProduct)是不好的(如果营销选择不同的名称会怎么样?);我喜欢使用逻辑子系统的名称。 让我们假设您的建筑汽车租赁系统。然后CarRental将被视为此应用的核心功能。然后我将使用以下命名空间结构(Serra是我公司的名称):

    // For classes Customer, Account, Car
    Serra.CarRental.Domain;    
    // I use Dao as a general abbreviation for "Data Access Objects"
    // Dao interfaces go here:
    Serra.CarRental.Dao;     
    // Linq implementation for Dao interfaces  
    Serra.CarRental.Dao.Linq;
    // For Services specific to the car rental domain: 
    // AccountService and RentalService and CarAvailabilityService
    Serra.CarRental.Services;  
    // For UI objects (not relevant in you situation?)
    Serra.CarRental.UI;
    // general service code; ignorant of the CarRental domain (e.g. an EmailService)
    Serra.Infra.Service;       
    

答案 2 :(得分:0)

我怀疑您的应用程序的用户会看到这个。 首先,您需要的是功能。这就是你最后会卖的东西。

您还需要尽可能降低维护费用。以下是您的代码组织方式。 第二件事 - 尽量减少维护费用。

因此,要决定如何组织解决方案,您应该回答一些问题:

  1. 挑选的结构如何帮助我 做一个维护和添加新的 特征
  2. 它将如何帮助新的 开发人员开始在我的内部编码 溶液
  3. 就是这样 程序集/文件夹/类名称 可识别和描述性的?
  4. 我忘了的问题。
  5. 这是你的目标。但不是你要找的规则。 如果新开发人员理解它们,您可以选择任何名称。

    可能(作为一种启发式方法,如果你使用像Resharper或Refactor!Pro这样的重构工具),你可以从单个程序集和单个名称空间开始。在开发过程中,您将看到如何更改项目结构以更好地满足您的需求。然后重构它。

    在38:18-39:45(约1.5分钟)观看talk。如何回答一些问题有很好的做法。