- 浏览: 456044 次
- 性别:
- 来自: 北京
博客专栏
-
张小庆,在路上
浏览量:8779
文章分类
最新评论
-
bad_brain:
很好的文章,帮助我快速了解zookeeper提供的能力以及为什 ...
Zookeeper与paxos算法 -
ixu:
支持,已经买了 是对工作流和BPM的很好总结啊
无知者无畏,一本写了四年的书 -
yangsong158:
看来,我与这个时代有些脱节了。必需加快赶上来。谢谢你的奉献。必 ...
无知者无畏,一本写了四年的书 -
黄粱一梦11:
目标 人没有目标就很容易迷失自己,常常陷入困惑中
PM成长日记第二话-一定要想清楚自己要什么 -
fenian_zhq:
支持。就凭你这个感悟,必须买一本收藏!
无知者无畏,一本写了四年的书
关于Domain Model的讨论已经非常多了,炒炒冷饭,这里是自己的一些做法。
以Workitem(工作流里的工作项)作为例子。
最开始的做法:
一个实体类叫做Workitem,指的是一个工作项或者称为任务项
一个DAO类叫做WorkitemDao
一个业务逻辑类叫做WorkitemManager(或者叫做WorkitemService)
主要看看WorkitemManager,因为主要逻辑集中在这里
public class WorkitemManager { private WorkItemDAO workItemDAO; public void setWorkItemDAO(WorkItemDAO workItemDAO) { this.workItemDAO = workItemDAO; } /** * 提交工作项 * @param workitemId 工作项ID */ public void commitWorkitem(String workitemId){ WorkItem workitem = workItemDAO.getWorkItem(workitemId); //当前工作项结束 workitem.complete(); int sID = workitem.getSequenceId(); //找到所对应的节点 InstActivity instActivity=workitem.getInstActivity(); //查找是否存在下一工作项 WorkItem sequenceWorkitem = workItemDAO.findSequenceWorkItem(instActivity.getId(), sID + 1); //如果不存在则触发节点流转 if (sequenceWorkitem == null) { instActivity.signal(); } //否则把下一工作项激活 else { sequenceWorkitem.setExecutive(); } } }
Workitem类里有一些状态转换的逻辑,这样避免直接调用get/set属性方法
public class Workitem{ private int state = WorkitemInfo.PREPARE; /** * 委派工作项 */ public void commission() { if (state != WorkitemInfo.EXECUTE && state != WorkitemInfo.SIGNINED && state != WorkitemInfo.TOREAD&& state != WorkitemInfo.SUSPEND) throw new WorkflowException(Messages.CANNOT_ALTER_WORKITEM_STATE); setState(WorkitemInfo.COMMISSIONED); setCommitted(new Timestamp(System.currentTimeMillis())); } /** * 完成工作项 */ public void complete() { if (state != WorkitemInfo.SIGNINED) throw new WorkflowException(Messages.CANNOT_ALTER_WORKITEM_STATE); setState(WorkitemInfo.COMPLETE); setCompleted(new Timestamp(System.currentTimeMillis())); } }
接下来的做法:
三个类不变,将WorkitemManager打平,将逻辑移动到Workitem
public class WorkitemManager { private WorkItemDAO workItemDAO; public void setWorkItemDAO(WorkItemDAO workItemDAO) { this.workItemDAO = workItemDAO; } /** * 提交工作项 * @param workitemId 工作项ID */ public void commitWorkitem(String workitemId){ WorkItem workitem = workItemDAO.getWorkItem(workitemId); //当前工作项提交 workitem.commit(); } }
实际上此时WorkitemManager的功能非常有限,仅仅是事务边界和获取workitem对象,甚至在一些情况下可以省略。
通过一个Container类将spring的applicationContext进行封装,然后通过getBean()的静态方法即可访问被spring所管理的bean。实际是将workItemDAO隐式注入了Workitem。
public class Workitem{ /** * 提交工作项 */ public void commit() { if (state != WorkitemInfo.EXECUTE && state != WorkitemInfo.SIGNINED && state != WorkitemInfo.TOREAD&& state != WorkitemInfo.SUSPEND) throw new WorkflowException(Messages.CANNOT_ALTER_WORKITEM_STATE); setState(WorkitemInfo.COMMISSIONED); setCommitted(new Timestamp(System.currentTimeMillis())); int sID = workitem.getSequenceId(); WorkItemDAO workItemDAO=(WorkItemDAO)Container.getBean("workItemDAO"); //查找是否存在下一工作项 WorkItem sequenceWorkitem = workItemDAO.findSequenceWorkItem(instActivity.getId(), sID + 1); //如果不存在则触发节点流转 if (sequenceWorkitem == null) { instActivity.signal(); } //否则把下一工作项激活 else { sequenceWorkitem.setExecutive(); } } }
这样带来的好处是业务逻辑全部被封装到Domain Model,Domain Model之间的交互变得非常的简单,没有频繁的set/get,直接调用有业务语义的Domain Model的方法即可。问题在于单元测试时脱离不了spring的容器,workItemDAO需要stub。我觉得这个问题不大,反而是Domain Model开始变得臃肿,在业务逻辑复杂时代码行急剧膨胀。
现在的做法
以上三个类保持不变,增加一个类WorkitemExecutor,将业务逻辑移步。
public class Workitem{ /** * 提交工作项 */ public void commit() { if (state != WorkitemInfo.EXECUTE && state != WorkitemInfo.SIGNINED && state != WorkitemInfo.TOREAD&& state != WorkitemInfo.SUSPEND) throw new WorkflowException(Messages.CANNOT_ALTER_WORKITEM_STATE); setState(WorkitemInfo.COMMISSIONED); setCommitted(new Timestamp(System.currentTimeMillis())); WorkitemExecutor workitemExecutor=(WorkitemExecutor)Container.getBean("workitemExecutor"); workitemExecutor.commitWorkitem(this); } }
public class WorkitemExecutor { private WorkItemDAO workItemDAO; public void setWorkItemDAO(WorkItemDAO workItemDAO) { this.workItemDAO = workItemDAO; } /** * 提交工作项 * @param workitemId 工作项ID */ public void commitWorkitem(Workitem workitem){ int sID = workitem.getSequenceId(); //找到所对应的节点 InstActivity instActivity=workitem.getInstActivity(); //查找是否存在下一工作项 WorkItem sequenceWorkitem = workItemDAO.findSequenceWorkItem(instActivity.getId(), sID + 1); //如果不存在则触发节点流转 if (sequenceWorkitem == null) { instActivity.signal(); } //否则把下一工作项激活 else { sequenceWorkitem.setExecutive(); } } }
将业务逻辑拆分成两部分,一部分在Workitem,另一部分委托给WorkitemExecutor。实际上是Domain Model将复杂逻辑的情况重新外包出去。调用的时候,面向的接口还是Domain Model的方法。注意到WorkitemExecutor和WorkitemManager的API是非常相似的。实际可以这样认为,传统的方式
Client->(Business Facade)->service(Business Logic 部分依赖Domain Model)->Data Access(DAO)。
现在的方式
Client->(Business Facade)->Domain Model->service->Data Access(DAO)。
另外,在返回client端的查询的时候还是倾向于直接调用DAO,而不是通过Domain Model。
评论
其实上只是颠倒了下调用的位置,以前我需要调用service,现在只要调用domain 即可。但是实际应用中,我的代码中具有大量domain,它们如果去调用service会非常bt,现在直接调用相关domain,而且这些相关domain是hibernate帮我注入的,这样用起来就爽的多了。代码也更容易理解。
在服务层中为贫血对象充血(装备逻辑方法)。
但自从深度使用动态语言后,才发现自己被Java害了
曾经一个不是牛人的牛人对我说过,面向对象只是一个思想
是解决逻辑问题的一个思路,不可能在代码中完美的体现OO,
现在想来,到底Java和JavaScript谁更OO呢?
也不好吧 实体类很可能会出现继承的情况,我觉得不如把实体类包装一下,合理的运用一下泛型,会省很多事
Agree!
very very very bad smell. : )
why? 耦合?依赖?
very very very bad smell. : )
发表评论
-
Zookeeper与paxos算法
2012-03-22 20:36 16805一、 zookeeper是什么 ... -
关于异常的问与答
2010-09-16 22:34 1139今天的问题是关于异常 ... -
一家公司发展的胡言乱语
2010-01-16 23:06 2882终于一天早上,睁开极 ... -
数据驱动测试
2009-12-05 22:25 4212我们从一个最简单的登录例子开始。最开始我们需要验证在用户名和密 ... -
《Head First Process-深入浅出流程》连载预告
2009-10-17 22:58 6192似乎一到年末,就会忙 ... -
也说炮轰
2009-10-05 13:13 1950社区里目前最火的无疑 ... -
使用selenium测试showModalDialog模态对话框
2009-07-27 21:10 7039Selenium目前没有提供对IE模态对话框(即通过showM ... -
(Multi-stage Continuous Integration)多阶段持续集成
2009-05-26 23:08 1245一、目前的情况 目前我 ... -
JbpmSide 流程设计器进度
2009-03-26 22:15 4442汇报一下设计器当前进度以及下一阶段主要的开发目标。 当前进度主 ... -
jBPM-side流程设计器功能规划
2009-03-08 21:57 2244目标: jBPM-side ProcessDesigne ... -
Flex框架Riawave应用以及对AJAX开发框架的思考
2009-03-01 22:05 1205Jbpmside要使用Flex开发流 ... -
你服务,你全家才服务
2009-02-19 14:18 1674在拥挤的公交车上读完《工作流管理(模型、方法和系统)》,自从搬 ... -
工作流技术基础读后
2009-02-09 18:03 1683大概花了三天的时间读完这本书,书本身也 ... -
BPM向左,工作流向右(二)工作流系统杂谈
2008-11-07 11:28 2320当 面对一个完整的工作流系统时,你可能会被它众多的功能所困惑: ... -
基于memcached的SNA实现
2008-10-28 17:34 3702系统要集群,使用SNA方案。一、 缓存的处理缓存要使用统一的缓 ... -
SNA方案之session炒冷饭
2008-09-04 14:49 2075SNA方案中,session的处理是一个重要方面。原帖见这里: ... -
一次性能调优的实战
2008-09-01 12:56 1917项目情况:是一个大型 ... -
BPM向左,工作流向右(一)什么是业务流程
2008-08-26 17:43 2406从事工作流以及相关开 ... -
js组件的测试,是个问题
2008-08-11 19:06 1094用js编写自己的组件,测试一直是个头疼的问题。最开始大量使用a ... -
工作流之收回
2008-07-15 18:31 1590收回 收回是工作 ...
相关推荐
贫血模型和充血模型是两种在软件开发,尤其是面向对象编程中常见的设计策略,主要应用于领域驱动设计(Domain-Driven Design, DDD)中。这两种模型主要关注于业务逻辑和数据之间的关系,以及如何在软件架构中有效地...
这种设计将业务规则和操作完全分离到独立的服务或管理类中,通常称为Transaction Script。在失血模型中,domain object的角色非常有限,它们更像是数据容器,而非具有行为的对象。例如,`Item`实体类只负责存储拍卖...
充血模型,也被称为“Rich Domain Model”,是领域驱动设计(DDD)中的一种核心概念。在软件开发中,领域模型是对业务领域的抽象和建模,它包含业务规则、逻辑和状态。充血模型强调对象应该拥有自己的行为和状态,而...
缺铁性贫血病历模板.doc
背景:小细胞性低铬性贫血的最常见原因是铁缺乏性贫血(IDA)和β-地中海贫血特征(β-TT)。 这项工作的目的是比较各种简单指标的有效性,以区分铁缺乏性贫血和β-地中海贫血性状。 对象和方法:通过全血筛查,血清...
背景:产后出血是全世界孕产妇死亡的主要原因,贫血是其间接原因之一。 分娩期间贫血会增加发生PPH的风险,甚至在中度PPH后仍可能导致产妇死亡。 未确诊的PPH和产后贫血增加了社区晚期孕妇死亡的风险。 这项研究的...
【血液透析患者贫血的管理】是针对慢性肾脏病(CKD)患者,特别是进行血液透析的患者,如何有效管理和治疗贫血问题的专业讲座或教材。贫血是CKD患者常见的并发症,随着肾功能的恶化,贫血的发生率逐渐增加。本资料...
根据这些特征,可能的贫血类型包括珠蛋白生成障碍性贫血、缺铁性贫血、巨幼细胞贫血、铁粒幼细胞贫血以及慢性感染或慢性炎症性贫血。 2. 案例2中的44岁女性患者,血红蛋白55g/L,红细胞2.10×10^12/L,根据世界卫生...
贫血模型or领域模型的举例对比,让你初步了解贫血模型与领域模型的区别和概念
5. 实验结果:研究结果显示,低剂量和高剂量的肉苁蓉多糖均能显著促进骨髓细胞从G0/G1期向S期,以及从S期向G2/M期的转化,表明肉苁蓉多糖能够激活造血细胞周期,提高骨髓细胞的DNA合成及细胞增殖活性。此外,肉苁蓉...
总的来说,选择贫血模型还是充血模型,取决于项目的需求、团队的技术水平以及对代码质量的要求。在实践中,理解这两种模型的优缺点,并根据具体场景灵活选择,是提升软件开发效率和质量的关键。
在Asp.net开发中,"充血模型"是一种提倡领域对象拥有丰富行为和业务逻辑的设计模式,相对应于传统的"贫血模型"。"贫血模型"通常将数据模型、业务逻辑和数据访问分离,使得领域对象仅包含属性,而业务逻辑和数据操作...
再生障碍性贫血(AA)是一种骨髓造血功能衰竭的疾病,主要由药物、化学物质、放射线、病毒感染等因素引起,以全血细胞减少、进行性贫血、出血和感染为特征。在中国,该病常见于青壮年人群,男性患病率高于女性。病因...
背景:尼日利亚为全球镰状细胞性贫血负担贡献了30%。 胆石症通常发生在镰状细胞性贫血儿童中,可能仍未被诊断,模仿腹部血管闭塞性危机或因结石性胆囊炎而变得复杂。 早期识别患有胆石症的镰状细胞性贫血儿童可减少...
简介:在地中海贫血中反复输血和肠道铁吸收增加会导致铁超负荷,各种活性氧的催化产生会触发氧化应激。 内皮作为暴露于活性氧中的第一个器官,由于内皮功能障碍会触发高凝作用,其粘附分子会显着增加。 目的:探讨铁...
接下来,我们谈论“充血的领域模型”(Rich Domain Model)。在传统的贫血模型中,领域对象通常只包含数据,而业务逻辑则分散在服务层或其他地方。然而,在充血模型中,领域对象不仅包含了数据,还封装了大量的业务...
形态分类包括大细胞性贫血(如巨幼细胞性贫血)、正细胞性贫血(如急性失血性贫血、溶血性贫血)和小细胞低色素性贫血(如缺铁性贫血、铁粒幼细胞贫血、地中海贫血)。病因和发病机制分类则涉及红细胞生成减少(如...
公司分布:报告从多个维度对公司进行了分类,包括不同种类、不同档次、不同区域和不同应用领域,从而提供了抗贫血药物行业产品结构以及各类细分产品的市场需求的深入了解。报告详细调研了不同细分产品的市场容量、...
抗贫血药行业(2021-2026)的企业市场突围战略是企业在激烈的市场竞争中寻找增长点和竞争优势的关键所在。本报告旨在为抗贫血药行业的企业提供一系列深入的分析和实用的建议,以帮助他们在未来五年内实现市场的突破。 ...