软件业处于中世纪黑暗时代,DDD带来了文艺复兴 - threedots


如果您的软件设计糟糕透顶,拥有出色的 Kubernetes 集群和最花俏的微服务基础架构将无济于事。

几年前,我在一家SaaS公司工作,该公司遭受了可能所有可能的软件开发问题。代码是如此的复杂,以至于增加一些简单的变化可能需要几个月的时间。所有的任务和项目的范围都是由项目经理单独定义的。开发人员不明白他们在解决什么问题。如果不了解客户的期望,许多已实现的功能都是无用的。开发团队也没有能力提出更好的解决方案。

尽管我们有微服务,但引入一个变化往往需要改变大部分的服务。架构是如此紧密耦合,以至于我们无法独立部署这些 "微服务"。企业不理解为什么增加 "一个按钮 "可能需要两个月。最后,利益相关者不再信任开发团队。我们都感到非常沮丧。但情况并不是没有希望。

我很幸运,对领域驱动设计有一点了解。在那个时候,我还远远不是这个领域的专家。但我的知识足够扎实,可以帮助公司最大限度地减少,甚至消除很大一部分提到的问题。

一段时间过去了,这些问题在其他公司并没有消失。即使这些问题的解决方案存在,而且不是什么神秘的知识。人们似乎没有意识到这一点。也许是因为像GRASP(1997年)、SOLID(2000年)或DDD(领域驱动设计)(2003年)这样的老技术经常被遗忘或被认为是过时的?这让我想起了发生在历史上的黑暗时代的情况,当时古老的知识被遗忘。同样地,我们可以使用旧的想法。它们仍然有效,可以解决现今的问题,但它们经常被忽视。这就像我们生活在软件黑暗时代。

另一个相似之处是专注于错误的事情:
在历史上的黑暗时代,宗教压制了科学
在软件黑暗时代,基础设施正在压制重要的软件设计技术。
我并不是说宗教不重要。精神生活是超级重要的,但如果你正在遭受饥饿和疾病的折磨,就不重要了。基础设施的情况也是如此。如果你的软件设计很糟糕,那么拥有令人敬畏的Kubernetes集群和最花哨的微服务基础设施并不能帮助你。

软件黑暗时代是一个系统问题
软件黑暗时代是一个非常强大的自我延续的系统。如果不了解大局,你就无法解决系统性问题。系统思考是一种有助于分析这种复杂问题的技术。我使用这种技术将软件黑暗时代可视化。

你可以看到事情的一个依赖耦合大循环,它们相互加速。如果没有干预,问题会变得越来越大。领域驱动设计如何能解决这个问题?

与大多数著名的编程大师不同,我们并不希望你只是相信我们的故事。我们可以随便编造它。幸运的是,我们可以通过科学来解释为什么它能发挥作用。更确切地说,通过优秀的《The Science of Lean Software and DevOps 》一书为基础的科学研究。书中描述的研究提到了最好的,和表现最差的团队的特点。其中最关键的因素之一是松散耦合的架构。

如果你认为微服务可能给你带来松散耦合的架构--你就大错特错了。我曾多次看到微服务比单体的耦合度更高。这就是为什么我们需要的不仅仅是基础设施解决方案。这就是领域驱动设计(DDD)发挥作用的时候了

DDD不起作用?
也许你知道有人尝试过DDD,但对他们不起作用?

也许你曾与一个不太了解DDD的人合作过,他试图强行使用这些技术,并使一切变得过于复杂?

也许你在Twitter上看到一些著名的软件工程师说DDD不起作用?

也许对你来说,这是一个传说中的圣杯,有人声称对他们有用--但还没有人看到它。

让我们不要忘记,我们正生活在软件的黑暗时代。来自上一个时代的想法有一个问题--有些人可能会错过DDD的最初观点。在2003年首次提出DDD的背景下,这并不令人惊讶。

要进入DDD世界并不容易。很多书籍和文章都因为过度简化而忽略了最重要的DDD要点。它们也经常用抽象的例子来解释,脱离了现实。太长、太复杂、无法理解的例子也并不罕见。

让我尝试用最简单的方式来解释DDD。

从黑暗时代到文艺复兴
DDD技术可分为两部分。战术性模式和战略性模式。战术性领域驱动设计模式是关于如何在代码中实现解决方案。战术性DDD中没有火箭科学--它都是面向对象编程的良好实践。但在编写代码之前,你需要知道要实现什么。这就是战略DDD模式进入游戏的地方。

