Skip to content

前端团队年度总结

x

全景回顾

2021-2022 RoadMap

x

问题域

业务视角

  • 产品规模

x

  • 团队规模

x

  • 我们似乎正在用与产品规模不匹配的人数,做着可复制的产品。但每一次复制,又稍微有那么一点不同。
  • 以后还会有 7到15号项目,我们真的需要用人海战术去堆出这些产品么?
  • 经济学里有个词叫“复利”。爱因斯坦说:复利是这个世界的第八大奇迹。维护代码逻辑的可复用性,就是技术的复利效益。
  • 因此,为了让技术产生复利,来看看我们面临的哪些技术问题?
  • 矛盾点:产品业务发展太快,人力资源不匹配;

技术视角

  • Mindera 遗留系统问题

    • 遗留系统是一把双刃剑

      • 遗留系统既是我们的重要资产和宝贵财富,是我们谈判桌上的筹码;
      • 但同时,从技术架构设计层面,由于业务发展太快,旧的架构已经很难承载新的业务需求,成了一个亟待解决问题。
    • 症状

      • 图示

      x

      • 阶段 1:正常,都是线性增长。
      • 阶段 2:需求数正常增长,业务代码行数开始增长,测试代码行数大幅度增长。
      • 阶段 3:业务代码行数开始大幅增长,测试代码行数剧增(超出屏幕),而需求数开始下降。
      • 后果

        • 从业务最开始,到长期迭代后,复杂度提升带来的问题。做一个相同的需求,最开始可能 1 天就可以搞定,但长期迭代后,可能要 3 天,甚至更多,
        • 这并不是开发人员主观上导致的,而是代码状态的维护成本太高,做到最后经常会出现牵一发而动全身。
        • 关键是:抑制了业务的迭代速度。
    • 分析原因

      • 坏味道

      x

      • 层次定义模糊;边界不明确;牵一发而动全身,散弹式修改。
      • 反模式,反设计原则:导致系统无法茁壮成长。
    • 面对的挑战:如何平滑过渡?

      • 如何解决遗留系统问题,既能老的功能模块提供原有的业务能力,继续发挥作用?同时不影响新系统随着更复杂的业务升级迭代?
  • Alpha 平台架构问题

    • 最初的架构

      • 业务逻辑简单

        • 功能与用户耦合性高;角色概念不明显
        • 从只有买卖双方单一租户,到真正多租户实现
        • 要么为每个租户提供一个代码仓库? 要么在代码中大量的if-else?
        • 为了更好的复用代码,不得不为所有租户提供全量的代码?影响性能,且与客户需求不符合。
      • 单体结构

        • 代码量大,局部的故障很容易影响到整体软件;
        • 多人开发,每次合并代码,需要解决大量冲突;
        • 部署周期长:多人开发,统一发布;无法持续交付,影响迭代速度。
        • 技术栈单一/技术框架版本,无法发挥技术多样性带来的优势;
        • 技术框架版本升级风险大,无法利用新技术理念带来的红利。
    • 面临的考验:敏捷应对业务变化的同时,且保持架构稳定?

      • 随着业务范围扩大,业务逻辑变得复杂,原来结构简单的结构再也无法承担更复杂且多变的业务需求?
      • 什么样的技术架构,才能应对快速交付项目需求,且保持稳定?

解决域

乔布斯:如果上层做对了,底端的一切都会随之而来。

重构代码

  • 锁:重构代码 -> 钥匙:clean code
  • Why Clean Code

    • Later equals never:你永远不会回头清理你的shit

    x

    • 混乱代码的代价

      • 生产力下降,成本提升
      • 与华丽的新设计说再见
      • 制造混乱,延误排期
  • Principles: How Clean Code

    • 易读的代码:读/写代码耗时比超过 10:1
    • 童子军军规:让营地离开时比来时更干净
    • 代码感:Design Thinking
    • x 类比:OKR 与 KPI

      • KPI:一个多少复杂度的需求多少人天完成
      • OKR:管理复杂性,提高复用性,保持生产力
      • 正确的做事 vs 做难而正确的事
  • When: 去熵减/去嘉实需求时

    • 去熵简/去嘉实意味着你对代码的修改遍布软件的每个角落,而测试需要全面的回归;
    • 在一个恰当的时机,即在「去熵简」的同时,用最小的人力代价,为系统进行了「熵减」。

