首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >老文再发:从0~1构建零售企业的低代码平台

老文再发:从0~1构建零售企业的低代码平台

原创
作者头像
Delphi Shen
发布2026-02-10 10:34:40
发布2026-02-10 10:34:40
1240
举报
文章被收录于专栏:腾讯云TVP腾讯云TVP

原文发表于2022年6月

很多人对于用低代码构建核心业务系统都存在担心,在我帮助信通院推进与构建低代码无代码标准的过程中,也发现各路CIO/CTO对之有大量不同的看法,他们也有大量的疑惑存在,蛮常见的一个观点就是:低代码没法做ERP。

所以今天我们来细细地聊一下这个问题,从细胞层面来剖析一个案例平台,也让更多对低代码只停留在字面意义上认知的同学们,有一个深入围观解剖低代码平台的机会。

这套低代码平台开发于2004年,与Oracle开始构建Apex是同一年,最早的用户包括深圳新一佳(年营业额200亿,100家大型卖场)、李锦记无限极、上海家得利、马来西亚最大零售商Sunshine集团等中大型企业,鉴于年代比较久远,所以当时它能做到的,现在一定能够做到,它不能够做到的,现在很多也都能做到。作为这个平台的设计者,刚好详细的与大家分享一下设计过程,一是希望对所有开发低代码平台的同学有所启发,二是希望能够给甲方的同学一些更清晰的认知。

首先是起源,为什么想做这样一个平台,在好多场合我也都分享过一个模块编译了160多次的故事,本质是因为软件的迭代要求太高,即使我们使用的是当时最高效的开发工具之一“Delphi”,但还是跟不上客户的需求迭代,纯粹的用高代码方式费时费力,简单地说,没钱挣

我们先看一下当时的背景:2004年,零售业大发展,2001年加入WTO以后,2~3年内零售就会向外资开放,所以连锁企业个个都飞速发展,对系统的要求也越来越高,企业大发展意味着管理控制力的下降,这时候对系统的功能要求也是日新月异。

那个时候,中国还没有形成完整的管理体系,对零售管理的理念也是五花八门,主要的派系有万客隆(麦德龙)、沃尔玛、家乐福(大润发、好又多)、日系7-11、港系Circle 便利等等,随着运营高管背景的不同,都会深深的带着原来企业的烙印,这时候对软件挑战极大,换一个高管,基本所有的报表和流程都要重新迭代一次,不然,验收是不要想通过的。

2004年,当年Intel推出的CPU是奔腾四,现在几乎所有人的手机性能都远远超过了它,鉴于零售业大量的数据和运算需求,有些规模比较大的企业会购置小型机来进行运算、SAN来进行数据存储。当时新潮的软件架构是SOA(Service-Oriented Architecture 面向服务的架构),数据库开发也有了ORM的雏形。

那么,我们需要怎么做一套适合零售企业的系统平台呢?

\\\

图片
图片

图源:沈欣,来自Intelligent Deployment Center(简称“IDG”)智能布署平台

首先是抽象,必须把所有的业务抽象出来,有了抽象就有了架构,因为使用的开发语言Delphi本身就是一种面向对象的语言,以前的开发中,也自己写了大量的控件进行封装,所以大约用了一周的时间,把所有零售系统功能抽象为3块:“业务对象”、“业务逻辑”、“查询”、由于零售业流程性较弱,到后期用了一种很有意思的方式加入了流程管理。

其次是目的,为什么要搞这么一个平台?只有一个口号:提升零售管理系统的开发效率,具体分为几点:“开发人员分层”、“减少低级错误”、“绝大多数客户需求调整时,无需重新编译程序“。

需要注意什么?只有两个字“性能”,因为平台一定带来性能的损失。作为核心业务系统,性能不行,那就是完全的失败了,这个问题又受限于当时的软硬件环境。

我们下面就以上这些内容一一切开、掰碎、分享一下当时的整体思考过程,同样分为三步——

1)抽象

首先是零售业务的抽象,这是当时能够想到的最极致的抽象方式了,我们逐一分析一下。

