显式 or 隐式:软件/配置/服务的声明是显式(explicit)的还是隐式(implicit)的,显式的声明管理成本更低,反之则更高。例如我们可否在一个地方清晰地看到所负责应用依赖的所有云资源(explicit),还是需要去分析代码看应用使用的众多 Diamond 动态配置,逐个分析后才能知道其依赖的资源(implicit)。
结构化的 or 无结构的。软件/配置/服务的声明是否有清晰一致的结构,结构化的内容更容易理解,管理成本低,反之则高。例如 Maven 的 POM 清晰定义了 Java 依赖的声明结构,相比之下,各应用的启动脚本是无结构的,可以没有约束地定义,理解成本很高。清晰的结构通常是一种比较合理的抽象。
一处修改 or 处处修改。众多系统/应用的相关软件/配置变更可否在一处完成。例如当我们升级 JDK 的时候,会需要为几百个应用做几百几千次的代码修改才能完成,这种做法显然成本是很高的。如果这几百个应用都在同一个代码库中,即用 mono repo 的形式管理,且这个代码库的结构得到很好的维护,那么升级 JDK 需要的代码修改量就会大大降低。
自动验证 or 手工验证。软件/配置的修改,都需要在生产环境变更后才能生效,这一点和自动化单元测试和集成测试的逻辑是一致的,是否存在自动验证也会极大影响修改的成本。如果需要手工验证,再放大到数百应用,这个成本就非常高了。
对于一个有着成百上千研发人员的技术团队来说,让每个研发去处理类似 JDK 升级这样的工作,是非常低效的。处理这样的问题需要非常丰富的知识,而且这些知识大家平时几乎都是用不到的,因此学习成本很高,而且学了一次之后,后续几乎都用不到了。因此,在一个团队中让少数几个专家去处理这类问题,效率会高很多。同样的问题,例如一个罕见的类冲突,专家几分钟就解决了,而普通的研发往往需要消耗数小时。进一步的,专家会把这些脑中的知识积累成高质量的文档,基于这些知识和大模型技术,这样的专家服务就可以 AI 服务的形式提供,如 Amazon 披露的:
Most developers actually only spend a fraction of their time writing new code and building new applications. They spend a lot more of their cycles on painful, sloggy areas like maintenance and upgrades. Take language version upgrades.
A large number of customers continue using older versions of Java because it will take months—even years—and thousands of hours of developer time to upgrade. Putting this off has real costs and risks—you miss out on performance improvements and are vulnerable to security issues.
…
Amazon Q will analyze the entire source code of the application, generate the code in the target language and version, and execute tests, helping you realize the security and performance enhancements of the latest language versions.
Recently, a very small team of Amazon developers used Amazon Q Code Transformation to upgrade 1,000 production applications from Java 8 to Java 17 in just two days. The average time per application was less than 10 minutes.
Aone Copilot 团队也投入在做类似的工作,相信不久的将来大家也能用到类似的产品能力。
7.2 IaC
IaC(Infrastructure As Code)即基础设施代码化,前文提到我们期望软件供应链能够得到显式和结构一致的描述,这正是代码的优势。实际工作中的场景是,这些基础设施的数据分散在各类系统中,有些系统的数据质量高,有些系统的数据质量较差。在建站这类的场景中,架构师无法从单一的系统中获取系统的全貌,而需要组织一个临时的团队从四处搜集数据,然后通过一次次的尝试去验证。IaC 就是要把基础设施的数据交还给用户,各系统负责处理基础设施的变更。有了显式和一致结构的描述后,DRY(Don’t Repeat Yourself)才有可能。例如,当数千 Java 应用的启动脚本都是各自维护和定制的时候,就无法从中去提取类似服务优雅上下线、服务预热、Spring Boot application profile 注入等通用的功能函数。这类编码抽象的思想在 Java / Go 这样的程序中大家都会自然而然的想到,但是在基础设施描述这类大量的配置类数据中,应用得就少很多。
1、Software as Capital 这本书从经济学的视角帮助分析软件供应链,非常有启发。2、Software Enginngering at Google: https://abseil.io/resources/swe-book,本书的第一章第 2 节 “Scale and Efficiency” 首次让我意识到了代码修改需要考虑 Scalability 问题。参考链接:
[01]Welcome to a New Era of Building in the Cloud with Generative AI on AWS