重构架构

  • 锁:重构架构 -> 钥匙:DDD
  • 第一步:分而治之:前端微服务

    • “微服务是具备有限上下文、松散耦合、面向服务的架构。”

    x

    • 小船好掉头;泰坦尼克号撞冰山
    • 小步快跑:增量升级,独立构建、部署、交付。
    • 特别适用于复杂业务场景,并且提升交付速度。
    • 但仅仅如此,并不能从根本上解决系统或软件退化的问题?

      • 软件退化的根源

        • 现象

          • 软件设计质量最高的时候是第一次设计的那个版本 当第一个版本设计上线以后就开始各种需求变更 这常常又会打乱原有的设计。
          • 每次需求变更 -> 软件修改->质量下降
        • 根源

          • 软件的 本质 就是对真实世界的模拟。
          • 软件中业务逻辑正确与否的唯一判断标准,就是是否与真实世界一致。

            • 如果一致,则软件okay;
            • 如果不一致,则会提bug,提新需求。
          • 软件要做成什么样 既不由我们来决定,也不由用户来决定 而是由客观世界决定

            • 与其按照客户要求被动做软件,不如主动深入理解业务,分析软件。
          • 按照真实世界开发软件,不就简单了吗?

            • 软件的业务逻辑会越来越接近真实世界 品 ,使得我们的软件越来越专业; 同时业务逻辑就会变得越来越复杂软件规模也越来越庞大。
            • 最初只能认识真实世界中那些简单、清晰、易于理解的业务逻辑把它们做到我们的软件里; 还有很多不简单、不明了、不易于理解的业务逻辑没做到软件里。
            • 简单 -> 复杂
          • 保证软件设计质量不退化

            • 逐步调整软件的程序结构,由简单程序结构转变为复杂程序结构。
            • 但软件通常发展规律是:在原有简单结构中塞代码。导致,简单结构,承载复杂业务逻辑内容。 => 软件退化。
            • “开放-封闭“原则

              • 对于功能扩展是开放的( Open for Extension ); 开放原则 即当系统需求发生变更时,可以对软件功能进行扩展,使其満足用户新的需求
              • 对软件代码的修改是封闭的( Close for Modification ); 封闭原则 即在修改软件的同时,不要影响到系统原有的功能所以应当在不修改原有代码的基础上实现新的功能
            • 不要过度设计

              • 每一种 “灵活设计”,只能应对一种需求变更 不能真正解决未来变化问题的设计,称为“过度设计”
              • 期望的变更未发生,增加系统复杂度,成为摆设;未期的变更发生了,原有程序结构不能满足现在需求,重新设计。
              • 为当前需求进行设计,使其刚刚满足当前需求;使设计最简化,代码最少。(最小公倍数)
            • 关键:毎次需求变更的设计,只有保证毎次需求变更时做出正确的设计,オ能保证软件以一种良性循环的方式不断维护下去。

      • 领域驱动设计的思想

        • 「将对软件的分析和设计还原到真实世界中。」
  • 第二步:领域驱动设计之领域模型

    • 充血模型

      • 充血模型更完备,更优雅,更加接近真实世界;但需要很强的代码设计能力,和更多的基础设施;

      x

    • 贫血模型

      • 贫血模型更简单,易于实现;但会产生大量无意义代码,会让软件退化加剧;

      x

    • 结合业务需求和基础设施的现状,选择贫血模型,让代码层次清晰; 但保留对充血模型的演进可能。

  • 第三步:领域驱动设计之限界上下文

    • 最小完备

      • 自治单元履行的职责是完整的,同时避免添加不必要的职责
    • 独立进化

      • 减少限界上下文变化对外界的影响
    • 自我履行

      • 由自治单元自身决定要做什么,对于不属于自身的行为应转交给其他上下文
    • 空间稳定

      • 减少外界变化对限界上下文内部的影响

