Books - Domain-Driven Refactoring - 1

This is where Domain-Driven Design (DDD) steps in. Since its introduction by Eric Evans in 2003, DDD has served as a transformative approach for designing software systems that reflect the intricacies of real-world domains. The approach offers strategies for modeling complexity, structuring applications, and enabling effective collaboration between technical and business teams. This book is our contribution to the rich ecosystem of DDD knowledge, aiming to guide you through the principles, patterns, and practices that make DDD not just a philosophy but a practical toolset for modern software development.

这就是领域驱动设计(DDD)发挥作用的地方。自从 2003 年由埃里克·埃文斯(Eric Evans)提出以来,DDD 已成为一种变革性的方法,用于设计能够反映现实世界领域复杂性的软件系统。该方法提供了建模复杂性、构建应用程序以及促进技术团队与业务团队之间有效协作的策略。这本书是我们对 DDD 知识丰富生态系统的贡献,旨在引导你了解 DDD 的原则、模式和最佳实践,使 DDD 不仅是一种理念,更成为现代软件开发实用的工具集。

Who this book is for

* Developers who want to move beyond coding and understand how to design systems that solve real-world problems effectively

想要超越编程,并了解如何设计能够有效解决实际问题的系统的开发者

* Architects tasked with creating modular, maintainable, and scalable solutions in increasingly complex environments

负责在日益复杂的环境中创建模块化、可维护和可扩展解决方案的架构师

* Technical leaders who seek to foster collaboration between cross-functional teams and ensure that technical decisions support business goals

寻求促进跨职能团队协作并确保技术决策支持业务目标的技术领导者

Chapter 1, Evolution of Domain-Driven Design

