第1968篇:软件工程的本质与AI的关系——复杂性管理在AI时代的新挑战
第1968篇:软件工程的本质与AI的关系——复杂性管理在AI时代的新挑战
Fred Brooks在1987年写了一篇论文叫《没有银弹》(No Silver Bullet)。他在里面区分了两类复杂性:本质复杂性(Essential Complexity)和偶然复杂性(Accidental Complexity)。
本质复杂性是业务本身的复杂性,是你无论用什么工具都无法消除的——保险理赔的规则本来就复杂,航班调度的约束本来就多,这不是技术问题。
偶然复杂性是我们在解决问题的过程中自己制造的额外复杂性——糟糕的抽象、不一致的命名、循环依赖、深层次耦合……这些是可以被更好的工具和方法论消除或减少的。
Brooks当时说的是:大多数技术进步,都只能解决偶然复杂性,本质复杂性无法被技术消除。
三十多年过去了,AI来了。很多人觉得AI是这篇论文的反例——"AI能理解业务语义,理解自然语言,是不是可以直接让业务人员和AI对话,绕过技术层?"
我觉得这个期待误解了Brooks的意思,也误解了AI的能力边界。今天想认真说说这件事。
软件复杂性的三个来源
Brooks的分析框架非常有价值,但我想在它的基础上更细化一层。软件系统的复杂性,我认为有三个来源:
来源一:领域复杂性(Domain Complexity)
这是Brooks说的本质复杂性的一部分。业务领域本身有多少规则、约束、例外、边界条件,这决定了软件系统的基本复杂度下限。
金融系统的清算规则、医疗系统的诊断流程、物流系统的路由算法——这些领域的复杂性不因为你用了AI就消失了。
来源二:技术复杂性(Technical Complexity)
这是随着系统规模增长自然积累的技术挑战:一致性、分布式协调、性能优化、高可用设计。这一层的复杂性有很大一部分是由技术本身的限制带来的,例如CAP定理告诉你分布式系统无法同时保证一致性、可用性和分区容错性。
来源三:组织复杂性(Organizational Complexity)
这是最少被讨论,但现实中影响最大的一类复杂性。一个系统是由多少团队、多少工程师协作开发的?他们有没有共同的架构认知?信息传递有没有损耗?
Conway定律说:系统的架构往往反映了组织的沟通结构。这个规律在AI时代并没有失效,反而因为AI工具的引入,出现了新的变种。
AI解决了什么,没解决什么
在这三类复杂性上,AI的影响是非常不均匀的。
对偶然复杂性(大部分是技术复杂性的子集):AI有显著帮助。
代码生成、重构、单元测试生成、文档补全——这些都是在减少偶然复杂性的工作。工程师原来要花大量时间写boilerplate代码,现在AI能帮忙省去。原来的代码审查要靠人工记住大量规则,现在AI能自动检查。
这是真实的、可测量的生产力提升。
对领域复杂性:AI既有帮助,也有新挑战。
帮助在于:AI在某些领域有比单个工程师更广泛的知识面,能帮助快速了解一个陌生领域的规则。在写代码处理某个业务逻辑时,AI可以提醒你"这里可能有X例外情况"。
新挑战在于:AI理解的领域知识是从大量文本中"统计提取"的,而不是通过真实业务验证的。当业务规则非常细分、非常特殊时,AI的知识是不可靠的,甚至会提供听起来很有道理但完全错误的"专业建议"。
我遇到过一个案例:团队用AI辅助设计了一个数据处理流程,AI给出了一套合理的流程设计。但这套流程忽略了该行业特有的一个合规要求(数据必须在特定时间窗口内被处理并归档),这个要求在通用文献里几乎不会提到,只有深耕这个行业的人才知道。结果上线后才发现合规问题,改造成本很高。
对组织复杂性:AI目前几乎没有帮助,甚至可能加重。
这是最被忽视的一点。
当AI能快速生成代码时,各个团队更容易快速构建自己的"AI功能",但这些功能之间的一致性、数据模型的兼容性、接口契约的维护——这些依然是人的问题,依然需要架构协调,依然受制于组织沟通结构。
甚至可能更糟:因为AI降低了"写代码"的门槛,更多人可以快速写出功能性代码,但这些代码缺乏整体设计考量,系统级别的耦合和不一致性会增长得更快。
"AI让每个人都能写代码"这件事,如果没有同步提升架构治理能力,最终结果可能是更大规模的技术债。
复杂性管理在AI时代的新形态
我用一张图来展示这个变化:
基于这个分析,AI时代的复杂性管理有三个新的重点:
重点一:建立领域知识验证机制
AI提供的领域知识和业务规则,必须有一个明确的验证机制,不能直接用进代码。
实践上,这意味着:
- 对AI生成的业务逻辑代码,需要领域专家(不只是技术人员)参与评审
- 建立业务规则的显式文档(不是代码注释,是可以独立阅读的业务规则清单)
- 关键的合规性检查清单,不能依赖AI自动生成,必须有业务专家维护
// 一个业务规则注册的例子
// 把业务规则从代码里"提升"为显式可管理的配置
@Component
public class BusinessRuleRegistry {
private final Map<String, BusinessRule> rules = new LinkedHashMap<>();
@PostConstruct
public void initRules() {
// 每条规则都有:描述、来源文档、最后更新日期、负责人
register(BusinessRule.builder()
.ruleId("PRICING_SPECIAL_CUSTOMER_001")
.description("VIP客户在季末最后三天享受额外折扣")
.sourceDocument("销售政策手册2024版-第5章")
.lastVerified(LocalDate.of(2024, 11, 1))
.owner("sales-team@company.com")
.implementedIn("PricingService.calculateDiscount()")
.build());
register(BusinessRule.builder()
.ruleId("COMPLIANCE_DATA_RETENTION_001")
.description("用户行为数据必须在90天内归档至合规存储")
.sourceDocument("数据合规手册-监管要求第3条")
.lastVerified(LocalDate.of(2024, 10, 15))
.owner("compliance@company.com")
.implementedIn("DataRetentionScheduler.runRetentionJob()")
.build());
}
// 定期提醒:规则超过6个月没有验证的,需要重新确认
public List<BusinessRule> getStaleRules() {
LocalDate threshold = LocalDate.now().minusMonths(6);
return rules.values().stream()
.filter(r -> r.getLastVerified().isBefore(threshold))
.collect(Collectors.toList());
}
}这个模式把业务规则从代码里的"隐藏逻辑"变成了"显式文档",使得AI辅助开发时生成的代码更容易被验证——你可以对照规则注册表检查AI生成的代码有没有遗漏关键规则。
重点二:架构守护自动化
AI让代码产生速度加快,意味着架构规则被违反的机会也增多了。你不能依赖人工评审来追上代码产生的速度,需要把架构约束变成自动检查。
// 使用ArchUnit做架构规则自动化检查(在CI/CD里运行)
@AnalyzeClasses(packages = "com.company.aiplatform")
public class ArchitectureRulesTest {
@ArchTest
static final ArchRule AI_LAYER_ISOLATION =
layeredArchitecture()
.consideringAllDependencies()
.layer("AiModules").definedBy("..ai..")
.layer("BusinessLogic").definedBy("..service..")
.layer("DataAccess").definedBy("..repository..")
.whereLayer("AiModules").mayOnlyBeAccessedByLayers("BusinessLogic")
.whereLayer("DataAccess").mayNotAccessAnyLayer();
@ArchTest
static final ArchRule NO_DIRECT_AI_API_CALLS_FROM_CONTROLLERS =
noClasses().that().resideInAPackage("..controller..")
.should().dependOnClassesThat()
.resideInAPackage("..openai..")
.because("Controller层不应直接调用AI API,必须通过Service层");
@ArchTest
static final ArchRule AI_CALLS_MUST_HAVE_TIMEOUT =
methods().that().areDeclaredInClassesThat()
.resideInAPackage("..ai.client..")
.should(haveTimeoutAnnotation())
.because("所有AI调用必须配置超时,防止级联阻塞");
}这类自动化架构检查能在代码合并到主干之前就发现架构违规,不需要人工在每次评审时重新检查。
重点三:认知复杂性的新维度——AI代码的可理解性
这是一个新问题,在纯人工编码时代几乎不存在。
当工程师用AI大量生成代码时,有一个问题:这些代码有没有人真正理解过?
AI生成的代码可能能跑,能通过测试,但如果没有人能解释它为什么这么写,一旦出现问题,排查成本极高。而且更危险的是:当业务需求变化,需要修改这段代码时,如果没有人真正理解它,修改往往是"改了能跑就行",而不是"按正确的设计思路修改",长期下来会积累大量AI生成的技术债。
我给团队定了一个规则:任何AI生成的超过50行的代码块,负责的工程师必须能够在不看AI解释的情况下,向另一名工程师讲清楚这段代码的设计逻辑。 如果讲不清楚,不能合并进主干。
这个规则很严格,但它逼着工程师真正理解AI生成的代码,而不是"AI说能跑就行"。
Brooks的论文在今天是否还正确
我认为:比以前更正确了。
AI是目前为止对偶然复杂性打击力度最强的技术工具,但它丝毫没有减少本质复杂性——业务的本质复杂性永远在那里,需要人去理解和驯服。
与此同时,AI带来了一类新的挑战:当生产力工具的能力超过了工程师的理解能力增长速度时,系统的整体理解度会下降,而不是上升。 这是AI时代新的复杂性来源,需要在工程管理上主动应对。
软件工程的核心能力从来不是"写代码",而是"管理复杂性"。AI改变了写代码的方式,但没有改变复杂性管理的本质要求。这既是AI工具的边界,也是工程师价值的所在。