迁移遗留系统

  • 锁:遗留系统迁移 -> 钥匙:整洁架构
  • 方案:冰淇淋勺 & 搭积木

    • 三种常用方案

    x

    • 冰淇淋勺策略:是 Martin Flower 提出的一种策略,也被称为扼杀者方法。

      • 可以想象有一大桶冰淇淋,这桶冰淇淋就代表现有的架构,可以用勺子从桶中挖出你们想要的冰淇淋,这个挖出的部分就是要做拆分的服务。最终可以将大桶冰淇淋挖出一个个独立的服务,这里服务包含不同的业务逻辑。
      • 这种方式是逐渐修改原有系统,并且逐步对服务进行拆分试错然后过度到单独的资源上运行。每次拆分对系统的影响较小,但是整个系统的拆分和重构需要较长时间。
    • 乐高法策略(搭积木),把原有的系统想象成一大块乐高积木,我们只需要往上面添加小的乐高积木模块就行了,添加的小模块就是一个个微服务。

      • 这样一来就不用对老产品进行调整,新的功能通过微服务的方式实现并且集成到老的产品中。不过需要通过一种能够让微服务与老产品联系的方法,这里会使用到接口编程以及适配器模式。
    • nuclear 策略,对老旧系统推到重来,重新设计架构。需要花费大量分析和重构的时间,这个周期比较长,成本也是较高的。

  • 整洁架构

    • 架构图

    x

    • 业务实体:封装关键业务逻辑
    • 用例:完成设计目标
    • 接口适配器:将用例和业务实体的数据格式转化为外部系统数据格式

重构发布流程

  • 重构发布流程:DevOps

团队发展

康威定律:系统架构与团队组织沟通结构

  • 从小步快跑的前端微服务架构,到敏捷团队。

敏捷团队建设

  • 团队卫星模式

    • 职能团队(稳定)

      • 团队愿景:“以奋斗者为本,追求极客技术文化”,专业方向制定与指导,负责解决业务相关的专业性难题,打造学习型、极客工程师文化团队。
      • 目标:确保技术架构演进的稳定。
      • 架构维护
      • 技术调研
      • 技术决策
      • 技术影响力
    • 项目团队(敏捷)

      • 团队愿景:“以客户为中心,聚焦客户价值创造”,团队由完成业务共同目标所需要的各职能团队员工组成,秉承”目标一致、合作无间、敢于挑战”团队理念,快速响应用户需求,打造业绩型、主动型的敏捷研发团队。
      • 目标:以客户为中心,确保业务交付的敏捷。
      • 产品质量
      • 项目进度
      • 敏捷理念
  • 以人为本。团队在前,项目在后。

    • 敏捷的核心在于以人为核心的迭代开发、增量交付、需求驱动。
    • 以alpha阶段的成功为平台,继续发挥,体验到了一种步步为营的感觉。

项目管理

  • 一个关于项目生命周期的故事。

x

未来规划

从实践到方法论沉淀(3D)

  • 3D模型

x

  • Design Thinking 设计思想:以设计师的视角和系统性思考,对业务持续探索。
  • Domain Driven Design 领域驱动设计:持续设计和演进业务和技术。
  • DevOps: 更快速、流畅的交付,持续验证业务设计思路的正确性。

敏捷理念

  • alpha阶段后,把用户反馈统计的功能做好;然后能检测到用户需求的变化时,真正体验到敏捷开发的重要性。
  • 敏捷理念的核心是:反馈机制。
  • 技术不好,不要谈敏捷:传统项目管理 vs 敏捷项目管理 => 汽车 vs 摩托车

团队成长

  • 让团队里的人能够进入状态来工作而不被打断——让个体高效。
  • 发掘成员的潜力:正确的人在其适合的方向上成长——团队成长与个人成长的统一。

技术影响力

  • 对于技术保持敏感,关注前沿技术,保持公司在技术上的竞争力。
  • 周期性组织技术分享,好的主题和内容整理成博客,发布在公司内部。
  • 将实践经验与理性思考结合,归纳整理成为技术文章,发布到有影响力的技术论坛:增加公司的技术影响力,同时在与其他技术专家的互动中,公司的技术发展线路会越来越明朗。