为啥域驱动设计似乎只在 C# 和 Java 等静态语言中流行? [关闭]

Posted

技术标签:

【中文标题】为啥域驱动设计似乎只在 C# 和 Java 等静态语言中流行? [关闭]【英文标题】:Why does domain driven design seem only popular with static languages like C# & Java? [closed]为什么域驱动设计似乎只在 C# 和 Java 等静态语言中流行? [关闭] 【发布时间】:2011-05-11 06:03:42 【问题描述】:

领域驱动设计已成为我的首选架构。我已经找到了大量关于在 ASP.net 框架中应用 DDD 原则的书籍和教程。它的灵感似乎主要来自于 Java 开发人员长期以来所做的事情。

对于我的个人项目,我开始更倾向于 Python,尽管我发现很难放弃静态类型。我希望能在使用动态语言应用 DDD 方面找到很多帮助。似乎没有关于 Python 和 DDD 的任何内容。这是为什么?显然,DDD 可以很好地应用于 Python。人们不会在 Python 中承担如此大的项目吗?或者考虑到动态类型,在 Python 中应用 DDD 是否更容易,从而减少所需的学习量?

也许我的质疑是由于我缺乏使用 Python 的经验。您对我的任何建议将不胜感激。

【问题讨论】:

刚刚阅读了关于域驱动设计的***页面,我对它的理解与以前差不多。 请制作这个社区维基。 “我开始更倾向于 Python,尽管我发现很难放弃强类型”-> Python 是强类型的。 @stefanw 我猜他正在考虑静态类型检查。 我想说“静态”与“动态”的区别与为什么 DDD 与 Java、C# 等相关联的原因较少,而这些语言与“企业”软件系统和上下文相关联的原因更多快速变化和对故障的低容忍度并存。例如,DDD 实际上在华尔街一些拥有大量 Python 代码库的大型机构中相当流行。 【参考方案1】:

我认为它在其他地方肯定很流行,尤其是函数式语言。然而,与大蓝皮书相关的某些模式并不适用于动态语言,并且像 Rails 这样的框架往往会导致人们远离有界上下文的想法

但是,DDD 成为无处不在的语言的真正推动力在动态语言中肯定很普遍。 Rubyists 尤其喜欢构建特定领域的语言——想想黄瓜特性最终的样子,这就是 DDD!

请记住,DDD 根本不是一个新想法,它只是以一种被 C# 和 Java 人员很好地接受的方式重新打包。这些相同的想法在其他地方以不同的旗帜出现。

【讨论】:

【参考方案2】:

我认为用动态语言编写好的 DDD 项目是完全可能的,但比静态语言更难维护。为什么?

工具

使用静态类型的语言,工具通常更强大。这就是为什么有些人使用TypeScript 而不是普通的JS,因为它可以通过简化重构来帮助您扩展代码。当您维护 DDD 代码时,每次都会出现重构,因为业务有时会发生变化,并且您对模型的了解每天都在发展,有了这些知识,您的代码也必须发展。我的大部分经验都是使用 C#,并且我用它构建了很多 DDD 项目。现在我在一个用 Ruby 编写的 DDD 项目中工作,我最怀念的一件事是缺乏强大的 IDE。在 Ruby 或 Python 中,人们习惯于使用文本编辑器,而不是 IDE。我很难看到有人写一些 IDE 或文本编辑器应该为我写的东西(即缺乏自动完成)。很难看到人们在 Vim 中搜索文件的完整路径只是为了打开它并查看方法或类的详细信息 - 例如,在 VS Code 或 Visual Studio 中,单击F12 就足够了转到定义类或方法,没有文件歧义。而且我什至没有谈论调试经验,看到人们在他们的代码中写binding.pry(对于非 ruby​​ 开发人员来说有点像 js 中的“调试器”关键字)让我很伤心在终端中调试它,而不仅仅是在行上设置断点。该列表比这更大,但我认为它足以说明“工具”的重点。

OOP 表现力

在 Python 和 Ruby 等一些动态语言中,您没有像接口和 abstract classes 这样的所有 OOP 功能。这有时会给代码的表达性和清晰性带来一些困难。

