xufei / blog

my personal blog
6.67k stars 762 forks source link

从前端角度看企业软件的研发过程 #51

Closed xufei closed 3 years ago

xufei commented 5 years ago

这是一篇我想写了很久的文章。一直以来,企业软件前端工程体系处于一个很尴尬的局面,无数前端对它有过各种吐槽:技术栈老旧、封闭,体验差,而项目和交付经理又会觉得开发效率太低。据我所见,大部分吐槽的人并没有理解造成这些状况的深层原因,或者说,当自己去构建这么一套体系的时候,并不理解在选型和技术集成过程中,存有哪些可能的决策点。

本文尝试从一些角度去给出自己的见解,为了说明构建这个领域前端技术体系的种种考虑,同时也会述及对应的业务特性。

业务特征

目前存在的企业软件,一般是以两种形态运作的:

通常来说,前者更侧重于通用性,价格较低,复杂度一般不会特别高;后者一般提供了各种可能的定制,但价格较高,可能会有非常复杂的形态。

价格是企业选择软件的一个很重要因素,所以我们能看到,很多客户在选择软件的时候,对功能点的选择非常精细,有时候不得不舍弃一些相对次要的功能,而且,他们常常会抱怨软件实在太贵了,也并没有那么好用。

另外一头,从软件开发商的角度看,需要尽可能避免一次性的定制需求,需要努力把它们复用到其他客户那里,以此来摊薄开发成本,所以,会需要从各种角度去提高需求的复用率,降低一次性开发成本。

从刚才提及的两种部署形态来看,都有一些问题需要解决。

云端 SaaS 模式的软件,一般会从工具属性或者行业角度入手,较好地满足通用功能,一般面临的问题是可定制性。用户往往借助垂直能力,或者是通用行业模板,解决了自己的第一步问题,但随之而来,就会有更多的诉求:

中小企业在成长过程中,不可避免会需要这些诉求,SaaS 系统应当有随之成长的能力,这才是不掉队的本质。因此,当侧重于工具领域,比如:IM、协同、知识库等体系的 SaaS,其后必定需要开放很大程度的开放与定制能力,要不然,多系统集成一定会成为一个巨大的瓶颈。

我们可以参照电子行业的发展来看待问题:

几十年前,市面上存在很多各类专用设备,比如说,导航设备,那时候会有不少厂家,定制一个小的机器,然后在其上跑专用的软件。用户为这个功能所支付的价格,实际上是软件加上这个硬件的总和。再比如,数码相机,它仍然会需要有一个机器,尽管用户所需要的只是其拍摄、预览与存储能力。

现在来看,这类设备的销量大幅下降,因为手机这样的通用设备的能力得到了增强,硬件部分被合并同类项了。

那么,我们可以问自己一个问题,软件也会这样吗?

软件的同类项是什么?

是 IaaS 吗?
是 PaaS 吗?
还是?

我们是否应当为业务之外的附属基础设施,支付重复的费用呢?

回头再看企业私有部署系统,通常面临的问题就更多一些,但大部分问题都是在下面几个方面:

私有部署软件价格高的原因有两个方面:需求复杂,开发代价高。需求的复杂是不可避免的,这是业务方的原生复杂度,而需求的沟通反复,则往往成为此类交付的核心痛点,与之相比,连耗费巨大的定制化开发过程都不可避免地成为其附属环节了。

几乎所有这个领域的软件交付厂商都很早就采用了大中台,小前台的作战方式,然而在实践过程中,仍然会因为前台部分过重,中台部分难以很实际地对前台产生帮助,形成一种非常尴尬的局面,最终导致双方的互相不信任。

我个人认为,这个问题的症结在于中台支撑能力的偏弱。传统意义上的中台支撑,其技术化程度较高,往往是提供各类中间件、组件库、约定研发模式、构建发布、持续集成等等底层能力,但是在另外一件事情上做得不够远,那就是业务描述能力。

什么是业务?如何描述业务?

谁有业务抽象能力,谁就会赢得下一轮竞争。这个竞争的关键,一定不是因为你提供了多少种中间件,多少种组件,那些只是底层可扩展的能力。

中台能力

