Jdon Framework Domain-Driven Design(DDD)开源框架_第1页
Jdon Framework Domain-Driven Design(DDD)开源框架_第2页
Jdon Framework Domain-Driven Design(DDD)开源框架_第3页
Jdon Framework Domain-Driven Design(DDD)开源框架_第4页
Jdon Framework Domain-Driven Design(DDD)开源框架_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、JdonFrameworkDomain-Driven Design(DDD)开源框架开源框架彭晨阳 ()实际需求 日常企业信息化过程中,经常会一些表单数据需要输入数据库,如果可以在一两个小时内完成这样的应用是很多信息主管的想法。 中大型信息系统都是从当时一两个表单数据应用基础上建立起来。Simplify the Best 1. 能够在一两个小时内快速开发简单应用系统。 2. 能够在此架构基础上无缝平滑发展成为一个可方便维护、可灵活拓展、可伸缩的中大型系统。 JdonFramework(以下简称JF)就是这样一个简单易使的轻量框架。 JavaEE多层架构MVC表现层持久层服务业务层领域模型CQR

2、S(命令查询分离) ArchitectureUser interfaceServiceDomainEvent/Message BUSInfrastructureQuery/ReportingCommandsCommandsEventsJF在JEE架构位置技术背景p由于多层结构导致代码复杂,系统编码复杂,容易混乱,无法控制。p可选择范围太多导致学习成本比较高,无法使初学者快速上手。p目前J2EE标准技术只注重中大型系统,小型单机系统市场被忽视,可伸缩的小中型系统不容易开发。 轻量框架新一代轻量框架 框架是现代Java开发的中心。框架为王: 1. 灵活性,完全松耦合,实现多层解耦。 2. 快速性,

3、多层结构代码快速组装。 3. 可伸缩性,小型系统架构具备向中大型扩张的可能性,一劳永逸解决小中型系统的各方面需求,如缓存/性能。JdonFramework特点 DDD : 领域驱动设计,通过突出领域模型作为整个系统的中心作用,以领域模型的设计驱动表现层和数据库的开发设计。 IOC或DI:完全自动识别的依赖注射模式,可以完全摆脱类与类之间的依赖关系,大大提高开发效率和重构速度。 Cache:内置缓存自动支持,借助Terracotta能够无缝将应用程序拓展到云计算架构。DDD 领域驱动设计(Domain Driven Development )简称DDD 。 为什么要使用DDD/MDD? 有15种

4、理由。 DDD + DSL(领域语言或框架)是目前软件主流趋势。 JF是一种DSL性质框架,未来会发展到真正DSL。Evans DDD大师说DDDDDD特点 统一语言:统一语言:一个无处不在(ubiquitous )的语言,项目中所有人统一交流的语言。减少沟通疑惑,减少传达走样。使得软件更加适合需求。 统一领域模型统一领域模型:领域专家和程序员统一使用一种模型,没有数据库数据表等专业软件技术干扰。 专门的业务领域层专门的业务领域层:领域层除了业务没有其他,没有软件架构 框架等等底层技术。以模型为核心的卫星图Domain Model Domain ServiceLoggingGUIPersist

5、enceDDD优点坏设计之一:失血模型 尽管使用MVC模式和框架,但是将大部分业务逻辑写在控制器Controller中,如Struts的Action。甚至一个Action有几千行。 尽管使用SOA的服务,但是将大部分业务逻辑写在服务中。 在上面两种设计中,模型是只有setter/getter方法失血模型。模型对象成了纯粹的数据包装,没有业务行为和方法。 失血模型导致软件难于拓展和维护,重新回到面向过程的编程老思路。随着时间推移,开发效率降低。坏设计之二:基于数据表的设计 最初订单有OrderItemId, OrderId, ProductId 和 Qty。 后来添加 MinDeliveryQt

6、y 和 PendingQty字段,这是和订单交货有关。 订单和订单交货是两个概念,但是我们把这些字段都混合在一个类中了。 尽管采取了OO设计,但这还是一种带有数据库设计影子的坏设计。 DDD设计:将实体的职责分离到不同限定场景 。领域设计和数据库设计不同 领域不是把实体看成铁板一块,一开始就把它分解到各种场景。 下订单和订单交货交付是两个场景,它们应该有彼此独立的接口,由实体来实现。 在数据库中它们是一个,也就是说,从ER模型上看,它们是一个整体,但是从domain model领域模型角度看,它们是分离的。 领域设计:以Domain Model核心 Domain Model是JF系统的第一个设

