AI 辅助软件工程:软件生命周期驱动的 AI4SE

生成式 AI 并非银弹。

当我们谈及 AI 辅助软件工程时,我们期望的是 AI 能在改善即有流程的现状,同时提供更多的可能性,诸如于:

  1. 自动代码修复: 利用 AI 技术分析代码并提出修复建议,帮助开发者更快速地解决问题。
  2. 智能代码补全:类似于 GitHub Copilot 和 TabNine,根据上下文预测开发者可能编写的下一行代码,大大提高编码效率。
  3. 代码重构: 识别出需要重构的代码片段,并提供重构建议,并应用代码重构。
  4. 单元测试生成: 自动生成单元测试,帮助开发者确保代码的正确性和可靠性。
  5. 代码合并和冲突解决:帮助自动化代码合并过程,并智能解决合并冲突。
  6. 性能优化建议:学习历史数据和性能模式,帮助开发者识别出影响性能的代码部分,并提供具体的优化方案。
  7. 安全漏洞检测: 检测代码中的安全漏洞,并提供修复建议。
  8. 代码审查助手: 自动检测代码中的问题并提出改进建议,提供详细的审查报告,帮助审查人员更高效地进行代码评审。
  9. ……

但是,并非所有的环节都需要结合 AI、适合 AI,有些环节反而会因为 AI 的引入而增加复杂性,降低效率。

AI 要解决什么问题?软件工程面临的挑战

我们总期待生成式 AI 能解决一部分软件开发中的问题,但是限制我们软件交付速度的往往不是技术,而是人。人与人之间的协作、人对需求的理解、人对已有代码的理解等等。 理想情况下,只有人被取代了,那么问题才会消失。可是,AI 并不能代替你去坐牢,所以最后还是需要人来做决策。

生命周期内的挑战

完全按照某一特定的开发流程来开发软件是不现实的。在组织中,我们总是允许每个团队根据自己的现状,来适当地改造软件开发流程。也因此,每个团队所面临的 挑战也是不同的。诸如于,我们典型的分析方式是根据软件生命周期的不同阶段来审视和分析。

如下是由生成式 AI 生成的软件生命周期的挑战:

  1. 需求分析阶段
    • 需求变更和管理:需求往往会在项目生命周期中发生变化,不良的变更管理可能导致项目延迟和成本增加。
    • 需求不完整或不清晰:如果需求定义不清晰或不完整,可能会导致后续阶段的问题,如设计和开发时的误解或错误。
  2. 设计阶段
    • 架构设计挑战:设计阶段需要考虑系统架构、模块化、性能和可扩展性,这些方面的决策会对整个项目的成功产生深远影响。
    • 设计与需求的一致性:确保设计方案与需求规格的一致性,以及如何适应可能的变更。
  3. 开发阶段
    • 技术选型和工具挑战:选择适合项目需求的技术栈和工具集合是一个重要的决策,可能会影响到开发进度和产品质量。
    • 团队协作和沟通:大型项目中,多个开发者的协作和沟通是关键,特别是在分布式团队或跨时区工作的情况下。
  4. 测试阶段
    • 全面性测试覆盖:确保测试用例覆盖所有功能和边界情况,以及如何处理复杂系统的集成测试。
    • 自动化测试和持续集成:实现自动化测试并结合持续集成可以显著提高软件质量和开发效率。
  5. 部署阶段
    • 部署流程自动化:设计和实施可靠的部署流程,包括配置管理、版本控制和部署自动化,以降低部署错误的风险。
    • 环境一致性和兼容性:确保在不同环境(开发、测试、生产)中软件的一致性和兼容性,尤其是涉及复杂的分布式系统时更为关键。
  6. 维护阶段
    • 问题追踪和修复:确保能够及时发现和解决生产环境中出现的问题,需要有效的问题追踪和处理流程。
    • 版本管理和更新:管理和维护软件的不同版本,包括安全更新和功能更新,以及如何进行版本回退和紧急修复。

总的来说,这些挑战是非常常见且具体的,放到一个大型组织中,上述问题几乎也是非常相似的。当你进行详细的分析之后,你会发现,AI 只能解决一部分问题, 并且经典的软件工程方法和工具也能解决一部分问题,当然了最后所有的问题都是人的问题。

其它挑战

除此,我们还会遇到一些外部的挑战,这些挑战可能会对软件开发团队的工作产生影响,包括但不限于:

  1. 项目管理和进度控制
    • 资源管理与分配:确保项目所需资源(人力、技术、资金)的有效管理和分配,以支持软件开发的不同阶段。
    • 风险管理:识别、评估和管理项目中可能出现的风险,包括技术风险、市场风险和组织风险,以最小化其对项目目标的负面影响。
  2. 质量保证和标准遵循
    • 质量管理系统:实施和维护适当的质量管理系统,以确保软件质量达到用户期望和行业标准。
    • 安全性和合规性:确保软件在设计、开发和部署过程中符合安全标准和法规要求,特别是涉及用户数据或敏感信息的应用程序。
  3. 项目间协作
    • 跨团队协作:确保不同团队之间的有效沟通和协作,特别是在大型和分布式团队的情况下,以确保整体项目目标的一致性和实现。
  4. 遗留系统和技术债务
    • 云原生和微服务架构:这些技术推动了软件开发的灵活性和可扩展性,但也带来了新的挑战,如服务治理、服务发现和跨服务的数据一致性。
    • DevOps 实践:自动化部署、持续集成和持续交付(CI/CD)的实施,以及开发团队与运维团队之间协作的增强,要求文化和工具的整合。
    • 容器化技术(如Docker):管理和部署容器化应用程序的复杂性,以及与传统部署方式的集成和过渡。