许多描述DDD的资料都把大部分时间花在了战术模式上。有时,他们甚至跳过战略模式。你可以只使用战略模式来练习DDD。在一些项目中,使用战术性的DDD模式甚至是矫枉过正。不幸的是,大多数人都在做完全相反的事情。他们只使用战术模式而不使用战略部分。这真是太可怕了。

如果有人问我在产品软件工程中是否存在银弹,我只有一个选择:领域驱动设计战略模式。战略性DDD可以帮助我们得到有关的答案。

  • 你要解决的是什么问题?
  • 你的解决方案能否满足利益相关者和用户的期望?
  • 该项目有多复杂?
  • 哪些功能是不必要的?
  • 如何分离服务以支持长期的快速发展?

这些问题在实施新项目、增加新功能或进行重构时是必不可少的。战略性的DDD模式为我们提供了一种方法,使我们能够一致和可预测地回答这些问题。

一些工程师告诉我,他们 "只是工程师"。他们并不太关心谁在使用他们的软件或为什么使用。他们只是在实现,比如说,JIRA任务--在输入端和输出端建立一些字节的服务。这样的心态导致了工程师和他们的客户之间的严重脱节,而我们作为工程师,正试图解决这些问题。没有适当的沟通,就很难创造出能以正确方式帮助客户的解决方案。这就是最终的目标--而不是简单地处理字节。

在项目的规划阶段花费少量的时间是很诱人的。尽快开始编码,早点结束。当任何人有这样的疑问时,我喜欢说:"用5天的编码,你可以节省1天的计划"。没有问过的问题不会神奇地消失。

克服软件黑暗时代的最好方法是从多个角度来攻击它。让我们看看DDD模式是如何攻击这个系统的。

事件风暴
事件风暴对于战略DDD模式和一般的软件开发来说是一个游戏规则的改变。我不相信为什么它还没有被世界上的每个团队所采用。

事件风暴是一个研讨会,期间有问题的人(通常是开发人员)与有答案的人(通常是利益相关者)会面。在会议期间,他们可以快速探索复杂的业务领域。在开始的时候,你专注于建立一个完全基于领域事件(橙色便签)的工作流程。事件风暴是一个超级灵活的方法。得益于此,你可以验证你的解决方案是否符合预期要求。你也可以根据会议的目标,探索数据流、潜在问题或用户体验。


验证解决方案是否没有漏洞,是否符合用户的要求只需要几分钟。在开发和部署的代码中引入变化和验证想法是非常昂贵的。改动黑板上的便条是非常便宜的。

一个土木工程师或火箭工程师可以很快看到一个错误的结果。他们可以在完成建造过程之前看到一些明显的错误。对于软件来说,这就不那么简单了,因为它不容易被看到。我们的大多数关键决定不会伤害任何人。功能开发和维护方面的问题不会在一天之内出现。

当你计划一个大项目或只是一个单一的故事时,事件风暴都能发挥作用。这只是一个你想花多少时间的问题。当我们为一个故事使用它时,它可以是10分钟到几个小时之间。对于较大的功能,我们倾向于花费一天到几天的时间。

会议结束后,你应该对以下问题有正确的答案。

  • 你想解决什么问题--而不是猜测什么对终端用户有用或假设 "我们对一切都很了解"。
  • 利益相关者是否对提议的解决方案感到满意--而不是在半年后的实施中去验证。
  • 问题的复杂性很容易看出来--这就清楚了为什么增加一个按钮可能需要大量的工作。
  • 初步了解如何按职责分割你的微服务--而不是盲目地将 "类似的事情 "归类。

最后,你会从利益相关者那里得到更多的信任,因为你在共同规划一个解决方案。这比在地下室里孤立地进行编码要好得多。

事件风暴的优秀之处在于,一个正确的会议的结果可以直接映射到代码中。它应该能帮助你在开发过程中避免许多讨论,并大大加快你的工作速度。


你必须以一个明确的目的开始。在一个项目上的时间可以飞快,在你知道之前,你已经在一个项目上花了半年的时间,却发现它对任何人都没有用。你有这种经历吗?这种情况比你想象的要经常发生,这就是为什么有些人对 "工程师 "失去信任,以及我们如何最终成为没有任何自主权的开发者。

担心我们需要为运行会话 "损失 "多少时间是很常见的。思考为运行会话所损失的时间并不是正确的方法。相反,你应该考虑如果你不运行会话,你会失去多少好处。我听说过这样一个故事:运行一次 "事件风暴 "会议后,项目的实施就停止了几个月。这听起来很糟糕,但在会议期间,团队发现当前的假设是完全无效的。继续进行该项目将导致完全的失败。即使该会议在短期内看起来很耗时,但该公司避免了几个月的无用开发。

