问题空间和解空间
哲学家常常会围绕真实世界和理念世界的映射关系探索人类生存的意义,即所谓“两个世界”的哲学思考。软件世界也可一分为二,分为构成描述需求问题的真实世界与获取解决方案的理念世界。整个软件构建的过程,就是从真实世界映射到理念世界的过程。
如果真实世界是复杂的,在映射为理念世界的过程中,就会不断受到复杂度的干扰。根据Allen Newell和Herbert Simon的问题空间理论:“人类是通过在问题空间(problem space)中寻找解决方案来解决问题的”,构建软件(世界)也就是从真实世界中的问题空间寻找解决方案,将其映射为理念世界的解空间(solution space)来满足问题空间的需求。因此,软件系统的构建实则是对问题空间的求解,以获得构成解空间的设计方案,如图所示。
为什么要在软件构建过程中引入问题空间和解空间?
实际上,随着IT技术的发展,软件系统正是在这两个方向不断发展和变化的。在问题空间,我们要解决的问题越来越棘手,空间规模越来越大,因为随着软件技术的发展,许多原本由人来处理的线下流程慢慢被自动化操作所替代,人机交互的方式发生了翻天覆地的变化,IT化的范围变得更加宽广,涉及的领域也越来越多。问题空间的难度与规模直接决定了软件系统的复杂度。
针对软件系统提出的问题,解决方案的推陈出新自然毋庸讳言,无论是技术、工具,还是设计思想与模式,都有了很大变化。解决方案不是从石头里蹦出来的,而必然是为了解决问题而生的。
面对错综复杂的问题,解决方案自然也需要灵活变化。软件开发技术的发展是伴随着复用性和扩展性发展的。倘若问题存在相似性,解决方案就有复用的可能。通过抽象寻找到不同问题的共性时,相同的解决方案也可以运用到不同的问题中。同时,解决方案还需要响应问题的变化,能在变化发生时以最小的修改成本满足需求,同时保障解决方案的新鲜度。无疑,构成解空间的解决方案不仅要解决问题,还要控制软件系统的复杂度。
问题空间需要解空间来应对,解空间自然也不可脱离问题空间而单独存在。对于客户提出的需求,要分清楚什么是问题,什么是解决方案,真正的需求才可能浮现出来。在看清了问题的真相之后,我们才能有据可依地寻找真正能解决问题的解决方案。软件构建过程中的需求分析,实际就是对问题空间的定位与探索。如果在问题空间还是一团迷雾的时候就贸然开始设计,带来的灾难性结果是可想而知的。徐锋认为,“要做好软件需求工作,业务驱动需求思想是核心。传统的需求分析是站在技术视角展开的,关注的是‘方案级需求’;而业务驱动的需求思想则是站在用户视角展6开的,关注的是‘问题级需求’。”
怎么区分方案级需求和问题级需求?方案级需求就好比一个病人到医院看病,不管病情就直接让医生开阿司匹林,而问题级需求则是向医生描述自己身体的症状。病情是医生要解决的问题,处方是医生提供的解决方案。那种站在技术视角展开的需求分析,实际就是没有明确问题空间与解空间的界限。在针对问题空间求解时,必须映射于问题空间定义的问题,如此才能遵循恰如其分的设计原则,在问题空间的上下文约束下寻找合理的解决方案。领域驱动设计为问题空间与解空间提供了不同的设计元模型。对于问题空间,强调运用统一语言来描述需求问题,利用核心子领域、通用子领域与支撑子领域来分解问题空间,如此就可以“揭示什么是重要的以及在何处付出努力”。除去统一语言与子领域,其余设计元模型都将运用于解空间,指导解决方案围绕着“领域”这一核心开展业务系统的战略设计与战术设计。
战略设计和战术设计
对于一个复杂度高的业务系统,过于辽阔的问题空间使得我们无法在深入细节的同时把握系统的全景。既然软件构建的过程就是对问题空间求解的过程,那么面对太多太大的问题,就无法奢求一步求解,需要根据问题的层次进行分解。不同层次的求解目标并不相同:为了把握系统的全景,就需要从宏观层次分析和探索问题空间,获得对等于软件架构的战略设计原则;为了深入业务的细节,则需要从微观层次开展建模活动,并在战略设计原则的指导下做出战术设计决策。这就是领域驱动设计的两个阶段:战略设计阶段和战术设计阶段。
战略设计阶段要从以下两个方面来考量。
- 问题空间:对问题空间进行合理分解,识别出核心子领域、通用子领域和支撑子领域,并确定各个子领域的目标、边界和建模策略。
-
解空间:对问题空间进行解决方案的架构映射,通过划分限界上下文,为统一语言提供知识语境,并在其边界内维护领域模型的统一。每个限界上下文的内部有着自己的架构,限界上下文之间的协作关系则通过上下文映射来体现和表达。