软件的复杂性,是一个很泛的概念。
但是一直都是开发过程中的一个难题,本文旨在探讨如何去从容应对复杂性。
01
软件的熵增、构造定律
01
zs熵增定律
熵的概念最早起源于物理学,热力学第二定律(又称“熵增定律”),表明了在自然过程中,一个孤立的系统总是从最初的集中、有序的排列状态,趋向于分散、混乱和无序;当熵达到最大时,系统就会处于一种静寂状态。
软件系统亦是如此, 在软件系统的维护过程中。软件的生命力会从最初的集中、有序的排列状态,逐步趋向复杂、无序状态,直到软件不可维护而被迫下线或重构。
02
构造定律
自然界是如何应对这复杂性?这在物理中被称为构造定律 (Constructal Law), 是由Adrian Bejan于1995提出的:For a finite-size system to persist in time (to live), it must evolve in such a way that it provides easier access to the imposed currents that flow through it.
对于一个有限大小的持续活动的系统,它必须以这种方式发展演进:它提供了一种在自身元素之间更容易访问的流动方式。
这个定理在自然界中比比皆是,最典型的比如水循环系统,海水蒸发到大气,下雨时降落在地面,一部分渗入地面流入江河,一部分继续蒸发,不断循环。这种自发性质的设计反映了这一趋势:他们允许实体或事物更容易地流动 - 以最少的能量消耗到达最远的地方,就连街道和道路这些人为地构建物体,往往也是有排序的模式,以提供最大的灵活性。
02
如何应对软件系统的复杂性?
软件系统的复杂性往往是被低估的。复杂越高,开发人员会感到不安。对其的理解认知负荷代价就越高,我们就更不快乐。真正的挑战是在构建我们的系统时要保持其有序以及工程师的生产方式。
Ousterhout教授在《软件设计的哲学》书中提到:软件设计的最大目标,就是降低复杂度(complexity)。
就是设计符合业务的构造定律的演进方式,一种可以以最小的开发维护成本, 使业务更快更好的流动发展的方式。
03
软件复杂性来自哪里, 如何解决?
01
不确定性的来源
1、业务的不确定性2、技术的不确定性3、人员流动的不确定性02
如何面对不确定性
面对外部的确定性,转化为内核的确定性。面对外部的不确定性,找到稳定的内核基础。
1、专注问题域
当下互联网发展速度是迅猛的, 软件的形态也在不断地变化演进。面对未来的业务及变化,横向业务与纵向业务的发展都是不确定性的。
Robert C. Martin提到的BDUF,永远不要想着在开始就设计好了全部的事情(big design up front),一定要避免过度设计。除非能够十分确认的可预见变化, 业务边界,否则专注解决当前1-2年内业务变化设计, 讲好当下的用户故事,专注解决眼前的问题域。 面向不确定设计,增量敏捷开发。
2、确认稳定的系统内核
随着业务的变化、系统设计也要持续演进升级。没有一开始就完美的架构, 好的架构设计一定是演化来的,不是一开始就设计出来的。
一个健康公司的成长,业务横向、纵向会发展得会越来越复杂,支持业务的系统也一定会越来越复杂。
系统演进过程中的成本,会受到最开始的设计、系统最初的内核影响的。面对外部业务的不确定性, 技术的不确定性,外部依赖的不确定性。一个稳定的内核应该尽量把外部的不确定性隔离。
- 业务与技术的隔离。以业务为核心,分离业务复杂度和技术复杂度。
- 内部系统与外部依赖的隔离
- 系统中常变部分与不常变部分的隔离
- 隔离复杂性(把复杂性的部分隔离在一个模块,尽量不与其他模块互动)
03
无序性
系统和代码像多个线团一样散落一地一样,混乱不堪,毫无头绪。
04
如何面对无序性
1、统一认知(秩序化)2、系统清晰明了的结构(结构化)3、业务开发流程化(标准化)注:这里说的流程化并非指必须使用类似BPM的流程编排系统,
而是指对于一个需求,业务开发有一定的顺序, 有规划的先做一部分事情,开发哪一个模块再去做剩下的工作,是可以流程化的。
05
规模
业务规模的膨胀以及开发团队规模的膨胀,都会带来系统的复杂性提升。
06
如何面对规模膨胀带来的复杂性
1、业务隔离, 分而治之2、专注产品核心竞争力的发展3、场景分层
1、关键场景
投入更多的开发、测试资源、业务资源(比如单元测试覆盖率在90%以上)在关键场景。
2、普通场景
更快,更低成本、更少资源投入地完成普通场景的迭代
07
认知成本
是指开发人员需要多少知识才能完成一项任务。
在引入新的变化时,要考虑到带来的好处是否大于系统认知成本的提升,比如:之前提到的BPM流程编排引擎,如果对系统带来的好处不够多也是增加认知成本的一种。
不合适的设计模式也是增加认知成本的一种,前台同学吐槽的中台架构比较高的学习成本, 也是认知成本的一种。08
如何降低认知成本
1、系统与现实业务更自然真实的映射,对业务抽象建模
软件工程师实际上只在做一件事情,即把现实中的问题搬到计算机上,通过信息化提升生产力。
2、代码的含义清晰,不模糊3、代码的整洁度4、系统的有序性, 架构清晰5、避免过度设计6、减少复杂、重复概念, 降低学习成本7、谨慎引入会带来系统复杂性的变化