【问题标题】:Some Questions about structuring domain-driven-design namespaces关于构建领域驱动设计命名空间的一些问题
【发布时间】:2011-05-20 07:19:39
【问题描述】:

我有一些关于框架设计的一般性问题。

我正在 C#.NET(框架 3.5)和 SQL 2008(使用 LINQ)中为 iPhone 应用程序构建 API。我遵循了领域驱动设计模式(在一本书中)和 具有以下文件夹结构:

Core
- DataAccess
--Impl
-Domain
-Impl

Core 是我的核心 API 库 - 我的 DLL。 DataAccess 包含数据访问接口 DataAccess.Impl 包含存储库(LINQ to the DB) 域包含我的大部分数据类型和属性。 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

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

我们非常感谢您的建议(以及任何示例)。

谢谢。

【问题讨论】:

  • 有人想试试这个吗?我可以做些什么来改进/澄清我的问题?谢谢。
  • 我假设这是一个 .NET 后端,iPhone 应用程序将通过互联网访问它(是吗?)。 “其他开发人员”是在开发 iPhone 应用还是在这个 .NET 后端工作?
  • 或者是某种monotouch 应用程序在 iPhone 上运行?
  • 嗨,Marijn,感谢您的回复/cmets。我正在设计服务器和 web api,“其他开发人员”正在开发 iPhone 应用程序,并期待访问 web 方法。
  • 在这种情况下,您可能想要创建一个易于使用的 Web 服务外观,类似于 Will 的建议。

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


【解决方案1】:

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

以我的拙见,还没有必须公开的内容,即静态类,假设我们考虑外观设计模式,它公开了您的库子系统特性和功能。

外观设计模式解释:

  1. Façade Design-Pattern - (Gang of Four);
  2. Facade pattern (Wikipedia)。

那么最后,你的代码应该做什么?只需公开您应该知道的必要内容,因为您是唯一了解您正在开发的系统的人。

简而言之,我经常使用外观模式,以便我可以将我的类、实现和几个相关子系统隔离在外观的底层。假设我们是一家全新的汽车经销商。这个立面将是巨大的窗户,让您可以看到暴露在展厅中的汽车。你得想想这个立面暴露了什么。它只暴露汽车吗?

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

希望这对您有所帮助! =)

【讨论】:

  • 这个外观很可能建立在现有的 DDD 解决方案之上。
  • 我认为这就是 OP 正在寻找的。​​span>
  • 谢谢你告诉我,Marijn!
  • 是的,同意(很抱歉耽搁了……疯狂工作!)。谢谢威尔!
  • 我很高兴能帮上忙,Code Sherpa!延迟没问题,毕竟你是那个等待的人。 =) 保重!
【解决方案2】:

如果我没记错的话,你问的是两个问题:

  1. 如何构建 DDD 应用程序?
  2. 那些长的命名空间名称呢?

我的回答相当冗长 - 我冒昧地将它分成两个回答者。

这是第二个问题的答案:

2。那些长的命名空间名称呢

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

  • “产品”和“核心”两个词的重复
  • 通用术语“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;       

【讨论】:

  • 今天晚些时候我会尝试回答你的另一个问题。
  • @Code Sherpa:是你在质疑如何构建 DDD 应用程序?重新阅读您的问题后,我不再那么确定了。
  • 您好,Marijn,谢谢。好吧,我真的在寻找一个好的方法,但是由于我已经开始使用 DDD,所以我现在不做任何改变可能是有道理的。除非有人指出 DDD 对于我正在尝试做的事情来说是“错误的”。再次感谢!
  • @Code Sherpa:我想不出 DDD 以及所有鼓励它的技术都不可行的场景。
  • +1 您的回答带来了有关 DDD 及其不同层的详细信息,即解耦项目与解决方案的方式。我自己可以从你的回答中得到启发。=)
【解决方案3】:

我怀疑您的应用程序的用户会看到这一点。 您需要的第一件事是功能。这就是你最后要卖的东西。

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

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

  1. 挑选的结构将如何帮助我 进行维护并添加新的 功能?
  2. 它将如何帮助新 开发人员开始在我的内部编码 解决方案?
  3. 仅此而已 程序集/文件夹/类名是 可识别且具有描述性?
  4. 我忘记的问题。

这是你的目标。但不是您正在寻找的规则。 如果新开发者能够理解,您可以选择任何名称。

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

在 38:18-39:45(约 1.5 分钟)观看此 talk。有一些关于如何回答一些问题的好习惯。

【讨论】:

    猜你喜欢
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2010-11-29
    • 2011-10-08
    相关资源
    最近更新 更多