所谓中台能力,不仅是指在一家软件公司里,其中台团队对业务研发团队的支撑能力。整个一个软件公司,对客户来说,也应当相当于一种中台能力,那么,到底提供怎样的能力才能有助于各行业的发展呢?

很可能一线互联网公司的研发人员还是很难理解其他一些公司的痛点:

这其实是个很难的问题,先不说多数公司是很难养得起一支高质量研发团队的,即使愿意出钱,也未必养得出。一家传统行业公司的平均薪资是取决于它所在行业的,大部分行业都达不到 IT 和金融的收入水平,他不愿意付出媲美一线互联网公司的薪资就会招不到人,他愿意付出这个薪资,就会导致自身企业中的一些意见,人性大抵如此。

因此,很多公司的软件都面临一个问题:

这个过程是非常痛苦的。如果把软件公司自身作为中台,其核心价值应该在两个方面:

当这两个能力比较好的时候,需求变更所造成的反复成本就可以缩小,业务方,无论是自身业务,还是客户那边,都更加有机会去把 IT 系统尽快调整到适合自己公司的业务发展需要上。

技术细节的屏蔽、可扩展性的支持,对这两者的权衡,将成为技术中台成败的关键因素。

开发技术

作为软件形态的一种,企业软件除了共性的问题,比如需求的正确实现,一般还需要重点考虑以下几点:

这几点,几乎是影响大部分企业软件生死存亡的要素。所以,通常会需要在自身的研发过程中,去产生各种各样的快速研发、需求分支管控方案。

前面我们提到,对业务的描述是一个核心竞争力。为什么呢?

因为几乎所有软件企业,都不会希望自己做的东西是一次性的,都希望能沉淀,并且尽可能作为一种平台能力,交付给其他客户使用,以达到同等成本下,盈利的最大化。

在面向行业的交付领域,我们一定能听到这样的描述:给客户甲提供的某某功能,客户乙也想要。他想要,怎么给呢?

传统的研发管理,其分支是基于代码的,代码实际上是一种很底层的抽象,尤其因为跨越了多个不同技术栈(服务端、Web、客户端),导致很难去描述:这个需求改了哪些地方,也就因此,很难去描述业务的增量与合并。

所以,在不同项目、不同分支之间迁移需求,对研发人员来说,是一个非常苦闷而麻烦的事情,这也就是“描述业务、解释业务”的意义所在。我们需要把业务描述成一种线性的东西,去除抽象细节,可以升级,可以 diff。

对业务的抽象,除了有助于研发过程,还可能让懂得业务的人员参与,甚至拉动客户侧的一线人员,共同参与改造升级自己的业务过程。从一个大的角度去看,中台定制能力的低技术门槛化,必定是一个长期趋势。

人员分工

当前,一个有意思的问题是:在你心目中,按照角色划分,企业软件前后端开发人员的比例应当大致是怎样的?

最近几年被谈得很多的一个名词是“前后端分离”,处于不同场景的人对它做出了不同解释。虽然在分界、实践路线上各有差异,有一个共识是:这意味着前后端工作职责的分离,前端去处理偏展示的部分,后端侧重于存储和服务相关的逻辑,两者通过某种基于接口描述的约定来协作。

在企业软件领域,有很大一部分应用至少十多年来都一直就是这么协作的,大部分把分界点定在 HTTP 请求这个位置,这是一个比较天然的分界,两侧的代码执行过程分别位于浏览器(或者广义的各种端上)、服务器。

前后端的职责分离,有时候又会带来协作上的麻烦。大部分的业务,无论前端还是后端,复杂度都没有到很高的程度,如果职责分离所带来的协作成本大于同一个人,往往就不如“全栈”。

全栈是一个筐,什么都可以往里装。通常这么一个全栈业务开发人员,需要同时有两种不同的开发和构建环境,有各自的包管理机制,编程语言和范式。虽然他的职责专注于业务实现,可是常常要在不同的工作上下文中切换,包括编写不同模块(前端,后端)所导致的思维方式的转换,而工具复杂度往往也造成了一定程度的困扰。从协作关系来说,我们应当想办法降低至少一端的工程复杂度。