A) 业务对象,零售有大量的表单,很多软件企业以表单驱动为荣,但是表单本身就是一种经常变动的东西,我们经常发现,为了以后分析能够多一个维度,我们的表单就要增加一个字段,不同的管理风格视角大不相同,因此这是一个迭代的重灾区。业务对象内部也有层级,我们需要设计一个可以容纳比较复杂的业务对象的体系,但是实际应用中发现,大部分时候,2层已经足够。

我们在以前做数据库应用时,经常碰到一些好几张表的关联,做查询时性能很低,因此我们采用了这样的方式来设计业务对象: 首先,业务对象是一个表或者多个表的集合,其次,他们之间需要通过一个ID字段或多个字段进行关联。比如订单对象是一个订单头+一个订单体,两者之间用订单编号关联,对于连锁体系,可能还需要加上店号字段进行关联。

复杂一些的,例如商品资料对象,商品主表之外,需要加上条码表(一个商品可能有多个条码),门店表(一个商品是否在这个门店销售),分色分码表(内衣就会有尺码、色码、罩杯三个维度)、商品供应商表(商品和供应商间有一个多对的关系),商品BOM表(商品可能由不同比例的原料商品加工而成,组合商品表(商品会被临时打包成组合进行销售)。

通过业务对象,我们可以目标清晰的知道我们要对哪些数据表进行读取与操作。如何构建这个业务对象呢?我们做了一个工具,你把表的名字给他,它自动取出每一个字段,进行一个简单翻译,构建了一个SQL,你可以对这个SQL做一些小调整,然后给他设定关联字段,你需要几个表就设定几个表,最后记录为一个数据对象。

谈到数据对象,一定会有数据字典的概念,在这里,我们加入了一个数据字典,因为数据库命名比较规范,因此在业务对象构建的自动工具中,可以自动匹配数据库字段名来进行数据字典的构建,包括:字段中文名(还可以外挂多语言表,应用时一键实时切换),显示标签,显示格式、是否必填,最大值最小值,录入时的限制、新增记录时的默认值等等。

为了有更多的灵活性,还加入了情景模式,比如,同样是StoreNumber门店编号这个字段,在普通时候中文显示为”门店编号“但是在Transfer(调拨)场景下,需要显示为”调入门店“。数据字典还承载了ID和名称的子表关系,这些简单的子表数据量不大,因此就直接在数据字典里面处理了,比如主表里是国家ID,对应显示不同的国家名字放在另一个子表这种。

为什么要设计业务对象?就是为了灵活改动,同时,只要遵循一定规范,开发工作变得很简单高效,以前经常碰到的新手程序员不记得给界面上字段加上录入限制啥的这一类低级问题,都可以一次开发,多次收益。

2)业务逻辑

其次是业务逻辑,这是很有意思的一部分,当时的设计是倒推式的,先看哪些是开发重灾区,尤其是哪些今天客户要求由A改到B,明天由B改到C,后天又要求你改回A的需求。作为乙方,客户是上帝,他想咋改就咋改,但是,我必须要用最低的成本陪他折腾。

当时列了大概十个经常需要软件迭代的“灾区”,业务逻辑一直是一个重灾区,我们知道,企业随着发展,管理的视角、重点、都会变化,有时候,碰到了某些“运动“,又会临时提出新的要求。这些要求有一个特点,他们都会在某个操作节点发生。这些操作节点又分为三类,事前事中事后

图片
图片

图源:沈欣提供,来自IDG智能布署平台中的业务逻辑搭建

我们会发现,事前——意味着做之前你就要告诉我,事中——意味着做的时候你要告诉我,事后——意味着做完以后我们要回顾,那么在遍布于企业管理工具的“审核“按钮后面,其实就隐藏着大量的细节

很多时候,使用系统就是为了自动化,比如一张订货单,里面100个商品,如果是手工填入订货数量,保不齐就有这么几个商品考虑不周,导致订货数量过大或者过少。

这时候,我们需要进行一个简单的自动计算,例如,对于该次订货的某个商品的数量,需要保证他单张订单订货数量不得超过30 X日均销量,原理很容易理解,但是靠人工核对肯定不现实,这时候系统就需要自动核对,这就是隐藏在审核按钮后面的逻辑。

