SagooIoT 把产品能力拆成两个清晰的层次:
- 专业版 (
sagooiot-professional,modulesagooiot):设备、产品、物模型、接入、权限、时序、告警底座等核心能力 - 企业版 (
sagooiot-enterprise,modulesagoo.cn/sagooiot):租户、项目、工作流、Agent、级联等增量业务
依赖方向固定、不可反向:
text
企业版 ──调用──► 专业版
专业版 ✗ 不依赖企业版
这一条决定了:核心可以独立演进、独立交付;增值业务可以快速叠加,却不会把核心代码搅成「企业版特供」。
一、为什么要拆成两个 module
很多物联网平台把「基础能力」和「行业/增值功能」堆在同一个代码树里。短期跑得快,中期就会出现:
- 核心发布被增值需求拖住节奏
- 不需要租户/工作流的客户,也被迫背一整套企业逻辑
if 企业版散落在设备、权限等主干路径上,行为越来越难讲清楚
SagooIoT 的选择是产品分层落地为 Go module 分层:
| 专业版 | 企业版 | |
|---|---|---|
| 定位 | 核心平台 | 增值业务 |
| 能否独立构建运行 | 能 | 联编专业版能力 |
| 是否包含对方业务 | 不包含企业版业务 | 不复制核心实现 |
工作区用 go.work 把两个 module 放进同一构建视图,本地开发体验连贯;专业版本身不依赖企业版,发行与定制边界干净。
二、Go internal:不是障碍,是护栏
专业版把实现放在 sagooiot/internal/... 下。按 Go 语言规则,这些包只能被专业版 module 内部导入 ------企业版即使和专业版同名片段相近,也不能直接 import "sagooiot/internal/service"。
这正是我们想要的:
- 核心实现不被外部模块直接触碰,避免「抄一条 service 调用」变成隐性耦合
- 企业版只能走公开契约,核心重构时边界清晰
- 社区版 / 专业版发行不必担心增值代码伸进主干内部包
internal 把门关上;真正对外的窗口,我们主动开在公开目录里。
三、pkg/proxy:企业版调用专业版的正式出口
企业版要拿当前登录用户、做数据权限过滤、查设备详情、同步子平台数据------答案都在专业版。既然不能碰 internal,专业版就提供公开适配层:
sagooiot/pkg/proxy
它的职责很单纯:
- 把专业版已稳定的核心能力,包装成企业版可导入的函数与模型
- 只出不进 :专业版业务代码不依赖
pkg/proxy,内部继续走internal/service - 企业版统一经此出口(及其它已公开的
pkg/*)使用核心,不绕路、不复制第二套设备/权限实现
text
企业版 module
│ import sagooiot/pkg/proxy
▼
pkg/proxy ← 公开适配层(契约出口)
│
▼
internal/service / logic ← 核心唯一实现
对应关系一目了然:
| 导入方 | 目标 | 结果 |
|---|---|---|
| 专业版内部 | sagooiot/internal/service |
允许 |
| 企业版 | sagooiot/internal/service |
禁止(语言规则 + 产品边界) |
| 企业版 | sagooiot/pkg/proxy |
允许(正式出口) |
这不是「临时绕路」,而是刻意设计的跨版能力出口 。约定文档见:专业版与企业版模块边界约定。
四、这套设计带来的优点
1. 核心干净,增值不污染主干
专业版禁止依赖企业版,也禁止在设备等主干包写 if 企业版。企业版特有逻辑留在 module/*,需要核心配合时,在专业版加通用能力再经 proxy 暴露------主干始终可单独讲清楚、单独测试、单独发版。
2. 一份核心实现,多处业务复用
登录用户、数据权限、设备/产品模型等,权威实现只有专业版一套。企业版的项目、工作流、Agent 等模块都通过同一出口取身份、裁数据,避免「每个增值模块自己再实现一遍权限」。
3. 交付形态灵活
- 只要核心能力 → 专业版即可
- 需要租户、项目、工作流等 → 叠加企业版模块
客户按需组合,而不是被绑死在「大一统二进制」上。
4. 演进节奏可分开
核心侧可以持续打磨接入、时序、插件与权限底座;企业版可以并行迭代增量业务。两边通过稳定出口协作,而不是互相改对方内部包。
5. 可插拔扩展点(SPI)与出口配合
例如多租户:专业版只留最薄底座(字段 + 钩子 + Noop),企业版模块 Register 接入。这和 pkg/proxy 同一思路------专业版提供扩展面,企业版提供增值实现 ,而不是把 SaaS 逻辑写死进核心。详见 11-多租户。
6. 对开发者友好的边界语言
用 Go 自带的 internal 表达「实现私有」,用 pkg/proxy 表达「跨版可用」。新人看 import 就能判断:碰不到的是核心内脏,该用的是公开出口------比散落的口头约定更硬、更好执行。
五、和「堆在一个仓库里」比,差在哪里
| 单仓大泥球 | SagooIoT 双 module + proxy | |
|---|---|---|
| 核心能否独立交付 | 难 | 能 |
| 增值是否污染主干 | 很容易 | 依赖方向禁止 |
| 企业版如何用核心 | 直接改 internal / 复制代码 | 统一走公开出口 |
| 权限/设备模型 | 易出现多套实现 | 专业版一份权威实现 |
| 客户选型 | 往往只能全要 | 核心与增值可组合 |
六、一句话总结
专业版负责把门锁好的核心能力;企业版负责在门外把增量业务做漂亮;pkg/proxy 是两边握手的正式走廊。
Go 的 internal 帮我们守住实现边界;公开适配层帮我们把「企业版可以调用专业版、专业版从不调用企业版」落成可编译、可评审的工程事实。
这就是 SagooIoT 选择的分层方式:不是把所有功能糊在一起,而是让核心足够稳、增值足够快。