产品团队经常因为早期过度设计造成的混乱而陷入困境。
一旦团队壮大,以前微不足道的事情突然需要很长时间才能完成。最终,有人问:“为什么要花这么长时间?”工程师们感到惊讶和沮丧。这不可能是代码库的问题——它遵循了最佳行业标准。
创始人很难在为时已晚之前注意到这一点。 通常,这甚至连技术领导者都会感到惊讶。
过度工程是如何开始的
您可能之前见过过度工程。这是一个由两个人组成的团队使用十个微服务,并痴迷于无关紧要的微小性能调整。或者采用流行但不稳定的技术,并在单个虚拟机就足够好的情况下大力发展基础设施。或者重新发明已解决的问题并从头开始实施。
构建复杂系统并想象技术能让你领先是件很有趣的事。但事实并非如此——大多数软件都很无聊。你创建的东西中只有一小部分是独一无二的。
不过,我们也有理由大胆设想。创始人对这项技术有着宏伟的愿景,他们明确表示: 我们需要扩大规模。我们正在创建一个操作系统来颠覆我们的行业。我们现在必须编写核心软件,以后再添加功能。
也许这会导致人们过度思考多年来已经解决的问题。如果你正在打造下一个独角兽,为什么要使用在一台服务器上运行的一个数据库?这并不能让你在其他想成为独角兽的人中脱颖而出。如果你的目标是明星,最好设计一些支持这个想象中未来的东西。
但在此阶段,您还需要快速交付和验证。您必须在构建产品的过程中保持动力,因此您担心会迷失在混乱的代码库中。您会感到保持高标准的压力。
为了避免这种混乱,人们很容易过度设计,但这只会让情况变得更糟。 它会占用你本可以花在真正有用的基本事项上的时间。 如果你的 CI 管道不是绿色的,谁会在乎你是否实现了服务网格?如果本地环境很糟糕,你还需要那个自定义框架吗?水平扩展如何让你免于编写无法维护的代码?
高质量
您的挑战是在过度设计和构建混乱的原型之间找到平衡。它介于快速行动和正确行事之间。
我们往往认为速度和高质量是对立的。要想生存,就必须快速。但质量到底意味着什么呢?
工程师对质量有强烈的意见和模糊的想法。有些人将其理解为“我不喜欢这个代码。它应该使用另一种设计模式。”他们对格式化非常虔诚。他们抱怨说:“给我们时间重构。”这是一种幼稚的想法,与产品工程相去甚远。它以质量为借口来提升自我。代码不应该是最终目标。
另一种观点是将质量视为灵活性。构建易于扩展和配置的系统让人感觉很有成就感。如果你想为了好玩而解决代码难题,这很酷。但是如果你想交付可用的软件,你需要一些限制。专注于眼前的事情。使用经过验证的、枯燥的技术堆栈。远离创造性或动态的解决方案。 如果你对构建某种通用的东西来解决未来的问题感到兴奋,请检查是否可以将其简化为现在可以使用的东西。
您可能不需要在短期内进行扩展。但如果您投资基础,那么在需要时它们会为您提供良好的服务。
基本信息
在早期,我喜欢关注开发者的体验。我更愿意为工程师准备一个良好的工作环境,而不是创建一个支持所有可能用例的框架或平台。
从头开始需要构建很多东西,新工作很快就会堆积如山。良好的基础可以减少在非产品方面浪费的时间。它们可以帮助您快速迭代,与为了代码美观而进行重构相比,这具有真正的价值。
最重要的是,挫败感是生产力的最大杀手。 它可以彻底改变工程师的心态,从“感觉不像在工作”变成“这是我最不想做的事情”。
我首先要选择的是自动构建系统(CI/CD 管道),它可以运行测试和静态分析,构建项目并将其部署到生产环境中 — 最好是一个易于配置的现代化系统。相同的步骤在功能分支上运行,因此主分支永远不会中断。
它不必太复杂。如果您需要git pull,就让它运行吧。它很容易设置,所有工程师每天都会受益。您不能承受部署因损坏的更改而受阻,也不能花时间讨论 linter 可以发现的琐碎问题。
接下来,准备一个出色的本地开发环境。 它应该易于设置、随处可用并且运行速度快。您应该能够在本地运行具有相同版本和结果的 CI 工具。使用实时代码重新加载,以便使用起来很愉快。
最后,制定一些常见事项的指导方针。 想想你构建应用程序的构建块。组装元素比创建通用框架更容易。它让你可以保留一些标准,而不必试图预测所有未来的用例。
这更多的是关于健康的约束,而不是正确地做事。您不想每周讨论如何编写 HTTP 处理程序、调用外部 API、使用数据库事务或定期运行函数。尽早做出决定并结束讨论,这样您就可以专注于编写重要的代码。
无论如何,要小心那些难以逆转的决定。 固执己见的框架让开始变得容易,但摆脱它们可能需要好几个月的时间。
瞄准中间
我喜欢钟摆的比喻:一旦我们走向一个极端,并被其结果所困扰,我们就会不惜一切代价避免它,并转向另一个方向。这适用于生活中的许多事情,包括技术炒作周期。
例如,考虑交付软件。服务是一种部署代码的方式,而不是隔离单元。因此,使用模块进行隔离。但要准备好在需要时启动单独的服务。永远坚持使用庞大的整体与从分布式系统开始一样极端。但不知何故,我们倾向于从一个极端走向另一个极端。
同样,一旦我们处理混乱的代码库,我们就会开始格外关注质量。然后,很容易在另一个方向上走得太远,并对你的下一个项目进行过度设计。
我仍然觉得找到这种平衡很有挑战性。这是一个永无止境的讨论话题,没有明确的答案。有一件事我确信会有所帮助: 如果你见过极端,至少你知道要瞄准中间的某个地方。
趁还没太迟
当我听说团队在混乱的系统下苦苦挣扎时,我突然想到,过去的一个简单的决定本可以避免这种情况。一旦你陷入困境,迁移出去就非常困难。相比之下,从头开始构建感觉要容易得多。
我希望我们有指标来跟踪这一点,但我怀疑这是否可行。例如,实现高测试覆盖率很容易,但这并不意味着您的测试有任何意义。
我发现一个行之有效的方法是定期发布小功能。 关键技能是将工作分成有意义的部分。最简单的方法是通过人为的界限进行划分,例如每个微服务一个功能或将后端和前端部分分开。相反,目标是实现端到端完整但足够小的变更以便快速发布。
不过,要小心不要将其作为目标指标。它会鼓励在代码中使用捷径,将你拉向混乱的代码库。