单元测试

你需要编写更多的单元测试来代替编译器可以为你做的事情。

动态输入

如果你想做某种类型检查,你需要使用duck typing。您无法从编译器获得任何帮助。

动态类型语言的好处

远离典型化地狱

在 OOP 动态与静态语言之间进行选择时,总是需要权衡取舍。 像 C# 和 Java 这样的静态类型语言的一个常见问题是,有时类型系统会使代码变得缺乏表达力和过于冗长。一些开发人员倾向于落入generics typification hell。但并非所有静态类型语言都有这个问题(F# 就是其中之一——因为强类型推断)。

测试

在某些情况下,没有静态类型也有帮助,例如,您不想创建一个接口只是为了注入您的类并使其可测试。在这些情况下,接口对可读性没有帮助,实际上它会损害可读性,因为您需要创建一个哑文件(接口),它除了测试代码的愿望之外不代表任何东西。在 Ruby 中,您可以通过多种方式做到这一点,而无需创建接口,例如:

class DispatchOrderService
  def initialize(overrides = )
    @repository = overrides.fetch(:repository) do
      ::Infra::OrderRepository.new
    end

    @mail_service = overrides.fetch(:mail_service) do
      ::Infra::MailService.new
    end
  end

  def dispatch(order)
    order.dispatched
    repository.save(order)
    mail_service.notify_order_dispatched(order)
  end
end

是的,通过这种方法,我们打破了clean architecture,因为该类知道具体的“基础设施”实现。但这是一个可以通过依赖注入解决的问题(在 Ruby 中,这些框架也总是破坏干净的架构,或者太难看以至于有人不想使用它,在我们的项目中,我们通过实例化依赖项来创建自己的 DI 容器 在项目启动时手动)。

结论

因此,我认为用 Ruby 编写好的“企业”DDD 应用程序是可能的,即使它比使用静态语言困难。我当前的项目就是其中一个例子(60k 行代码并且仍然可以维护)。

@GeorgeMaueris 提到的这一点也很重要。您可能会在框架中实施 DDD 时遇到问题,这些问题会强加给您组织代码的方式。在这里,我们选择使用Hanami 而不是 Rails,因为这个原因,但即使是 Hanami 也更“有主见”,这是我们想要的。我真的不建议任何人寻找“框架”来构建 DDD。设计/架构因应用程序而异,并且也在不断发展。当您选择“DDD”框架时,有时您会面临自己与它的斗争(做变通方法或猴子补丁)。

所以,也许你可以问我为什么选择 ruby​​。这里使用 Ruby 的要点是几乎 100% 的团队由 Ruby 开发人员组成,我们不想重复困难:学习 DDD + 一种新的编程语言。比纯粹的技术决策更具有战略意义。没有它,公司(一家初创公司)可能不会走这么远。

2018 年编辑:

对于依赖 DDD 方面的项目,我们放弃了 Ruby 和 Python。现在我们正在使用 Kotlin 并且非常满意。主要的好处是这里列出的:

IntelliJ 的最佳 IDE 支持。这使我们的重构速度大大加快,在编译时产生错误,并且减少了为编译器可以为我们做的事情编写测试的工作量。 用于依赖注入、ORM、functional programming 的优秀和流行框架 语言本身的另一个好处(空安全、数据类等)

2019 年编辑:

我们写了一系列关于从 Ruby 迁移到 Kotlin 的文章。你可以看到它here。

【讨论】:

