How to Deal With Technial Debt - 如何应对技术债务(总结)

AI 摘要: 技术债务是指在软件开发过程中为了快速交付产品而采取的一种权衡,如果不及时处理和还清技术债务,可能会降低开发速度、增加维护成本和风险增加。为了管理技术债务,可以采取持续集成和自动化测试、定期重构、优先级排序和文档记录等解决措施。技术债务的现象包括业务流程混乱、业务域不清晰、服务边界模糊、编码规范缺乏等,成因涉及团队和个人两个方面。解决技术债务的方法包括基础治理和建设、项目和需求实施中的债务降低以及技术专项治理。技术管理者应重视技术债务并进行合适的治理,研发人员应重视技术方案设计、遵循规范并持续学习和提升技能。

1. 技术债务了解

技术债务(Technical Debt)是指在软件开发过程中为了快速交付产品而采取的一种权衡,即在当前阶段选择使用不完美或者低质量的解决方案来满足需求,从而导致未来需要花费更多时间和资源进行修复、重构或优化。

技术债务可以比喻为一个贷款:当你选择以较高利率借入资金时,你必须承担额外的成本。类似地,在软件开发中,如果团队选择通过牺牲代码质量、设计原则或最佳实践来迅速推出功能,则会产生技术债务。这可能包括编写临时性代码、缺乏文档、遗留问题等。

技术债务有几个主要特征:

  1. 借用时间:将问题推迟到以后处理。
  2. 累积效应:随着时间推移,技术债务可能会累积并对项目产生更大影响。
  3. 利息成本:维护和修改现有代码所需的额外工作量。
  4. 隐含成本:由于延迟修复和重构带来的风险增加。

如果不及时处理和还清技术债务,它可能会导致以下问题:

  1. 降低开发速度:随着技术债务的累积,代码变得越来越复杂和脆弱,增加了新功能的开发时间。
  2. 增加维护成本:由于技术债务带来的额外工作量,维护现有系统所需的资源和时间也会增加。
  3. 风险增加:技术债务可能导致潜在的安全漏洞、性能问题或其他质量问题。

为了管理技术债务,常见解决措施:

  1. 持续集成和自动化测试:确保及时检测和修复问题。
  2. 定期重构:通过改进设计、优化代码结构等方式减少技术债务。
  3. 优先级排序:根据影响程度和紧急程度对技术债务进行分类,并按照优先级解决。
  4. 文档记录:记录已知的技术债务并跟踪其状态。

2. 技术债务现象、成因分析、解决方案

技术债务可以从日常研发过程中发现技术债务体现,分析其成因,最终给出系统解决方案,基于这三大块做系统介绍和分析总结(第一性原理)

技术债务分析

2.1. 技术债务有哪些现象?

可以从软件、团队、个人三个方面看下技术债务现象,常见有业务流程混乱,业务域不清晰,服务边界模糊,研发人员不清楚系统全貌,新人在微服务架构中,难决策应该将功能在哪个服务扩展;架构设计不合理,业量稍微大一些,系统出现各种响应慢、报错问题;服务代码难维护,新增一个功能或者修改一个 Bug 耗时 1 ~ 2 周,研发效率低,维护的人很痛。

  • 软件视角
    1. 业务流程: 业务流混乱,业务域模糊,系统或服务职责边界不清晰,维护人员难以理解和维护,不清楚功能更应该在哪个业务域、服务进行集成
    2. 系统架构:系统架构链路冗长,过度设计,缺乏分层,技术栈不统一,软件版本不兼容;架构设计缺乏扩展性,不够灵活,无法支撑业务增长,经常要推倒重来;
    3. 服务代码:代码缺乏分层和抽象,面向过程编程;服务、函数、参数命名不合理;函数职责不清、代码流程混乱;整体可读性和可维护行差,难扩展和维护
  • 团队视角
    1. 问题或故障频发:三天两头出问题,系统不稳定,产品、业务吐槽,客户投诉
    2. 研效、质量低下:功能需求开放耗时长、质量低,人力成本高,出了 Bug 拉一圈人,效率极低
  • 研发人员视角
    1. 规范标准缺乏:没有统一的研发规范和标准,基于经验口口相传,个凭本事完成需求,吐槽代码屎山
    2. 相互推诿:难啃的业务、系统不愿碰,吃力可能不讨好,还容易出现故障 Bug,不愿意维护
    3. 幸福度低:天天加班找 Bug、修 Bug,缺乏成就感

