如何阻止软件退化?

从软件退化说起

软件开发行业,尤其是互联网相关行业中,软件工程的首要职责是对于利益点、风口业务的支持与落地。而这两者都是有着与时间相关的属性的。也就是说,同样的一件事,如果没有在正确的时间内做到,那可能也就没有意义了。所以软件行业是一个争分夺秒的行业。

那么当真的风口到来时,软件工程的开发是否能快速跟上目标呢?希望总是好的,但是现实是很骨感的。当新的目标出现的时候,你会发现总有那么多的额外逻辑拖慢了脚步。

项目工程什么时候是最优秀的时候呢?如果你是一个认真负责的开发人员的话,那么这个答案理应是当这个软件最开始设计出来的时候。这时候的软件是完美的符合功能预期甚至还能满足开发人员对其未来扩展的幻想(很有可能不能成真)。而更现实的是,在进行之后的功能迭代的时候,常常会和原有设计冲突,那么在这种情况下完成需求后,软件的整体质量往往是会下降的。而在周而复始的循环里,团队会花费大量成本进行对业务的维护,最终会在一次迭代中发现,这个软件如果不重构就再也维护不下去了。

举一个订单支付的场景,第一次的需求可能是这样的:

查询人员
计算付款信息
返回支付用路由信息

而在第二次的版本迭代时我们需要加入对于不同折扣方式的处理,可能就变成了:

查询人员
计算付款信息
    if 优惠卷
    elsif 限时活动
    else 原价
返回支付宝用路由信息

然后第三次变更的时候可能对用户人员以及支付方式加入判断:

查询人员
    if 会员
    elsif 年费会员
    else 新客
计算付款信息
    if 优惠卷
    elsif 限时活动
    else 原价
查询支付用路由信息
    if 支付宝
    elsif 微信
    else 银行卡

尽管是为代码,但可以看到代码量已经比原有的逻辑多了很多。当然这肯定还没有结束,比如各种其他的消费活动:预售、秒杀、拼团、返券等等。随着业务逻辑增加,代码不可避免地会膨胀,变得更加难以维护。

从软件的本质说起

随着业务迭代,代码的质量降低了,但是这是为什么呢。这就不得不从软件的本质来说起。

软件的本质是在代码中模拟客观世界的交互。

所以软件逻辑是否正确,就可以通过其交互是否与客观世界一致来判断。

以第一节为例子我们就不难理解,假如你在餐厅点餐,无论你是用的小程序app来操作,还是服务员直接为你点餐,遵循的都是上面的伪代码流程。所以抛开代码规范不谈,上述支付逻辑与客观世界一致的

如果在第一次进行系统开发的时候就已经知道了最终的这个客观逻辑的存在,那么在进行系统设计的时候就不会那么被动了。因为尽管需求方、客户可能没有发现这些客观规律,但是如果识别出来了对应的在客观世界中的逻辑,那么我们就可以提前为可能存在的业务逻辑进行设计。对于上一节中的支付场景来说的话,就是在一开始就识别出会员、折扣、支付路由这三个可能的扩展点。

那我们是不是直接按照客观世界来开发?

必然是否定的,因为他太复杂的。 因为太复杂所以无法直接输出。

所以我们软件开发实际上是在对客观世界进行抽象。提取出来简单、清晰、易于理解的逻辑。就如同第一版本的支付流程。但是随着系统的上线,更多地看起来不那么直观的需求暴露了出来,他们没有没有那么明确,但是却补充了客观世界的逻辑,满足了用户的诉求,这些功能逻辑会让软件变得更加负责,但是却会让用户感觉软件更加好用。

如果用是否接近客观世界来判断软件是好用还是不好用的话,那么软件的演进方向就可以认为是:“难用、清晰”到“好用、复杂”的转变。

image-20220205004527928.png

从简单到复杂

复杂的软件也可以有很优秀的设计。各种大型项目本身也是有先例的。但是为了支撑起复杂的业务,必然的需要使用各种设计模式以及架构原则对系统进行抽象提取。但反过来说对一个 add()方法中的a+b直接进行抽取,把符号运算与加数和被加数都进行抽象(实际上正交设计正是如此),不是说这种设计方式不可以,但是如果对于当前可预知的内容外做太多额外的逻辑设计的话,不免有过度设计之嫌。

过度设计的问题在于:通过经验或者参考过往方案进行的提前设计,如果预期未能兑现,则会造成额外的成本损失。

所以,在第一小节中第一次的支付需求设计的流程并无问题。简单的问题应该简单设计,复杂的问题再进行复杂抽象。设计本身没有问题,那么问题来自后续的迭代。

先说一个显而易见的结论:我们应该随着程序业务逻辑变得复杂时逐步地调整程序结构,让其从简单程序结果变成复杂程序结构。

但实际上这个并不这么容易实现,就如同一开始的支付逻辑一样。因为在实际业务中没有一个明确的边界告诉你:你的软件已经足够复杂了,需要调整程序结构了。那么在各种工期时间的安排下,人们自然而然地就更倾向于在原有简单结构的代码基础上进行业务逻辑调整。而这样最后的后果就是:当发现程序已经足够复杂的时候却发现为时已晚。

这个时候我们就可以发现,软件退化的根源并不是开头说的:需求变更。需求变更只是表象的诱因,而根据上文我们也可以发现,软件退化的根源是:

在业务逻辑变得复杂的同时,没有根据业务重新调整程序结构。

所以,解决软件退化也就呼之欲出:

要保持软件设计质量不退化,必须要在每次需求变更的时候,根据变更点调整原有程序的设计结构。

如何调整

实际上,如果对于一段业务逻辑的设计,我们有各种不同的设计原则、策略模式可以参考。如果让你单独的新设计一个需要支持5、6中优惠的业务逻辑的话,我们可以直接套用策略模式来对业务进行封装。这样就可以让这部分的业务块满足开发-封闭原则(OCP)即:可以扩展新的优惠模式,同时又可以保证每次调整业务代码只涉及其中的一个类文件。

新的逻辑我们容易想得明白,但是如果对于已有逻辑的改造又该如何来呢。直接在原有逻辑上修改,就又无法满足OCP原则了,难道OCP原则在这种情况不适用吗?

按咱们习惯地先给出结论:

对于程序结构改造的业务逻辑,应该分为两步走:

  • 在不添加新业务逻辑的基础上,对原来程序结构进行调整,以便支持新业务的扩展性

  • 实现新功能

这样我们就可以发现,在第一步的调整时候,由于是原有业务,所以并不涉及新功能的扩展,可以单纯地调整程序结构。而当进行第二步的时候,只需要在扩展的基础上实现单独的业务就可以了,那么就满足OCP原则。

由于进行了两步走,第一步的时候实际上是与原有逻辑一致的。此时可以复用原来业务中的所有测试用例,以及单元测试,用很低的成本就可以保证代码的正确性。

而这样就也可以避免在早期开发的时候为了预留扩展功能,对系统添加了所以的各种功能支持而带来的过度设计。两步走的方案可以让我们在早期时候不必关心与后续的扩展性,只用“刚好”地完成业务就可以了,而让新的需求出现的时候,才是我们根据已有业务进行代码结构调整的时候。

最后

软件不退化的关键是保证每次需求变更的时候,做出正确的设计,才能保证软件以一种良性循环的方式不断维护下去。尽管原则如此,在实际执行的过程中也是十分困难,而难点正是保持良好的设计。就如同前文说的,每一次需求变更都意味着引入了更加复杂的客观世界逻辑,那么如何对这些越来越复杂的客观世界逻辑进行设计,也是我们的重要课题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容