65

项目初期的最优技术实践

 5 years ago
source link: http://www.phodal.com/blog/short-time-project-best-practise/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

所谓最优,就是从一堆不非最佳的方案中找到最好的一个,或者整合一个。

在我最近的三个项目里,项目的周期都太短了,大抵都在 3~6 个月之间。短周期的项目里,对于开发人员的能力增长并不是一件好事——我们所能沉淀的知识比较少。但因为项目周期太短,也带来了一定的挑战性,或许是关键的 “坑位” 带来的挑战。

几乎所有的长期项目都是从短期项目开始的——多数情况下,只有我们验证了 idea 是可行的,我们才会投入更多的时间、精力去演化这个项目。长期项目带来的主要挑战是:人员能力增长、架构演进以及代码实践。而短期项目的主要挑战是:技术实践与业务进度的冲突。即我们在追赶业务进度的同时,如何实施好的技术实践。

于是乎,在最近的日子里,我开始在思考:如何进行最优的技术实践。按我的理解,我将项目初期的实践分为了三个时期:

  • 技术准备期。进行一系列充分、不充分的技术工作,从搭建脚手架,到部署测试等等。
  • 业务回补期。填补第一个时期造成的业务落后问题,技术实践业务来证明技术的价值。
  • 成长优化期。持续地对项目的技术和业务进行优化,以实现开发及业务人员的诉求。

每个时期都有自己要所要面对的挑战。

技术准备期:探索技术

这是一个 技术 First,业务 Second 的阶段。

一旦开发一个新的项目,我们就得做大量的技术准备工作。哪怕是我们已经有了一个现成的脚手架,但随着时间的推移,其中的一些依赖版本就需要更新,又或许是有一些依赖在这个项目又用不上,还需要进行一系列的定制化。

对于复杂的项目,我们还需要进行一系列的技术探索方面的工具。以为将来的开发,打下深厚的基础(避免被骂)。

概念验证:原型

在我的上一个项目里,才算正式接触 PoC ( 概念验证)这个阶段。但是,我发现并不是上一个项目独有的,只是在那个项目里,PoC 的阶段比较长,达到几周的长度。而一般的项目,这个阶段可能是一周,也可能是几天,几个小时——因为之前已经有了相关的经验。

概念验证(英语:Proof of concept,简称POC)是对某些想法的一个较短而不完整的实现,以证明其可行性,示范其原理,其目的是为了验证一些概念或理论。概念验证通常被认为是一个有里程碑意义的实现的原理。[^wiki_poc]

在这个概念验证阶段里,实践的是对于一些技术理论的探索。比如我们看上了微技术、微前端等新技术,或者 GraphQL 等新框架,并且计划在这个项目中使用,那么我们就需要去验证它是否能真正的被用上?

可当我们预先设想的技术和架构不能应用时,那么我们到底是采用原有的系统架构,还是新设计一个合理的架构,还是采用 B、C 方案?这个问题就变成一种考验,在这个时候到底什么是第一优先级,技术、业绩还是业务?但是不可避免的,我们又花费了大量的时间在原型设计上。

迭代 0

完成概念验证之后,I0 就要完成项目配套的技术准备工作,如创建脚手架、搭建持续集成、进行更细粒度的技术选型等。

迭代 0,又名为 I0,看这名称就可以发现它与敏捷软件开发的关系。开始一个项目开发的时候,进入的是迭代 1 的开发,那么迭代 0 呢?我们可以将其视之为,所有迭代之前的准备工作。它在这种定义之下,在项目不复杂的情况下,PoC 阶段会被列入迭代 0 的工作中。而项目复杂的时候,PoC 则会独立于迭代 0。有意思的是,在方案和咨询公司里,如我司,是 PoC 都是在开始项目前进行一部分,而在项目进行时进行另外一部分。

在 PoC 编写的是一些粒度较粗的代码,并且为了追求效率和验证,可能有大量的 Code Smell(代码坏味道),诸如注释的代码、未使用的代码、不经测试的代码等等。因此我们需要在迭代 0 ,对架构进行更细粒度的整理和优化。同时,我们还需要确认大部分的未来将使用到依赖软件,这些依赖在可见的未来还会经过修改,但是进入开发阶段时应该是 可用的 。除此,我们还要进行部署的准备工作,尝试进行第一次部署,包含 内部部署

迭代 0 除了技术准备工作,还需要进行内部的技术培训——只是简单的技术培训,用于介绍系统的架构,开发注意事项等等的内容。当然了,即使已经有相应的培训,还需要准备基础的架构方面的文档,以及必要的一些规范。

这个阶段结束的标志是,项目成员可以进行正常的项目开发,这个开发和未来开发没有区别。

业务回补期:应对第一次 Deadline

在这个阶段里,业务开发已经进入了正轨,但是可能存在一定的进度落后。于是变成了 业务 First,技术 Second

毕竟欠下的债(业务)总是要还的。 这是一步价值证明的阶段,也是调配落后的进度与先进的生产力的时期。

除此,由于内部技术的问题已经解决了,我们还需要关注于与第三方集成,并开始着手准备应用的测试,即第一次上线的相关事宜。

追补业务

…作者太懒,没什么想补充的…

上线准备

在这个时期里,我们所要面临的第一个挑战是:第一次 Deadline 及其上线。

