企业软件项目扼杀了程序设计 - Tim


这篇文章的灵感来自于 HackerNews 上的一条评论,我再也找不到了。它的要点是“虽然架构经常被过度设计,但代码本身却经常被设计不足”。如果有人认出作者,我会很乐意归于他们。作为免责声明,本文描述了我在过去 10 年担任顾问的经历。可能有一些框架和方法可以解决我将要描述的问题,但它们要么没有得到应用,要么没有得到很好的应用。
 
什么是企业软件开发?
我对企业软件的理解深受 Martin Fowlers 在“企业应用程序架构模式”(2002,Addison Wesley)中定义的影响。

  • 为组织内部使用而开发
  • 处理来自多个来源的复杂、持久的数据
  • 适用于复杂的业务规则
  • 通常是多用户系统(意思是并发)
  • 通常集成到更大的系统环境中

在与其他开发人员交谈时,企业应用程序的工作经常被贬低。当然,这些项目不会开发令人兴奋的新技术,不会编写新的流编解码器或使用区块链(这仍然是一回事吗?)。但是,虽然表面上看起来微不足道,但企业软件开发正试图解决有关数据的非常困难的问题。开发人员必须处理来自不同来源的大量数据。这些源中的每一个都可能定义相同的实体,只是在它们自己的域中略有不同,这使得这些域之间的转换非常复杂。此外,他们需要在不断增长的系统中考虑大量复杂的业务规则。
 
软件开发项目的问题
我作为外部开发人员和顾问参与了许多企业软件项目,经常会看到项目方法论干扰了软件的目标。在我看来,项目不是开发优秀软件的合适环境。一个项目的核心属性是:
  • 项目时间和预算有限
  • 项目团队只在有限的时间内组成

项目经理的任务是确保在时间和预算内完成项目目标。如果这些目标在某种程度上得到满足,则该项目被认为是成功的。预算通常是固定的,要完成的目标也是固定的。
对我来说,第一个基本缺陷是固定结局,这意味着软件在某个时候“完成”了。通常通过将开发工作分为“项目阶段”和“维护阶段”来“解决”。项目完成后,开发团队通常会解散,软件被移交给“维护团队”(通常有大量初级开发人员)。
这种方法的一个好处是,项目团队需要在软件移交之前对其进行彻底的记录,这将我们引向了项目设置中的第二个缺陷:将软件从一个团队移交给另一个团队时,在此过程中会丢失很多知识。为了减少项目工作的界限,许多公司尝试在这些项目中应用敏捷框架,主要是 SCRUM。
就个人而言,我有从未见过 SCRUM 或任何敏捷方法在项目设置中起作用。不过,我有偏见,因为真正践行敏捷价值观的公司不会在项目设置中进行软件开发,更不用说外部顾问了。他们会意识到他们的应用实际上是不断改进的产品
 
标准化
考虑到上面列出的缺陷,整个开发生命周期中的主要关注点之一是避免代码中的“意外”。如果代码被新的项目团队或维护团队采用,它应该很容易理解,以便可以以尽可能少的努力添加新功能或错误修复。
这方面的主要工具是标准化。
在较大的企业中,通常有一个“企业架构”团队,它位于所有软件项目之上并标准化开发过程。在哪个版本中使用哪种语言?允许使用哪些框架、库?需要哪些技术栈,哪些测试方法?可以考虑哪些架构指南?这种宏观架构通常以惊人的细节规定。
在某种程度上,这很有意义:如果您的软件开发人员必须在项目设置中工作,他们将不得不随着时间的推移处理大量代码库。维护团队可能同时负责许多不同的应用程序。如果开发人员在所有这些应用程序中“感到宾至如归”,因为他们立即识别结构和技术,他们可以更快地开始工作。
难的部分是避免设置太多规则。我曾为确定要使用的确切 Spring Boot 版本的客户工作。如果版本是企业架构师升级的,那么整个公司就得整体升级。我曾为客户工作过,他们规定只使用 Hibernate 和 Hibernate 查询语言 (HQL),禁止在 POJO 上使用原生 SQL、其他框架或投影。
在专业方面,开发人员不必熟悉 SQL,并且访问数据库的方式是标准化的,当然,这导致大多数应用程序的性能低于标准。此外,无法利用非常昂贵的 Oracle 企业数据库的专有特性。
但即使这些标准化在软件项目中导致了巨大的问题,企业架构师也不会争论。
 
分层架构
标准化的黄金标准是分层架构。再次引用 Fowler 的《企业应用架构模式》的定义,分层是一种分解复杂软件系统的技术。从理论上讲,将持久性、领域逻辑和表示分离在不同的层中可以使应用程序的推理更容易。每一层只需要知道下面的层,例如领域层知道持久层,但不知道它是被REST服务、Web应用程序、富客户端还是终端接口调用。这不仅以易于发现的方式构建应用程序,而且还使得将应该分离的不同关注点交织在一起变得更加困难。但它也会将应用程序域逻辑切割成单独的子域,并且会对性能产生影响。
 
为什么这一切会导致代码设计不足?
软件开发人员的环境越标准化,他们的代码就越不完善。对我来说,设计不足的代码是可以实现其目标的代码,性能更高、冗长或重复更少。坚持上面的例子:如果开发人员被禁止编写原生 SQL,他们将受到 HQL 的限制,编写较慢的查询或需要从他们的应用程序中获取多个查询来完成一项任务。如果在每个细节中都规定了确切的语言、框架、库,开发人员有时需要使用这些工具来解决他们的需求,而不是使用正确的工具来解决他们的问题。如果要积极遵循分层架构,那么 50% 的代码将是层之间的映射器。如果你总是不得不考虑项目完成后可怕的代码移交,
 
如何改善现状?
将您的软件视为产品,而不是项目。然后,您可以从宏观架构中消除过多的细节。如果开发软件的团队在更长的时间内保持一致,他们就可以“冒险”更多地专注于他们的技术,为他们必须解决的问题选择合适的工具和架构风格。他们可以“冒险”编写更复杂的算法,利用他们语言中鲜为人知的部分。知识将留在团队中,就像团队本身一样。尽管微服务现在远远落后于炒作周期的高峰期,但它们可以成为实现这一目标的非常有用的工具。