Since the birth of software development in the 1960s, developers strived to create better applications to deal with the complexity of the world. During the following 20 years, many reports emerged pointing out the inefficiency of software systems and their design processes. We also went through the infamous software crisis that led to many incidents, such as the Therac-25 (https://en.wikipedia.org/wiki/Therac-25).

自 1960 年代软件开发诞生以来,开发者们一直努力创造更好的应用程序来应对世界的复杂性。在接下来的 20 年里,许多报告指出软件系统及其设计过程的低效。我们还经历了臭名昭著的软件危机,导致了许多事件,例如 Therac-25(https://en.wikipedia.org/wiki/Therac-25)。

The turning point arrived in 1968 during the NATO conference where the issue was acknowledged, and people started laying the groundwork for software engineering as a formal discipline (https://docslib.org/doc/9230794/crisis-what-crisis-reconsidering-the-software-crisis-of-the-1960s-and-the-origins-of-software-engineering).

转折点发生在 1968 年的北约会议上,当时这个问题被承认,人们开始为软件工程作为一个正式学科奠定基础(https://docslib.org/doc/9230794/crisis-what-crisis-reconsidering-the-software-crisis-of-the-1960s-and-the-origins-of-software-engineering)。

Progression of the software development approaches

Between the 1980s and 1990s, the awareness of the software crisis led to the rise of various “silver-bullet” approaches that did not, however, provide a definitive solution. The famous article, No Silver Bullets, written by Fred Brooks, took the problem head-on and brought to the attention of the reader that there are mainly two different kinds of complexity; essential and accidental (you will read in depth about them in Chapter 2).

在 20 世纪 80 年代至 90 年代,人们对软件危机的认识导致了各种“银弹”方法的出现,然而这些方法并没有提供确切的解决方案。弗雷德·布鲁克斯撰写的著名文章《没有银弹》直面了这一问题,并将两种主要类型的复杂性——本质性和偶然性——呈现在读者面前(你将在第 2 章深入阅读它们)。

In Steve McConnell’s book, Software Estimation: Demystifying the Black Art, there is a really interesting concept called “cone of uncertainty,” which exposes part of the problem with a simple diagram (Figure 1.1). This diagram points out that estimates created early in the project are subject to a high degree of error. As you can see, these estimates can be off by a factor of four both in high and lower ends. The application of this concept was in the estimate process, but it maps very well to the problem that DDD tries to solve. A deep understanding of the domain leads to stronger models, greater project resilience, and more accurate estimates. This could be only obtained by investing time in understanding the problem. As also stated in the book itself,”The reason the estimate contains variability is that the software project itself contains variability.”

在 Steve McConnell 的书中《软件估算:揭秘黑色艺术》,有一个非常有趣的概念叫做“不确定性锥”,它通过一个简单的图表(图 1.1)揭示了问题的一部分。这个图表指出,项目早期创建的估算会存在高度误差。如您所见,这些估算在高端和低端都可能相差四倍。这个概念的应用是在估算过程中,但它与 DDD 试图解决的问题非常契合。对领域的深入理解会带来更强的模型、更高的项目弹性和更准确的估算。这只能通过投入时间来理解问题才能获得。正如书中自己所说,“估算包含变异性是因为软件项目本身包含变异性。”

As a result of this awareness, as predicted by F. Brooks, and the evolution of development methods, such as object-oriented programming, we assisted in the rise of new development tools called RAD (e.g., Delphi, Visual Basic, Paradox, Visual FoxPro), which provided solutions to the accidental complexity of the problem, while still leaving room for improvement to essential complexity.

由于这种意识,正如 F.布鲁克斯所预测的,以及开发方法的演变,例如面向对象编程,我们协助推动了称为 RAD(例如 Delphi、Visual Basic、Paradox、Visual FoxPro)的新开发工具的兴起,这些工具为问题的偶然复杂性提供了解决方案,同时仍为本质复杂性留下了改进空间。

What he realized was that the traditional approach in software design was focused on translating the complexity of the business flows with just technical solutions (DB first, anyone?).

他所意识到的是,传统的软件设计方法专注于用技术解决方案来翻译业务流程的复杂性(DB 优先,对吧?)。

His proposal was to first do a deep exploration and modeling of the problem space (we will delve into it in Chapter 2) and only then try to find an acceptable solution. This approach could only be achieved by involving a continuous collaboration between developers and domain experts.

他的提议是首先进行深入的问题空间探索和建模(我们将在第 2 章中深入探讨),然后才能尝试找到一个可接受的解决方案。这种方法的实现只能通过开发者和领域专家之间的持续合作来完成。

What is domain-driven design (DDD)?

First, we can say what DDD is not. It is not a framework, or a library, to be installed on our computers to guide us in the development of software systems.

At the heart of DDD are two interconnected principles: ubiquitous language and bounded context.

DDD 的核心是两个相互关联的原则:通用语言和边界上下文。

Ubiquitous language is a shared vocabulary consistently used by all stakeholders, including domain experts, developers, and business teams. It eliminates ambiguities in communication, ensuring that everyone involved speaks the same language when discussing the domain. This shared understanding directly influences the accuracy and clarity of the software model, aligning it closely with the business domain.

通用语言是所有利益相关者(包括领域专家、开发人员和业务团队)一致使用的共享词汇。它消除了沟通中的歧义,确保在讨论领域时,所有参与者使用同一种语言。这种共同的理解直接影响软件模型的准确性和清晰度,使其与业务领域紧密对齐。

Bounded context defines the boundaries within which a specific domain model and its associated ubiquitous language apply. These boundaries prevent overlaps or inconsistencies between different parts of a system, enabling teams to work independently within their assigned contexts. This modular approach simplifies the management of complex systems and ensures that changes within one context do not unintentionally affect others.

限界上下文定义了特定领域模型及其相关通用语言的适用边界。这些边界防止系统不同部分之间出现重叠或不一致,使团队能够在其分配的上下文中独立工作。这种模块化方法简化了复杂系统的管理,并确保一个上下文中的变更不会无意中影响其他上下文。

As an example, you can think of the game that many Agile coaches use, the broken telephone. The game points out how with each hand-off of information from one person to another, the information is always altered due to the interpretation of each individual.

例如,你可以想到许多敏捷教练使用的游戏——传话游戏。这个游戏指出了信息在从一个人传递到另一个人时,由于每个人的解释,信息总是会被改变。

In human conversations, context is naturally developed as people engage in dialog. When someone enters the discussion midway, they often ask, “Who or what are you talking about?” rather than directly inquiring, “What is the context?”

在人类对话中,随着人们的互动,语境会自然地形成。当有人中途加入讨论时,他们通常会问“你们在谈论谁或什么?”而不是直接询问“背景是什么?”

Without context, meaning can be ambiguous, distorted, or even completely lost. A lack of context when joining a conversation can lead to misunderstandings, as the newcomer may make incorrect assumptions about the subject at hand. Similarly, an abstraction can only be as accurate as the shared understanding of the context among all participants in the communication.

没有上下文,意义可能变得模糊、扭曲,甚至完全丢失。在加入对话时缺乏上下文会导致误解,因为新人可能会对所讨论的主题做出错误的假设。同样,一个抽象只能精确到所有沟通参与者对上下文共享理解的程度上。

As stated before, one of the main goals of DDD is to reduce as much as possible this phenomenon by establishing a common language to make explicit the implicit.

如前所述,领域驱动设计的一个主要目标是通过建立共同语言来尽可能减少这种现象,使隐含的内容显式化。

Communication is key to understanding the problem we need to solve. DDD wants to be an alternative to an anemic list of requirements and delivery of the software. This can be achieved by starting by trying to understand the problem instead of defining a list of requirements. We should not start with one, or more, ready-made solutions, because requirements are in fact a solution to the problem and are given to us at the beginning of the project exactly when we do not know anything about the domain. This means that we are unable to clearly understand whether they really are the solution or not. Requirements capture a stakeholder’s perspective of the system at a particular point in time and are subject to change.

沟通是理解我们需要解决的问题的关键。领域驱动设计(DDD)旨在成为一份贫血的需求列表和软件交付的替代方案。这可以通过从尝试理解问题开始,而不是定义一份需求列表来实现。我们不应该从一个或多个现成的解决方案开始,因为需求实际上是问题的解决方案,而我们是在项目开始时对领域一无所知的情况下得到这些需求的。这意味着我们无法清楚地理解它们是否真的是解决方案。需求捕捉了利益相关者在特定时间点对系统的视角,并且可能会发生变化。

DDD aims to help create software more aligned with the business goals, more adaptable to change, and easier to maintain over time. To ease the conversation, DDD focuses on the business domain, so it is necessary to clarify its meaning right from the start.

领域驱动设计旨在帮助创建更符合业务目标、更能适应变化、且更易于长期维护的软件。为了简化讨论,领域驱动设计聚焦于业务领域,因此有必要从一开始就明确其含义。

What you will do, exactly, is better understand the business domain, which is the main area of activity of our brewery, and refactor your way toward a more resilient and scalable application using baby steps instead of a “big bang change” (or nuclear option, as we call it).

你将要做的是更深入地理解业务领域,这是我们啤酒厂的主要活动领域,并使用小步快跑的方式而不是“大爆炸式变革”(或如我们所说的“核选项”)来重构,从而构建一个更具弹性和可扩展性的应用程序。

Now that we know what “domain” is, why “driven”? By the book, the term implies that the design of the software is guided by someone or something. In our case, it is based on a deep understanding of the domain, and only after understanding a domain, we’ll introduce technical considerations or implementation details.

现在我们已经知道“领域”是什么,为什么是“驱动”?根据书中的解释,这个术语意味着软件的设计是由人或某种事物引导的。在我们的情况下,它是基于对领域的深刻理解,只有理解了领域之后,我们才会引入技术考虑或实现细节。

Finally, “design” simply refers to the process of creating a solution.

最后,“设计”仅仅指的是创建解决方案的过程。

Refactoring is a crucial part of the DDD approach. It involves restructuring existing code without changing its external behavior to improve nonfunctional attributes. In the context of DDD, refactoring is not just about code; it’s about refining the model to better reflect the domain as your understanding deepens.

重构是领域驱动设计方法的关键部分。它涉及在不改变外部行为的情况下重新组织现有代码,以改善非功能性属性。在领域驱动设计的背景下,重构不仅仅是关于代码;它还关乎随着你对领域理解的深入,不断优化模型以更好地反映领域。

This continuous alignment of the software model with the evolving understanding of the business domain is one of the key principles of DDD. Regularly revisiting and refining the model ensures it accurately represents the current state of the domain. This iterative process of refining and improving the model is where refactoring comes into play.

将软件模型与不断发展的业务领域理解持续对齐是领域驱动设计的关键原则之一。定期回顾和优化模型可以确保它准确反映领域的当前状态。这种不断优化和改进模型的过程就是重构发挥作用的地方。

In practice, refactoring with DDD involves several steps:

在实践中,使用领域驱动设计进行重构涉及多个步骤:

1. Understanding the Domain: Before any refactoring, you need a deep understanding of the business domain. Engage with domain experts to gather insights and ensure the model accurately reflects the domain knowledge.

理解领域:在进行任何重构之前,你需要深入理解业务领域。与领域专家合作,收集见解,并确保模型准确反映领域知识。

2. Identifying Areas for Improvement: Look for parts of the code where the domain model is not well represented or where technical debt has accumulated. These are prime candidates for refactoring.

识别改进区域:寻找代码中领域模型未能良好表示或技术债务累积的部分。这些是重构的首选目标。

3. Applying DDD Patterns: Use DDD patterns, such as aggregates, entities, value objects, and services, to restructure the code. Ensure that these patterns are applied in a way that enhances the clarity and integrity of the domain model.

应用 DDD 模式:使用 DDD 模式,如聚合、实体、值对象和服务,来重构代码。确保这些模式的应用方式能够增强领域模型的清晰性和完整性。

4. Maintaining Functionality: Refactor in small steps to ensure that the system remains functional throughout the process. Use automated tests to verify that existing functionality is preserved.

保持功能:小步进行重构,确保整个过程中系统保持功能。使用自动化测试来验证现有功能是否得到保留。

5. Continuous Integration: Integrate changes frequently to catch issues early and ensure that the refactored code works well with the rest of the system.

持续集成:频繁集成变更,以便尽早发现问题,并确保重构的代码与系统的其他部分良好协作。

6. Feedback Loop: Regularly review the changes with domain experts to ensure that the refactoring aligns with their understanding of the domain. Use their feedback to further refine the model.

反馈循环:定期与领域专家审查变更,以确保重构与他们对领域的理解保持一致。使用他们的反馈来进一步优化模型。

This iterative process ensures that the software remains adaptable to changes in business requirements and it is easier to maintain and extend over time.

这种迭代过程确保软件能够适应业务需求的变化,并且随着时间的推移更容易维护和扩展。

How DDD changes the approach to the problem

DDD fundamentally transforms the approach to software development by placing the business domain at the heart of the development process. Traditional software development methodologies often start with technical considerations, such as data modeling, database design, or user interface wireframes.

领域驱动重构从根本上转变了软件开发方法,将业务领域置于开发过程的核心。传统的软件开发方法论通常从技术考虑开始,例如数据建模、数据库设计或用户界面线框图。

While these aspects are essential, DDD shifts the focus from technical priorities to aligning software design with fundamental business concepts, resulting in more relevant, flexible, and maintainable systems.

虽然这些方面至关重要,但领域驱动设计将重点从技术优先级转移到使软件设计与基本业务概念保持一致,从而产生更相关、更灵活且更易于维护的系统。

DDD emphasized the importance of explicitly defining context to ensure the precise interpretation of an abstraction. It advocates for a mindset shift where the primary focus is the alignment between all the members of the team and avoiding misunderstanding. This is one of the primary ways DDD is used to change the approach to problem-solving. This common language is something shared between the stakeholders, domain experts, developers, and end users and is as strict as a programming language. The good thing is that it is a vocabulary that is understood by each party and its consistent use allows every team member to easily refactor parts of the code that do not align with business requirements. It also strongly reduces misunderstandings and ensures that the code base evolves in harmony with the business.

领域驱动设计强调明确定义上下文以确保抽象的精确解释。它提倡思维方式的转变,主要关注团队所有成员之间的对齐并避免误解。这是领域驱动设计用来改变问题解决方法的主要方式之一。这种通用语言是利益相关者、领域专家、开发人员和最终用户共享的,其严格程度不亚于编程语言。好的方面在于,这是一种被各方理解的词汇,其一致使用使每个团队成员能够轻松地重构与业务需求不一致的代码部分。它还大大减少了误解,并确保代码库与业务和谐发展。

DDD encourages developers to immerse themselves in domain knowledge and collaborate closely with domain experts (e.g., business analysts, end users, etc.). This deep exploration of the domain allows developers to gain a comprehensive understanding of the concepts, rules, processes, and behaviors that govern the real-world problem space. Obviously, this is not something that is achieved easily, but requires exploration and experimentation with several iterations with a lot of the time spent, as we will see in the next chapter, in what is called the problem space.

领域驱动设计鼓励开发者深入领域知识,并与领域专家(例如业务分析师、最终用户等)紧密合作。这种对领域的深入探索使开发者能够全面理解支配现实问题领域概念、规则、流程和行为。显然,这不是一件容易实现的事情,而是需要通过多次迭代进行探索和实验,花费大量时间,正如我们将在下一章看到的,在所谓的“问题领域”中。

Just as in human conversations, fully grasping a model requires establishing the appropriate context and clear boundaries. A model, as we have noted, is a structured system of abstractions. Beware that a model remains an oversimplification of reality as defined by Rebecca Wirfs-Brock (https://weave-it.org/blog/overcoming-additive-bias-software-design):

就像人类对话一样,要完全理解一个模型,需要建立适当的背景并明确界限。正如我们所指出的,模型是一个抽象的结构化系统。要小心,模型仍然是现实的一种过度简化,正如 Rebecca Wirfs-Brock 所定义的(https://weave-it.org/blog/overcoming-additive-bias-software-design):

A model is a simplified representation of a thing or phenomenon that intentionally emphasizes certain aspects while ignoring others. Abstraction with a specific use in mind.

模型是对事物或现象的简化表示,它有意强调某些方面而忽略其他方面。具有特定用途的抽象。

These contexts help manage the complexity of large software systems by allowing different parts of the system to evolve independently. Each bounded context contains its own domain model, which is consistent and isolated from other contexts. This modularization is crucial for refactoring as it allows changes to be made within one context without impacting others, thus reducing the risk of introducing errors and improving the system’s overall maintainability.

这些上下文通过允许系统的不同部分独立演进来帮助管理大型软件系统的复杂性。每个限界上下文都包含其自己的领域模型,该模型是一致的,并且与其他上下文隔离。这种模块化对于重构至关重要,因为它允许在一个上下文中进行更改而不影响其他上下文,从而降低引入错误的风险并提高系统的整体可维护性。

In addition to bounded contexts, DDD leverages tactical patterns such as entities, value objects, aggregates, repositories, and services. These patterns provide a structured approach to encapsulating domain logic, ensuring that changes can be implemented cleanly and systematically. For example, entities represent objects that have a distinct identity and life cycle, while value objects encapsulate attributes and behaviors without identity. Aggregates are clusters of related entities and value objects that are treated as a single unit for data changes, ensuring consistency and integrity within the model.

除了限界上下文,领域驱动设计(DDD)还利用战术模式,如实体、值对象、聚合、存储库和服务。这些模式为封装领域逻辑提供了一种结构化的方法,确保变更可以清晰且系统地实施。例如,实体表示具有独特身份和生命周期的对象,而值对象则封装属性和行为但不具有身份。聚合是相关实体和值对象的集群,它们被视为一个单一单元进行数据变更,确保模型内部的一致性和完整性。

Repositories abstract the data access layer, providing a clean interface for storing and retrieving aggregates. As described in Martin Fowler’s book, Patterns of Enterprise Application Architecture, (https://martinfowler.com/eaaCatalog/repository.html) a repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection.

仓库抽象了数据访问层,为存储和检索聚合提供了清晰的接口。正如在马丁·福勒的《企业应用架构模式》一书中所述(https://martinfowler.com/eaaCatalog/repository.html),仓库在领域层和数据映射层之间进行中介,类似于内存中的领域对象集合。

Domain services encapsulate domain logic that does not naturally fit within an aggregate, promoting a clear separation of concerns. Its main use is to coordinate one or more aggregates removing as much as possible the coupling between them.

领域服务封装不适合聚合内的领域逻辑,促进关注点的清晰分离。其主要用途是协调一个或多个聚合,尽可能减少它们之间的耦合。

These patterns not only facilitate cleaner and more maintainable code but also make it easier to refactor and extend the system in response to the ever-changing business requirements.

这些模式不仅有助于编写更清晰、更易于维护的代码,还使得根据不断变化的业务需求重构和扩展系统变得更加容易。

Furthermore, DDD encourages iterative development and continuous refactoring. This iterative process allows teams to incrementally improve the system, making small, manageable changes that collectively lead to significant enhancements in the code base’s quality and functionality. These concepts do not apply to a green field project but are also true for the refactoring of a legacy system.

此外,领域驱动设计鼓励迭代开发和持续重构。这种迭代过程允许团队逐步改进系统,通过进行小而可控的变更,共同提升代码库的质量和功能。这些概念不仅适用于绿色田野项目,也适用于遗留系统的重构。

To close, by placing the domain at the center of the design process, DDD helps bridge the gap between the technical and business perspectives. As already stated, it significantly changes the approach to problem-solving in software development by prioritizing a deep understanding of the business domain, fostering clear communication through a ubiquitous language, and structuring the system using bounded contexts and well-defined design patterns. This methodology not only makes the refactoring process more efficient and effective but also ensures that the software evolves in alignment with the business’s needs, resulting in more robust and maintainable systems.

最后,通过将领域置于设计过程的核心,领域驱动设计有助于弥合技术和业务视角之间的差距。如前所述,它通过优先理解业务领域、通过通用语言促进清晰沟通,以及使用限界上下文和明确定义的设计模式来构建系统,从而显著改变软件开发中的问题解决方法。这种方法论不仅使重构过程更加高效和有效,而且确保软件与业务需求保持一致,从而产生更健壮和可维护的系统。

In conclusion, DDD transforms refactoring by prioritizing domain understanding and communication, leading to more intuitive, business-aligned, and resilient software solutions.

总之,领域驱动设计通过优先考虑领域理解和沟通,转变了重构,从而带来了更直观、与业务一致且更具弹性的软件解决方案。

Chapter 2, Understanding Complexity: Problem and Solution Space

In the previous chapter, we went through the history of DDD and what it tries to solve. We also started to talk about the need to explore the domain, improve our knowledge of it, and find solutions in an iterative way. In this chapter, we will delve into problem and solution spaces, and by the end of it, you will have a clear understanding of their importance not only when approaching a greenfield project but also when refactoring one that already exists. Such a project may already be drifting away with useless features or complexity that do not represent the business anymore. You have probably seen many such types of projects that try to solve problems they themselves create, rather than adding value for the user.

在上一章中,我们回顾了领域驱动设计的历程及其试图解决的问题。我们还开始讨论探索领域、提升对领域的认知以及以迭代方式寻找解决方案的必要性。在本章中,我们将深入探讨问题与解决方案空间,到本章结束时,你将清晰地理解它们在处理新项目以及重构现有项目时的重要性。这样的项目可能已经因无用的功能或不再代表业务的复杂性而偏离轨道。你很可能见过许多此类项目,它们试图解决自己创造的问题,而不是为用户增加价值。

We will explore the intricate nature of modern complex systems and how to navigate their inherent complexity. Understanding these concepts is a fundamental skill for DDD as it allows us to deconstruct and manage the various components that define your system.

我们将探讨现代复杂系统的复杂性质以及如何驾驭其固有复杂性。理解这些概念是领域驱动设计的核心技能,因为它使我们能够分解和管理定义你系统的各个组件。

Specifically, we’ll cover the following main topics in this chapter:

在本章中,我们将具体涵盖以下主要主题:

* Dealing with complexity  处理复杂性

* Problem and solution space

问题和解决方案空间

* Decision-making and biases

决策与偏见

Dealing with complexity  处理复杂性

One of the best things about the nineties was that you could deploy new versions of systems with ease. When you were ready, you simply took down the application, upgraded it, and then put it back online. The same was true for our awesome SQL scripts that updated the DB in one fell swoop and, until the end of the nineties, most systems were deployed this way.

九十年代最棒的事情之一是你可以轻松部署新版本的系统。当你准备好了,只需关闭应用程序,进行升级,然后重新上线。对于我们的强大 SQL 脚本也是如此,它们能一次性更新数据库,直到九十年代末,大多数系统都是这样部署的。

These days, you can no longer afford to do this anymore because you do not have the luxury of being able to take down all the components of a system and upgrade them all at once. You must take into account that different teams are working on different components at different speeds, and there could be a lot of DBs that need to be kept somewhat aligned. What we are trying to say here is that the main reason this is not an acceptable way of doing things anymore is because at the root of everything lies complexity. Modern systems are so big and complicated that complexity itself is an inherent characteristic. No matter what you are dealing with, complexity arises from various sources—such as the sheer number of components, their interdependencies, and the dynamic nature of their interactions.

如今,你再也负担不起这种方式了,因为你没有奢侈到可以一次性关闭系统所有组件并进行升级的条件。你必须考虑到不同团队在不同速度下工作在不同组件上,而且可能有很多数据库需要保持一定程度的同步。我们想说的是,这种做法不再可接受的主要原因在于,一切的根本在于复杂性。现代系统如此庞大和复杂,以至于复杂性本身已成为其固有特性。无论你处理什么,复杂性都源于各种因素——比如组件数量之多、它们之间的相互依赖性以及它们交互的动态性质。

Understanding complexity involves recognizing its multifaceted nature and can be classified into two main types: essential complexity and accidental complexity. Essential complexity is intrinsic to the problem domain and cannot be removed. It is the complexity that arises from the nature of the problem itself. For example, the complexity of a financial trading system is inherent due to the numerous rules, regulations, and market conditions it must adhere to.

理解复杂性涉及认识到其多面性,可分为两种主要类型:本质复杂性和偶然复杂性。本质复杂性是问题域固有的,无法消除。它是源于问题本身的复杂性。例如,金融交易系统的复杂性是固有的,因为它必须遵守众多规则、法规和市场条件。

Accidental complexity, on the other hand, stems from the solution domain. It is the unnecessary complexity introduced by poor design decisions, inefficient processes, or inadequate tools. Reducing accidental complexity is mandatory for managing and simplifying systems.

另一方面,偶然复杂性源于解决方案域。它是由于糟糕的设计决策、低效的流程或不足的工具引入的不必要复杂性。减少偶然复杂性对于管理和简化系统是必要的。

Figure 2.1 is a summary of the key points to classify complexity.

图 2.1 是对分类复杂性的关键点的总结。

Figure 2.1 – Key points when dealing with complexity

As we can see in Figure 2.1, there is a lot to take into consideration when dealing with complexity, but do not worry; we have tools created by very smart people that can help us tackle it.

如图 2.1 所示,处理复杂性时需要考虑很多因素,但不必担心;我们拥有由非常聪明的人创造的工具,可以帮助我们应对它。

One of the first tools we would like to introduce to you is the Cynefin framework (https://en.wikipedia.org/wiki/Cynefin_framework).

我们想要介绍给你们的第一个工具是 Cynefin 框架(https://en.wikipedia.org/wiki/Cynefin_framework)。

Cynefin framework  Cynefin 框架

The Cynefin framework was developed by Dave Snowden in 1999, and its name, pronounced /kəˈnɛvɪn/ kuh-NEV-in, is a Welsh word that means “habitat.” We can sum it up by saying that it is a sense-making device that helps individuals and organizations understand and navigate complexity. Figure 2.2 shows the Cynefin template.

Cynefin 框架由 Dave Snowden 于 1999 年开发,其名称发音为/kəˈnɛvɪn/ kuh-NEV-in,是一个威尔士语词汇,意为“栖息地。”我们可以将其总结为一种帮助个人和组织理解与导航复杂性的认知工具。图 2.2 展示了 Cynefin 模板。

As we can see in Figure 2.2, the framework categorizes situations into five distinct contexts.

如图 2.2 所示,该框架将情境分为五个不同的背景。

Clear context  清晰背景

Clear context represents the “known knowns.” This means that the relationship between cause and effect requires analysis or expertise but is still predictable. Best practices or well-defined rules are already in place. In this situation, the advice is to “sense–categorize–respond”: first, establish the facts (“sense”), then categorize them, and finally, respond by following the rules or applying the best practices. Here, the DDD strategic patterns are useless because we already have a clear vision of the domain and so we can move directly to implementing tactical patterns.

清晰背景代表“已知已知”。这意味着因果关系需要分析或专业知识,但仍然是可预测的。最佳实践或明确定义的规则已经存在。在这种情况下,建议是“感知-分类-响应”:首先,建立事实(“感知”),然后对它们进行分类,最后通过遵循规则或应用最佳实践来响应。在这里,领域驱动设计(DDD)战略模式是无用的,因为我们已经对领域有清晰的认识,因此可以直接进入战术模式的实施。

Complicated context  复杂的背景

Complicated context represents the “known unknowns”—situations where the relationship between cause and effect requires analysis or expertise but it is still predictable. Good practice and expert advice are applicable. As we can see in Figure 2.2, the framework suggests “sense–analyze–respond”: assess the facts, analyze, and apply the appropriate good operating practice. In this specific domain, strategic and tactical patterns are essential to increase its understanding and start moving to a clear context.

复杂的背景代表了“已知的未知”——那些因果关系需要分析或专业知识才能理解,但仍然可以预测的情况。良好的实践和专家建议都适用。如图 2.2 所示,该框架建议“感知-分析-响应”:评估事实,分析,并应用适当的良好操作实践。在这个特定领域,战略和战术模式对于提高其理解并开始转向清晰的背景至关重要。

Complex context  复杂上下文

Complex context represents the “unknown unknowns.” As it were, it is when cause and effect are deducible only in retrospect, there are no right answers, and patterns emerge through interaction. Emergent practices are needed here. “Probe–sense–respond” takes place: small-scale experiments (“probe”) to explore the space and generate data, sense the results, and respond with actions. Strategic patterns with explorative tools come to the rescue to help us root a better vision and comprehension of this context. Tactical patterns are useless here.

复杂的背景代表了“未知的未知”。换言之,当因果关系只能事后推论,没有正确答案,模式通过互动出现时,就是这种情况。这里需要涌现的实践。“探测-感知-响应”发生:小规模的实验(“探测”)来探索空间和生成数据,感知结果,并采取行动做出响应。具有探索工具的战略模式来帮助我们扎根对这个背景更好的愿景和理解。战术模式在这里毫无用处。

Chaotic context  混乱的上下文

In a chaotic context situation, cause and effect are unclear because there is no clear relationship, and immediate action is required to stabilize the situation. We must “act–sense–respond”: act to establish order, sense where stability lies, and respond to try to turn a chaotic context into a complex context. Novel practices emerge. In this specific context, the pattern of DDD does not help, but we should use other exploration tools to give us a starting point on which we could start to apply strategic patterns.

在混乱的上下文情况下,因果关系不明确,因为没有明确的关系,需要立即采取行动来稳定局势。我们必须“行动—感知—回应”:行动以建立秩序,感知稳定所在,回应以尝试将混乱的上下文转变为复杂的上下文。新的实践会出现。在这种特定情况下,DDD 的模式没有帮助,但我们应使用其他探索工具来给我们一个起点,我们可以从那里开始应用战略模式。

Confusion context  困惑情境

The confusion context is in the center of Figure 2.2 and represents situations where there is no clarity about which of the other contexts apply. As written by Snowden and Boone in their article A Leader’s Framework for Decision Making (https://strategicleadership.com.au/wp-content/uploads/2017/06/A-Leader%E2%80%99s-Framework-for-Decision-Making-HBR-Nov-2007.pdf): “Here, multiple perspectives jostle for prominence, factional leaders argue with one another, and cacophony rules.”

混淆上下文位于图 2.2 的中心,它代表那些对其他适用上下文缺乏明确性的情况。正如斯诺登和博恩在他们的文章《领导者的决策框架》(https://strategicleadership.com.au/wp-content/uploads/2017/06/A-Leader%E2%80%99s-Framework-for-Decision-Making-HBR-Nov-2007.pdf)中所写:“在这里,多种视角争相突出,派系领导者相互争论,嘈杂声主导一切。”

Table 2.1 summarizes when we should use strategic, tactical, and explorative patterns.

表 2.1 总结了何时应使用战略、战术和探索性模式。

To conclude with a practical example, let us look at the one given by the author himself in 2007. It refers to an incident that happened in 1993 at the Brown’s Chicken and Pasta restaurant in Palatine, Illinois. A shooter murdered seven employees, and as a result, Deputy Police Chief Walt Gasior had to deal with a situation in which the local police faced all the domains. He had to act immediately to manage the initial panic (chaotic), keep the department running by following standard procedures (simple), ask for expert help (complicated), and keep the community calm in the following weeks (complex).

以一个实际案例来总结,让我们看看作者自己在 2007 年给出的那个例子。它指的是 1993 年在伊利诺伊州帕拉丁的布朗鸡肉面馆发生的一起事件。一名枪手杀害了七名员工,结果,副警察局长沃尔特·加西奥尔不得不处理一个当地警察面临所有领域的局面。他必须立即行动,管理最初的恐慌(混乱),通过遵循标准程序(简单)使部门继续运作,请求专家帮助(复杂),并在接下来的几周内保持社区平静(复杂)。

Residuality theory  剩余性理论

Another powerful tool we have in our toolbox is residuality theory (https://www.sciencedirect.com/science/article/pii/S1877050921007420). Formulated by Barry O’Reilly, it states that the future of a system is determined by its residues, which are the remnants left behind after the system has been affected by a stressor.

我们工具箱中的另一个强大工具是残余性理论(https://www.sciencedirect.com/science/article/pii/S1877050921007420)。该理论由巴里·奥赖利提出,它指出系统的未来由其残余性决定,而残余性是指系统在受到应激因素影响后留下的残留物。

Residuality theory is a pivotal concept in the realm of DDD, offering a structured approach to understanding and improving complex systems. At its core, residuality theory examines how a system retains its structure and behavior after being subjected to changes or disruptions, referred to as stressors.

残余性理论是领域驱动设计(DDD)中的一个关键概念,它提供了一种结构化的方法来理解和改进复杂系统。其核心在于,残余性理论研究系统在受到变化或干扰(称为压力源)后如何保持其结构和行为。

Imagine a legacy e-commerce platform that struggles to handle peak shopping seasons, such as Christmas or Black Friday. Each peak period acts as a stressor, revealing underlying issues such as slow performance or system crashes. By applying the residuality theory, we analyze these stress responses to identify persistent problems and areas resistant to change.

想象一个难以应对高峰购物季(如圣诞节或黑色星期五)的遗留电子商务平台。每个高峰期都充当一个压力源,暴露出潜在问题,如性能缓慢或系统崩溃。通过应用剩余性理论,我们分析这些压力响应,以识别持续存在的问题和难以改变的区域。

This method allows us to target refactoring efforts more effectively, ensuring that improvements address the root causes of system fragility. By refactoring this aspect, we enhance the system’s robustness, making it more resilient to future stressors. With this approach, we can better pinpoint which area of our system needs refactoring and design a system that gracefully adapts to evolving demands and challenges.

这种方法使我们能够更有效地定位重构工作,确保改进能够解决系统脆弱性的根本原因。通过重构这一方面,我们增强了系统的鲁棒性,使其更能抵抗未来的压力。采用这种方法,我们可以更准确地确定系统哪个部分需要重构,并设计出一个能够优雅地适应不断变化的需求和挑战的系统。

O’Reilly’s residuality theory presents a nuanced understanding of how systems evolve and sustain themselves through the continuous accumulation of past states and interactions. This theory wants to shift our perspective on change, suggesting that systems (what he calls naïve architectures) do not simply go through isolated, linear steps but are profoundly shaped by the “residue” that remains when facing changes. These residues are active, influential components that affect how systems adapt, resist, and evolve over time.

奥赖利残余性理论提出了一种细致入微的理解,即系统如何通过持续积累过去的状况和互动来演变并维持自身。这一理论试图转变我们对变化的认知,指出系统(他称之为天真架构)并非仅仅经历孤立、线性的步骤,而是深受面对变化时留下的“残余”的深刻影响。这些残余是活跃且具影响力的组成部分,它们影响着系统在时间中的适应、抵抗和演变。

To truly understand a system, one must consider these residuals, which manifest in various forms, such as legacy code in software, ingrained processes in organizations, or established cultural norms within communities. Each of these residues carries with it the weight of past decisions, interactions, and contexts, creating a complex web that influences current and future states. For example, in the realm of software development, understanding the intricacies of legacy code is essential for making informed decisions about future development and integrations.

要真正理解一个系统,就必须考虑这些残余,它们以多种形式显现,例如软件中的遗留代码、组织中根深蒂固的流程,或社区内形成的既定文化规范。这些每一项残余都承载着过去决策、互动和背景的重量,形成了一个复杂的网络,影响着当前和未来的状态。例如,在软件开发领域,理解遗留代码的复杂性对于就未来的开发和集成做出明智决策至关重要。

Residuality theory advocates for a holistic approach to change management and system design. It encourages us to look beyond immediate actions and outcomes and to consider the deeper, more persistent influences that shape a system’s behavior. By doing so, we can better predict potential challenges, identify areas of resistance, and develop strategies that are more aligned with the underlying reality of the system. This approach contrasts sharply with traditional models of change that often overlook the importance of historical context and residual effects, leading to strategies that may be effective in the short term but fail to sustain over time.

残余性理论提倡一种整体性的变革管理和系统设计方法。它鼓励我们超越眼前的行动和结果,去考虑那些塑造系统行为的更深层次、更持久的因素。通过这样做,我们能够更好地预测潜在挑战,识别阻力区域,并制定更符合系统深层现实状况的策略。这种做法与传统变革模型形成鲜明对比,后者往往忽视历史背景和残余效应的重要性,导致短期内有效的策略却无法持久。

In practical terms, applying residuality theory means engaging in a continuous process of reflection and analysis, where past experiences are not just acknowledged but are critically examined to understand their ongoing impact. This involves not only identifying the residues but also interpreting their significance and leveraging this understanding to inform future actions. For instance, in a business context, leaders might analyze past project failures and successes to identify persistent patterns that could influence current initiatives. In software development, teams might conduct thorough code reviews to understand how past coding practices and design decisions affect current performance and scalability.

在实际应用中,运用残余性理论意味着进行持续反思和分析的过程,不仅承认过去的经验,还要批判性地审

Stressors and refactoring

压力源与重构

A stressor, in the context of refactoring, is any external factor or event that places pressure on the system and tests its stability, performance, and resilience. As per the example before, this pressure can be caused by a spike in the number of users, unexpected behaviors, and network or hardware failures. These are practical tests that reveal the system’s weaknesses and bottlenecks. Do not equate this with Netflix’s Chaos Monkey though. You identify stressors with brainstorming sessions, analysis of the production system in its ecosystem, or by using random simulation.

在重构的语境中,压力源是指任何施加压力于系统并测试其稳定性、性能和弹性的外部因素或事件。以之前的例子为例,这种压力可能由用户数量激增、意外行为以及网络或硬件故障引起。这些都是实际的测试,可以揭示系统的弱点和瓶颈。但不要将其与 Netflix 的混沌猴等同起来。你可以通过头脑风暴会议、分析生产系统在其生态系统中的运行情况,或使用随机模拟来识别压力源。

Observing and analyzing how your system behaves under these stress scenarios allows you to gain critical insights into system weaknesses and bottlenecks. This understanding is crucial for effective refactoring, enhancing the system’s ability to handle future stressors, and improving overall robustness and reliability.

观察和分析系统在这些压力场景下的行为,可以帮助你深入了解系统的弱点和瓶颈。这种理解对于有效的重构至关重要,能够增强系统应对未来压力的能力,并提高整体稳健性和可靠性。

If you want to learn more on the topic, we suggest watching the speech O’Reilly gave at NDC Oslo in 2023 on YouTube (https://www.youtube.com/watch?v=0wcUG2EV-7E).

如果您想了解更多关于这个主题的内容,我们建议您观看 O'Reilly 在 2023 年 NDC 奥斯陆会议上发表的演讲(https://www.youtube.com/watch?v=0wcUG2EV-7E)。

EventStorming  事件风暴

Last but not least, we want to bring your attention to EventStorming (https://www.eventstorming.com/), a tool created by Alberto Brandolini. This tool is especially useful for the exploration of your domain and is different from other similar tools (i.e., domain storytelling). The idea behind it is quite simple; since your goal is to understand the complexity of the domain, bring all the interested parties, from domain experts to stakeholders, to the table and build a domain model together that is understandable to everyone. There is no single format for EventStorming; it is more of a family of workshops aimed at graphically representing the complexity of key information flows within organizations using events as an exploration tool. There are three main kinds of formats we can choose from, and every single one is specifically designed for different moments of exploration. Let’s go through them in the next sub-sections.

最后但同样重要的是,我们想将您的注意力引向由 Alberto Brandolini 创建的工具——事件风暴(https://www.eventstorming.com/)。这个工具特别适用于领域探索,并且与其他类似工具(例如领域故事讲述)有所不同。其背后的理念相当简单;由于您的目标是理解领域的复杂性,因此将所有利益相关者——从领域专家到利益相关者——召集到一起,共同构建一个每个人都能理解的领域模型。事件风暴没有单一的格式;它更像是一系列旨在使用事件作为探索工具,以图形方式表示组织内关键信息流复杂性的研讨会。我们可以从三种主要格式中选择,每一种都专门设计用于探索的不同阶段。让我们在下一节中逐一介绍它们。

Big picture  大局

When you must deal with the refactoring of a code base, you need to understand what this solution solves, and you need to talk to all the stakeholders of the project, all the businesspeople, and all the developers. The goal is to build a model that represents the flow of all data in your domain. Everything starts by hanging a sheet of paper on the wall, typically 10-15 meters in length (but it usually grows a lot more), and applying fundamental ingredients on it—orange sticky notes. These notes represent events that occur in the domain, and, usually, after a couple of hours of discussions and writing of orange stickies, you will see that processes start to emerge on the wall as a flow represented by all the orange sticky notes. From here, you will be able to start exploring with the stakeholders the different ways in which they perceive the same problem.

当你必须处理代码库的重构时,你需要理解这个解决方案解决了什么问题,并且需要与项目的所有利益相关者、所有业务人员以及所有开发人员沟通。目标是构建一个能够代表你领域内所有数据流的模型。一切始于在墙上挂一张纸,通常长度为 10-15 米(但它通常会增长得更多),并在上面应用基本元素——橙色便利贴。这些便利贴代表领域中发生的事件,通常经过几个小时讨论和书写橙色便利贴后,你会发现墙上开始显现出流程,这些流程由所有的橙色便利贴表示。从这里开始,你将能够与利益相关者一起探索他们看待同一问题的不同方式。

In this phase, it is important to understand whether these ways are simply different in solving the problem or whether each stakeholder has a different point of view on it. You will end up with a defined common language between developers, business experts, and stakeholders. Figure 2.3 shows an example of events in an EventStorming session with added notes about topics that must be covered during the detailed analysis of the flow. The scope of the big picture is to highlight the main events and potential pain points throughout the business flow.

在这个阶段,重要的是要理解这些方法是否仅仅是解决问题的不同方式,还是每个利益相关者对它有不同的观点。最终,你将定义开发人员、业务专家和利益相关者之间的共同语言。图 2.3 展示了一个 EventStorming 会议中的事件示例,并添加了在流程的详细分析中必须涵盖的主题的注释。大局的范围是突出整个业务流程中的主要事件和潜在痛点。

Process modeling  过程建模

In this case, the scope of the exploration is more limited, and so is the team dimension. You need to create a space in which each stakeholder can contribute to creating the model, and for this reason, you cannot use tools such as UML, otherwise, only developers could participate, or Business Process Modeling Notation, because only businesspeople could participate. You need to enable conversations between all the members of the domain so that you can create a model to share between them.

在这种情况下,探索的范围更加有限,团队规模也是如此。你需要创建一个空间,让每个利益相关者都能为创建模型做出贡献,因此你不能使用 UML 等工具,否则只能由开发者参与,或者业务流程建模符号,因为只能由业务人员参与。你需要促进领域内所有成员之间的对话,以便创建一个可以与他们共享的模型。

In Figure 2.4, you can see all the types of sticky notes that you can use during an EventStorming session. Having a common model avoids misinterpretation, and with that, you don’t lose any details on the business flow.

在图 2.4 中,你可以看到在 EventStorming 会议期间可以使用的所有类型便利贴。使用统一模型可以避免误解,并且因此,你不会丢失业务流程的任何细节。

Figure 2.4 – The grammar of EventStorming process modeling

To achieve this goal, you have to add more types of sticky notes to EventStorming’s grammar. You do not need a design of the processes as a result of your exploration, but to encourage the conversation, so that you can use a tool as simple as possible to be understood by everyone. For example, during refactoring, it is very important to identify the right boundaries to split our monolith with. That separation represents the way in which you will extrapolate the microservices architecture.

要实现这一目标,你需要在 EventStorming 的语法中添加更多类型的便利贴。你的探索结果不需要是一个流程设计,而是为了鼓励对话,以便你可以使用尽可能简单的工具让每个人都能理解。例如,在重构过程中,识别出正确的边界来拆分我们的单体应用非常重要。这种分离代表了你会用来推断微服务架构的方式。

Software design  软件设计

With the previous workshop, you end up with a clear definition of the domain boundaries. Now, with this third format, you are going to explore in detail every single one of them, so that the grammar will be richer.

通过之前的研讨会,你最终得到了领域边界的清晰定义。现在,通过这个第三种格式,你将详细探索每一个边界,使语法更加丰富。

Figure 2.5 – All of the elements used during EventStorming

With this workshop, you will identify the aggregate of your bounded context, as well as the domain events, commands, services (internal and external), policy, and all the objects you need to design your solution. The aim of this workshop is to provide a detailed structure of the software for the team using the language that you discovered during the previous EventStorming sessions, and the details of all objects discovered in this one.

通过这个工作坊,你将识别你的限界上下文的聚合,以及领域事件、命令、服务(内部和外部)、策略以及你设计解决方案所需的所有对象。这个工作坊的目的是为使用你在之前的 EventStorming 会议中发现的语言的团队提供软件的详细结构,以及在这个会议中发现的所有对象的细节。

Now that you have understood the importance of knowledge, you can discover how deep you can go into the problem and try to solve it.

现在你已经理解了知识的重要性,你可以发现你可以深入到问题的哪个程度并尝试解决它。

Problem and solution space

Among the many phrases apocryphally attributed (https://quoteinvestigator.com/2014/05/22/solve/) to Albert Einstein, there is one that goes as follows:

在众多据传(https://quoteinvestigator.com/2014/05/22/solve/)归于阿尔伯特·爱因斯坦的名言中,有一句是这样的:

“If I had an hour to save the world, I would spend 55 minutes defining the problem and only 5 minutes finding the solutions.”

“如果我有一个小时来拯救世界,我会花 55 分钟来定义问题,只花 5 分钟来寻找解决方案。”

We could summarize this statement by saying that the problem space is the set of all the problems that your application should solve, while the solution space is the set of all solutions that address each given problem.

我们可以将这句话总结为:问题空间是指你的应用程序应该解决的所有问题的集合,而解决方案空间是指针对每个给定问题所提供的所有解决方案的集合。

Allen Newell and Herbert Simon in their book Human Problem Solving argue that we, as human beings, tend to be problem solvers. We see this daily in our team while developing software. We tend to seek and try to find a solution as quickly as possible and leave the problem space as quickly too. We are uncomfortable staying in this area, but it is where our client needs to reside; it is the zone that allows us to acquire more information about the problems our client asks us to solve through the software we will develop for them because writing software means solving business problems! Essentially, this space constitutes the foundation upon which the solution space will rest. Mathematically speaking, the problem space is always a subset of the solution space. Therefore, we should not rush to leave the former to move, with poor domain knowledge, to the latter. As developers, to demonstrate our capabilities, we tend to provide a solution as soon as possible, as if to show that we are good at our job by providing solutions fast to our clients.

艾伦·纽厄尔和赫伯特·西蒙在他们合著的《人类问题解决》一书中认为,作为人类,我们倾向于成为问题解决者。在我们团队开发软件时,我们每天都能看到这一点。我们倾向于尽快寻找并尝试找到解决方案,然后迅速离开问题空间。我们不喜欢待在这个区域,但客户需要待在这里;这是让我们通过将要为他们开发的软件获取更多关于他们要求我们解决的问题信息的区域,因为编写软件就意味着解决商业问题!本质上,这个空间构成了解决方案空间的基础。从数学上讲,问题空间始终是解决方案空间的一个子集。因此,我们不应该急于离开前者,带着贫乏的领域知识去后者那里。作为开发者,为了展示我们的能力,我们倾向于尽快提供解决方案,仿佛通过快速向客户提供解决方案来证明我们工作能力强。

By acting this way, however, we do not delve deeply enough into the problem; we are taking a shortcut to exit an uncomfortable zone. If we are then given requirements, our biases suggest the solution to propose! Unfortunately, such a solution will always be incomplete, at best, and wrong, at worst, because it is at this stage that projects begin to fail. We will realize it later when it is already too late, but the root of the failure lies in not having thoroughly investigated the problem space.

然而,采取这种方式,我们并没有深入探究问题;我们是在走捷径以逃离一个不舒适的区域。如果我们随后被给出需求,我们的偏见就会建议我们提出解决方案!不幸的是,这样的解决方案总是不完整的,至少是错误的,最坏的情况是,因为正是在这个阶段项目开始失败。我们会在太晚的时候才意识到这一点,但失败的根源在于没有彻底调查问题空间。

Staying in the problem space means resisting the urge to prematurely jump into solutions. It requires a disciplined approach to fully understand and articulate the problem before considering any solution. This involves engaging with stakeholders to capture their perspectives, conducting thorough research, and employing techniques such as domain modeling and scenario analysis to explore all facets of the problem.

留在问题空间意味着抵制过早跳入解决方案的冲动。它需要一种自律的方法,在考虑任何解决方案之前充分理解和阐述问题。这包括与利益相关者互动以捕捉他们的观点,进行彻底的研究,并采用领域建模和场景分析等技术来探索问题的各个方面。

By deeply investigating the problem space, we uncover the underlying causes, constraints, and nuances that might not be immediately obvious. This process often reveals critical insights that significantly influence the design and implementation of the solution. It ensures that the problem is framed correctly, which is essential for creating effective and sustainable solutions.

通过深入探究问题领域,我们能够揭示那些可能并不显而易见的基础原因、约束条件和细微差别。这一过程往往能揭示关键洞察,从而显著影响解决方案的设计与实现。它确保问题被正确地界定,这对于创建有效且可持续的解决方案至关重要。

Furthermore, staying in the problem space helps to mitigate biases and assumptions that can cloud judgment. It promotes a culture of curiosity and continuous learning within the team, where questions are encouraged, and diverse viewpoints are valued. This collaborative exploration fosters a shared understanding of the problem, aligning all stakeholders around a common goal.

此外,停留在问题领域有助于减轻可能蒙蔽判断的偏见和假设。它促进了团队内部好奇心和持续学习的文化,鼓励提问,并重视多元化的观点。这种协作探索培养了人们对问题的共同理解,使所有利益相关者围绕共同目标达成一致。

Neglecting this phase leads to superficial solutions that fail to address the core issues. Projects that skip through problem investigation often suffer from scope creep, missed requirements, and ultimately, failure to deliver value. In contrast, a robust exploration of the problem space lays a solid foundation for successful projects, ensuring that solutions are not only technically sound but also relevant and impactful.

忽视这一阶段会导致表面化的解决方案,无法解决核心问题。跳过问题探究的项目往往面临范围蔓延、需求遗漏,最终无法交付价值。相比之下,对问题领域的充分探索为成功项目奠定了坚实基础,确保解决方案不仅技术上可靠,而且具有相关性和影响力。

Figure 2.6 summarizes the differences between them.

Figure 2.6 – Problem space versus solution space

The urge to provide an adequate solution soon from the start means starting off on the wrong foot. We all know that our applications start small but are destined to grow over time, some very quickly: as customer demands grow, a small deviation at the beginning of the journey will lead us to a destination different from what was imagined, making it increasingly difficult to align our solution with the actual problem solution.

从一开始就急于提供充分的解决方案意味着一开始就踏错了步。我们都知道我们的应用开始时规模很小,但注定会随着时间的推移而增长,有些增长非常迅速:随着客户需求的增长,在旅程开始时的一个小偏差将导致我们到达一个与想象不同的目的地,使得我们的解决方案越来越难以与实际问题的解决方案保持一致。

How can we avoid all of this? By staying in the problem space as long as possible, just like in Einstein’s quote. Even Evans proposes an exploratory model, consisting of continuous iterations of analysis, proposal, and feedback, as shown in Figure 2.7.

我们如何避免所有这些问题?就像爱因斯坦的名言一样,尽可能长时间地停留在问题空间中。即使是伊文斯也提出了一个探索性模型,由分析、建议和反馈的持续迭代组成,如图 2.7 所示。

Figure 2.7 – Model exploration whirlpool

Evans defines the action of finding a solution from the beginning to the entire problem as what we colloquially call big front design: a block “locking in our ignorance.” The problem with this type of approach is that we are forced to make a lot of important decisions about our solution when we have less knowledge of the problem itself.

埃文斯将从头到整个问题寻找解决方案的行为定义为我们所俗称为大前设计:一个“锁定我们的无知”的模块。这种方法的缺点在于,当我们对问题本身了解较少时,被迫要做出许多关于解决方案的重要决策。

To counter this, Dan North suggests extreme caution in moving toward a definitive solution. In his article Introducing Deliberate Discovery (https://dannorth.net/introducing-deliberate-discovery/), he advocates for a proactive exploration of the domain knowledge, emphasizing the importance of identifying and understanding what we do not yet know about the domain. Let’s spend some time going through the important parts of the article.

为了应对这种情况,Dan North 建议在迈向最终解决方案时要极其谨慎。在他的文章《介绍刻意发现》(https://dannorth.net/introducing-deliberate-discovery/)中,他提倡主动探索领域知识,强调识别和理解我们尚未了解的领域的重要性。让我们花些时间回顾一下这篇文章的重要部分。

Deliberate discovery  刻意发现

The main terms covered in North’s article are as follows:

诺斯文章中涵盖的主要术语如下:

* Deliberate discovery: Emphasizes the importance of actively seeking knowledge to reduce ignorance in projects.

刻意发现:强调主动寻求知识以减少项目中的无知。

* Learning versus ignorance: Identifies ignorance as a primary constraint to project success and highlights the need for proactive learning

学习与无知:将无知视为项目成功的主要制约因素,并强调主动学习的重要性

* Accidental versus deliberate learning: Contrasts passive, accidental learning with intentional, deliberate discovery to accelerate knowledge acquisition

偶然学习与有意学习:对比被动、偶然的学习与有意、自觉的发现,以加速知识获取

* Non-linear discovery: Discusses how learning happens in irregular, often unexpected ways

非线性发现:讨论学习如何在不规则、往往出乎意料的方式中发生

* Assumption of problems: Advocates planning with the expectation that unpredictable problems will arise, thus preparing better responses

假设问题:主张在预期不可预测的问题会出现的情况下进行规划,从而准备更好的应对措施

The key recommendations made by North are as follows:

North 提出的关键建议如下:

* Focus planning on knowledge acquisition rather than merely estimating the task

将规划重点放在知识获取上,而不是仅仅估算任务

* Recognize and address various forms of ignorance (technical, domain-specific, organizational)

识别并解决各种形式的无知(技术、领域特定、组织层面)

* Make deliberate efforts in discovery to significantly improve project outcomes by reducing unknowns early

通过早期减少未知因素,在探索中做出刻意努力,显著提升项目成果

* Acknowledge that learning happens in spurts, often influenced by unforeseen challenges

承认学习往往在突发的挑战影响下进行

* Prepare for bad events proactively to mitigate their impact on projects

主动准备应对不良事件,以减轻其对项目的影响

Now let us look at another perspective that delves into the risks of big front design stemming from lack of awareness. Interestingly, “lack of awareness” is termed as the “2nd order of ignorance” in Phillip G. Armour’s article titled The Five Orders of Ignorance (https://cacm.acm.org/opinion/the-five-orders-of-ignorance/)

现在让我们从另一个角度探讨因缺乏意识而导致的宏大前端设计风险。有趣的是,在菲利普·G·阿莫尔的《无知五阶》(https://cacm.acm.org/opinion/the-five-orders-of-ignorance/)一文中,“缺乏意识”被称为“第二阶无知”。

.Five orders of ignorance

无知五阶

The main argument in Armour’s article is that the true product of software development is the knowledge embedded in the software; creating functional software requires understanding what “works.”

阿莫尔文章的主要论点是,软件开发真正的产物是嵌入在软件中的知识;创建功能软件需要理解什么是“有效的”。

If knowledge is the key, then the following is also true:

如果知识是关键,那么以下也是正确的:

* Building effective software is primarily about acquiring the necessary knowledge

构建有效的软件主要在于获取必要的知识

* Software development should be viewed as a knowledge-acquisition process rather than a product-production activity

软件开发应被视为一个知识获取过程,而不是产品生产活动

Starting with these considerations, we end up with five orders of ignorance:

基于这些考虑,我们最终得出五个无知等级:

* 0th order ignorance (0OI): Lack of ignorance – you know something and can demonstrate it

0 级无知(0OI):缺乏无知——你知道某事并能证明它

* 1st order ignorance (1OI): Lack of knowledge – you don’t know something, but you know what you don’t know

第一级无知(1OI):缺乏知识——你不知道某事,但你知道自己不知道什么

* 2nd order ignorance (2OI): Lack of awareness – you don’t know you don’t know

第二级无知(2OI):缺乏意识——你不知道自己不知道什么

* 3rd order ignorance (3OI): Lack of process – you don’t know a suitable process to find out what you don’t know

第三级无知(3OI):缺乏流程——你不知道一个合适的流程来找出自己不知道什么

* 4th order ignorance (4OI): Meta ignorance – you don’t know about the five orders of ignorance

四阶无知(4OI):元无知——你不知道有五种无知

If ignorance is the opposite of knowledge, how can we remain in the problem space to bridge 1OI and increase awareness of 2OI? How do we control our tendency to propose solutions too quickly?

如果无知是知识的对立面,我们如何能保持在问题空间中,以弥合 1OI 并提高对 2OI 的认识?我们如何控制自己提出解决方案过快的倾向?

Bridging gaps in ignorance

填补知识空白

To address the challenge of navigating between known and unknown gaps in knowledge, we recommend the following useful tips:

为了应对在已知和未知知识差距之间导航的挑战,我们推荐以下实用建议:

* Maintain control of the discussion: You don’t have to talk continuously, but you have to avoid the discussion converging too quickly to a conclusion. Often, a signal to a colleague is enough to change the focus of the conversation with the client. The main reason for maintaining control of the discussion is that clients—or their representatives—often assume certain information is understood and leave it unsaid, so it’s up to us to surface and clarify those assumptions.

掌控讨论方向:你不必持续发言,但需避免讨论过早达成结论。通常,向同事发出一个信号就足以改变与客户的对话焦点。掌控讨论的主要原因是客户——或其代表——常常假定某些信息已被理解而未明确表达,因此需要我们揭示并澄清这些假设。

* Listen to different solutions: In initial meetings with a client, participants are often hesitant to speak or propose ideas. Then, after the ice is broken thanks to our capable agile coach, solutions start to emerge and sometimes conflict with each other. It is important to maintain a healthy and positive environment by including everyone’s suggestions in the solution space.

倾听不同方案:在与客户初步会面时,参与者往往不愿发言或提出想法。随着我们出色的敏捷教练打破僵局,解决方案开始浮现,有时彼此冲突。重要的是通过将所有人的建议纳入解决方案空间来维持健康积极的氛围。

* Keep the main solution hidden: As the moderator of the problem exploration, your task is to keep the solutions that globally prove to be valid hidden for as long as possible. For example, if you use EventStorming as an exploration tool, let participants continue to attach sticky notes to the wall, and perhaps guide them in a direction so that the main solution emerges autonomously. Highlight solutions that seem similar and focus attention on them to understand whether they are different expressions of the same solution or totally different ones.

隐藏主要解决方案:作为问题探索的主持人,你的任务是尽可能长时间地隐藏那些被证明具有全局有效性的解决方案。例如,如果你使用事件风暴法作为探索工具,让参与者继续在墙上贴便利贴,并可能引导他们朝某个方向发展,以便主要解决方案能够自主浮现。突出看似相似的解决方案,并集中注意力理解它们是同一解决方案的不同表达方式,还是完全不同的方案。

Staying in the problem space is certainly uncomfortable for both parties: the client and the supplier. The former feels a bit under pressure due to the countless questions they keep receiving, and the latter, often us, can’t wait to propose a solution. Completely addressing the client’s problem takes time, and it’s not always convenient to insist on deeper investigation or prolonged questioning during the first meeting. The important thing is to identify the boundaries of the problem and start proposing a solution that can be revisited for feedback and continued after potentially adjusting the course.

对于客户和供应商双方来说,停留在问题空间中肯定是不舒服的:前者由于不断收到无数问题而感到有些压力,后者,通常是我们,迫不及待地想提出一个解决方案。完全解决客户的问题需要时间,而且在第一次会议中坚持进行更深入的调查或延长提问时间并不总是方便的。重要的是要确定问题的边界,并提出一个可以用于反馈并在可能调整方向后继续的解决方案。

Our domain will always be in constant evolution, if only for everything that belongs to the level of unknown unknowns – the things we still don’t know we don’t know but will discover as we become greater experts in the domain we are working on. At this point, we need to understand how to approach such a solution, from an architectural point of view. And for this, we need to explore the domain before creating a model.

我们的领域将始终处于不断演变之中,至少对于属于未知未知层面的一切而言——那些我们尚未意识到自己不知道,但当我们成为我们正在工作的领域的更高级专家时将会发现的事情。在这个阶段,我们需要从架构的角度理解如何处理这样的解决方案。为此,在创建模型之前,我们需要探索领域。

Deleuzian walk  德鲁兹式漫步

We have already seen how the abstractions of reality can be dangerous to solve a problem. Creating a good model is the primary goal, either during the first design of your solution or while you are working to refactor it. But how do we do this? EventStorming, like storytelling and other tools, is good for exploring the domain together with all team members before creating a model. However, an alternative way to run an exploration is to simply experience the domain itself, just as we explore the territory around us when we walk.

我们已经看到现实中的抽象可能对解决问题是有害的。创建一个好的模型是主要目标,无论是在您解决方案的第一次设计期间,还是在您进行重构时。但我们如何做到这一点呢?EventStorming,就像讲故事和其他工具一样,在创建模型之前与所有团队成员一起探索领域是很好的。然而,进行探索的另一种替代方法是直接体验领域本身,就像我们漫步时探索周围的领土一样。

This form of exploration is known as the Deleuzian walk and describes an alternative way of learning. The term comes from the ideas of Gilles Deleuze, as described in his 1968 book Difference and Repetition, which can be summarized as follows:

这种探索形式被称为德勒兹式漫步,描述了一种替代性的学习方法。该术语源自吉尔·德勒兹的思想,如他在 1968 年出版的《差异与重复》一书中所阐述的,可以总结如下:

* Philosophy of difference: Deleuze challenges traditional philosophy’s focus on identity and sameness, advocating for a deeper exploration of differences

差异哲学:德勒兹挑战传统哲学对同一性和相同性的关注,倡导更深入地探索差异

* Repetition and novelty: He explores how repetition can generate new meanings or variations, challenging the idea that repetition simply reinforces what already exists or remains the same.

重复与新颖性:他探讨了重复如何产生新的意义或变化,挑战了重复仅仅强化既存事物或保持不变的观念。

* Ontology: Deleuze presents being as inherently different, emphasizing uniqueness over uniformity

本体论:德勒兹提出存在本质上是不同的,强调独特性而非一致性

* Time and memory: The roles of time and memory are scrutinized for their impact on cultivating differences

时间和记忆:审视时间和记忆在培养差异方面所起的作用

* Conceptual tools: Deleuze navigates through his arguments employing complex philosophical constructs such as the virtual, the actual, and intensity

概念工具:德勒兹通过运用虚拟、实在和强度等复杂的哲学结构来阐述他的论点

When you walk along a new path for the first time, you are totally involved in looking at the map to be sure to get back home safely. After a few times, you start to discover new things on your journey because now you know the path, and you can pay attention to the environment around you, the mountains around the valley, or the river at the bottom. You will see new landscapes or discover new alternative ways of traveling in the same space. When you bring your friends with you, they will see different things, because their interests are different from yours. Instead of understanding the world around you, you are contemplating it, and you become very rich. You are changing your way of thinking, from learning from the map (linear), in which the map provides an objective, well-defined, description of the walk, to observing the world around you with your eyes and discovering new things (laterally).

当你第一次走一条新路径时,你会完全专注于查看地图以确保安全回家。几次之后,你开始在旅途中发现新事物,因为你已经熟悉了这条路径,可以留意周围的环境,山谷周围的山峦,或河底。你会看到新的风景,或在同一空间中发现新的旅行方式。当你带上朋友一起时,他们会看到不同的东西,因为他们的兴趣和你不同。你不再只是理解周围的世界,而是在思考它,你变得非常丰富。你的思维方式发生了改变,从通过地图学习(线性),地图提供了对行走过程的客观、明确的描述,转变为用眼睛观察周围的世界,发现新事物(横向)。

This metaphor is quite fitting for domain exploration. As the environment changes during the different seasons, your domain also changes due to new business requirements, or simply because the world changes constantly and so does the business flow. This means that our structure is constantly changing, and implementing certain structures too early could be very dangerous and unproductive.

这个比喻非常适用于领域探索。随着不同季节环境的变化,你的领域也会因新的业务需求而变化,或者仅仅因为世界在不断变化,业务流程也在不断变化。这意味着我们的结构也在不断变化,过早地实施某些结构可能会非常危险且低效。

During domain exploration, knowledge is much preferable in contrast to the developer’s need for an immediate concrete implementation. So, Deleuze’s ideas map perfectly with the model exploration whirlpool shown in Figure 2.7. Basically, it is important to discover your domain iteratively and increase your knowledge of the domain step by step. Remember that you are a developer and do not necessarily know from the start the domain you will work on.

在领域探索过程中,知识远比开发者对立即具体实现的渴望更为重要。因此,德勒兹的思想与图 2.7 中所示的模型探索漩涡完美契合。基本上,发现你的领域需要迭代进行,并逐步增加你对领域的认知。记住,你是一名开发者,从一开始并不一定知道你将要工作的领域。


Decision-making and biases

决策与偏见

By now, it should be clear why it is important to spend most of our time understanding the problem instead of finding a solution, and now we can delve into the last aspect of handling complexity. This includes cognitive aspects of decision-making and how biases can impact the process, especially in the context of refactoring complex systems using DDD patterns and principles. Understanding these cognitive processes will help you make more informed and rational decisions during your refactoring journey.

到现在为止,应该很清楚为什么我们应该将大部分时间用于理解问题而不是寻找解决方案,现在我们可以深入探讨处理复杂性的最后一个方面。这包括决策的认知方面以及偏见如何影响这个过程,特别是在使用领域驱动设计(DDD)模式和原则重构复杂系统的背景下。理解这些认知过程将帮助你在重构旅程中做出更明智和理性的决策。

Understanding System 1 and System 2

理解系统 1 和系统 2

Daniel Kahneman, a renowned psychologist and Nobel laureate, introduced the concept of two systems of thinking in his book Thinking, Fast and Slow. These systems are fundamental to understanding human decision-making processes and are called System 1 and System 2.

丹尼尔·卡尼曼,一位著名的心理学家和诺贝尔奖得主,在他的著作《思考,快与慢》中提出了两种思维系统的概念。这些系统是人类决策过程的基础,被称为系统 1 和系统 2。

System 1 is efficient for routine tasks and familiar situations but can be prone to biases and errors when dealing with complex or unfamiliar problems. System 2, on the other hand, is slower and more deliberate and allows us to make more rational and informed decisions, especially when dealing with unfamiliar or complex situations. Their key traits are as follows:

系统 1 适用于常规任务和熟悉的情况,但在处理复杂或陌生问题时容易产生偏见和错误。而系统 2 则较慢且更审慎,使我们能够做出更理性、更明智的决策,尤其是在处理陌生或复杂情况时。它们的主要特征如下:

* System 1 – fast and intuitive: System 1 operates automatically and quickly, with little or no effort and no sense of voluntary control. It is our intuitive system, which we use for quick judgments and decisions. Examples of System 1 thinking include the following:

系统 1——快速且直观:系统 1 自动且快速运行,几乎不需要努力,也没有自愿控制的意识。它是我们的直觉系统,用于快速判断和决策。系统 1 思考的例子包括以下:

    * Recognizing a familiar face in a crowd

在人群中认出熟悉的面孔

    * Answering simple arithmetic questions (e.g., 2 + 2 = 4)

回答简单的算术问题(例如,2+2=4)

    * Driving a car on an empty road

在空旷的路上开车

* System 2 – slow and deliberate: System 2 allocates attention to the effortful mental activities that demand it, including complex computations. It is our analytical system, which we use for critical thinking and complex problem-solving. Examples of System 2 thinking include the following:

系统 2——缓慢而审慎:系统 2 将注意力分配给需要它付出的努力性心理活动,包括复杂的计算。它是我们的分析系统,我们用它来进行批判性思维和复杂问题解决。系统 2 思维的例子包括以下:

    * Solving a complex mathematical problem

解决一个复杂的数学问题

    * Making a strategic decision in a business context

在商业环境中做出战略决策

    * Refactoring a complex software system

重构复杂软件系统

The importance of Systems 1 and 2 in refactoring

系统 1 和系统 2 在重构中的重要性

Refactoring, particularly in complex systems, requires a balance between intuitive and deliberate thinking. Here’s how understanding and applying System 1 and System 2 can enhance your refactoring efforts.

重构,尤其是在复杂系统中,需要在直觉思维和刻意思维之间取得平衡。这里是如何理解和应用系统 1 和系统 2 来提升你的重构工作。

To leverage both systems, you must understand when and how to use them during the refactoring process. Starting with System 1, an experienced developer can quickly recognize patterns, code smells, and where to start a refactoring process through past experiences. Also, for minor tasks, such as extracting small methods, System 1 can be effective. System 2 kicks in when you deal with large-scale refactoring, such as restructuring an entire module or re-architecting a system. Here, deliberate thinking is crucial. It also helps in creating a refactoring plan and identifying potential risks ahead. As a last important thing, System 2 can help mitigate biases that could emerge with System 1.

要利用这两个系统,你必须了解在重构过程中何时以及如何使用它们。从系统 1 开始,有经验的开发者可以通过过去的经验快速识别模式、代码异味以及重构的起点。此外,对于提取小方法等小任务,系统 1 可以很有效。当处理大规模重构,如重构整个模块或重新架构系统时,系统 2 会介入。这时,刻意思维至关重要。它还有助于制定重构计划并提前识别潜在风险。最后一点重要的是,系统 2 可以帮助缓解系统 1 可能产生的偏见。

Common cognitive biases in refactoring

重构中的常见认知偏差

Refactoring is as much a mental process as a technical one, and our cognitive biases can significantly impact the outcomes. Recognizing these biases and taking steps to counteract them can help you avoid potential pitfalls. Let’s look at the main ones and what you can consider doing to mitigate them.

重构既是技术过程,也是思维过程,我们的认知偏差会显著影响结果。认识到这些偏差并采取措施加以对抗,可以帮助你避免潜在陷阱。让我们看看主要的偏差以及你可以考虑如何减轻它们。

Anchoring bias  锚定偏差

Anchoring bias occurs when we rely too heavily on the first piece of information encountered (the “anchor”) when making decisions. As stated, this might mean sticking to the first solution or design without considering other alternatives. You should encourage team discussions and explore multiple solutions before settling on a decision.

锚定偏差发生在我们做决策时过度依赖遇到的第一条信息(“锚点”)。如前所述,这可能意味着坚持第一个解决方案或设计,而不考虑其他替代方案。你应该鼓励团队讨论,并在做出决定前探索多种解决方案。

Here’s how to counteract it:

这是如何应对它的方法:

* Encourage exploration: Actively brainstorm multiple solutions before committing to one. Use tools such as design spikes or proof-of-concept development to evaluate alternatives.

鼓励探索:在做出决定前积极头脑风暴多种解决方案。使用设计尖峰或概念验证开发等工具来评估替代方案。

* Adopt decision frameworks: Use structured techniques such as decision matrices to evaluate options objectively.

采用决策框架:使用决策矩阵等结构化技术来客观评估选项。

* Set a “cooling-off period”: Give the team time to reflect on initial ideas before making a final decision.

设置“冷静期”:给团队时间在做出最终决定前反思初步想法。

Confirmation bias  确认偏差

Confirmation bias is the tendency to search for and remember information that confirms one’s preconceptions. This can lead to ignoring critical feedback or alternative approaches during refactoring. To mitigate this bias, you can seek different opinions and rely on thorough code reviews to challenge your decisions.

确认偏误是指人们倾向于寻找和记住符合自己先入为主观念的信息。这可能导致在重构过程中忽视关键反馈或替代方法。为了减轻这种偏误,你可以寻求不同意见并依赖彻底的代码审查来挑战你的决定。

Here’s how to counteract it:

这是如何应对它的方法:

* Foster a culture of challenge: Encourage team members to play devil’s advocate during discussions. Assign someone to question the prevailing assumptions in every meeting.

培养挑战文化:鼓励团队成员在讨论中扮演反对角色。指派专人负责在每次会议中质疑主流假设。

* Emphasize diverse perspectives: Actively involve people from different roles or with varying expertise to review designs and refactoring plans.

强调多元视角:主动邀请来自不同角色或拥有不同专业知识的成员来评审设计和重构计划。

* Automate feedback: Use tools such as static code analyzers and automated tests to surface objective insights, reducing reliance on subjective interpretations.

自动化反馈:使用静态代码分析器和自动化测试等工具来揭示客观见解,减少对主观解释的依赖。

Availability heuristic  可得性启发式

The availability heuristic involves prioritizing events based on vividness or recency instead of their frequency, such as a plane crash versus a car crash. The latter is more frequent, but we tend to think of the former more often. This can result in overestimating the importance of recent events that are not the norm and potentially lead us to suboptimal refactoring decisions. We should force ourselves to base our decisions on objective data rather than recent experiences alone.

可得性启发式是指根据生动性或近期性来优先考虑事件,而不是根据其频率,例如飞机失事与汽车事故。后者更为频繁,但我们往往更常想到前者。这可能导致我们高估非正常近期事件的重要性,并可能引导我们做出次优的重构决策。我们应该强迫自己基于客观数据而非仅凭近期经验来做决策。

Here’s how to counteract it:

这是如何应对它的方法:

* Rely on historical data: Analyze metrics such as defect rates, code churn, or feature usage to guide refactoring priorities

依靠历史数据:分析缺陷率、代码变更率或功能使用情况等指标来指导重构优先级

* Maintain a refactoring log: Document past refactoring efforts, lessons learned, and their outcomes to ground future decisions in accumulated knowledge

维护重构日志:记录过去的重构工作、经验教训及其结果,以便将未来的决策建立在积累的知识基础上

* Encourage structured retrospectives: Reflect regularly on past decisions to identify patterns that can inform better judgment

鼓励结构化回顾:定期反思过去的决策,以识别可以指导更好判断的模式

Practical example – refactoring a legacy system

实际案例——重构遗留系统

Let’s consider a practical example to illustrate the application of System 1 and System 2 thinking in refactoring a complex system. Imagine you are tasked with refactoring a monolithic application into a more modular and maintainable structure using DDD principles. This scenario provides an excellent opportunity to demonstrate how both types of thinking can be leveraged throughout the refactoring process.

让我们通过一个实际案例来说明在重构复杂系统时如何应用系统 1 和系统 2 的思维。假设你被要求使用领域驱动设计(DDD)原则将一个单体应用程序重构为一个更模块化和可维护的结构。这个场景为展示这两种思维如何在重构过程中发挥作用提供了绝佳的机会。

Your approach would likely begin with an initial assessment, combining both System 1 and System 2 thinking. You’d use your intuitive System 1 to quickly identify obvious code smells and areas that need improvement. Simultaneously, you’d engage your analytical System 2 thinking to perform a detailed analysis of the system’s architecture, dependencies, and business domains. This deeper, more deliberate analysis provides a comprehensive understanding of the system’s complexity.

你的方法可能从初步评估开始,结合系统 1 和系统 2 的思维。你会用系统 1 的直觉快速识别明显的代码异味和需要改进的领域。同时,你会运用系统 2 的分析性思维对系统的架构、依赖关系和业务领域进行详细分析。这种更深入、更审慎的分析提供了对系统复杂性的全面理解。

With a clear picture of the system, you move on to strategic planning, which primarily involves System 2 thinking. You develop a strategic plan for the refactoring process, carefully breaking down the monolith into bounded contexts. This step requires thoughtful consideration of the system’s structure and business logic. As part of this planning, you identify key aggregate roots, entities, and value objects within each bounded context (we will do a recap on these terms in Chapters 3 and 4), laying the groundwork for a more modular and domain-aligned architecture.

有了对系统的清晰认识,你便可以进入战略规划阶段,这主要涉及系统 2 型思维。你为重构过程制定战略计划,小心地将单体系统分解为限界上下文。这一步需要对系统的结构和业务逻辑进行深思熟虑的考虑。作为这一规划的一部分,你需要在每个限界上下文中识别关键的聚合根、实体和价值对象(我们将在第 3 章和第 4 章中回顾这些术语),为构建更模块化、与领域对齐的架构奠定基础。

The actual refactoring process is where both System 1 and System 2 thinking truly shine in tandem. You apply System 1 thinking for straightforward refactoring tasks within each bounded context. These might include simple code cleanup, renaming for clarity, or extracting obvious methods. For more complex tasks, you switch to System 2 thinking. This includes defining new interfaces, decoupling dependencies, and ensuring data consistency across the newly defined boundaries. The interplay between quick, intuitive decisions and deeper, more analytical thinking allows for efficient progress while maintaining the integrity of the refactoring effort.

实际的重构过程是系统 1 和系统 2 思维真正协同发挥光芒的地方。你用系统 1 思维处理每个限界上下文内的简单重构任务,这些任务可能包括简单的代码清理、为清晰而重命名,或提取明显的函数。对于更复杂的任务,你切换到系统 2 思维。这包括定义新接口、解耦依赖关系,以及确保在新定义的边界上数据的一致性。快速直觉决策与更深入、更分析性思维之间的相互作用,使得重构工作高效推进,同时保持重构工作的完整性。

Throughout the refactoring process, continuous review and adaptation are crucial. You regularly review the refactoring progress with your team, using System 1 thinking to identify quick wins and immediate improvements. At the same time, you employ System 2 thinking to address any emerging challenges or changes in requirements. This balanced approach ensures that you can make rapid progress while also adapting to the evolving needs of the project and catching any potential issues before they become significant problems.

在整个重构过程中,持续审查和调整至关重要。你定期与团队一起审查重构进度,用系统 1 思维识别快速见效和即时改进。同时,你运用系统 2 思维处理任何出现的挑战或需求变化。这种平衡方法确保你能快速推进,同时也能适应项目不断变化的需求,并在问题变得严重之前捕捉到任何潜在问题。

By understanding the dual systems of thinking and recognizing common cognitive biases, you can improve your decision-making process during refactoring. Leveraging System 1 for routine tasks and System 2 for complex problem-solving allows for a balanced and effective approach. Always remain vigilant of biases, seek diverse perspectives, and apply deliberate thinking to tackle the complexity inherent in refactoring.

通过理解思维的两种系统并认识到常见的认知偏差,你可以在重构过程中改进决策过程。利用系统 1 处理常规任务,系统 2 解决复杂问题,可以实现平衡有效的方法。始终警惕偏差,寻求多元视角,并运用刻意思考来应对重构中固有的复杂性。


Summary  摘要

In this chapter, you discovered tools to help understand and pragmatically approach complexity. You gained a comprehensive understanding of handling modern systems’ complexity by effectively separating and navigating the problem and solution spaces while mitigating biases in decision-making. You learned how to approach the complexity of modern systems, the importance of remaining in the problem space as long as possible, and how thinking about the solution changes from thinking about the problem. Additionally, you explored the differences between System 1 and System 2.

在这一章中,你发现了帮助理解和实用方法处理复杂性的工具。你通过有效分离和导航问题与解决方案空间,同时减轻决策中的偏差,获得了处理现代系统复杂性的全面理解。你学习了如何应对现代系统的复杂性,尽可能长时间地停留在问题空间的重要性,以及从思考问题到思考解决方案时思维方式的转变。此外,你还探索了系统 1 与系统 2 之间的区别。

In the next chapter, we will delve into context mapping and strategic patterns. You will learn how to identify and map the various contexts within your domain, understand the relationships between them, and apply strategic patterns to manage these contexts effectively. This will enable you to align your system’s design with its business goals, ensuring a more cohesive and adaptable architecture.

在下一章中,我们将深入探讨上下文映射和战略模式。您将学习如何识别和映射您领域内的各种上下文,理解它们之间的关系,并应用战略模式来有效管理这些上下文。这将使您能够使系统的设计与其业务目标保持一致,确保更具凝聚力和适应性的架构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜流冰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值