骷髅编程

骷髅编程

💡 原文中文,约25200字,阅读约需60分钟。
📝

内容提要

本文介绍“骷髅编程”方法:先定义抽象接口和核心业务逻辑(骨架),再填充具体实现(血肉),使组件可插拔、易测试。作者用Clojure实现寻找网页外链环路的实例,通过协议、回调函数和并发管道搭建骨架,测试后装配爬虫、过滤器和判定组件。文章强调抽象分离易变与稳定部分,并反思对象必要性,推荐接口优先设计。

🔎

延伸解读

接口优先设计的实践价值

文章通过Go和Clojure的对比,展示了接口(或回调函数)如何让核心业务逻辑与具体实现解耦。这种设计使得存储层、爬虫等组件可插拔,便于测试和替换。例如,用FakeStorage测试业务逻辑,无需依赖真实数据库。这种“面向接口编程”不仅提升代码灵活性,也降低了需求变更时的修改成本,是应对软件易变性的有效手段。

骷髅编程与LLM协作的潜力

作者提出“骷髅编程”概念:先定义抽象接口和核心逻辑,再填充具体实现。这种方式特别适合与LLM协作,因为开发者手写骨架后,可让LLM生成具体实现,而无需担心整体架构失控。清晰的接口和函数签名能提高LLM生成代码的准确性,同时减少上下文消耗。不过,作者也提醒需审查生成代码,且版权问题需谨慎。

并发实现的陷阱与反思

在实现爬虫并发时,作者最初用channel和go-loop,但发现任务生产者和消费者耦合导致性能未提升。后改用future实现并行递归,但仍有阻塞问题。这提醒我们,并发设计需明确生产者和消费者分离,否则可能事倍功半。作者也反思了对象必要性,认为Clojure的defmulti/defmethod可能更简洁,但需权衡类型安全。

Q&A

什么是骷髅编程?

骷髅编程是一种编程方法,先定义抽象接口和核心业务逻辑(骨架),再填充具体实现(血肉),使组件可插拔、易测试。

骷髅编程的核心思想是什么?

核心思想是将易变的部分(如数据库、具体实现)与稳定的部分(核心业务逻辑)分离,通过接口或回调函数定义抽象边界,使核心逻辑不依赖具体实现,从而易于测试和替换。

在Go语言中如何实现骷髅编程?

在Go中,通过定义接口(如EntryStorage)来描述存储操作,业务逻辑只依赖接口,不依赖具体实现。测试时可以使用假实现(FakeStorage)注入,之后可以替换为真实实现(如MySQL或JSONL存储)。

在Clojure中如何实现骷髅编程?

在Clojure中,可以使用回调函数或vtable(包含函数引用的映射)来实现抽象。例如,将存储操作封装在映射中,业务逻辑通过调用映射中的函数来执行,测试时传入假实现即可。

骷髅编程有哪些好处?

好处包括:核心逻辑简单清晰,易于测试;组件可插拔,便于替换和扩展;开发初期可忽略底层细节,专注于核心逻辑;与LLM合作时,接口定义清晰有助于生成准确代码。

骷髅编程的实例是什么?

作者用Clojure实现了一个寻找网页外链环路的程序,通过定义协议(如Odysseus、Crawler、Gatekeeper)和回调函数搭建骨架,测试后再填充具体实现(如爬虫、过滤器、判定组件),最终成功找到环路。

骷髅编程与依赖反转原则有什么关系?

骷髅编程体现了依赖反转原则:核心业务逻辑依赖抽象接口,而不是具体实现,使得依赖方向与数据流向相反,提高了灵活性和可维护性。

骷髅编程中如何测试核心逻辑?

通过注入假实现(如FakeStorage或假管线)来测试核心逻辑,无需依赖真实组件。例如,在Clojure测试中,用假爬虫和假判定函数验证递归函数的正确性。

🏷️

标签

➡️

继续阅读