与上述的软件生命周期挑战相比,这些外部挑战更多地涉及到组织和行业层面的问题,更难通过 AI 来解决。

应用 AI 之前:经典工具可行吗?

现阶段,我们(包含笔者在内)将 AI 当成一把锤子,看到的问题都是钉子(锤子效应),尝试用 AI 来解决所有问题。但是,AI 并不是银弹,也并不是万能的。

而过去的几十年里,在软件工程领域已经积累了足够的经验和知识,形成了一系列经典的工具和方法,用于解决软件开发和维护过程中的各种问题。 这些工具和方法包括代码质量检查、架构设计、自动化测试、安全测试等,已经在实践中得到了广泛应用。这些工具和方法包括但不限于:

  • SonarQube:用于代码质量检查和静态代码分析的工具,可以帮助开发团队发现和修复潜在的代码问题。
  • ArchGuard:用于架构设计和评估的工具,可以帮助团队设计和优化系统架构。
  • ArchUnit:用于架构单元测试的工具,可以帮助团队验证架构设计的一致性和正确性。
  • EvoSuite:用于自动生成测试用例的工具,可以帮助团队提高测试覆盖率和质量。
  • Checkstyle:代码风格和质量检查工具,可配置规则来确保代码符合指定的编码标准。
  • FindBugs:用于Java代码的静态分析工具,帮助开发者发现常见的编程错误和潜在的安全漏洞。
  • OWASP Zap:开源的安全测试工具,用于查找Web应用程序中的安全漏洞和漏洞利用。
  • ……

除此,还有诸如 SAST (Static Application Security Testing) 和 DAST (Dynamic Application Security Testing) :这两种测试方法结合了不同的工具和技术,分别用于静态和动态地评估应用程序的安全性。

  • Facebook's Aroma:一个代码推荐系统,可以从大型代码库中提取代码模式,并为开发者提供优化建议。
  • SourceGraph:一个代码搜索和导航工具,可以帮助开发者快速定位和理解代码库中的代码片段。
  • ……

当然了诸如此类的工具和方法,也需要大量的开发成本。

现在,考虑一下 AI 要解决什么问题?

现在,我们再考虑一下 AI 能不能解决问题?以及 AI 要解决什么问题?针对于不同的场景,方案是不同的。我们分析了市面上的主要 AI 工具,发现 AI 工具 的两种主要实现策略:

  • 增强现有工具。诸如结合 AI 通过分析大量的代码库和历史数据,生成更智能和精确的代码检查规则,帮助开发团队及时发现潜在的错误和漏洞。
  • AI 原生的软件工程工具。市面上的工具如 GitHub Copilot、Testim.io、Snyk(DeepCode)等,都是基于 AI 技术构建的新型软件工程工具,可以帮助开发团队提高生产力和质量。

由于生成式 AI 存在的幻觉问题,我们更倾向于增强现有工具,而不是完全替代。

实现策略:增强现有工具

在代码质量等场景,已经有大量的团队尝试直接将所有的上下文发给 AI,然后交由 AI 来处理。这种方式不仅是低效的,而且也会导致 AI 无法真正发挥作用。 在这些场景中,类似的方案应该是:

  • 生成检查规则:像 SonarQube 和 Checkstyle 这样的工具可以利用AI技术生成更智能和精确的代码检查规则。AI 能识别出更有效的代码质量问题,并提出更具针对性的检查建议,帮助开发团队及时发现潜在的错误和漏洞。
  • 误判处理:在静态代码分析中,经典工具有时会误判某些代码片段或模式。AI 可以识别这些误判,并提供更准确的判断或建议,帮助开发团队减少误报,节省审查和修复的时间。
  • 辅助边界测试用例生成:工具如 EvoSuite 用于自动生成测试用例,结合AI技术可以更快速地生成全面且有效的测试覆盖。AI能够分析代码逻辑和历史的错误模式,生成更具预测性和全面性的测试用例,帮助团队提高软件质量和稳定性。
  • 辅助架构治理边界:像 ArchGuard 和 ArchUnit 这样的工具在架构设计和测试中发挥重要作用。AI 通过分析大量系统使用数据和性能指标,提供优化架构的建议和模型,帮助团队设计更高效、可靠和可扩展的系统架构。
  • ……

在诸如于 CodeQL 和 SonarQube,结合领域的 AI 模型或者 RAG,我们可以生成对应的代码检查规则,而不是人工编写。随后,再结合 AI 来帮助人们处理过程中的误差问题。

实现策略:AI 原生的软件工程工具

在特定的小流程中,AI 原生的软件工程工具可能会更加适用。这些工具通常是基于 AI 技术构建的新型软件工程工具,可以帮助开发团队提高生产力和质量。诸如于:

  • GitHub Copilot:一个基于 OpenAI Codex 的代码补全工具,可以根据上下文自动生成代码片段,提高开发效率。
  • Testim.io:基于AI的端到端测试自动化工具,帮助开发团队快速创建、执行和维护测试用例。
  • Snyk(DeepCode):一个AI驱动的代码审查工具,通过机器学习算法检测代码中的错误、漏洞和潜在问题,并提供修复建议。
  • ……

它们的特别是针对于特定的场景,如测试、代码、质量,构建专用的模型和工具,以真正释放 AI 的潜力。