全栈并不是只有全部使用 JavaScript 开发这么一个选项,这只是一种可能的方式:我们选择了把后端轻量化。但与之相对,也有一种把前端轻量化的方式。

多年来,人们尝试以不同的方式编写视图,有一种东西叫做 GWT,业务开发人员使用 Java 来编写视图代码,然后构建之后,生成 JavaScript 在浏览器中执行,这也是一种实际能够运作的机制,在某个时间段可能是异端,可是:为什么我们能够接受用 TypeScript、CoffeeScript、Reason、Elm 去编写 Web 视图,偏偏就觉得使用 Java 很奇怪呢?

语言并不是我们需要重点关注的东西,我们还是把目光投向视图本身。

即使是今天,我们仍然可以看到一些很奇特的东西流行着,比如 layui,在很多前端眼中,这是一个很过时的东西,然而,这并不影响很多开发人员选择它,而且,用它来开发业务,似乎效率也没有低很多。

这可以说明一个问题:在存在大量封装组件的前提下,具体在使用哪套技术栈开发,其实对研发效率并没有实质性影响,提高研发效率的东西是组件库,而不是某种具体框架,因为在存在约束的前提下,业务开发人员实际上只使用了这种框架一个非常小的子集。平台侧的技术人员所需要掌握的各种细节能力,业务开发团队并不一定需要全部掌握。仅仅写个 CRUD,就需要懂得各种编程语言底层理念甚至范畴论,这很明显是有问题的,这类方式也因此不利于周边生态的发展,对于阿里这类尝试连接天下的各种行业大中小企业的生态核心企业,其严重程度很可能远超想象。

为什么 VueJS、微信小程序这类东西,大家都认为技术细节上存在许多可改进的地方,然而其用户群体却一再增大到难以想象的程度,一线互联网公司的精英派开发人员跟这个社会的大环境到底存在多大的隔阂,为什么中国共产党从农村起家,最终击败了精英派的国民党反动派,其原因值得深思。能让多少人参与进这个事情,很可能才是决定走到多远的关键因素,我们没有理由放弃社会中的每个人,仅仅因为他不能很快学会你熟悉的技术栈。

所以,长远而言,如果我们拥有了描述业务的能力,则研发过程的细节都是可被抽象,可被在底层升级的,这不是每个人都需要去关心的事情。我们现在用手机,并没有几个人去关注它的 CPU 集成了多少个元件,屏幕上一个像素点到底由什么东西组成,它们都被抽象掉了。

另外一个方面,开发方式也需要考虑成本。交付型项目的盈利很大程度上取决于成本控制,一线互联网公司的开发人员普遍是意识不到这个问题的,因为本质上他参与的研发项目是不计成本的,他不需要去关注人员的薪资,上下游环节配合等相关的成本因素,但在交付领域,这些全都是问题。

推而广之,业务软件的研发流程也是一个很可怕的事情。当我们面对一个业务的时候,按照一线互联网公司的通常做法,会发现流程是非常长的:

在此过程中,一旦产生变更,则基本上要涉及全流程的每个人,其沟通代价是阻碍高效交付的核心问题,所以,在业务侧的全栈化必定是一个非常重要的事情,否则成本无从控制。这些角色中,最好只存在产品 + 研发两个大角色,甚至在轻量业务中,借助平台能力,让二者进一步合并。

收拢角色的前提就是,每个环节需要砍掉过于灵活的可定制性,这个过程非常痛苦,并且非常考验抽象能力,但在大的生产过程中,则是非做不可的事情。

我们能给业务侧提供什么样的能力,这是平台侧研发人员需要时刻思考的东西,不要强求他变成你这样的人,才能用你的东西,要时刻从全流程的角度去看问题,找到阻碍生产力提升的地方,并且去改造它。

设计体系

我们谈企业软件领域的前端,就绕不开设计体系。一直以来,企业软件领域的设计风格都以丑陋、风格过时等缺点广为诟病,谈及这个问题的时候,就需要阐述这么一个答案:企业软件领域好的设计风格到底应该是怎样的?

近年来,我们可以看到以蚂蚁 Ant Design,阿里 Fusion 为代表的,包含设计理念和组件库的一体化方案,各自的主打也都是企业级产品、中后台领域,那么,它们会是这个答案吗?