如果我们进一步细化,可能还需要针对“促销商品“的订货适当放宽,又比如月饼这一类的季节性商品,到中秋节前一天必须买完,那么距离中秋的日期和订货数量之间又要有一定公式来保障不会订多,再比如同样是酱油,根据商店对应的消费者的价格带不同,不同价位产品之间的库存又需要有一定控制;诸如此类,林林总总,这个审核按钮后面可能会跟着20~30个不同的业务控制点的关系,而这些控制点,又会和企业的规模、业态、品类有着关系,这意味着,即使只有20个控制点,但是不同企业有着不同的排列与组合,这也是我们一开始提到的订货功能迭代了160多次的核心原因。

那么怎么办呢?是的,我们把不同的控制点抽象成一个一个独立的业务逻辑,部署实施的时候,我们根据客户的具体情况来进行勾选即可。这就是低代码的雏形,我们将业务逻辑用低代码形式开发,可以沉淀与积累,在不同用户上就可以反复使用,而无需重新开发。

我们仍然回到表单驱动这个概念,我们发现,表单本质是一个业务对象,常见的业务操作例如新增、修改、审核,甚至打印,都是一个一个业务逻辑组,这样,我们完成了业务控制逻辑的抽象。

下一步,如果这些个审核的逻辑检查无误了,那么就要进行数据库的实际操作,也就是写入物理表,这里也可能会有很多步骤,比如,先要取出唯一单号,然后对应业务对象进行一一写表。

同样,这里也有着大量的不确定性。比如,A超市100多家,横跨不同城市与省份,一个新商品是否在不同省份的门店进行售卖,需要一个独立的“商品引入门店“动作;但是B企业只有3家标准超市门店,我们做新商品的审核时,一旦审核完成,我们就应该在门店和商品的关联表中,对这三家门店都自动增加对应关系。所以A超市不能执行自动引入门店这个操作,而B企业则有这个自动化的需求。因此,我们把这个”自动引入门店“独立为一个业务执行逻辑,可以根据不同企业的要求进行配置。

3)查询

最后是,查询。

查询其实是一个非常非常广泛被运用的功能,比如,我们进入一个模块,往往第一件事就是先进行一个查询,然后对查询出来的结果进行详细的编辑等处理。同样,我们在进行一个对门店的管理操作,往往会点一个小按钮,在弹出窗口中选择一个或多个门店,然后再进行操作,一些日常的报表,比如门店当日销售,门店实时商品分类销售排行,都在业务系统的各个角落分布着。查询的条件也是经常会变动;比如,今天财务可能要对所有商品的税率进行核对,起因可能是国家新的税务政策,这时候,他们要么独立做一张报表进行查询,也可能会要求在商品管理模块中,增加一个对税率的查询条件,从而让各个部门的采购自己核对与调整,毕竟,很多超市有上万个品项,财务不方便自己直接去操作。

特别的,查询还面临一个性能的问题,我们经常看到的自由组合条件查询功能,在性能上有非常大的短板,毕竟当时才2004年,最新的CPU是奔腾4 处理器而已,做数据库的同学也都知道,针对任意组合的查询,由于没办法提前进行索引的优化,性能是无法保障的。

所以,我们采用了SQL构建(SQL,Structured Query Language,结构化查询语言,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统)的方式,你只需要写一个恰当的SQL,工具会自动地构建界面,查询条件只需要进行极少量配置,就可以生成一个查询功能,大到复杂报表,小到点下下拉框显示不同结算条件。在这里,SQL就是低代码的工具。对于复杂业务逻辑的SQL,因为全部进行了拆分,反而变得非常简单。

图片
图片

图源:沈欣提供,来自IDG智能布署平台中搭建设置所有[业务检查]和[业务过程]中SQL用到的参数

在当年的这个平台上,无论是数据对象、业务逻辑、查询,都是用SQL工具来构建的,好处是人才好找,SQL是大学的必修课嘛,而Java、Net的人才,被互联网和游戏公司挖走得太快了……很多企业本身就有一些软件人才的储备,他们一般都精通SQL,可以直接从数据库为企业高管取数,写报表等, 对于这一类人员,大概2周左右时间,就可以非常熟练的使用这个平台。

