2016年/03月/28日

首页回退

一些原则

这是一篇国内某博主的文章,写得非常好,算是一个总结,汇集很多书籍或者个人文章的思想精华

原文

软件也像人一样,具有生命力,从出生到死亡,会经历多种变化。软件架构设计也不是一蹴而就的,是不断地演进发展。但为了能较好的发展,在软件设计时需要考虑一些原则。

清晰原则:使用简洁接口,简单部件组合

编程的本质就是要控制复杂度,后期维护会占用大部分的时间。 降低整体复杂度,用清晰的接口把若干简单模块组合成一个复杂的系统。 对外隐藏细节,“不要与陌生人说话”。 多数问题局限天一个局部,不要影响到全局。

小结:本质是分而治之,复杂问题简单化,抽象框架,有序组全。

清晰原则:清晰胜于机巧

代码直白易懂,代码是给人看的,不是给机器看的。 维护代码的人,其中也你包括你自己,善待代码,就是善待自己。 不要了一点性能提升而引入复杂的算法,不要为了炫耀技能而编写晦涩难懂的代码。 复杂晦涩的代码是Bugs的温床,高昂的维护成本将抵消可怜的性能提升。

小结:代码简洁晚懂,谨慎引入复杂度。

简洁原则:设计简洁,降低复杂

复杂问题简单化是一个设计者的能力体现,避免不必要的使用问题复杂化的因素。 在市场导向下,在不良的架构上很容易堆砌花哨无用的新特性,导致软件趋于复杂。 在进度压力下,不会做出各种折中的个性与不和谐的新特性开发。

小结:过滤排序需求,追求稳定简洁。

组合原则:组合,接拼,编排

把复杂问题分解为一条程序处理链条。 程序之间可以通信,前者的输出是后者输入。 通信方式尽量采用简单协议,并且与语言无关。 组合程序之间无内部状态依赖,互相独立,处理链上下游不做假设,可替换。

小结:面向微服务的设计。

透明原则:设计与实现分离可见

设计简单,包括流程、数据结构、接口,在代码级别容易理解。 支行时刻可通过输出信息或者接口查询运行状态,可控制程序是否正确运行。 执行调试链、健康状态可跟踪、可分析。

小结:简单设计,简明实现,状态监控。

吝啬原则:除非别无它法,不要编写庞大的程序

程序庞大包括两个方面:程序体积大与程序复杂而维护困难。 模块和函数尺寸都有一个上限,比如单模板代码10K,单函数100L。 导致程序庞大的因素:先天设计不良,后天维护增加新特性。

小结:合理设计,考虑扩展性,对庞大保护警惕。

吝啬原则:有的放矢,按需分配资源

若可能,当一个事情发生时候再分配资源,而不是预先分配,初始化时静态分配最小资源,随着业务动态增加资源分配。 异步消息环境下,消息通信带来上下文切换,代价高昂。 必要时对消息数据合并,打包发送,减少对网络资源的消耗。 业务处理与消息发送分离,数据组织独立,统一打包发送。 控制并发实例的数据,分批处理,防止下游过载各实例之间的恶性竞争通信资源。

小结:按需分配资源,珍惜消息通信机会。控制并发,避免消息突发。

健壮原则:健壮源于透明与简洁

软件在超过设计者设想的意外场景下也能够运行良好。 Bugs是一种异常,复杂性和特殊处理都是Bugs的温床。 逻辑透明,接口简单有助于减少Bugs,即使出现Bugs也容易排除。 软件设计时要考虑异常输入,边界条件,和过载场景。 软件模块之间要处理流程上考虑能务匹配,流控,过载保护。

小结:简单透明,处理能力匹配;考虑异常场景,提升健壮性;匹配上下游处理能力,闭环控制为主,开环控制为辅。

表示原则:把知识叠入数据,简化统一处理逻辑

数据抽象建模,使用数据之间的关联关系来体现业务逻辑,或者领域知识,使得业务处理逻辑代码简单一致稳定。 可通过修改数据模型可以支持新业务,逻辑处理代码不用修改。

小结:领域模型驱动设计,数据数据提练来描述业务本质。

缄默原则:只输出有用的信息

保持沉默,良好的行为是默默地工作,决不唠唠叨叨,碍手碍脚,程序也是如此。 输出大量无用的信息会耗费资源,淹没重要信息,干扰维护人员定位问题。