7、计开发对象。 每个Model都必须有一个主键;或唯一标识。 由Domain Model延伸界面模型和持久实体。基于JF的DDD最佳实践基于JF的DDD最佳实践JF架构 Model 领域模型,包括实体模型 值对象和领域服务,与技术架构无关。相当于鱼;生存空间是缓冲器中 Service/Component 技术组件架构,用以支撑领域模型在计算机系统运行的支撑环境,相当于鱼生活的水。空间在Context container,例如ServletContext中。 两者以Domain Events模式交互:异步 命令。Model command Component Domain Model ModelD

8、omain ServiceServiceLoggingComponentGUIPersistenceComponentMessageMessageMessageMessageComponent architectureJF的架构流程图DDD实体模型 每个实体模型必须有一个唯一标识,如User对象必须有一个userId。 该实体模型必须以Model注解。以Model标注的对象实例将存在缓存中,存在寿命以缓存设置ehcache为主。 服务模型必须以Service注解。服务实例化分单例、多例、池化Pool等三种方式。Domain Events 在Evans DDD实现过程中,经常会碰到实体和服务Se

9、rvice以及Repository交互过程,这个交互过程的实现是一个难点,也是容易造成失血贫血模型的主要途径。 Domain Events提出解决方案, JF提供的异步观察者模式为Domain Event实现提供更优雅的解决方案。详细文章见:http:/ interfaceServiceDomainEvent/Message BUSInfrastructureQuery/ReportingCommandsCommandsEvents保证纯净: No实体模型注射 领域模型中只有业务,没有计算机软件架构和技术。 不要将和技术相关的服务和功能组件注射到实体模型中,例如数据库Dao等操作。 由领域模型

10、通过Domain Events机制指挥Domain 服务和其他功能组件,包括数据库操作。http:/jonathan- Domain EventsDownload SourceDomain Events 工作原理Domain Model ModelListernerComponentJava concurrent FutureDomain MessagePool.run使用使用Java concurrent的的Future API 相关更详细原理见“使用future实现内置异步API” Domain Events 并发策略 异步消息 懒惰加载, 使用java 并行模型 类Actor Model

11、 Model 只能通过消息时间彼此联系,这个消息是异步 非堵塞 属于“fire-and-forget”。 DCI Architecture 在具体运行场景时,通过将业务逻辑方法注射到 Model标注的领域模型对象中更多优点 松耦合 业务逻辑能够与技术架构解耦,将”做什么”和”怎么做”分离 EDA架构Event-driven Architecture 异步事件驱动模式 异步懒惰加载Asynchronous Lazy-load 类似函数式语言的懒功能,只有使用时才真正执行。 真正可伸缩性 通过与JMS结合,可以在多核或多个服务器之间弹性扩展。异步懒加载好处 即用即取数据,随时运算。 函数功能只有在

12、它的返回结果需要时才真正执行计算,类似erlang Scala等函数式语言。 再也Hibernate LazyInitializationExceptions错误烦恼, 没有Session持续打开(Session打开就是数据库连接一直打开,耗费资源,性能杀手) 不需要Open Session in View 反模式,不再需要使用SSH或S2SH组合中,在web.xml配置Spring的OSIV过滤器,这时耗费资源和危险的,特别是嵌套错误抛出时。 可以在MessageListener处集成入JMS,JMS是可伸缩性并带有分布式事务方案,可以保证持久化等事务精确完成。模型的异步 + 懒加载假设假设

