今天给大家带来的是 2B 范畴的一个架构难题,咱们终究也没有找到一个较好「处理」方案, 或许说它本来便是一个伪命题。
让我渐渐跟你道来…
软件的区别方式
首要从软件系统的区别方式讲起。软件系统的区别有许多种方法,拆分的意图无非都是:分治、复用、阻隔、扩展性、笼统等等。
最为常见的便是分层架构
分层架构将软件系统区别为若干层次,每个层次都是相互独立的,各自担任不同的功用和职责,经过清晰的接口和协议进行通讯,然后完成系统的可扩展性、可保护性、可测验性、可重用性等特色。
比方一个典型的 Web 系统的“三层架构”:
-
表明层(Presentation Layer)
:担任用户界面、用户交互和用户输入输出等功用,经过 Web 页面或许客户端应用来展现和操控数据的呈现方法。 -
事务逻辑层(Business Logic Layer
):担任系统的事务逻辑处理、数据处理和其他事务规则的完成,为表明层供给数据和事务逻辑的支撑。 -
数据访问层(Data Access Layer)
:担任数据的存储和访问,为事务逻辑层供给数据访问的接口和完成。
微服务架构
跟着系统的复杂化,咱们需求将系统拆分为更小的子系统,来处理性能、保护性、扩展性等诸多问题。比方引入了微服务、微前端等处理方案,这个本质上是一种笔直方向的拆分
:
乃至咱们在应用内部还会进一步拆分, 依照事务聚合度拆分红不同的模块:
这便是分治的魅力吧。
多业态
在 2B 范畴,让咱们更扎手的是,还要面对多业态问题
。
什么是多业态?
让 ChatGPT
来解释一下:多业态是指一个企业或许品牌在不同的事务范畴或职业中具有不同的业态,例如同一个品牌既能够开设餐厅,也能够开设酒店、咖啡店、快餐店、影院等不同的业态。多业态的企业或品牌经过在不同的业态中供给不同的产品和服务,以满意不同顾客的需求和偏好,添加企业的收入和商场份额。
多业态并不是一种结果,而是一种手段。比方在笔直范畴耕耘多年的企业,想要扩展创收,就会将触角伸到其他职业,即所谓的跨界。还有便是一些初创企业,就像无头苍蝇一样,将网撒向不同的职业,来探究出路。
咱们便是属于后者。不过也有或许前期策略是在仿照有赞
的嫌疑(究竟有赞在 18、19 年是当红的 SaaS 炸子鸡),铺设了许多职业:医药、教育、文旅、零售、地产、汽车…
也便是说在这种「广撒网」的商业策略下, 咱们需求在「一套代码」中适配“多业态”:
然而多业态并不是简略的笔直方向
的进一步细分,而是多了一个维度
。如果说分层是 1D、 笔直区别是 2D、再加上多业态,便是 3D 了!
这些职业多态
会横向击穿笔直拆分后的模块壁垒,职业的多样性会渗透到程序的各个旮旯,开闭准则形同虚设。不管是前端仍是后端,这是都是一个非常大的应战。
现状便是本文标题中讲的,多了一个维度之后,对开发而言是灾难性性,整个项目便是一个大泥球。
一切职业的代码都堆砌在一同,充满着各种区别职业的 if/else 语句、耦合牵扯、渗透在项意图各个旮旯… 总之这或许是程序生计难得一见的代码屎山!
给大家一个直观的体会
笔直的软件拆分有许多方法论,比方微服务、 DDD。而多业态,在软件职业并找不到太多这样的最佳实践。
且不管这是否是战略上的错误。作为技能开发咱们只能遵守它, 并需求在战术上进行弥补。企业对软件开发的要求并不会因而降低,它仍是会要求你的代码要区别「复用性」,要能快速应变各种需求、支撑快速迭代…
产品架构
上图是咱们团队根本结构,也是产品结构
(康威规律)、更体现了咱们的项目交给方式
。许多非 SasS 化的 2B 公司的应该都是这类方式。
对咱们来说更大的应战在于:下流的项目能尽量复用上游的功用,防止重复作业,并且要求上游的更新能向下传递,乃至不排除下流兼并到上游的或许性。
能感受到它的难度了吗?
怎样处理?
战略上的调整
从近几年安排架构上面的调整,能够反映软件架构的战略调整,它定下整个研制系统的基调。别的这些改变,也反映了咱们对 2B 职业探究和认知上面的改变:
初创团队便是一个单体团队(左图所示),接着开端多职业撒网,原本的项目上渐渐堆砌出各种职业的形状(右图所示)。
跟着事务发展起来,一些发展较好的职业成立了事业部,专门担任项意图交给。
跟着职业的深化,事业部渐渐堆集起来了更多职业 Known How
,通用的标品现已无法满意需求,事业部开端成立职业标品团队
,在职业标准化产品上做更多深化的定制开发;别的事业部内部持续细分专门的交给团队。
职业 Known How 指的是某个职业内部特定的、非揭露的常识和技能,一般只有在该职业内部的从业人员才能够把握和理解。这些常识和技能或许包含职业内部的标准、工艺、流程、技能、经验等方面的内容,是职业内部的中心竞争力和商业机密。
到这个阶段「产品研制」开发的「标品」就处于一种比较为难的方位。一来它究竟不是为特定职业打造的,现已不能满意职业的定制化需求,无法完成开箱即用;二来产品研制部门离实在的客户也比较远,很容易凭空捏造,产品没有经过商场打磨,质量较差。
人们开端对「产品研制部」的价值产生了怀疑。
于是「产品研制」的出路是持续做下沉,不再做所谓的大而全标品,而是做好中心的渠道化才能
,比方会员系统、CDP、SCRM、MA(Marketing Automation)…
这些渠道化才能,剥离了详细的职业特点,并向未来的 SaaS 化挨近。
多业态的架构难题,从笔者的视点来看,在战术上是根本是无解的。经过上面的战略调整能够看出,咱们渐渐规避了这些问题。
也就说,咱们没有处理它,而是绕过了它,乃至说咱们抛弃了这条道路也不为过。
经过上面的调整咱们能够看到:
- 掩盖的职业在渐渐收敛,不赚钱的、走不通的职业爽性就抛弃了。
- 另一方面,在详细职业和渠道上愈加专注,不再寻求打造一个大而全的、能够掩盖多职业的单一产品。
战术上的适配
尽管,咱们终究经过战略上的调整规避了多业态架构难题,但这究竟是「果
」。推动战略上调整的「因
」,并不是因为战术上的施行难度,而是企业的商场适应。
尽管战略的调整能够从根上处理了问题,但这是一个绵长的演进进程(大概五年)。 一开端咱们也预料不到现在的结局。因而在过去适当长的时间内,咱们一直都在尝试战术层面
去处理多业态问题。
下面讲一讲,前端是怎样应对这些问题。
准则
首要建立一些行事的准则,作为后边详细施行的指导方向, 比方:
- 统一标准。完好的项目版图规划到许多团队、上下流的参加,咱们必须统一标准。
- 保持交流。因为咱们需求拉通上下流,进行一些常识和代码的传递,交流是很重要的。
- 更新/联动,阻隔/复用机制。咱们需求在结构层面供给代码上下流更新、联动,复用、阻隔等机制。
- 生态共建。规定上下流团队需求一同共建生态,沉淀常识和职业 Known How.
- 互不影响、独立开发、独立布置。
- 开闭准则。对下流扩展敞开,对修改关闭。
- 分离重视点。
建立共建的规模和上下流的协作关系
即定义了一些团队之间的协作标准,比方:
- 上下流团队之间职责区别、共建的规模
- 交流机制
- 发布更新的频率和方式
- 分支标准等等
微观上:职业阻隔/事务聚合
在微观的层面上,定义了两大方法或主张:
-
职业阻隔。为了阻隔不同业态,咱们提出了两个方法
- 分支阻隔。不同业态有不同的分支前缀(比方
团队名/dev
、团队名/master
),然后做到开发上互不搅扰。能够从上游标品团队的分支中单向兼并
,来完成下流同步 - 模块/文件的阻隔。在这里咱们主要运用
业态扩展名
, 比方index.js
、index.ky.js
、index.home.js
, 有点类似于React Native
(*.android.js
,*.ios.js
) 或许Taro
的特定渠道文件。在编译时,根据当前业态进行条件编译。
- 分支阻隔。不同业态有不同的分支前缀(比方
-
依照事务聚合。模块依照事务进行聚合,而不是根据菜单/功用:
- ❌ 菜单。这个问题主要出在 B 端,许多前端理所当然会依照导航菜单来拆分应用,问题便是菜单并不一定能准确地表达事务的鸿沟,而且菜单是多变的,受运营的影响比较大。 这个我在 微前端的落地和治理实战 中也有讨论
- ❌ 功用聚合。例如, 全局依照功用区别目录,一切事务模块都堆在一同
src /components A.js B.js /pages /api /...
- ✅ 事务聚合。依照事务范畴的鸿沟进行笔直的拆分:
A 范畴 /components /pages /api B 范畴 /components /pages /api
微观上:复用和扩展方式
微观的分支、业态扩展名能够完成职业阻隔
,让多个团队在同一个库房下互不搅扰,又能够交融开发。
而微观上层面,主要重视代码的复用和扩展机制,意图则是让职业能够最大限度地「复用」标品
的功用和代码。
笔者在实践进程中,总结了许多「规划方式」, 比方:
方式 | 创意来历 | 概要阐明 | 适用场景 |
---|---|---|---|
原子才能组合方式 | 低代码渠道,前端组件化建立,流程编列 | 先对应用程序进行分层,再组成拆分原子才能。完成自上而下的可组合。 | 应用的整体架构 |
插件方式 | VSCode、各种支撑插件的工具 | 分离重视点,提取中心才能和外壳。经过插件接口扩展中心才能。 | 固定、安稳的事务 |
钩子方式 | 许多 Web 结构都供给了钩子函数、或许生命周期方法,对结构进行扩展 | 预留插槽,按需填充。 | + 合适比较固化的事务流程,比方登录、下单 + 合适比较固化的界面布局,经过插槽扩展某个区块的显现 |
掩盖方式 | 依靠注入 | 经过依靠注入掩盖原有的完成 | |
承继方式 | 类承继 | 在掩盖方式基础深化定制 | 完成文件级别的掩盖,完全重新完成功用。和 index 导出兼容。业态阻隔 |
重复/阻隔方式 | React Native、Taro 条件编译 | 无可退路的退路。拷贝代码,深度定制,互不搅扰 | 差异性较大,没有合理扩展方案的情况 |
因为文章篇幅原因,关于这些规划方式的细节,请移步到这里
没有银弹
在多业态的架构难题上,笔者并没有想到卓有成效的方法。反而跟着战略的调整,这个问题变得不再重要。
上文介绍的战术适配,也仅仅能够完成「阻隔」问题。而「复用」问题,我只是给出了一些规划方式,实践执行起来比较困难:一则是需求的改变和多样性足以打破各种夸姣的假设; 二来这会提高复杂度,不是一切开发者都具有良好的架构规划素养。
最后,跟着商场的改变,驱动企业战略上的调整,企业家逐步抛弃了在产品上做大做全的梦想。 咱们的各种挣扎,终究不过是炮灰,并没有太多实践的意义。
当然,对我来说也不是一无所得,历史经验教训:
- 不要过度寻求复用。它是一把双刃剑,重复不见得便是坏事,咱们需求在复用性和阻隔性之间权衡利弊。
- 不要寻求大而全。更要做深做精。
- 用奥卡姆剃刀做减法。抛弃那些不切实践的梦想。
- 战略和战术配合。不要只在战术层面钻牛角尖。
- Keep it simple and stupid。 简略便是美,在规划和开发进程中,尽量寻求简略和易于理解的方案,防止过度规划和复杂性。重视用户最中心的需求。
本文完,求赞求收藏求转发。