阅读 630

降低软件复杂度

本文原创:yangyanchun

在进行软件开发时,我们常常会追求软件的高可维护性,高可维护性意味着当有新需求来时,系统易扩展;当出现bug时,开发人员易定位。而当我们说一个系统的可维护性太差时,往往指的是该系统太过复杂,导致给系统增加新功能时容易出现bug,而出现bug之后又难以定位。

什么是复杂度

修改扩散

修改时有连锁反应,相互依赖,耦合度高,某部分代码不能被独立地修改和理解,必定会牵涉到其他代码。

认知负担

开发人员需要多长时间来理解功能模块,从代码中难以找到重要信息

不可知

开发人员在接到任务时,不知从哪里入手,数据流向混乱。

复杂性的危害在于,它会递增。你做错了一个决定,导致后面的代码都基于前面的错误实现,整个软件变得越来越复杂。"我们先把产品做出来,后面再改进",这根本做不到。

如何降低复杂性

重视设计和细节的改进

拒绝战术编程,采用战略编程

战术编程致力于完成任务,新增加特性或者修改Bug时,能解决问题就好。这种工作方式,会逐渐增加系统的复杂性。如果系统复杂到难以维护时,再去重构会花费大量的时间,很可能会影响新功能的迭代。

战略编程,是指重视设计并愿意投入时间,短时间内可能会降低工作效率,但是长期看,会增加系统的可维护性和迭代效率。

code.jpg

设计两次

为什么该方案可行?

架构图、接口设计、时间人力估算

在已有资源限制下,为什么该方案是最优的?

在关键点或争议处提供二到三种方案,并给出建议方案

水平分层,垂直分模块

层次和抽象

复杂性下沉,尽量让用户使用简单,接口要简单,实现可以复杂。

深模块:功能强大,接口简单,是抽象的最佳实践,通过排除模块内部不重要的信息,让用户更容易理解和使用。

浅模块:功能简单,接口复杂,无助于解决复杂性。因为他们提供的收益(功能)被学习和使用成本抵消了。

class.jpg
好的 class 应该是"小接口,大功能",糟糕的 class 是"大接口,小功能"。好的设计是,大量的功能隐藏在简单接口之下,对用户不可见,用户感觉不到这是一个复杂的 class。

异常处理

尽可能减少需要处理异常的可能性

用户必须面对所有的 error异常"反正我告诉你出错了,怎么解决是你的事。",正确的做法是,除了那些必须告诉用户的错误,其他错误尽量在软件内部处理掉,不要抛出。

通用和专用

满足当前功能,快速实现,接口设计通用化

满足当前需求最简单的接口是什么?在不减少功能的前提下,减少方法的数量,意味着接口的通用性提升了。

接口的使用场景有多少?如果接口只有一个特定的场景,可以将多个这样的接口合并成通用接口。

满足当前需求情况下,接口的易用性?如果接口很难使用,意味着我们可能过度设计了,需要拆分。

注释文档

比如“好代码是自注释的”、”没有时间“、“现有的注释都没有用,为什么还要浪费时间”等等。这些观点是站不住脚的。“好代码是自注释的”只在某些场景下是合理的,比如为变量和方法选择合适的名称,可以不用单独注释。但是更多的情况,代码很难体现开发人员的设计思路。好的注释可以减少文档工作。

使用注释提升系统可维护性, 重视what、why,而不是how(而不是代码是如何实现的)

文章分类
前端
文章标签