曾经遇到过一个系统需求,需求分析人员在听到客户说要增加"修改员工密码"功能后,就原封不动的把这个功能写在了文档中。如果把这个需求交给实现人员,很多实现人员,会在"员工"(Employee)这个类中加一个属性"password"。如果仅用名词法,来验证需求,完全符合:"员工",是一个比较重要的概念。"什么的什么,可以提取为属性",因此"员工的密码"可以提炼为"员工"类的password属性。
实现人员嘘了口气:"万事OK。"
真的OK吗?
需求场景:员工和用户的分离。
如果把密码放在了员工中,基于CRUD的做法,我们通常会把对员工的修改放到了一个界面上。也就是说,管理员增加一个人员,系统默认设置对应人员的密码。
这个时候,IT部门提出异议了,增加员工,是人力资源部门的事情,而是否给员工开放账号,是信息中心的事情,不是所有的员工都开放账号的,HR部门无权擅自开放账号。
"账号?","是啊,"IT部门的人说,"用户账号啊"。
得,我们丢了一个重要的概念 --用户。
同样的道理,员工办理离职的时候,也是要先去信息中心销户,然后再去HR部门办理离职,因此,我们把Password放到员工中,是不合适的。员工需要和用户分开。
需求场景:员工和客户、供应商、合作伙伴的合并:
客户提出新的需求:原先我们建立的都是员工和密码,现在,我们要打通企业的供应链,给我们的供应商和客户包括合作伙伴,有条件的开放系统的功能。因此,他们也要有账号和登录密码。
是分开设置代理,还是把他们合并成一个抽象类?在不考虑系统性能的前提下,我们可以暂时套用《分析模式》的做法,抽象出Person (或Party)领域对象来。
需求场景:分别的账号登录
客户说:"我希望员工在登录后,只选择他想使用的岗位角色?"什么意思?
"比方说张X,在集团公司内是出纳,而在集团的某个下属公司,是会计,他上午在集团上班,下午,在下属公司上班。因此,登录的时候,需要选择角色。"
客户是不会太轻易的就区分出员工和用户的区别的,在描述的时候,就会混淆着使用员工和用户这两个概念。另外,岗位和角色,也是非常类似的两个概念。
在没有统一的独立的登录服务器的情况下,你感觉,这种方式实现起来有问题(想想,都会有什么问题?),于是说服客户:"给你建两个账号行吗?",用户也没有细考虑,居然同意了。因此,这时的一个Person,就对应了两个账号,密码呢?自然不能放到Person中了。
我们再想像一下这时的登录过程,简单的交互步骤如下。
actor使用账号和密码登录,
系统验证账号和密码有效,显示允许的功能操作。
需求场景:选择性激活
如果客户坚持只能一个人只能用一个用户账号登录,会是什么样子?
使用用户账号 和password 登录,系统需要列出其所有的角色,角色按所属公司列出,
actor激活某公司下的某种角色。(关于角色的动态激活,可以参考RBAC模型,这里不再多讲。)
要考虑的问题就产生了(用例中的扩展流):
actor已经在其他的地方登录了系统(激活了其它角色了)怎么办?
我们现有的领域模型是,角色是跟公司(法人)相关的,如果客户又提出,角色和部门相关,哪该怎么办?
需求场景:限界上下文
我和BSP的主要负责人建华,曾经就人员和用户,以及岗位和角色的类似,进行了大量的讨论。得出来的结论是,这是从不同的角度在看待同一事物,在企业资源模型中,HR是重要的企业资源,而在权限模型中,人力是作为受限单元的。因此,他们应该分属于两个不同的限界上下文,而限界上下文,也是领域模型的一个重要的组成部分。
题外话:
作为LoushangBSP产品的参与者,我曾经为这些需求问题(比我举出来得要多的多)困扰过许久,还好,现在,BSP中的组织机构和权限模型已经相对丰富,足以应对这些需求场景了,现在,我可以把一些简单的需求,共享给大家。