二十年前我从程序员开始的时候,就一直梦想着能够象搭积木一样构建软件。二十年过去了,这个梦想终于实现了。上一篇我谈到中台之所以是解决企业数字化转型中必需的平台,它的关键作用就在“合”“分”“聚”三言。 “合”,让企业实现了标准一致的管理,集成一体的业务,这是数字化的基础; “分”让企业业务实现了独立部署、弹性化、复用化、共享化,变成支撑企业数字生态无数业务场景的零部件。 “聚”让企业得以快速的、任意的组合它们已经有的业务能力,去构建数字生态中的千人千面的个性化场景,但却不会破坏企业管理的标准和一致。 这一篇来讲一讲我们如何实现软件行业一直的梦想,像搭积木一样的生产软件。 二十年前我从程序员开始的时候,就一直梦想着软件也能够像工业化产品一样,用有限的零部件组装出无限的应用场景。于是我一直非常执着于研究各种软件方法和技术。在2008年的时候,我已经深入研究UML5年了,用所有的心得体会写了《大象——Thinking in UML》这本号称中国UML第一书的著作。十年过去了,至今这本书还在销售。我曾经沾沾自喜过。但从2012年起,我开始意识到了问题。《大象》一书无非是纸上谈兵罢了。UML也好,领域驱动也好,Scrum,TTT……所有的软件方法都只是看上去很美,但你却无法将它落地。一个再资深的架构师,无论用什么样的软件方法,他只能够将他的设计变成文档和图,却无法直接将设计变成代码。而写代码的码农们,对这位高明的设计师的设计能理解多少,能实现多少,谁也说不清。再迭代几个版本后,实现代码与当初的设计早已是风马牛不相及。写代码的我们都选择习惯性不去触碰那个似乎永远都无法解决的痛:设计与实现代码永远不一致。于是聪明的程序员干脆承认了这个现实,然后发明了敏捷方法,采用低文档,测试驱动等方法,美其名曰快速试错,快速迭代,打一枪看看效果再改进。但这类方法其实是一种掩耳盗铃的现实主义,用试错代替设计,并不表示软件不需要设计,只是换个形式的投机取巧罢了。对大型、超大型或复杂软件来说,试错成本会高到无法接受——比如,你敢在航空控制软件上试错吗?血淋淋的教训就在眼前。低设计的敏捷只能是战术,永远不能上升到战略层面。 设计与实现不一致的根本原因,是设计无法直接转化成代码,必须靠人工翻译。UML曾经试图将各种设计直接转换成代码,但这些代码是散乱、无序、不可管理的,距离真正的业务实现代码太远。到了2015年,我和我的团队意识到了微服务架构是能够将设计直接转换成代码的载体,并找到了它的解决方案:模型驱动的微服务架构。再经过4年的研发、实践、改进、再实践。在GiSP平台的第5个版本发布后,模型驱动的微服务架构终于成熟了。 模型驱动,准确说,是领域模型驱动,有兴趣的读者可以自己去搜索了解。模型驱动的微服务架构,即是采用模型驱动方法,直接将模型驱动设计结果转变成微服务代码。 在实践中我们扬弃了模型驱动的许多细枝末节的规范方法,只取了它的核心。并且在实践过程中我们发现了很多原始方法中过于学院派的理想主义做法。我们不迷信权威,只相信能做出最好软件的方法就是最适合的方法。因此我们依据开发的现实,做出了一些扩展和改变。有些定义已经与原始定义不一致了。下表列示了原始定义与我们的设计要素的映射。左边是原始概念,右边是我们实现的概念。
我们再针对上述的概念做了封装,把很多概念固化和封装到了平台的操作过程中。实际上设计者在使用GiSP平台做微服务设计时,并不会感受到那么多复杂的概念,而是非常直观和简单的操作。本篇的后续就会讲这一过程。 当我们实现了完整的模型驱动的微服务架构,将设计直接转化成了代码,从此让设计与代码实现永远保持一致。同时,我们赫然发现,我们实际上实现了软件行业一直以来的梦想:像搭积木一样的构建软件。整个模型驱动的微服务架构的建模过程可以总结为下图: 为了证明我不是在吹牛皮,接下来我就用实际的系统截图来说明整个搭建过程。读过上一篇的读者会发现,这个过程与上一篇内容几乎一致。这并不奇怪,上一篇讲的是采用“合分聚”的方法,基于微服务,采用零部件式的组装,完成一个中台架构的应用。换个说法,那就是像搭积木一样,一步步搭出整个业务系统来。所以读过上一篇的读者,就当从另一个角度,再次理解“合分聚”三言的精髓,它是如何像搭积木一样搭建一个业务系统的。 限于篇幅,这一篇我还是只能走马观花的演示一遍过程。很多的细节、原理、技术,都得分篇慢慢讲。 在设想开发一个软件的时候,通常的思路是以用户需求为中心,首先会找到软件用户是谁,应用场景是什么,用户要做什么,是怎么做的,然后去分析提供什么样的功能给他。这些功能是通过什么业务单据呈现出来的,又是由哪些数据对象构成的呢?这是一个正常的软件开发和分析设计过程,是符合我们人的自然思考逻辑的。 这其中,最重要的,就是识别出业务场景(模块)、业务行为(微服务)、业务对象(业务单据)、实体对象(数据对象)。当然,领域模型和面向对象的最基本思想:单一职责原则、高内聚低耦合原则、原子性原则,是贯穿始终的。 而在GiSP中的开发过程正是这个设计过程的反向过程。 第一步:构建全域共享的数据模型库数据对象即实体对象。在GiSP中,数据对象的建立将遵循唯一性和共享规则,建模结果将形成全域唯一和共享的数据对象库。数据对象默认共享给本开发项目,同时也可以开放给全域范围内的任何一个开发项目。 数据对象是最小的零件。在保证了数据对象的唯一、统一和共享之后,就可以进一步用它组装成更大一些的部件了——业务模型及微服务。 第二步、组装全域共享的微服务模型库我们通过Include和Reference两种语义,实现了将数据对象聚合成业务对象的过程。此时,业务对象已经从最小的零件变成了部件:它已经能表示一个实际存在的业务实体了。 在GiSP中,这一步被称为添加接口。可以看到灰色部分,基本的增删改查功能平台已经默认提供,不论是对业务对象的整体还是部分操作,这些方法都可以识别并处理。因此只需要关注业务逻辑的实现,不须再关心数据处理逻辑。 根据业务需求所添加的业务行为称之为自定义接口。 所有接口既是是一项业务功能,同是也是微服务的开放API。 自定义接口定义完成后,GiSP将自动产生框架代码,每个自定义接口会生成一个方法,包括方法名、输入输出参数都已经生成。开发人员只需要在方法体中添加业务逻辑代码即可。 这极大的提高了开发效率:只关注业务逻辑而不需要关注数据处理逻辑;也极大的提高了代码质量:不论开发人员素质如何,框架始终是一致的,不会因为开发人员的差异而导致结构混乱。 业务对象和业务行为配置完毕,GiSP将实时解析模型自动产生代码,并编译为一个微服务。经过简单的两步,一个可执行的微服务就创建出来了。 基于模型所编译出来的微服务规格相同,结构一致,并且所有业务能力均能以API形式开放。这就如同工业生产中的标准件一样,为服务间集成打造了坚实的基础。 每个微对象和微服务就如同组成一部电脑的电子元器件,而依赖关系就是描述一个电子元器件与其它电子元器件的消息交流通道。在GiSP中,服务的集成非常简单,它被称为服务依赖。根据实际业务需求,每个服务都可以依赖全域共享服务库中的任何一个服务。即使这个服务不是由自己团队生产的,只要别的团队共享给出来,它就可以被依赖。仿佛集成电路板将各种电子元器件连接在一起,集成模型将多个微服务集成在一起,共同构建起实际业务实现的流程和脉络,组成一个复杂的业务构件。 经过以上三步,我们完成了用数据对象组装业务对象,用业务行为+业务对象组装微服务,再用微服务组装业务集成的过程。非常简单的操作,背后却完成了极其复杂的组装逻辑。 现在,微服务已经变成了更大一些的积木块,可以称之为业务部件了。接下来,我们将可以用这些部件去组装更大的业务组件——模块。 第三步、组装全域共享的业务场景库在GiSP中,应用场景被称为“模块”。每个模块都是一个可独立运行的小场景。由多个页面,以及每个页面上与用户交互的多个按钮和事件构成。 创建一个新的模块: 创建模块中的多个页面: 为每个页面添加交互行为和事件,从共享服务库中选择要绑定的微服务,选择微服务的版本,并将该行为或事件绑定到微服务的某个开放API上。 完成上述配置后,一个独立模块就建立完成了。每个模块都会进入共享的场景模型库。再经过事先制作好的而面模板的渲染,模块就运行起来了: 经过这一步,我们用微服务这个业务部件,搭建出了业务场景这个更大的业务组件。最后,我们就可以用这些业务组件搭建最终系统了。 第四步、组装最终应用系统应用系统的组装零件来自于共享的模块。通过简单的菜单树和挂接模块操作,一个业务系统就被组装出来了。 经过一到四步,我们像搭积木一样,将数据对象组装为业务对象,用业务对象+业务行为组装成微服务,用微服务组装出了可独立运行的应用场景模块,最后用模块组装出最终业务系统。至此,我们完整实现了模型驱动的微服务架构,从而实现了像搭积木一样搭建软件的梦想。 更加难能可贵的是,由于GiSP从一开始就不是为单项目设计,而是在全局共享、多项目协作,甚至是跨实体协作的上下文环境中设计整个建模过程,从而在多个项目和多次迭代过程中,不断的在累积和改进数据对象库、微服务库和模块库。最终,自然而然的就形成了中台架构。 当业界还在讨论各种中台实现技术,怎么抽象服务,怎么设计接口,采用容器还是虚拟机时,我们已经利用模型驱动的微服务架构技术,实现了中台架构的自然开发方法和平台。可以说,在GiSP平台上,中台不需要特意的设计,随着项目和迭代,自然而然的就累积和改进出来了。这才是模型驱动的微服务架构技术最大的价值所在! 那么,新系统可以自然而然的中台化,那些亟待改进的旧系统又该怎么办?怎么能够优雅的逐步切换到中台架构中来呢?下一篇就讲这个吧。 感谢你的关注!如果希望对GiSP这个产品有更多的了解,点击文章下方的链接,可以到我们的官网上注册试用。 |
|