13、computeCount是一个非常耗是一个非常耗CPU的任务,使用的任务,使用并发策略可以消除并发策略可以消除这种延迟这种延迟。public int getMessageCount(DomainEvents domainEvents) if (messageCount = -1) if (messageCountAsyncResult = null) messageCountAsyncResult = domainEputeCount(account.getUserIdLong(); else messageCount = (Integer) messageCountAsyncResult.g

14、etEventResult(); return messageCount; 异步调用 第一次调用 getMessageCount方法,激活耗时的 domainEputeCount. 方法,这次调用中我们可以不需要范围结果。 第二次再次调用getMessageCount将得到前面耗时的计算结果,我们可以通过AJAX实现二次调用。 Download Sample Source集成JMS Component(“JMSListener ”) public class JMSListener implements MessageListener public void action(DomainMess

15、age message) Connection connection = connectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(destination); TextMessage message = session.createTextMessage(message.getSource); producer.send(me

16、ssage); 分布式CAP原理 Consistency(一致性), 数据一致更新 Availability(可用性), 响应性能 Partition tolerance(分区容错性) 可靠性 只可同时满足二点,没法三者兼顾。 架构设计师不要精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。 Web系统分服务器端和RIA浏览器,实际也是一个分布式系统。互联网是最成功的分布式系统。CAP原理实现 关系数据库ACID模型实现了CAP原理的一致性和可靠性,但是失去了响应性能可用性。 Dynamo和Base思想实现了CAP原理的响应性能 和一部分可靠性,降低了一致性要求。所以。 基于模型

17、缓存缓存的Jdon框架如果结合关系数据库,可以让架构师灵活选择以上两种思想倾向。Dynamo思想 一个Dynamo框架应该是这样:逻辑随着数据分布,任何模型都可以自己持久化,这样做的优点是系统有低延迟。 当Jdon框架应用部署在分布式环境中时,模型只要向所在的服务器技术组件通过Domain Events 和JMS发出持久化即可。 逻辑和数据都在模型中,完全符合Dynamo框架的“符合逻辑随着数据分布”定义。 可伸缩架构变迁之路Action少量业务Service业务逻辑失血模型基本逻辑(约束一致性方法)DDD充血领域模型薄Service薄Action分布式可伸缩方向等等使使用DDD后的架构传统老

18、架构JF分布式架构Domain ModelJMSPersistenceSend EmailOther ServicesMessageDomain ModelMessageDistributed CacheDistributed Cache基于领域模型的分布式架构 领域模型 + 分布式缓存缓存 + 存储 + JMS异步 领域模型带着逻辑和数据被分布式缓存缓存如Ehcache +Terracotta分布到多台机器中运行。 领域模型通过JMS驱动技术架构实现功能。 JMS= 集群集群无单点+分布式事务事务架构 业务数据装在领域模型中,关系数据库只是用来做存储,NoSQL(Not Only SQL),

19、领域模型数据和数据库数据不高度一致,低延迟。JdonFramework特点 DDD : 领域驱动设计,通过突出领域模型作为整个系统的中心作用,以领域模型的设计驱动表现层和数据库的开发设计。 IOC或DI:完全自动识别的依赖注射模式,可以完全摆脱类与类之间的依赖关系,大大提高开发效率和重构速度。 Cache:内置缓存自动支持,借助Terracotta能够无缝将应用程序拓展到云计算架构。Ioc/AOP轻量容器 依赖或或者控制关系的反转注射(Ioc模式)p通过配置/微容器解决POJO调用关系。p高度灵活和松耦合,实现对象的可更换。 面向方面编程(AOP)p提供在不改变原来架构基础上,动态增加/更换一

20、些普遍功能。 Out-of-the boxJF注射和拦截架构 Model:模型中可以通过字段的Inject将其他类注射进入,包括Component类。被注射的类如果有Introduce,将再次引入拦截器。 Component:技术架构中组件可以通过构造器直接注射进入其他Component组件,被注射的类如果有Introduce,将再次引入拦截器。灵活的注入和拦截 依赖注入Dependency Injection(DI or IOC) Service or Component 能够进行彼此注入,通过其类构造器 (不支持 setter方法注入). Service or Component也能被注入

21、到 Model 领域模型中,或者使用 domain events. 面向方面编程Aspect-oriented programming(AOP) 使用Introduce: Service or Component 能够将彼此引入作为拦截器. Model 能引入任何 POJO 或 Component作为它的拦截器DI/AOP架构: ModelClientxx.getA(“a”)AModelInterceptor for Awith Introduce B that needimplements interfaceand has IntroduceInject proxy of BIntercep

22、tor for Bwith IntroduceCache containerCInject proxy of cComponentIn Context Containerinterceptor模型内注射DI/AOP架构: ComponentClientxx.getA(“a”)A ServiceInterceptor (poincut=service)B that needimplements interfaceComponentInject proxy of BInterceptor for Bwith IntroduceContext container (ServletContext)如何

23、调用一个有依赖的服务?AOP Introduce使用方法 Introduce(名称) 为当前类引入拦截器,可以用在Model或Component中,名称是拦截器的Component(名称). 例如Introduce(c) - Component(“c”) 在当前类具体方法上使用Before After和Around三种拦截器激活的方式。注意使用Around对拦截器有特定写法要求,其他无。Introduce 引入拦截器被Introduce 引入的拦截器Component(c)public class C /被拦截器的Input参数将注射到inVal中 public Object testOne(

24、Object inVal) . /testOne 方法return 结果将被注射到被拦截器的return中 /被拦截器的方法myMethod2返回值将被引入此方法的inVale public Object testWo(Object inVal) Introduce的Around 如果某个类似于Introduce的Around,那么对被引入的拦截器有特殊要求写法:Interceptor(“aroundAdvice”)/1. 需要表明自己是Inteceptorpublic class AroundAdvice implements MethodInterceptor /2.需要实现 org.ao

25、ercept.MethodInterceptor接口 /3.完成接口的Invoke方法 public Object invoke(MethodInvocation invocation) throws Throwable Object o = ceed();/在此方法前后写包围around代码。 JF拦截器第二种写法/1. 指定被拦截的类是Component(“a”)和Component(“c”)Interceptor(name = myInterceptor, pointcut = a,c)public class MyIntercept

26、or implements MethodInterceptor /2.需要实现 ercept.MethodInterceptor接口 /3.完成接口的Invoke方法public Object invoke(MethodInvocation methodInvocation) throws java.lang.Throwable 被拦截器的类没有特别规定写法,只要标注Component(“a”)就可以,至于拦截a的什么方法,在拦截器invoke中实现。该方式将拦截定义在拦截器这里,和Introduce定义正好相反。自动注射的两个优势 完全可定制:面向对象编

27、程之父Grady Booch 说:对象最伟大之处在于其可被替代(The great thing about objects is they can be replaced) 而JF伟大之处是帮助你替代这些对象,甚至包括JF本身本身。 无需对象创建:颠覆对象使用之前必须创建的基本定律,正象无需关心对象销毁一样,您可以无需关心对象创建。JdonFramework特点 DDD : 领域驱动设计,通过突出领域模型作为整个系统的中心作用,以领域模型的设计驱动表现层和数据库的开发设计。 IOC:完全自动识别的依赖注射模式,可以完全摆脱类与类之间的依赖关系,大大提高开发效率和重构速度。 Cache:内置缓存

28、自动支持,借助Terracotta能够无缝将应用程序拓展到云计算架构。第三个特点: Cache 业务层可直接操作缓存,便于将业务状态保存到缓存中,实现以对象状态替代数据库进而提升性能的设计目的。 Jdon缓存在具体架构应用时可灵活设置在表现层/业务层/持久层等位置,通过拦截器使表现层访问缓存(依据缓存越提前越快原理);JF缓存架构PresentationDomainPersistenceCacheInterceptorIn aspect.xmlDomainCacheInteceptorIntroduce(“modelCache”)JF缓存特点 只要标识Model的实体,在表现层Jsp页面再次使

29、用时,将自动直接从缓存中获得,因为在中间业务层和表现层之间Jdon框架存在一个缓存拦截器CacheInterceptor,见框架的aspect.xml中配置。 为了能够在业务层也能够使用缓存,需要在业务层后面的持久层或Repository中手工加入缓存的Annotation标签。使用Annotation激活Cache在模型对象被创建或从数据库读取重构的地方必须加入Introduce(“modelCache”) 注解,这一步对于使用domain events是必须关键重要步骤Cache高可伸缩性 1. 使用JF开发的应用系统可无缝平滑升迁到EJB架构。同时支持POJO Services和EJB混

30、合运行,可接驳原有的EJB系统。 2.使用Terracotta透明轻量地分布式云计算内存产品,可以无缝将应用程序升级到云计算平台。可根据分布式CAP原理灵活架构。 (http:/ )JdonFramework其他特点 快速开发,简化代码,模型的CRUD操作流程固化,模板化编程。 CQRS模式:命令查询的责任分离Command Query Responsibility Segregation 。 模型状态的操作和批量查询分离,提供专门的批量查询支持。 支持远程胖客户端简化代码:杜绝Controller代码 MVC框架中的控制器/Action作用只是做前后台通讯转发,不能将多个功能混入控制器中,更不能写入业务。 JF采取MVC配置替代控制器/Action代码编写,从架构上杜绝了初级程序员将更多业务代码写入Controller/Action的可能。 节省编写Action代码工作,提高开发效率,实现MVC流程CRUD快速开发。MVC流程CRUD快速开发 应用软件中大量底层基础功能是CRUD (创建读写修改和删除),调试耗时而且不稳固。 传统开发中,一个模型的CRUD需要多个流程实现,没有技术含量的烦琐和麻烦。 JF将CRUD流程简化捆绑在配置,CRUD中只要创建功能调试正常,其他也就正常,无须烦琐调试。提高基础功能的调试时间。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论