SQL还有一个很好的优点就是性能高,毕竟是直接对数据库操作,对于一些复杂的查询,我们甚至还可以用临时表来优化,毕竟性能是我们考量的一个重要指标。

凡事有利就有弊,万一某个同学写了一个愚蠢的SQL怎么办?我们在工具中引入了一个性能审计功能,一旦打开这个开关,那么每一条通过平台执行的SQL都会被记录,包括SQL语句,执行参数,执行开始时间,执行结束时间,如果是循环执行某些小SQL,那么循环了多少次等等都会被记录,这样我们可以随时进行性能检查。

特别的,为了提高开发效率,针对常见的需求例如“查询结果计数”,“字段汇总”,“锁定查询结果表格的前几列”等等,都可以用配置方式完成,如果在SQL中针对不同结果(大于0小于0)做出配置,数据结果显示的颜色都可以自动完成,所有SQL生成的查询结果,也都可以挑出几列直接转换为各种折线图、饼状图。对于一个报表查询出来的结果,我们还可以配置成双击某一列,就会自动跳转至另一张报表,同时又自动将该条记录的信息作为跳转后报表的查询条件自动填入。

当然,鉴于OLAP和OLTP对服务器的要求不同,我们还是将特别复杂的查询都独立到业务系统之外,由BI工具来进行处理。

对于一套系统,权限是不可或缺的,对于零售业的特殊情况,还会有一些特别的权限维度,比如,两个人都是采购经理,但是一个管服装一个管家电,他们之间的数据需要隔离,也就是不能看到自己管理的品类之外的数据,这些都在平台的权限配置模块和所有查询模块中内置了,无需再次开发。

图片
图片

图源:沈欣提供 ,来自IDG智能布署平台中的设置功能页,设置系统中的所有权限

我们都知道,灵活的东西往往会失控,因此版本管理也是一早就注意到的功能。

软件开发是一个系统工程,我们可能会同时有三个环境:

一个是开发环境,在这里,可能同时存在几个新的功能在开发,他们可能需要对数据库结构有调整,比如增删了几个字段,这里的开发阶段的代码,和这些调整紧密关联;

第二个是测试环境,在这里,测试人员针对开发提交的代码、新数据结构等等进行部署和测试;

第三个是正式环境,这里有些规模比较大的企业还会设置多个灰度环境。

因此,我们开发的新代码,要到正式环境部署,必须有一个自动化工具,鉴于当时的低代码和功能都是采用了SQL,而且低代码平台自己(界面布局、执行逻辑、配置、数据字典等)也是以Blob方式存贮在数据库中,所以我们开发了一个导出功能,开发人员可以将自己对模块做的所有修改,都以多个SQL的方式导出,只需要将这个SQL包在新的环境执行一遍,就可以完成部署。同样的,也可以进行回滚。导出功能是可以打包进行的,如果我们给出了表单的各字段范围,还能够进行一定程度上的自动测试。

C/S架构在录入大量数据时,本地其实有个缓存,我们也利用了这个缓存做出了一些比较接地气的功能,比如录入个几百条数据,尚未提交,中途断电,当你打开电脑,会惊喜的发现数据都还在。C/S软件在录入的时候,执行效率比较稳定,因此,有很多盲录的高手,一边看着左边的打印文档,一边手指如飞的在键盘上敲编号,回车,敲数字,回车,这个也在系统中专门做了支持,如果录入的内容较多,还支持直接从Excel中拷贝进入剪贴板、直接粘贴进系统。

软件开发离不开文档,为什么后续的程序员都宁愿推翻重来而不愿意去修改代码,因为读代码太累了,有些稀奇古怪的功能背后是业务的差异化与特殊性,这时候,我们设计了一个文档工具,文档与模块紧密集成,可以记录每一次迭代的需求来自哪里,还可以记录对应的迭代版本做了些什么设计,形成了一个连续的研发体系,同时,平台可以帮助开发人员忽略掉那些常量、变量、内存回收、错误提醒的高代码,平台解耦了那些业务对象与业务逻辑以后,可以使得开发人员专注在实现业务功能的SQL代码和逻辑关系上,从而让软件的维护与迭代变得非常轻松。

