模块是 Korat 给出的答案。用一个应用同时服务餐厅、酒店、诊所和零售店,麻烦在于:诚实的版本是四个共用登录的应用,不诚实的版本是一个设置界面大到每家店看到的大多是与自己无关的东西的应用。Korat 走第三条路:业务类型选中模块,模块搭出界面,而公开主页和店主控制台都不硬编码任何关于“餐厅是什么”的知识。
模块契约
一个模块声明一组固定的东西,应用据此拼出其余一切。它给出一个 id;它认领的业务类型,决定这个模块是否适用于某家店;一个标签和一个目录标题;一个主行动号召,也就是顾客页最先呈现的那个按钮;以及一个目录视图——餐饮是菜单,住宿是房型,诊所是服务项目,零售是商品。
另外四项声明是可选的,而系统的价值正体现在那里。模块可以声明能力,它们会成为可分配给员工角色的新权限;控制台磁贴,出现在店主的仪表盘网格里;一块自己的控制台界面;以及一段面向顾客的页面区块,注入店铺的公开主页。四项都不声明的模块就是一个纯目录;四项都声明的模块会同时重塑应用的两侧。
另外还有一套共享 UI 套件——主 CTA 按钮、目录行、标签片、区块标题和空状态——模块应当基于它构建。这不是为了统一风格而统一风格:它是让一个单独编写的模块看起来像应用的一部分、而不是一块嵌入式挂件的原因。
四个核心模块就是业务类型
四个核心模块根本不是扩展;它们就是“业务类型”这件事本身的含义。餐饮认领 restaurant 和 cafe。住宿认领 stay、hotel、resort、apartment、condo 和 village——六个标签、一个模块,因为共管公寓的出租和民宿的一晚,差别在措辞而不在机制。服务认领 service 和 clinic,其中诊所变体把界面改称预约、患者和疗程,而不分叉代码。零售认领 retail。
因为它们是模块而不是一屏巨型界面里的分支,餐饮模块的厨房显示屏和选项组对一家酒店来说并不存在——不是藏在开关后面,不是被禁用,是不存在。一家店看到的界面面积,是它自称是什么的函数。
七个可安装扩展,对任何类型都适用
核心模块之上是四个扩展,全部与业务类型无关。团队权限最有意思,因为它是用其他模块搭出来的:它从每个已安装模块声明的能力构造出一个权限编辑器,所以装上一个新模块,它的权限就自动出现在编辑器里,不需要任何人去更新一份清单。
支付渠道加一块用于配置受理渠道的控制台磁贴,以及公开主页上一份顾客可见的渠道清单——一个扩展通过两个声明槽同时写到两侧。会员与订阅引入顾客可以直接从店铺主页购买的方案。续费提醒处理会员和疗程所产生的后续跟进。每一个都是按第三方将来会用的同一份契约写成的、已经发布的第一方模块——这是一种刻意的自律,因为一份契约只有在它的作者也被它约束时才是真的。
按店安装与卸载
扩展在店主控制台里的插件商店中管理,安装的作用域是单个商家。一位经营两家店的店主可以只在其中一家装会员功能,而两个仪表盘会真的不一样。
卸载在一个确认框后面,而确认框会说一句具体的话:数据不会被删除。这比听上去重要。人们在卸载按钮前犹豫,是因为他们假设它是破坏性的,于是把用不上的模块一直留着,控制台里堆满没人点的磁贴。告诉他们什么*不会*发生,才让这个按钮变得可用。卸载之后,扩展不再贡献任何东西——没有磁贴、角色编辑器里没有权限、公开主页上没有区块——但它的记录会在重装后依然在。
它目前还不是什么
第三方插件没有开放。插件商店自己就这么写着,而不是靠一层空的“更多敬请期待”货架去暗示别的。今天存在的是一套有真实契约的模块化架构、四个核心模块和七个照着它写的第一方扩展,全部通过同一条注册路径加载。第三方提交是已声明的下一步,不是一个已经上线的市场:没有开发者门户、没有审核队列,也没有公开的 SDK。我们这样描述,是因为架构才是有意思的部分而且今天为真,而市场只是一句关于未来的声明。
契约的检验标准是:一个完全照着它写、不碰任何核心代码的模块——磁贴、能力和页面区块——能否表现得像应用的原生部分。四个做到了。把这件事对外开放,与其说是技术问题不如说是政策和审核问题,而它还没被解决。
为什么是模块,而不是功能开关
功能开关关掉某样东西,模块贡献某样东西。差别体现在权限编辑器上:用开关的话,得有人维护一份所有能力的总清单,并记得去扩充它;用契约的话,团队权限扩展去问每个已安装模块声明了什么,然后据此构建编辑器,那份清单就无法过期。同样的模式也适用于仪表盘网格和公开主页——它们都不枚举功能,它们都去问。
它同时限定了新增一条垂直业务的成本。要加一种 Korat 今天还不服务的业务类型,那是一个模块:声明它认领的类型、一个目录、一个 CTA,以及需要的那几个可选槽位——不必去动控制台、页面渲染器或权限系统。这才是让一个超级应用可控、而不是慢慢堆成一坨特例的原因。
这里没有第三方插件市场。今天所有可安装的东西都是第一方的,应用里的商店也这么写。第三方提交是已声明的下一步——目前还没有开发者门户,也没有可供构建的公开 SDK。
插件代码目前仍然打包在 APK 里,而不是按插件在使用时加载。这是一个已知的限制,也是把商店向项目之外的人开放的明显前提。
- 必需声明
- id · 认领的业务类型 · 标签 · 目录标题 · 主 CTA · 目录视图
- 可选声明
- 能力 · 控制台磁贴 · 控制台界面 · 顾客页区块
- 核心模块
- 餐饮 · 住宿 · 服务 · 零售
- 扩展
- 团队权限 · 支付渠道 · 会员与订阅 · 续费提醒
- 安装作用域
- 按店
- 卸载
- 在一个明说数据不会被删除的确认框后面
- 第三方
- 未开放——只有第一方扩展
这里的扩展全部是第一方的——排队叫号、停车场这类模块并不是外部开发者写的,所以也不存在一个第三方拿到你店里数据的入口。
装上之后哪位员工能看到它,和我的职场用的是同一套按人分配的权限。