我正处于决定是否继续开发中型 Python 项目(约 100 个源代码文件)的阶段,团队由 3 名开发人员组成。单元测试、集成测试、服务、容器化、大量重构,因为业务需求不明确,并且会随时更改。我是接口定义和静态类型的坚定支持者,更愿意使用 C#,同时所有团队都熟悉 python。到目前为止,它处于边缘,我无法决定走哪条路。 @ulkas 我认为这种类型的变化发生得越快,伤害就越小。当我们决定进行此更改时,我们公司有 50 名开发人员,今天我们有超过 150 名。但是......有时最好等待“重构时刻”尝试在不同的服务中测试另一种语言(致电微服务,如果你愿意),然后把剩下的旧代码放在那里。 感谢分享经验。静态语言和动态语言的主要区别在于: 用静态语言构建软件是一个我们称之为工程的过程。这就像建造一座房子,我们总是从一个准确的蓝图开始(界面在这里播放),然后按照精确的设计来建造。使用动态语言就像绘画或作曲一样是一种艺术。它总是从模糊的概念开始,然后以非线性的方式逐步丰富产品。构建企业系统不是动态语言的好用例,因为 DDD 需要提前进行严格的设计。 @ulkas 和这里一样,不能决定,你最后做了什么。? @cikatomo 该项目在某个阶段停止了。我个人的结论是,当您知道自己在构建什么时,您的语言中的库/驱动程序存在,请使用静态类型。当你只是在做 PoC 时,python 没问题。但我真的不建议为更多 3 位以上的开发人员使用 python 一年之久的项目。绝对没有附加值,但肯定有很多限制。据我所知,人们倾向于选择 python 只是因为“他们知道它”,我遇到的每一位资深程序员,谁已经经历了他生命中的这段旅程,都试图避免使用 python【参考方案3】:

这个问题困扰了我很长一段时间,所以我决定收集关于这个主题的所有有价值的数据。最后我得到了this github repo。

还有一些代码示例:

1)On Django

2)On Flask

3)On Ruby

还有更多。但绝对不够。

【讨论】:

我也为这个repo做出了贡献。这是一个使用 Ruby on Rails 和分层架构的示例应用程序 不错!随时针对 ddd-dynamic repo 打开 PR,我很乐意接受!【参考方案4】:

到目前为止,与 Java 相比,Python 在企业中似乎还不太流行(但我相信风向是朝那个方向发展的。一个例子是 Django,它是由一家报业公司创建的)。大多数使用 python 的程序员可能要么进入科学计算领域,要么进入 Web 应用程序。这两个领域都与(计算机)科学相关,而不是特定领域的业务,而 DDD 最适用于特定领域的业务。

所以我认为这主要是一个遗产问题。 C# 和 Java 从一开始就针对企业应用程序。

【讨论】:

构建企业应用程序比 Python 等动态语言所能处理的要复杂得多。大多数 python 开发人员只知道构建网站或 CMS,这是非常简单的具有标准化功能的应用程序。 Python 是一种很好的语言,可用于数据处理、图像处理、脚本等方面的快速原型和个人生产力工具,而无需 DDD 且实用。对于初创公司,通常只有 1 或 2 个开发人员。使用动态语言可以更快地交付,而无需考虑如何在公司倒闭之前维护系统。【参考方案5】:

大多数关于设计/编码技术(如 TDD 和设计模式)的书籍都是用 Java 或 C# 编写的,因为这是目前最小的通用语言,并且拥有最广泛的用户群,或者至少是最大的能够阅读的人群并理解语言。这样做主要是出于营销原因,以便吸引最大的人群。

这并不意味着这些技术不适用于或用于其他语言。根据我对 DDD 的了解,大多数原则都与语言无关,而 AFAICR 最初的 DDD 书籍中几乎没有代码示例(但我已经读了几年了,所以我可能会弄错)。

【讨论】:

【参考方案6】:

如果领域驱动设计是一种有效定义的设计模式,那么为什么您使用哪种语言很重要?对设计哲学等的建议应该在很大程度上与语言无关。可以这么说,它们比语言级别更高。

【讨论】:

这不是设计模式。这是一种关于如何构建系统并获得需求的哲学。这本旗舰书碰巧包含一些设计模式,每个人都像秃鹰一样围着圈子转,但这些绝不是 DDD 的定义。

以上是关于为啥域驱动设计似乎只在 C# 和 Java 等静态语言中流行? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

在java中,为啥类实例也能访问静态域?

静态链表

域驱动设计可以用例驱动吗?

201671010145 2016-2017《Java程序设计》静态域与静态方法

为啥 C# 不允许静态方法实现接口?

c# 为啥要合理使用静态类