编程三境界: 编码、设计、模型。
引子
写一段程序很容易,3 岁小孩都能学会。可是,写一段优雅、简洁、可靠的程序,却不是 3 岁小孩能够搞定的事情。
编程即是表达逻辑。编程有三个境界:编码、设计、模型。 它们层层递进,难度越来越大,亦标志着编程技艺的三次飞跃性的突破。
编码
编码是最基本的逻辑表达活动。不必多加思考,一个普通人花一下午学习编程的基本知识,也能写出一段程序来,只要他能理解“加减乘除”、“如果-那么”,“一直做某件事-直到某个条件不能满足”。
在真实的软件开发活动中,常见的编码模式是:组装 API 参数、调用 API、获取数据、做一点业务处理、组装 API 参数、调用 API 、获取数据、……
while (programming career is not over) {
buildParam;
callAPI;
fetchData;
doBizLogic;
}
嗯,很多人很长一段时间都做的是这样的工作。然而,做一万小时重复性的事情,只能原地踏步,并不会带来编程技艺上的提升。不进则退。要如何真正的提升技艺呢 ?
重构是提升编程技艺的一个重要途径。重构意味着重新审视代码,用一种新的方式去理解代码逻辑的实现,追求更简洁更可靠的实现。比如,“精练代码:一次Java函数式编程的重构之旅”,即是用函数式编程的视角,让代码更加简洁,更加可复用。重构得越多,代码越简洁,编程技艺的提升就越快。这是每天写相似的业务代码无法比拟的。因此,重新去审视日常中的每一行代码:
- 对于冗长的飞流直下三千尺的代码流程,能不能切分成可以正交组合的多个函数,让主流程清晰可见 ?
- 对于拗口的山路十八弯的判断逻辑,能不能用更清晰的控制结构进行表达 ?
- 代码读起来和理解起来是否足够流畅 ? 如果不流畅,如何实现更加清晰自然 ?
- 代码在大量数据下是否有性能问题 ? 如果慢,是否可以通过数据结构和算法进行优化 ?
- 代码是否可以复用 ?如果难以复用,能否抽离出容易复用的部分,让实现类似需求更加轻松 ?
- 代码是否可以扩展应对不同需求 ? 如果难以扩展,是否可以将通用和差异分离开,更容易定制化 ?
重构,最终的目标其实就是让以后的编程工作更加轻松,花更少的时间,拿一样的收入。
设计
当持续重构的时候,也在持续地思考和设计。
代码即设计。设计,即是对现实问题进行抽象,提炼出基本的问题,用简洁的概念去描述和定义,揭示概念之间的关联,发展方法去处理,从而获得简洁优雅的设计。
比如,“从JSON中自动生成对应的对象模型” 即是一例。不是立即着手去编程,而是首先分析对应的数据模型和数据结构,提炼出要素,用设计模式分离不同的关注点,将表示与构建分离。后续要修改时,只要修改相应的一小块即可。
设计常常通过组件编程来实现。组件是具有一定接口和行为规范的实现。组件可以相互组合,构建更大的组件和子系统。组件有一个通俗的说法:积木。每种不同类型的积木都有特定的嵌口(接口),具有不同的形状(行为规范),可以与其它积木组装,构造更大的形状。
一切逻辑皆可组件化。用组件的视角去审视业务逻辑,将系统中的业务逻辑抽象成各种组件,应用层只需要针对特定需求进行组件编排。比如,“基于接口编程:使用收集器模式使数据获取流程更加清晰可配置” 将获取组装订单详情的普通流程变成了一个组件化的可编排的流程。业务逻辑即组件,业务即配置。
我接手的一个订单同步的系统,是一个组件化做得很好的系统。这个系统里基本只有各种各样的组件,相当于一个较为完备的工具箱。业务逻辑,也是作为业务组件来看待的。这样,订单同步任务所需要做的,只是将各种组件组合起来,构建一个完整的业务流程。
区分新手和高级工程师的一个区别,就是看他能不能从设计的角度来思考、分析和解决问题,从组件的角度来构建和优化系统。
模型
模型,是设计的深化。模型,是有序组织的数据模型和数据结构,以及基于其上的编排良好的应用控制结构。模型是软件系统的基石。数据模型三要素—— 一致性、完整性和完备性,基于其上的数据质量的可靠性,是软件系统的稳定性与持久发展的根基。
- 一致性:模型中的冗余数据是一致的,只存在单一的事实。冗余数据通常存于从库、副本、缓存、消息等。要实现多个冗余存储的一致性,难度和挑战性还是很大的。
- 完整性:模型中的数据及关联始终满足指定的约束关系;不会因为动态变化而破坏约束关系。完整性通常在构建数据模型之初就明确指定,并固化到模型的定义中。在变更数据时,必须满足模型的完整性的约束。
- 完备性:所构建的模型可以从理论上支撑各种通用需求和定制化需求,不会因为缺失某种数据而无法支撑需求。比如说,因为导出记录模型里缺乏一个总店ID,无法支撑连锁商家的订单导出需求,就可以说这个导出记录模型是不完备的。模型的完备性可以通过场景走查来完善和补缺。
鉴于我在这方面也在持续学习中,可以在后文中多多探讨和分享。一个值得学习和实践的设计理念是领域驱动模型设计(DDD)。从领域角度不断思考、审查和精炼系统的领域数据模型。
为什么说模型也是一种编程呢 ? 因为编程是表达逻辑,而逻辑实质是一种严谨的结构化的思维。模型正是结构化思维的集中体现。对模型的思考和精炼,往往需要追溯更深层的原理,需要全局的视角。
刻意练习
从刻意练习的角度来说,每日有所编程,并不能提升编程技艺。每日有所进步(哪怕只有微小的进步),才能促进编程技艺的提升。这种进步,或者来自于简单的代码重构,或者来自于大胆的全局结构重构,或者来自于有挑战性的编程课题,或者来自于设计先导的构思,或者来自于对模型完善性的推敲。
结语
要持续提升编程技艺,不能仅仅只是做重复性的编码工作。通过重构可以精炼逻辑的表达,通过设计可以提炼可复用的问题和方案,通过模型的审查和优化可以将系统的基石打磨得更加稳定。
编程,远不止于编码。模型之美,逻辑之美,表达之美,才是编程的最高目标,亦即编程的“道”。