前不久有一篇文章,对比了 Ant Design 与 SAP Fiori,这篇文章的结论我很不认同,并不存在两者相比谁更优秀的问题,而是两者目前并不处于同一个维度上。

企业软件领域的设计体系,在我看来应该包含以下部分:


我们能够看到,互联网企业推出的常见的设计体系,往往都在场景上比较固化,很侧重并依赖于单个:搜索+列表+表单 的场景,对于更复杂的组合,或者是高度集成的单一视图,则缺乏指导性。

从逻辑上讲,因为一切视图背后隐含的逻辑都是数据库表操作,都可视为单表 CRUD 的聚合,或者是包含了事务的这些 CRUD 的组合,那么,如果不介意思维上的关联,我们大可以用单表管理的方式描述一切业务,或者稍复杂一些,使用主从结构的视图来管理一对多的关联表。

这个逻辑,是目前市面上存在的一些产品的理论依据,比如说 airtable,它就围绕对单表操作的各种形态,以类似 Excel 的操作体验去完成各类业务系统的定制。

我们目前所能看到的各类管理系统,出于降低开发者心智成本的考虑,很普遍地使用了这样的设计,所以大家的界面千篇一律,一切业务都是一个管理控制台,每个页面所呈现的东西都比较有限,除了聚合的 Dashboard,一般界面上放三到四块东西就结束了。

需要注意的是,尽管这样开发出来的系统,从整体感上已经不错了,但整体体验应该也就是在及格线上。为什么呢?因为前面我提到,这降低的是开发者的心智负担,而不是使用者的。

从业务使用者角度看,他们可能存在很多诉求:

业务系统设计上的难点在于:

我们再回头来看之前提到的 Ant Design 和 SAP Fiori 的对比,会发现前者在一些细节上面有明显优势,但体系化方面则跟后者存在较大差距。

所以,如果从一个大型企业角度,整体看待设计体系,会要求更多的一致性,并且,在业务上提取更多的通用准则,这些准则可能是严格的,而不是倾向于宽松。

比如说:

某个数据表格中,行内有“修改”、“删除”这类的按钮,这个按钮的大小,什么行为的按钮应该是什么颜色,都需要去做约束,而不是任由开发人员发挥。

一个用于承载业务的中台体系,如果不收敛其设计规范和前端组件,则必然导致研发流程的反复性增加。

总的来讲,从设计形态上看,倾向于“约束”而非“发挥”。而在清晰定义并描述了这些约束的前提下,很多能力应当成为默认拥有的。防止出现不符合设计规范的东西出现,提供无需额外配置就默认达到 60-80 分体验的能力,这才是业务设计体系的实质。唯其如此,才有可能精简从产品到研发中间的环节。

前端架构

不适应业务的架构是失败的,作为工程与架构管控者,需要时刻思考在自己所处的环境下,存在什么痛点,什么环节,人员结构如何,主次矛盾分别是什么。

前端这个角色,受开源技术体系的影响太大了,很少人意识到:很多工程体系、库,都是需要被整合了再使用的。其整合方式取决于整个研发体系的业务形态与人员结构。

作为前端,可以尝试问问自己这些问题:

具体到企业软件前端领域,总的来说,可定制性会是一个很重要的方面,有一些可以关注的方面:

视图特征

企业软件视图层面的几个基本特点:

基础组件库

一般来说,组件库是大家都会注意到的技术依赖项,它在构建一个大型软件的过程中,几乎是必不可少的,不同的团队拥有对组件库的不同控制力度:

在这里,组件库的实现技术并不算特别重要,更重要的是对业务场景的覆盖程度。

业务组件

前端团队很容易对“业务组件”这个东西产生盲目而不切实际的追求,实际上,在企业领域,绝大部分“业务组件”是没有价值的。鲁迅先生教导我们:

其实地上本没有路,走的人多了,也便成了路。

这就好比是我们企图抽象一个大粒度的业务组件,给外界开了一些配置项。

但久而久之,配置项越来越复杂,比组件自身的内部实现还复杂了。

