The Nature of Complexity
复杂性的定义
复杂性就是和软件结构相关的,所有使得系统难以理解和修改的东西
下面使用公式来定义一个系统的复杂性

其中,cp和开发人员花在tp模块上的时间成正比
因此,如果一个模块十分复杂,但是不需要经常改动的话,那么该模块对整体系统的复杂性没有太大影响
复杂性的表现
改动传播
一次简单的改动导致了其他很多地方的修改
比如一个web系统,其中包含了多个页面,每个页面上的banner的背景颜色如果都手工指定的话,当需要修改时,需要修改多处;解决方法是,在一个地方定义banner的背景颜色,然后在其他页面中来引用这个设置

好的设计应该尽量减少每次决策导致的代码的修改
认知装载
一名开发人员在完成一个任务之前需要了解多少
如果一名开发人员在完成一个任务之前需要了解很多内容,那么就很容易出bug,因为很容易忽略一些重要的东西。
简单的例子就是使用C语言实现了一个方法,该方法会进行空间的allocate,并且返回一个指向该内存地址的指针;这种情况下,方法的调用者就需要自己释放空间,否则会导致内存泄露
Unknown unknown
为了完成一个任务,需要修改哪些代码并不明显

还是使用之前的例子举例,banner的背景颜色都使用引用的方式,指向了一个bannerBg,但是一些页面使用了另外一个属性darkedColor,该属性是显式地定义在指定页面中的。当背景颜色修改后,darkedColor需要跟着修改,但是很有可能开发人员忘记修改darkedColor,或者即使意识到需要修改,也需要去搜索使用到这个属性的页面,然后去一一修改
好的设计的表现
具有好的设计的系统应该是obvious的,在这样的系统中,开发人员可以很快地了解当前代码是怎么工作的,进行一些改动需要修改哪些地方。
复杂的起因
复杂主要有两种起因:依赖和不明
依赖
当开发人员无法理解一段代码,并且仅仅修改该代码就能完成任务时,依赖就产生了;当前代码和其他的代码相关,如果当前代码修改,另外一段代码也得跟着修改。
以网络协议举例,虽然接受者和发送者使用不同的代码,但是如果其中一方修改了代码,另外一方就得跟着进行修改,此时就产生了依赖
另外一个例子是,方法的签名和方法的实现,方法的签名在方法的实现和方法的调用方之间产生了依赖,如果向方法的签名中新添加一个参数,那么需要同时修改方法的调用和方法的实现
不明
当重要信息并不明显时,就出现了不明。
简单的例子就是变量的命名过于通用,比如time,变量的命名中并没有携带很多有用信息
在很多情况下,不明都是由文档的缺失导致的。但是如果系统需要过多的文档,那么也说明了该系统的设计并不合理
本文探讨了软件复杂性的定义,分析了其主要表现形式,包括改动传播、认知装载及未知未知的问题。深入讨论了复杂性的起因,如依赖和不明,以及如何通过良好的设计减少这些复杂性。
446

被折叠的 条评论
为什么被折叠?