在导出功能之上,还有一个逻辑导出的功能,将每一个业务逻辑以文字标题的方式按模块导出,目的是让不懂开发的业务人员可以通过这个逻辑导出的文字清楚的知道,这个审核按钮到底干了些什么。毕竟,我们问100个采购总监,99个都不会清楚系统到底干了啥。

图片
图片

刚才我们提到了流程,BPM工具其实一直做的不错,当然当时也有性能瓶颈的问题。在研发过程中,我们做了两个功能:

第一,业务逻辑可以和外部流程打通,比如发送短信、调用及回调OA流程等,可以方便的对接外部流程,满足标准审批的要求;

第二,在软件首页加入一个可以配置的流程图,这个流程图和权限系统集成,因为我们发现,零售从业人员更换频繁,他们碰到一个新的系统,往往会问的是俩个问题,“这个功能在哪里?我在干这个事之前需要先干(看)什么?”这个首页的流程图可以根据不同岗位的工作性质,加入常用的功能流程。

比如,先是一个超链接到FTP上的一个文档模板或者在线文档,填写上交,然后进入某个具体功能模块,填写数据,再进入某个报表,根据指引看一下报表发现问题,然后再打开某个具体功能模块做一些单据来解决刚才报表里发现的问题。在实施过程中,就可以帮助客户构建这个流程图。

随着服务客户的规模增长,性能还是一个无法摆脱的瓶颈,这时候我们发现配置的业务逻辑、业务对象,完全可以部署在不同的服务器与数据库,因此后来迭代了一个多数据库配置功能,可以指定某一个业务逻辑、业务对象、查询是在哪一台服务器上执行,也算是分布式部署的一个雏形,的确大大缓解了性能问题。

平台成熟后,我们将一直用于内部开发的工具整理了一下,加入一些常用的功能,在实施过程中我们直接给予客户培训,教会他们如何使用,后期的80%左右需求都是客户自己的几个懂SQL的同学自行迭代维护,客户省下了二开成本,我们突破了实施的运维的瓶颈,双赢。

从提出这个平台的设想到原型,大约5个开发人员加4个测试,花了半年时间,然后用了一年时间全面替换了客户的原有系统,2009~2010年,该平台进行了一次B/S迭代,从C/S架构平移到了C#.NET构建的B/S体系,2014年左右,又迭代了一个Java的版本,并可以在微软云的Azure SQL 上执行,2016年支持H5,2018年开始支持微服务架构,意味着原来执行的SQL可以全部替代为执行微服务。

同时,所有的业务逻辑业务对象也可以以微服务方式对外提供服务,十四年的时间内,系统的底层结构一直没有大的变动,只是适配了多种数据库,用不同语言重构了解释器。正是因为底层几乎没变,2019年还帮助十年前的客户马来西亚Sunshine集团进行了平滑升级,从C/S架构升级为基于云服务的B/S体系。

虽然从2017年开始我本人就没有再参与该平台的商业化迭代与开发,但是纵观系统的整个演变过程,我们认为,低代码完全可以用于复杂的大型核心应用,当低代码插上了云+微服务的双翅,犹如鲤鱼化龙,足以胜任企业内的大部分挑战。

以上就是这个十八年前(现在是2026年应该为22年前)的“低代码”平台从构思、到设计、研发、落地、应用的整个历程,我们可以看到,如果有对业务的深入理解,有着架构性思维体系,有面对复杂的体系进行抽象的能力,是完全可以用低代码做出一套可用、好用的核心业务系统的。

大道可以传承,也可以自悟,只要你的思维方向正确,又愿意投入时间去研究,前人能够做出来的,我们也一定能做出来。这篇文章希望能够给低代码从业人员和甲方人员一些启发,帮助大家少走一点弯路,少踩一点坑,就功莫大焉。

作者介绍:

沈欣,1996年开始从事软件开发,现为弯弓研究院联席院长/一级研究员、广东省连锁经营协会技术委员会主席、上海交通大学终身教育学院特聘讲师、中国信通院低代码/无代码推进中心技术专家、腾讯TVP智慧零售行业大使。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档