Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->系统管理 ->正文

对象建模笔记--角色建模3

来源:Linux-cn.com 作者:Webmaster 时间:2007-05-05 点击: [收藏] [投稿]

好吧,我们再次回到设计中,和你想象的一样,我们需求又发生了变化。现在我们需要加入限制逻辑了。我们规定,一位员工不能够从事两份的工作性职位,但可以在一份工作性职位外再兼任一份管理性职位。

废话少说,我们立刻开始修改我们的代码:


class Person {
public void addRole(PersonRole value)throws CannotAddRole {
if (! canAddRole(value)) throw new CannotAddRole();
_roles.addElement(value);
};
private boolean canAddRole(PersonRole value){
if (value.hasType("JobRole")){
Enumeration e = _roles.elements();
while (e.hasMoreElements()) {
PersonRole each = (PersonRole) e.nextElement();
if (each.hasType("JobRole")) return false;
};
};
return true;
};
…

非常精彩的代码。我们来看一看这段代码。我们要处理限制逻辑(约束条件),首先要解决的问题是了解清楚它的来源。因为这一类的设计往往源自于非功能性需求。限制逻辑的实现策略有非常多种。例如,把限制逻辑放在界面层,或是把限制逻辑用数据库的constraint来实现。我个人的意见比较偏向于把限制逻辑放在业务层,就像我们的代码所处理的那样。原因有三:首先,界面层往往部署在大量的客户机上,逻辑的修改非常不方便;其次,不同数据库的constraint有所差别,移植不便;最后,限制逻辑过于分散的话,会造成修改维护成本的上升。基于这几点原因的考虑,我比较倾向于集中在业务层实现限制逻辑。当然,和以上的设计思路一样,这还是要根据实际情况进行调整的。

下面一个考虑的因素是,限制逻辑放在哪些类中,又该放在类的哪个位置上。这是一直以来困扰我的一大问题,因为最经常遇到的一种情况是,限制条件往往是跨类的-即它和多个类相关,因此很难能够决定它的适合位置。这里我给出两种解决建议。之所以说是解决建议,是因为这个问题是无解的,只能够凭借

各位的经验来做具体的判断,但是有些建议能够帮助大家做决定。

第一种建议是,和你的领域专家讨论限制条件的位置。因为只有领域专家才有足够的经验和权威做出需求的决策。中间可以使用到一些技巧,例如CRC卡片,来帮助讨论。一般在这种讨论会上主要是把限制条件分配给某个或某几个业务实体类,要想真正确定其位置,还要结合建议二。

第二种建议是,如果遇到涉及到多个类的限制条件,那么也许意味着你需要设计某种体系结构来处理把这几个类整合起来。这种体系结构可能是继承树、管理类、外观类的组合。例如我们的代码就是这样。如果没有person类,我们可以不知道把这个限制逻辑放于何处。

好,在讨论了限制逻辑之后,我们又提出一个问题,这里的代码中,限制逻辑只有一个,如果限制逻辑很多怎么办呢?这时候你可以考虑专门为限制逻辑设计一种方法(类似于canAddRole),甚至是一个类来集中基础限制逻辑。但是如果你的限制逻辑太多,到了一种有碍观瞻的地步的时候,也许正说明你的设计结构存在某种问题。比如,我们完全可以不使用限制逻辑方法就实现以上的需求:


class Person {
public void jobRole(JobRole value){
_jobRole = value;
};
public PersonRole jobRole() {
return _jobRole;
};
private JobRole _jobRole;
}

代码是不是简单了很多?因此某些时候,无情的重构还是有必要的,它能够大大的简化代码。但是应该认识到,凡事都不可能一开始就完美无缺,一定存在一个进化的过程。对于代码的来说,结构的优化始终都是最重要的。因此,设计程序如果能够着眼于设计,着眼于代码结构,那出产的代码一定是高质量的。

噩梦终于要到头了,需求的最后一次变化是增加了职业分组的功能。这种情况是非常普遍的,比如每种职位需要属于某个部门,这就是对职业进行某一种分组。从另外一个层面上来说,这其实是连接其它设计模块的桥梁。因为我们讨论的模式虽然独立,但是对于软件来说,将各个独立的模式有机的连接起来也是非常重要的。因此,在下面的代码中,我们可以看看模式是如何扩展的:


class Person {
public void addRole(PersonRole value)throws CannotAddRole {
_roles.addElement(value);
};
public PersonRole roleOf(String roleName, Group group) {
Enumeration e = _roles.elements();
while (e.hasMoreElements()) {
PersonRole each = (PersonRole) e.nextElement();
if ((each.hasType(roleName)) && (each.group() == group)) return each;
};
return null;
};
private Vector _roles = new Vector();
…
public class PersonRole{
protected PersonRole (Group group){
_group = group;
};
public Group group(){
return _group;
};
protected Group _group;
…
public class Salesman extends PersonRole{
public Salesman (Group group){
super (group);
};
…

注意到,这里的连接设计是采用参数的方式进行的。分组作为一个参数传递给person和personrole。由于我们建立了personrole和group之间多对一的关系,因此在personrole中设置了类型为group的私有变量来保存这种关系。这里,我们认为职位和职位分组是一种单向的关系,因此不需要在group类中同步的处理。同样的,如果要加入限制条件的话,仍然需要考虑其实现位置。

我们想象一下,在group类的背后,可能也隐藏着大量的内部实现类或是协作类。这些类通过group和personrole之间的关系连接在了一起。

小结:

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:对象建模笔记--角色建模2   下一篇:我的E-Mail服务器为什么变慢了?

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号