走的人太多了,处处都是路,又没有路了。

视图其实是:Model - ViewModel - View 的最外延,每一层的灵活程度逐次增加,自身其实就可以视为一种配置文件了,在配置文件里抽组件,很可能是性价比最低的事情。

前端需要把视野往全局去放,才能在这个事情上找到更合适的权衡。

工程设施

时至今日,前端已经有了相对“正式”的开发环境,我们可以基于更先进的语言特性、更强大的工具去构建组件库或者业务视图,这些都是工程设施的重要组成部分。

然而,现在主流的前端构建体系,不一定非常适用于企业软件研发这么一个受限的领域。大如阿里的某个大部门,其 Web 系统数量可能上千,而公共的直接依赖项则未必过百,每次构建都要带着这些东西一起处理,对容器集群来说是不是一种巨大浪费,值得深思。

依赖管控

随着现代工程设施的引入,前端有了更明显的依赖管控机制,这个事情是一个双刃剑,一方面能得到更强大精确的依赖控制机制,另外一方面,引入了一些管理复杂度。

与构建相关的事情综合考虑,究竟是不是存在一个“公共基座”的东西,让业务方无需关注这么细节的组件版本升级、关联构建等机制,都是可以去探索的。

此类事情可能很多,其大的原则就是一个:开源技术栈应该经过怎样的定制和管控,给什么样的业务开发人员提供怎样的抽象程度?

小结

在我看来,一家理想的软件企业,其研发管控能力的分水岭应当是:能否升级自己 3-5 年前给客户交付的系统。这个事情非常难,但如果不难的话,又怎么会有机会呢?工程师的实质就是在给定的资源条件下,寻找目标的最优解。

天生我辈,自当无惧其深,不惮其远,上下而求索。阿里有句老话:路走对了,就不怕远。

zephyrpersonal commented 5 years ago

太应景了...早上还在和领导argue其中一些问题,心中甚为不爽。但看叔的思考,感觉自己路并没有走偏,欣慰。

tearf001 commented 5 years ago

很深入的探讨 要是软件行业的论文形式是杂志期刊,那么徐sir的诸多论文应该积累不少"教授分"

不说软件,建筑工程技术一样有这样的问题 比如,深基坑工程,其支撑结构在不同的城市,不同的施工企业有着完全不同水平的实现,一个体系足够大之后,总会有这样那样的问题.

差别是,工程经验越多越好,越老越香,软件经验积累有时候是负担,建筑工程专家技术上的突破到推广周期非常长,软件工程更像是头脑风暴

软件复杂,因为是世界的投射,最终软件会改变世界

guanpu commented 5 years ago

特地从ata追出来点赞

ayqy commented 3 years ago

业务组件一节有点意思,“处处都是路”其实不是坏事(不应该等于”又没有路了“),如果条条大道通罗马,无非是增加了一些选择成本,生产效率一定是高过每一次都开荒开路的。

无论业务组件还是基础组件,在我看来都是为了通过复用提升效率,分为3个阶段:

  1. 没有可拿来即用的现成东西(即没有路):开路。从此有了第一条路,紧接着出现了很多条路
  2. 有很多可选项拿来都能完成(即处处都是小路):选路。从中选择“最佳”实践,此时不能叫没有路,因为无论走哪条,成本一般都低过自己开路
  3. 采用最佳实践共识而无需选择(即一条主路):走默认的主路。最佳的小路下沉到环境中,成为默认,(该类业务场景中)不再有选择成本

从2到3需要个演进过程,但只是时间问题,真正难的是主路的规划,如何保障主路不会腐化回到2?这就要求控制好粒度,在“久而久之,配置项越来越复杂,比组件自身的内部实现还复杂了”之前,踩住刹车,重新审视城市规划,是否需要批一条新的主路,它的作用是什么?

wanghaisheng commented 3 years ago

所以,在不同项目、不同分支之间迁移需求,对研发人员来说,是一个非常苦闷而麻烦的事情,这也就是“描述业务、解释业务”的意义所在。我们需要把业务描述成一种线性的东西,去除抽象细节,可以升级,可以 diff。

业务描述这里可否展开说说 有啥好的方式吗