现有的项目里,一次功能变更可能带来了大量的缺陷。于是乎,我试着回溯项目的开发过程,寻找出导致问题的根因。现阶段,我只能想到时的只有实施技术战略性投资,也暂时也想不到更好的方法,以在开发初期解决问题。
我现在所在的项目是一个优化相关的项目,包含性能优化、架构优化等。这是一个差不多一年左右的技术型的软件项目。项目中存在着各种各样的技术挑战:文档的匮乏、缺乏经验丰富的开发者、缺乏领域专家、相关领域的专家无法提供技术支持……。总之,一系列的技术难点使得项目开发越来越困难。
尽管项目并非从无到有,但是仍旧相当多的开发工作需要大量预研。然而,由于 Deadline 的设定使得需求一个接一个的出现,而大量的开发工作又依赖于花时间的预研。因此,这个时候我们就会陷入了一个困境:
大量的功能架构在『临时性方案』之上,原有的临时方案进一步成为新的『临时性方案』的起点。因而,随着功能的进一步堆砌,即使修改少量的代码也会带来大量的问题。
我尝试把这个问题归究于上吊绳驱动开发(Deadline driven design),但是在仔细研究之后,我觉得这个归纳太广泛了。思来想去,我觉得用临时方案传染性会更为贴切一些。
临时方案传染性
我尝试去定义出临时方案传染性:
临时方案传染性是指软件开发过程中,因旧有临时方案的存在,导致新需求的设计方案无法实施,而只能再次选择设计出新的临时方案。也因此,新的方案也只能建立在旧有的临时方案之上,系统随着临时方案的蔓延进一步腐化,即所谓的传染性。
临时方案是在软件开发过程中很常见的一种模式,也并非所有的临时方案都具有传染性。这种传染性主要出现在复杂业务场景之下,又或者是严重依赖于架构设计的系统内。在这两种场景之下,我们可以发现它们都是缺乏前期设计导致的,缺少业务设计、业务转换架构的设计,又或者是架构的设计。
示例
想象一下,有这么一个需求是获取系统中的某类型的文件。首先,在初始阶段,我们已经知道了要支持所有的主流操作系统:Windows、macOS、GNU/Linux 等,而且我们也知道路径中的某一层级在未来是可变的。(PS:这是的文件操作只是代替真实案例)
但是呢,在第一个阶段,我们只需要支持 Windows 操作系统。由于文件是固定放在某个目录之下,所以我们只需要写死路径即可,如 。接着,我们的下一个需求发生了变化,其中的一个路径会根据条件发生变化,于是乎我们用正则做了个替换,它足够的简单而且快(PS:这也只是个替代案例)。
随后,在下一个版本中,我们需要支持 macOS,于是由于时间的原因,我们依旧写成了 。最后,现在我们需要支持二级目录可变更,如 。这个时候,我们已经没有一个更好的方案了。
因此,在后来的版本里,我们一步步这个基础之上进行大量的临时方案,因为原先的临时方案没有改用正式方案,导致后续有更好的方案无法实施。
原因
我尝试着从我遇到的一些案例、社区上的案例里,总结出一些原因:
技术第二。嗯,就是技术就是成本的那些公司的观点,不愿意去重视架构。
需求不确定性。大部分项目常见的问题,缺少经验丰富的业务分析员、项目经理。
时间难以估算。常见问题
缺少经验丰富的开发者。这个相对比较难解决,不过还可以找专家咨询。
关键架构设计不确定性太多。即架构中需要分析评估的内容较多,一个评估方向出错会影响进度。
资深工程师占比太少。一个想稳定发展的项目应该至少应该保持在 1:1 的水平。
缺少必要的工具。
风险过多。
总结之下,无非就是三点:
缺乏架构师、资深工程师。也就是缺乏相关领域的经验
项目本身过于复杂。
Deadline 驱动。上线时间影响了我们的技术决策
修正缺陷成本
而这些相关问题的讨论,已经是一个相当成熟的领域:
相关的学术讨论会的讨论结果表明,在大型项目的早期需求阶段进行的投稿,以及对设计的确认和验证可以把『成本-修改』的增长曲线从 100:1 降到 20:1。——《软件之道 :软件开发争议问题剖析》
也就是说,如果我们在前期进行技术调研的话,那么我们可以将项目的缺陷率减少到 1/5。
经典应对方案
从我们了解的情况来看,事实上,团队上的大部分人都知道怎么解决问题。长期的项目经验下来,他/她们也都成了经验丰富的开发者。只是呢,没有时间。
而对于少部分团队来说,因为业务上的成功,使得团队有了更多的时间和精力(主要是钱)来解决这一类问题。也因此,解决问题就变得越加容易了。
对于业务成功的团队,它们选择了更好的方案:重写,又或者是采用新的架构(重写的一种方言),比如微服务或者 DDD 方式。
临时应对方案
为了解决临时方案带来的问题,我们当时也需要产生一些临时的应对方案。
端到端测试
在某些场景之下,可以通过端到端测试以来覆盖原有的场景,进而避免原有的功能被破坏。它只是用来建立重构的防护网,以确保修改带来的缺陷不会大量出现。
更多的相关内容可以见:《系统重构与迁移指南》 ( https://migration.ink/ )
渐进式重构/修正
主要也是采用缓慢的方式,慢慢来确保架构能行驶在正确的路上。
嗯,同上,可以参考《系统重构与迁移指南》。
其它
架构设计的程度与腐化速度是成反比的。(当然,避免过度设计)
没有银弹。
领取专属 10元无门槛券
私享最新 技术干货