2.2. 结合软件生命周期,技术是服务于业务,思考技术债务成因?

技术债务:快速交付功能,选择折中、不完美方案,导致后续维护成本、复杂度变高 从软件视角看,技术债务可以概括为三个方面主要成因:**业务缺乏治理、架构设计不足、研发规范缺乏,**结合软件系统或服务是由团队中研发开发出来服务于业务这个点出发,再进一步从团队和个人分析债务成因:

2.2.1. 团队因素,导致技术债务形成:

  1. 业务和时间压力:老板需求、业务赶工,导致项目工期倒排,研发不得已选择折中方式或不合理方案;业务、产品缺乏业务架构流程系统梳理,业务的多样性、易变性,加上业务试错缺乏长远产品规划,研发就跟着产品或业务疲于奔命,最终留下一堆软件债务
  2. 缺乏标准和规范:研发个凭本事,借鉴或好或坏的架构、布局、编码规范,Copy 出来了一堆难维护代码
  3. 业务域缺乏治理:缺乏业务和流程的系统梳理,业务域、系统、服务边界模糊
  4. 基础设施落后,自动化低:CICD 流程不够自动化、测试环境不稳定,研发投入大量时间在环境问题处理上

2.2.2. 研发个人方面因素,导致技术债务形成:

  • 缺乏业务全局观(技术服务业务: 研发如果缺乏整体业务系统认知或业务洞察不够深入,仅关注到了自己的局部产品需求,没有关注业务上下游,导致业务流程拆分、架构设计不合理,以至于架构扩展性差,很快被推倒、迭代从来
  • 知识局限性(开放、合适),无法选择最合适的架构: 缺乏领域知识,没有调研、方案对比,基于经验主义,导致架构无法很好应对变化,不够灵活;亦或是过度设计,导致系统维护成本高,难维护;
  • 过度设计:技术崇拜、追求完美,晋升诉求,新系统设计过度复杂
  • 利己&将就心态(又不是不能用):嫌麻烦、对个人收益低,绩效不明显、不处理,缺乏重构演进动力,重构不容易获得成绩,一次次的纵容,最终堆积成了代码屎山

2.3. 如何应对技术债务

2.3.1. 技术管理者

重视技术债务,结合业务\产品特征,对齐目标,做好业务域划分,核心项目方案 CR,适当做提前设计,同时避免过度设计,识别流程、架构、服务、代码的坏味道,控制好技术需求和业务需求的资源分配,避免因技术问题导致业务迭代慢、支撑差的结果

  1. 基础治理和建设,人员培训、氛围营造,防范债务形成:
    • 业务域治理(邀请产品、业务负责人、模块负责人对业务开展讲解培训,帮助研发熟悉)
    • 编码规范制定&宣导(保持团队编码风格统一),结合 CICD 做代码自动化审查,降维护成本
    • 基础实施完善,增强 CICD 自动化和智能化能力
    • 增强员工培训,重视技术债务,学习软件架构设计、编码规范、CR 等技能
    • 技术氛围营造:重视软件质量、研效,对技术债务解决关注,考核倾斜
  2. 项目和需求实施中,降低债务形成:
    • 核心项目技术方案、架构设计 Review,确保大的方向没有偏差
    • 项目实施过程中,定期代码规范、设计组织审查,确保符合最初方案设想,遵循团队编码规范
  3. 出现技术债务,捎带或专项治理:
    • 功能迭代捎带消除:针对小型技术债务,可以在结合产品需求,做小批量,逐步优化消除技术债务
    • 技术专项治理:针对历史债务,系统化的治理,彻底根治

2.3.2. 研发人员

重视技术方案设计,遵循规范,定期总结复盘,持续提升和学习新的技能

  1. 重视技术方案设计
    1. 业务调研和分析:牢记技术是解决业务问题,否则只是在自 High,注意识别伪需求
    2. 不要过度设计:控制住技术成本边界、避免过度设计给软件带来的复杂度增加
    3. 不要将就设计:针对业务和时间倒排压力,尽最大努力选取适合后续演进的方案
    4. 创新和合适的权衡:既要保持对业务新技术敏感,也要结合团队和自身技术实际情况,遵循简单、合适、演化原则,保有 1 ~ 2 年前瞻性
  2. 遵循团队研发标准
    1. 遵循编码规范:不限于业务域、新起服务、命名、服务代码分层、抽象等考虑,提升系统可维护性
    2. 功能扩展性设计:遵循简单原则,适当采用设计模式,提升系统扩展性
    3. 识别坏代码味道:
  3. 总结复盘
    1. 文档沉淀&经验总结:对系统设计文档更新完善,对项目进行总结复盘,吸取经验,同类型问题在后续研发过程中想办法规避
  4. 持续学习和技能更新
    1. 业务和产品知识梳理&学习
      1. 关注行业信息、竟品分析、产品体验、业务流程梳理
      2. 业务和产品知识学习
    2. 架构设计知识系统学习
      1. 设计原则、理论:简单、合适、演化原则,CAP 理论、康威定律、KISS、SOLID、DRY、KISS
      2. 关注非功能设计:可用性、性能、扩展性、一致性、规模、成本、安全
      3. 架构模式:单体、分布式架构、微服务架构、中台化架构、事件驱动架构、微内核架构
      4. 方法论:DDD、业务分治、架构分层、单体模块化、组件化、公共库、小批量提交
      5. 微服务涵盖内容
        1. 业务域划分和治理
        2. 微服务框架、框架脚手架
        3. 服务注册发现、服务路由、服务容错、服务通信(RPC)、服务监控(全链路)、服务网关
        4. 容器化平台、研发测试生产环境搭建、基础设施 CICD 平台建设;
        5. 微服务治理、研效提升(研发标准、组件、公共库、代码分层、CR)
      6. 微服务杂项:CAP 存在,导致可用性、一致性权衡,分布式事务一致性;分布式共识算法;分布式 ID 生成;分布式一致性 Hash;
      7. 编码开发:设计模式、代码分层、命名、抽象、错误、日志、RPC、公共库,CR、识别坏代码味道、好代码标准、适当采用设计原则、设计模式
      8. 工程问题:CICD 研效平台、容器化部署平台
      9. 搭建测试套件(UT、环境) : 降低试错、调试成本,提升信心

3. 总结

拿软件系统和人体相比,技术债务很像身体疾病:在防护期,我们可以锻炼健身、健康作息、带口罩等手段,针对疾病提前做好预防工作,防止感染疾病;在疾病感染期积极采取治疗,遵循医嘱,按时喝药,也可以遏制疾病蔓延和治疗好疾病;如果拖到晚期,很可能错过最佳治疗时期,则可能需要手术治疗

  • 作为技术管理者,更多是从团队角度出发,重视和积极管理技术债务,在防护期持续做好业务域系统梳理、研发标准规范拟定、团队培训、基础设施建设,在项目施工期,做好架构设计把控、架构实施、研发规范 CR,出现了技术债务结合业务需求或拉出专项积极治理,有效提升研发效率、质量,以及团队研发幸福感,降低研发成本,以更好的支撑业务发展;

  • 作为研发人员,应该重视技术方案设计、积极丰富产品和业务知识、重视研发编码规范,同时不断持续和更新专业技能,以提升研发效率、质量,增加系统架构设计的可维护性和扩展性。

最后以《扁鹊见蔡桓公》结尾,感觉很契合面对技术债务的态度

扁鹊见蔡桓公,立有间,扁鹊曰:“君有疾在腠理,不治将恐深。”桓侯曰:“寡人无疾。”扁鹊出,桓侯曰:“医之好治不病以为功!”

居十日,扁鹊复见,曰:“君之病在肌肤,不治将益深。”桓侯不应。扁鹊出,桓侯又不悦。

居十日,扁鹊复见,曰:“君之病在肠胃,不治将益深。”桓侯又不应。扁鹊出,桓侯又不悦。

居十日,扁鹊望桓侯而还走。桓侯故使人问之,扁鹊曰:“疾在腠理,汤熨之所及也;在肌肤,针石之所及也;在肠胃,火齐之所及也;在骨髓,司命之所属,无奈何也。今在骨髓,臣是以无请也。”

居五日,桓侯体痛,使人索扁鹊,已逃秦矣。桓侯遂死。