事件建模
2018年,Adam Dymitruk提出了事件建模技术。这个符号和想法在很大程度上是基于Event Storming技术的,但增加了一些新的功能。它还额外强调了会议的用户体验部分。

一般来说,这些技术是相当兼容的。即使你继续使用Event Storming,你也会从Event Modeling中发现一些有价值的方法,你可以使用。

有边界的上下文和事务边界(聚合体)
Bounded Context是另一种战略性DDD模式,它帮助我们将大的模型分割成较小的逻辑片段。

它是实现适当的服务分离的一个关键。如果你需要接触一半的系统来实现和测试新功能,你的分离是错误的。

替代错误分离的是缺乏分离。通常,缺乏分离的症状是神的对象(巨大的对象,知道的太多或做的太多)。在这种情况下,变化将主要影响一个服务。这种方法的代价是更高的大系统故障风险和更高的变化复杂性。

换句话说--在这两种情况下,开发你的项目将更加困难。

一个有助于发现约束性上下文和聚合的伟大工具是(当然)事件风暴。

你可以在eventmodeling.org上阅读更多关于该技术的信息。

作为会议的结果,你可以直观地看到你应该如何分割你的服务和他们之间的接触点。

无处不在的语言
无处不在的语言是一种战略DDD模式,涵盖了在开发人员、运营、利益相关者和用户之间建立一种共同的语言。它是最被低估的战略DDD模式。因为谁会关心语言呢,对吗?

我花了很多时间才发现,开发人员和非开发人员之间有多少沟通问题是由于使用不同的语言造成的。而这是多么痛苦的事情。我鼓励你也要注意这一点。因为沟通不畅,开发人员没有解决正确的问题,因为没有人理解对他们的期望。

如果我告诉你,事件风暴会帮助你开发泛在语言UL,你会感到惊讶吗?与利益相关者一起运行会议迫使你与他们交谈。如果你不能理解对方,就很难一起建立一个解决方案。这就是为什么在研讨会上不要错过你的利益相关者是至关重要的!

DDD能解决所有问题吗?
即使DDD很好,它也不能解决我们的所有问题。管理你的期望是很重要的。即使我们在团队中高水平地使用这些技术,我们仍然会怀疑所创造的设计是否足够好。有时我们不知道如何处理这个问题。有时我们会从代码阶段回到设计阶段。有时我们会做出错误的决定。所有这些都是很好的情况。世界上没有一个团队没有这些问题。最好的办法是假设它会发生,不要感到惊讶。但我们知道,如果没有DDD,这些问题会更严重。

在使用DDD时,你应该特别注意避免。

  • 前期大设计。
  • 为 "未来 "实现代码。
  • 试图创造任何完美的东西。

相反,你应该:
  • 专注于在短时间内向用户提供MVP(我说的短时间是指1个月而不是6个月)。
  • 如果你需要实现一些 "未来 "的东西,因为以后会更难添加它 - 这是一个非常不好的迹象。你应该考虑如何使以后添加它变得容易。
  • 调和一下,即使你尽了全力,你的设计也不会从一开始就是完美的--随着时间的推移,改进它要好得多。

对于一些团队来说,可能需要大量的工作才能达到这个水平。但我可以根据我的经验向你保证,这是有可能的。而且,你从交付软件中再次获得的乐趣也是值得的!

如果你觉得你应该是一个技术领导才能提出这样的改进建议--那你就错了!在早期,当我还不是领导的时候,我已经在我工作的团队中提出了许多改进意见。你需要和你的队友有良好的争论。

我们总是在我们的文章中解释 "为什么 "这些技术是有效的。当你使用这些论据时,它们应该足以说服他们。如果因为你的团队思想封闭而无法工作,这就是考虑换工作的一个好理由。

软件文艺复兴
在一篇文章中很难对提出的技术进行非常深入的研究。我的目标是激发你对现状的质疑。我们的行业不应该是这样工作的。如果你不接受现状,我希望我激励你学习新技术。这是与软件黑暗时代斗争的最好方式。

如果你想了解战术性DDD模式,你应该查看我们以前的文章:previous articles.

这些例子是用Go写的,但它们可以很容易地移植到任何语言。Go的入门点也很低。谁知道呢,也许你会找到一种新的喜爱的语言呢? 

你在软件黑暗时代吗?

  • 你只是一个普通的码农?盲目地遵循别人强加的规则?
  • 有一个宗教裁判所吗?他们会试图仇恨和扼杀任何不寻常的方法?
  • 你是炼金术士?试图创造黄金?即使是没有科学依据的?

或者你正在你的地窖里偷偷地阅读禁书?也许你正在和我们一起寻找结束软件黑暗时代,开始软件文艺复兴的机会?