如果我们的项目依赖于第三方服务、平台,并且他/她们的上线周期,和我们是相近的。那么,这个时候与他们联合进行调试,就是一种挑战。特别是上线日期临近时,如果遇上 Bug,那么就需要反反复复确认。

当依赖 ready 时,我们就可以着手准备上线相关的事宜。小公司的购买相应的服务器,大公司的申请相应的资源、审批流程等等。

因此,在 Deadline 提前,进行磨合也是不错的策略。

测试

在一个前后端分离的项目里,我们在平时的开发里,已经进行了大量的联调,基本可以应对上线。

  • 我们可能还没有进行测试,无法验证业务的完整性。
  • 我们可能没有完整的测试规范,来保证整个流程正常。
  • 我们可能还没有准备好一个稳定的测试环境,以提供给测试人员进行测试。

即使是敏捷项目,在第一次时,测试人员进入项目的时间,也和瀑布型项目类似,略晚于开发人员进入项目测试。一来,前后端之间的联调可能没有完全 ready,二来,可测试的业务内容也相对比较少。但是敏捷项目在 QA 进入测试之后,便一直在项目中进行测试。测试除了带来功能的稳定,还会带给开发人员一堆的 bug,这些 bug 会进一步地影响项目的进度。

对于复杂的项目而言,自动化测试(单元测试、UI 测试等)在前两个阶段可能并不会出现——大量的时间被花费在相关的技术实现上。覆盖率在这一阶段要定一个基本的值,比如说 30%,先从 0 开始,然后再进入更高的数值。基于此此,我们才有机会进一步地提升代码的质量。

但是不管怎样,在第一次上线之后,我们实现了从 0 到 1 的阶段,接下来就是从 1 到 100 的时期了。

成长优化期:技术债与演进

这是一个技术证明业务、技术提升开发体验的阶段。同时,随着业务代码的堆砌,我们开始面对它们带来的挑战。

值得注意的是:

  • 如果一个项目的时间太短,那么它就不会遇到这些挑战。
  • 如果领导们看来技术不重要,那么这个时期实践就少一些。
  • 如果我们的能力不够,那么我们只能努力去提升。

但是不论怎样,作为一个手工艺人,我们总得有点 “ 追求 ”。

弥补技术债

这个时期,我们面临了一些遗留的技术问题,不得不去弥补这些债务,免得被利息拖垮了。

在技术准备期,我们花费了大量的时间在构建技术基础;在业务回补期,花了大量的时间、精力在支持业务的开发上。在这两个时期,我们都或多或少地采取了一些妥协方案,为的是能加快速开发流程。而在当前这个时期看来,这些问题将在未来成为我们的开发负担。因此,我们将其称为技术债。

这些债务,包含了很多方面,比如:

  1. 代码质量。常见的问题有: 接口、函数重复实现 ,即 a 成员在自己的功能内,实现过这个功能,但是 b 成员又实现一份,没有提取到公共的方法中。 实现方式、模式不统一 ,这一点常见于我们采用了某个框架来解决问题,但是真实场景下,可能又会采取过去的实践方式,诸如使用 Lambda、RxJava、Rx.js、Ramda 等框架来进行函数式编程。 少部分代码未按规范实践 ,这个问题更加常见,不仅仅存在于没有代码检视(Code Review)的项目,还存在于拥有 Code Review 的项目,未 Code diff 过的代码,往往容易被遗漏。

  2. 测试覆盖率,在面对技术不熟悉,业务又过急的情况下,测试往往是最先被抛弃的一环。值得商榷的是,国内的互联网公司都不会有测试这种东西,所以它们就存在这种长期的债务了。

  3. 依赖问题。依赖对于短期项目来说,并不是问题。对于长期项目来说,依赖没有及时更新是一个很严重的问题。诸如,我们使用的是 Redux 3.0 的版本,当 4.0 发布的时候,按照语义化版本的规则,它可能修改大量的代码,而我们不得不追随这个变化——除非,我们决定未来重写现在这个应用,否则大量依赖过旧的问题,会导致我们难以对代码进行重构,因而不得不重写应用。

除此,还有大量的前期我们设定的技术目标,我们也会在这个时期实施。

提升开发体验

时间一长,业务的进一步实施,我们便开始在堆砌业务代码。堆砌业务代码,对于某些技术人员来说是一件难熬的事情——每天都在重复工作经验,于是需要帮他们寻找一些挑战。对于技术负责人来说,堆砌业务代码就会轻松一点,毕竟风险会小一点。除此,有时候会为了绩效,也需要创造一些机会。基于多方面考虑,便需要去努力地提供开发体验。

在这个过程中,我们可能写了大量的类重复性代码。这些代码表面看上去并不是重复的,但是从抽象层来看是重复的。应对这种方式的方式之一,是可以用诸如《 如何在业务代码中提升:创建领域特定语言 》中的方式来进一步抽象出内部 DSL 代码。那么,我们就可以减少花费在业务代码上的时间,进一步地花费时间去抽象这一层抽象层。

除此,还会思考怎样去自动化一些代码的编写,比如在 UI 层采用的 Sketch2Code,又比如 Java 中的 XML 编程。

结论呢?

……这部分稿子被台风吹走了……


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK