严格意义上来说,这并不适合称之为架构问题,或者说应该加个范围:业务架构。我不知道这是不是一个通用性问题,至少我在多个项目中不止一次的遇见过这个问题。先来让我简单描述一下问题的具体表现吧~

目前我司正在做的是一个企业内部的ERP系统,在需求分析阶段我们根据企业内部实际的工作流程和角色,在软件系统中引入了预知对应的元素:

部门 > 用户

这非常的常规,部门和用户自然也是允许管理员根据企业需要动态的增删改的。目前为止都是美好的!接下来,我们需要根据需求继续将实际工作流程搬到软件中来。假设,我们有N个部门,不同的部门自然对应不同的工种,例如经理,财务,行政,销售等。每个工种都有自己的工作流程和要解决的实际问题。

问题来了,我们要为每个部门开发对应的软件功能,意味着在开发阶段,我们的功能就要确定针对的是哪个部门,这里就产生了依赖。由于“部门”是允许在软件开发完成上线后使用者动态操作的,如何能确保使用者的行为不会打破这种依赖呢?我想这样类似的问题你一定也碰到过,对吧?!

功能依赖数据

这种依赖只要不解决掉上面提到的那种干扰,就一定是不健全的。但,简单的将“部门”编辑权限关闭,以牺牲用户使用灵活度为代价的方案肯定也是耍流氓,那这中间的权衡应该是什么呢?

让我们撒开欢来思考,如果使用老套路,增加额外的一层来解决被依赖数据的稳定性,是不是一个好的方案呢?

比方说,引入“角色”概念进来,将功能与角色进行关联而不是关联部门,而这里提到的角色是使用者不可变的(注:可能这里叫“角色”容易让大家和权限对应的角色产生关联,但我实在想不出别的好名字,见谅)。

在开发阶段,我们根据需求实现某个业务流程,围绕该流程我们预置所需的角色。换句话说只要该业务流程还在,对应的角色就不会消失。

听起来是个不错的方案,但缺点是,使用者是否能很好的理解“部门”和“角色”的区别和用法?你能确保使用者在创建系统用户的时候很容易的就选择合适的部门和角色么?毕竟现实世界中,部门就足够用了,多出来的角色会让使用者十分的困惑,对他们来说这是个多余的玩意儿!

没错,角色的出发点本身就不是来自于真实需求,更多存在的理由是来自于我们的技术方案,或者说的更直接点,是实际需求和技术方案不匹配导致的。

这个依赖,也是真实的会影响代码的,回想一下以往我们的做法是什么?对于这种功能依赖数据的场景,更多的是使用配置文件,对吧?那现在一般都是前后端分离,意味着相同的配置项,前后端都要各自保存一份(或者提供对应的服务接口)。

总之,前后端最终都会对该配置文件产生强依赖。OMG,越说越可怕,我都不敢往下想了。

绕回刚才的方案,如果我们不引入角色,而是对部门提供额外的约束,例如分成预设部门和普通部门两种类型,预设部门不能编辑。这么做至少我们让使用者不会迷茫了,但依赖的问题还在。

依赖“倒置”

如果我们将这种依赖关系放手交给使用者来维护的话是否合适呢?思路类似很多框架常用的一种模式,我们提供对应的接口和界面来供使用者完成功能和部门之间的依赖维护,这么做无疑会增加使用者的操作负担,不过也不失为一种灵活可行的方案。但别着急高兴,继续分析。

我们的例子里,若在运行期间修改了功能和部门的关系,那该功能中之前产生的历史数据就有可能不能正常使用,例如由A部门切换到B部门后,原先历史数据中都是A部门下的用户数据,现在都作废了。抛开是否删除这些数据不谈,我们主要关注于这些数据的价值,多数场景下它们都是有价值的。至少,它们曾经代表了系统的一种状态,但它们现在却无法提供太多有意义的信息,甚至会对使用者造成一定程度的视觉干扰。

我们需要根据需求来对待它们,但问题的本质还是依赖改变导致的。如果我们只提供给用户仅一次的依赖绑定操作,之后不允许修改依赖,甚至连被依赖的部门都不能再删除,这又是一种需要权衡的妥协。

结论

这种依赖之所以讨厌,是因为牵扯的面太多,不仅在开发阶段,也在使用阶段。如何最终提供给使用者一个尽可能还原现实世界流程的,不引入陌生概念的方案,该方案还同时可以让开发者能尽可能高效灵活的组织代码,不暴露过多给接口调用方。

可惜,目前,我没有这么样的一个方案。你有么?