小结:沉默是金,惜时亦如金。输出的信息是必要的,有用的,不重复的。

补救原则:异常时候,干净退出,输出详细信息

当程序出现异常时,输出必要信息,使用简单方法结束。 宽容地接受,严格地发送,提升程序的容错能力。 程序要么正确执行,要么响亮倒塌。

小结:看待这个问题一分为二,选择异常恢复方法要保证对用户的业务逻辑影响最小为基本原则。因此并不是说所有的异常都是进程退出重启,有时可以告警,事件通知,让管理员来处理,给出明确的修复方案说明。

经济原则:宁花机器一分钟,不花程序员一秒

对于一个问题,选择算法的时候宁愿选择一个简单,但可能是效率低一些的算法,也不要选择一个性能好但复杂度很高的算法。 硬件的进步来弥补性能的下降,换来的是程序简单可靠,维护成本低。

小结:辩证地看问题,选择简单,把复杂留给机器,解放程序员。

生成原则:避免手工Hack,让程序去生成代码

人最不适合干大量重复细致的工作,或多或少都会出错,因此导致Bugs。 与此相反,计算机最适合干规则明确,重复枯燥的工作,而且不会出错。 对于一个规则明确的工作,一种可行的办法就是编写一个我程序,根据输入规则生成代码,让生成的代码去解决问题。

小结:分析规则,能按照规则生成代码,可检查发现问题。

优化原则:雕琢前先有原型,跑之前先学会走

90%的功能能够实现,比100%功能永远不能实现要好得多。 先求可行,再求正确,最后求快。 原型可能有效地解决关键技术,保证系统是可以实现的。 让客户看到可以执行的原型,对需求的理解更为准确,防止做无用功。 过早优化是万恶之源,过早地优化会破坏程序结构,代码与数据结构杂乱无章;过早优化不清晰系统瓶颈,局部优化破坏整体优化。

小结:性能是设计出来,不是优化来出来。

多样原则:拒绝封闭和唯一

系统开放,只有开放,才能进步,才能得到最为广泛的验证。 开放,可扩展,用户可定制,符合实际需求和获到高可靠性。

小结:系统开发,留给用户定制空间,毕竟需求具体多样性,我们不能穷尽,最终只有用户才能准确理解自己的需求。

同源原则:避免重复,数据同源

重复的代码不仅仅是浪费,也是Bugs的滋生之地。 出现大段代码重复,说明开发者缺少对代码控制与抽象提炼能务,优秀的工程轻易不会在进度压力下让步。 数据重复危害更大,一则浪费存储空间,二则容易出现不一致。 在性能允许的情况下,尽量共享数据或者按需订阅,避免全量订阅。 如果上述条件不具备,那么采用数据同源技术和一致性校验来保证数据的一致性。

小结:拒绝重复,必须重复的时候考虑通过工具同源和一致性校验。

扩展原则:设计时着眼未来,未来总比想象来得快

对于一个一次性的程序来讲,架构和设计只会带来成本上升,复杂度提高,与性能的下降。 当开发一个支持多种产品的软件平台,其生命周期可能是十年以上。用户的需求是不断地变化,硬件环境也是不断地变化。 只有适应变化,不能拒绝变化,可扩展性是软件非功能属性中,在大部分情况下排在可靠性,高性能之前

小结:不对外界进行假设,这些假设在时间面前都是脆弱的。

扩展原则:给雪球寻找一个核心

雪球都有一个内核,尽管可能是一粒不起眼的小石头。 常说软件要内聚,内聚需要核心。 微内核,插件化机制。框架即核心,框架之上定制好插件,构建系统。 从问题知识域发现稳定部分进行抽象提升,成为系统的框架。

小结:从框架的角度来看系统,框架之间的有机组合构建系统,系统的演化就是在框架稳定情况下增加替换相关的插件。

扩展原则:扩展就是少修改

软件可扩展性是有前提和应用场景的,不存在可以随意扩展的软件。 增加新功能做到不修改既有软件,代码无需修改,通过修改数据模型或者重新配置获得新特性。 修改集中在新增加的软件之上,也就是说在增加新特性时,对老代码封闭,对新代码新特性开放。

小结:系统开闭原则,修改对系统稳定不构成影响。