- 浏览: 4799223 次
- 性别:
- 来自: 上海
博客专栏
-
robbin谈管理
浏览量:135743
文章分类
最新评论
-
xly1981:
领导者是团队的灵魂。深入一线的过程,包括代码review,能帮 ...
robbin谈管理:改造团队的经验(2) -
jiehuangwei:
像这种总结比较性的ppt文档可以多发啊
Web并发模型粗浅探讨 -
linux1308:
看完学习到了很多东西,感谢推荐!
推荐一篇很好的RoR部署方案性能评测 -
zweite:
直接对搜索的结果进行缓存是不是会更快一点呢
漫谈应用缓存的命中率问题 -
kaogua:
现在已经是ruby2.0了, 不知道这个的效率是怎么样的, 是 ...
Ruby作为服务器端应用已经成熟了
domain model,又称为领域模型,是Java企业应用讨论的一个热门话题,JavaEye也曾经多次围绕这个话题讨论,我们来看个简单的例子:
一个简单的公司工时管理系统,记录员工的个人信息,每个员工的工作任务分配,以及工作所属类别(例如开发,还是测试,还是培训等等),其中每个员工有n个任务,员工和任务是一对多关系,每个员工也分别隶属于多个不同的工作类别,员工和类型是多对多关联关系,而每个任务也分别隶属于唯一的工作类别,任务和类别是多对一关系。另外系统不要求对部门信息进行维护,不需要department表。因此,在这个系统中使用四张数据库表:
users表保存员工信息,有name, password, gender, department, salary
tasks表保存工作任务信息,有name,start_time, end_time
kinds表保存工作所属类别,有name
kinds_users表是一张关联表,保存users表和kinds表的多对多关联外键的
系统的功能需求如下:
1、某部门录用一名新员工
2、某部门员工总薪水总和
3、某员工已经开始但尚未结束的任务
4、给某员工分配一项任务
5、所有用户当前已经开始但尚未结束的任务
6、对某一类别,给所有和此一类别相关的员工,批量新增一批任务
7、针对任务的统计功能,给定某类别,统计当月总的任务数,已完成任务数,未完成任务数
我们先看看用ruby如何实现系统的领域模型:
1、某部门录用一名新员工
2、某部门员工总薪水总和
3、某员工已经开始但尚未结束的任务
4、给某员工分配一项任务
5、所有用户当前已经开始但尚未结束的任务
6、对某一类别,给所有和此一类别相关的员工,批量新增一批任务
7、针对任务的统计功能,给定某类别,统计当月总的任务数,已完成任务数,未完成任务数
这里值得注意的是,RoR可以很方便的采用充血的领域模型,所有的业务逻辑都可以放在相关的domain model里面。这里的user,task和kind都是对应于数据库表的领域模型,而department是不对应数据库的纯业务逻辑的domain model。总共4个ruby文件,4个domain model,55行代码,所有要写的代码都在这里了,代码量确实非常少,每个domain model的颗粒度都比较大。
然后我们再看看如何用Java:
Java版本的实现代码大家都比较熟悉,因此绝大部分代码都省略了。Java版本需要3个持久对象,3个映射XML文件,3个DAO接口和实现类,4个Service和实现类,和一个IoC的bean组装文件,总共21个文件,全部逻辑写完整,代码行数至少上千行。
通过对比,我们可以看到Java比较流行的实现是贫血的模型,按照面向对象的基本原则,对象的状态应该和它的行为封装在一起,因此Java多出来的这些XXXService是一些从纯理论角度而言应该放入其相应的持久对象中去。但是Java实现充血模型从技术上有一定的难度,如何Service方法挪入到持久对象中呢?如何解决Dao的注入问题?如何解决domain logic方法的事务封装问题?前者可以通过AspectJ的静态织入来解决,后者也许可以通过织入或者annotation声明来解决。但不管怎么说,Java从技术上很难实现充血模型,而且即使实现充血模型,也会导致一个Java类好几百行代码的状况,其代码的可阅读性,模块解藕能力都会变得很差,因此我们认为Java不适合充血模型,在表达复杂的业务逻辑的能力上,Java要比ruby差很多:
结论:
对于Java来说,更加适合采用贫血的模型,Java比较适合于把一个复杂的业务逻辑分离到n个小对象中去,每个小对象描述单一的职责,n个对象互相协作来表达一个复杂的业务逻辑,这n个对象之间的依赖和协作需要通过外部的容器例如IoC来显式的管理。但对于每个具体的对象来说,他们毫无疑问是贫血的。
这种贫血的模型好处是:
1、每个贫血对象职责单一,所以模块解藕程度很高,有利于错误的隔离。
2、非常重要的是,这种模型非常适合于软件外包和大规模软件团队的协作。每个编程个体只需要负责单一职责的小对象模块编写,不会互相影响。
贫血模型的坏处是:
1、由于对象状态和行为分离,所以一个完整的业务逻辑的描述不能够在一个类当中完成,而是一组互相协作的类共同完成的。因此可复用的颗粒度比较小,代码量膨胀的很厉害,最重要的是业务逻辑的描述能力比较差,一个稍微复杂的业务逻辑,就需要太多类和太多代码去表达(针对我们假定的这个简单的工时管理系统的业务逻辑实现,ruby使用了50行代码,但Java至少要上千行代码)。
2、对象协作依赖于外部容器的组装,因此裸写代码是不可能的了,必须借助于外部的IoC容器。
对于Ruby来说,更加适合充血模型。因为ruby语言的表达能力非常强大,现在用ruby做企业应用的DSL是一个很热门的领域,DSL说白了就是用来描述某个行业业务逻辑的专用语言。
充血模型的好处是:
1、对象自洽程度很高,表达能力很强,因此非常适合于复杂的企业业务逻辑的实现,以及可复用程度比较高。
2、不必依赖外部容器的组装,所以RoR没有IoC的概念。
充血模型的坏处是:
1、对象高度自洽的结果是不利于大规模团队分工协作。一个编程个体至少要完成一个完整业务逻辑的功能。对于单个完整业务逻辑,无法再细分下去了。
2、随着业务逻辑的变动,领域模型可能会处于比较频繁的变动状态中,领域模型不够稳定也会带来web层代码频繁变动。
附件是完整的RoR版本的项目示例代码。要运行它,需要安装MySQL数据库(InnoDB表类型),Ruby和Ruby on rails环境。在MySQL数据库中分别创建demo数据库和demo_test数据库,修改demo\config\database.yml中的MySQL数据库配置,改成你的数据库密码。然后在项目跟目录下面执行:
rake db:migrate
rake db:test:clone_structure
rake test
即创建开发环境数据库,创建测试环境数据库,和执行所有的单元测试。领域模型代码位于demo\app\models目录下面;单元测试代码位于demo\test\units目录下面
你这个领域模型是根本跑不起来的。数据库根本就没有department这个表,你的department的users属性根本就是null,一跑就会出错。你的user.addTask方法也执行不了,没有Dao的支持,你再调用addTask,数据库里面也不增加记录。UserManager也不应该存在,这是属于user的domain logic。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
单独的领域模型当然跑不起来,和其它层装配起来就跑的很以欢畅了。
我写的Domain Model是根据Eric Evans的观点来的,很多持久化(包括事务)的操作超越了业务逻辑,需要被安排在应用服务层。
你写的那段不是MF的充血模型,而是事务脚本。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
这个不是讨论问题的最佳方法,太累了,你写的代码同样不能运行
寻找这样的错误是没有意义的,只要思路正确,在座的各位都可以把代码调试好。
OO思想或者实现不能应用到系统所有地方,JavaInActoin这么说也是很有道理的。
.....
Java版本的实现代码大家都比较熟悉,因此绝大部分代码都省略了。Java版本需要3个持久对象,3个映射XML文件,3个DAO接口和实现类,4个Service和实现类,和一个IoC的bean组装文件,总共21个文件,全部逻辑写完整,代码行数至少上千行。
不要把Java一棒子打死吧, TOB上的充血模型也是Java的, 哪里不好请指点出来, 否则还是说 "主流Java实现" 比较合适.
通过对比,我们可以看到Java比较流行的实现是贫血的模型,按照面向对象的基本原则,对象的状态应该和它的行为封装在一起,因此Java多出来的这些XXXService是一些从纯理论角度而言应该放入其相应的持久对象中去。但是Java实现充血模型从技术上有一定的难度,如何Service方法挪入到持久对象中呢?如何解决Dao的注入问题?如何解决domain logic方法的事务封装问题?前者可以通过AspectJ的静态织入来解决,后者也许可以通过织入或者annotation声明来解决。但不管怎么说,Java从技术上很难实现充血模型,而且即使实现充血模型,也会导致一个Java类好几百行代码的状况,其代码的可阅读性,模块解藕能力都会变得很差,因此我们认为Java不适合充血模型,在表达复杂的业务逻辑的能力上,Java要比ruby差很多:
用TOB的话, 开发者只需要关心自己的代码, 就是我给出的那么多, 没有混局的代码呀. 其余有些是在编译应用代码的时候把所有需要的额外逻辑都自动生成出来的, 不需要关心, 而且不改动应用类bytecode, 只要子类有权访问就不用反射, 可以说对运行期效率基本没有影响. 编译时速度有些影响, 但是不影响在IDE中开发时的自动提示, 重构和其它辅助功能, 编译上稍微多花点时间应该可以接受吧, 换来的是运行期比Hibernate快几倍到上千倍的效率.
附件是完整的RoR版本的项目示例代码。要运行它,需要安装MySQL数据库(InnoDB表类型),Ruby和Ruby on rails环境。在MySQL数据库中分别创建demo数据库和demo_test数据库,修改demo\config\database.yml中的MySQL数据库配置,改成你的数据库密码。然后在项目跟目录下面执行:
rake db:migrate
rake db:test:clone_structure
rake test
即创建开发环境数据库,创建测试环境数据库,和执行所有的单元测试。领域模型代码位于demo\app\models目录下面;单元测试代码位于demo\test\units目录下面
用RoR数据库还要自己建, 这点我自认TOB做得更好, 只要配置好连接参数, 运行期TOB会自动创建或者扩充数据库表结构, 应用开发人员只需要创建和修改Java源码, 编译后直接运行就可以了.
Java难于实现充血模型的根本原因还是在于:Java是静态类型的语言,难以运行期任意的动态改变其行为,所以必须依赖外部容器例如IoC进行对象依赖组装,也必须依赖特定的ORM框架进行增强其行为,这些容器和框架本质上都是通过动态代理方式来增强类,其结果就是对象的设计必须符合容器对它的要求,从而限制你追求理论上更完美模型的可能性。至于继承不继承类,这个根本无关紧要。
不知道大家有没有想过,为什么Java这么强调面向接口编程?面向接口编程为什么对Java这么重要?但是对于动态面向对象语言ruby来说,却根本不需要接口这种概念。这是因为在Java中是类型决定行为,所以类型的地位很重要,你一继承,对象的行为就被限制死了,所以Java很忌讳继承的使用;但是ruby的类型不决定行为,所以随便你怎么继承,也不会限制对象的行为。
技术的进步会影响到理论的实现和普及。在Java世界ORM流行之前,要对持久层进行对象建模,根本不切实际。我在2003年之前都是采取类似iBATIS的方式建模。
03年ORM开始流行,自从ORM框架逐渐成熟以后,人们可以开始在持久层进行对象建模了,这个时候Martin Fowler又说你们的模型是贫血的,必须给模型充血。04年的时候老马这么一说,着实让我们烦躁了一阵。你说要充血,可我们手里根本就没有输血的工具阿,何况我们贫血模型也用得挺好阿,干吗要充血?
05年以后RoR开始逐渐被人关注。这个时候我们发现原来RoR才是真正适合充血模型的工具。在RoR的支持下,充血模型果然可以玩的有声有色,所以我们也开始逐渐接受充血。
你这个领域模型是根本跑不起来的。数据库根本就没有department这个表,你的department的users属性根本就是null,一跑就会出错。你的user.addTask方法也执行不了,没有Dao的支持,你再调用addTask,数据库里面也不增加记录。UserManager也不应该存在,这是属于user的domain logic。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
单独的领域模型当然跑不起来,和其它层装配起来就跑的很以欢畅了。
我写的Domain Model是根据Eric Evans的观点来的,很多持久化(包括事务)的操作超越了业务逻辑,需要被安排在应用服务层。
你写的那段不是MF的充血模型,而是事务脚本。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
这个不是讨论问题的最佳方法,太累了,你写的代码同样不能运行
寻找这样的错误是没有意义的,只要思路正确,在座的各位都可以把代码调试好。
我写的RoR充血模型代码放在项目里面立刻可以跑的。至于你所谓的和其他层装配起来就可以跑的很欢畅,那么请你把你的代码和其他层装配好,然后作为附件上传,请大家来下载测试一下你的代码究竟能不能跑!你写了一个根本在实际项目中不能用的代码出来,能说明什么问题呢?
你这个领域模型是根本跑不起来的。数据库根本就没有department这个表,你的department的users属性根本就是null,一跑就会出错。你的user.addTask方法也执行不了,没有Dao的支持,你再调用addTask,数据库里面也不增加记录。UserManager也不应该存在,这是属于user的domain logic。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
单独的领域模型当然跑不起来,和其它层装配起来就跑的很以欢畅了。
我写的Domain Model是根据Eric Evans的观点来的,很多持久化(包括事务)的操作超越了业务逻辑,需要被安排在应用服务层。
你写的那段不是MF的充血模型,而是事务脚本。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
这个不是讨论问题的最佳方法,太累了,你写的代码同样不能运行
寻找这样的错误是没有意义的,只要思路正确,在座的各位都可以把代码调试好。
引用
一个简单的公司工时管理系统,记录员工的个人信息,每个员工的工作任务分配,以及工作所属类别(例如开发,还是测试,还是培训等等),其中每个员工有n个任务,员工和任务是一对多关系,每个员工也分别隶属于多个不同的工作类别,员工和类型是多对多关联关系,而每个任务也分别隶属于唯一的工作类别,任务和类别是多对一关系。另外系统不要求对部门信息进行维护,不需要department表。因此,在这个系统中使用四张数据库表:
users表保存员工信息,有name, password, gender, department, salary
tasks表保存工作任务信息,有name,start_time, end_time
kinds表保存工作所属类别,有name
kinds_users表是一张关联表,保存users表和kinds表的多对多关联外键的
系统的功能需求如下:
1、某部门录用一名新员工
2、某部门员工总薪水总和
3、某员工已经开始但尚未结束的任务
4、给某员工分配一项任务
5、所有用户当前已经开始但尚未结束的任务
6、对某一类别,给所有和此一类别相关的员工,批量新增一批任务
7、针对任务的统计功能,给定某类别,统计当月总的任务数,已完成任务数,未完成任务数
我们先看看用ruby如何实现系统的领域模型:
class User < ActiveRecord::Base has_and_belongs_to_many :kinds has_many :tasks, :dependent => :destroy do def processing_tasks find :all, :conditions => ["start_time <= ? AND end_time is null", Time.now] end end def apply_task(task_name) self.tasks << Task.new(:name => task_name, :start_time => Date.today) end def self.all_processing_tasks Task.find :all, :conditions => ["start_time <= ? AND end_time is null AND user_id is not null",Time.now] end end class Task < ActiveRecord::Base belongs_to : owner, :class_name => 'User', :foreign_key => 'user_id' belongs_to :kind def self.current_month_tasks(kind) kind.tasks.current_month_tasks end end class Kind < ActiveRecord::Base has_and_belongs_to_many :users has_many :tasks do def current_month_tasks month_begin = Date.today - Date.today.mday + 1 month_end = Date.today - Date.today.mday + 30 processing_tasks = find :all, :conditions => ["start_time <= ? AND end_time is null ", month_begin] processed_tasks = find :all, :conditions => ["end_time >= ? AND end_time <= ? ", month_begin, month_end] all_tasks = processing_tasks.clone all_tasks << processed_tasks unless processed_tasks.size == 0 return all_tasks, processed_tasks, processing_tasks end end def add_batch_task_to_users(task_name) self.users.each do |user| task = Task.new(:name => task_name, :start_time => Date.today) user.tasks << task self.tasks << task end end end class Department def self.employee(username, department) User.create(:name => username, :department => department) end def self.total_salary(department) User.sum :salary, :conditions => ["department = ?", department] end end
1、某部门录用一名新员工
Department.employee("robbin","开发部")
2、某部门员工总薪水总和
Department.total_salary("开发部")
3、某员工已经开始但尚未结束的任务
user.tasks.processing_tasks
4、给某员工分配一项任务
user.apply_task("学习Java")
5、所有用户当前已经开始但尚未结束的任务
User.all_processing_tasks
6、对某一类别,给所有和此一类别相关的员工,批量新增一批任务
kind.add_batch_task_to_users("学习单元测试")
7、针对任务的统计功能,给定某类别,统计当月总的任务数,已完成任务数,未完成任务数
Task.current_month_tasks(kind)
这里值得注意的是,RoR可以很方便的采用充血的领域模型,所有的业务逻辑都可以放在相关的domain model里面。这里的user,task和kind都是对应于数据库表的领域模型,而department是不对应数据库的纯业务逻辑的domain model。总共4个ruby文件,4个domain model,55行代码,所有要写的代码都在这里了,代码量确实非常少,每个domain model的颗粒度都比较大。
然后我们再看看如何用Java:
public class User { private Long id; private String name; private String password; private String gender; private String department; private int salary = 0; private List<Task> tasks = new ArrayList<Task>(); # omit getter/setter methods ...... } # omit User's ORM Mapping file public class Task { private Long id; private String name; private int duration = 0; private User owner; # omit getter/setter methods ...... } # omit Task's ORM Mapping file public class Kind { ...... } # omit Kind's ORM Mapping file public interface UserDao { public void addUser(User user); public loadUserById(Long id); # omit CRUD and other persistent methods ...... public List<User> findByDeparment(String department); } public interface TaskDao { # omit CRUD and other persistent methods ...... } public class UserDaoImpl { # omit implementations ...... } public class TaskDaoImpl { # omit implementations ...... } public class UserService { private UserDao userDao; public setUserDao(UserDao userDao) { this.userDao = userDao; } public int workload(User user) { int totalDuration = 0; for (Task task : user.getTasks()) { totalDuration += task.duration; } return totalDuration; } public employee(String username, String department) { User user = new User(); user.setName(username); user.setDepartment(department); userDao.addUser(user); } } public class TaskService { private TaskDao taskDao; public void setTaskDao(TaskDao taskDao) { this.taskDao = taskDao } public applyTask(String taskName, User user) { Task task = new Task(); task.setName(taskName); task.setUser(user); taskDao.addTask(task); } } public class DepartmentService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } private UserService userService; public void setUserService(UserService userService) { this.userService = userService; } public int totalSalary(String department) { ...... } ...... } # omit IoC Container weaving configuration's file
Java版本的实现代码大家都比较熟悉,因此绝大部分代码都省略了。Java版本需要3个持久对象,3个映射XML文件,3个DAO接口和实现类,4个Service和实现类,和一个IoC的bean组装文件,总共21个文件,全部逻辑写完整,代码行数至少上千行。
通过对比,我们可以看到Java比较流行的实现是贫血的模型,按照面向对象的基本原则,对象的状态应该和它的行为封装在一起,因此Java多出来的这些XXXService是一些从纯理论角度而言应该放入其相应的持久对象中去。但是Java实现充血模型从技术上有一定的难度,如何Service方法挪入到持久对象中呢?如何解决Dao的注入问题?如何解决domain logic方法的事务封装问题?前者可以通过AspectJ的静态织入来解决,后者也许可以通过织入或者annotation声明来解决。但不管怎么说,Java从技术上很难实现充血模型,而且即使实现充血模型,也会导致一个Java类好几百行代码的状况,其代码的可阅读性,模块解藕能力都会变得很差,因此我们认为Java不适合充血模型,在表达复杂的业务逻辑的能力上,Java要比ruby差很多:
结论:
对于Java来说,更加适合采用贫血的模型,Java比较适合于把一个复杂的业务逻辑分离到n个小对象中去,每个小对象描述单一的职责,n个对象互相协作来表达一个复杂的业务逻辑,这n个对象之间的依赖和协作需要通过外部的容器例如IoC来显式的管理。但对于每个具体的对象来说,他们毫无疑问是贫血的。
这种贫血的模型好处是:
1、每个贫血对象职责单一,所以模块解藕程度很高,有利于错误的隔离。
2、非常重要的是,这种模型非常适合于软件外包和大规模软件团队的协作。每个编程个体只需要负责单一职责的小对象模块编写,不会互相影响。
贫血模型的坏处是:
1、由于对象状态和行为分离,所以一个完整的业务逻辑的描述不能够在一个类当中完成,而是一组互相协作的类共同完成的。因此可复用的颗粒度比较小,代码量膨胀的很厉害,最重要的是业务逻辑的描述能力比较差,一个稍微复杂的业务逻辑,就需要太多类和太多代码去表达(针对我们假定的这个简单的工时管理系统的业务逻辑实现,ruby使用了50行代码,但Java至少要上千行代码)。
2、对象协作依赖于外部容器的组装,因此裸写代码是不可能的了,必须借助于外部的IoC容器。
对于Ruby来说,更加适合充血模型。因为ruby语言的表达能力非常强大,现在用ruby做企业应用的DSL是一个很热门的领域,DSL说白了就是用来描述某个行业业务逻辑的专用语言。
充血模型的好处是:
1、对象自洽程度很高,表达能力很强,因此非常适合于复杂的企业业务逻辑的实现,以及可复用程度比较高。
2、不必依赖外部容器的组装,所以RoR没有IoC的概念。
充血模型的坏处是:
1、对象高度自洽的结果是不利于大规模团队分工协作。一个编程个体至少要完成一个完整业务逻辑的功能。对于单个完整业务逻辑,无法再细分下去了。
2、随着业务逻辑的变动,领域模型可能会处于比较频繁的变动状态中,领域模型不够稳定也会带来web层代码频繁变动。
附件是完整的RoR版本的项目示例代码。要运行它,需要安装MySQL数据库(InnoDB表类型),Ruby和Ruby on rails环境。在MySQL数据库中分别创建demo数据库和demo_test数据库,修改demo\config\database.yml中的MySQL数据库配置,改成你的数据库密码。然后在项目跟目录下面执行:
rake db:migrate
rake db:test:clone_structure
rake test
即创建开发环境数据库,创建测试环境数据库,和执行所有的单元测试。领域模型代码位于demo\app\models目录下面;单元测试代码位于demo\test\units目录下面
- demo.zip (80.6 KB)
- 描述: 完整的RoR版本的项目示例代码
- 下载次数: 576
评论
45 楼
chunshui
2007-03-04
谢谢Robbin好文
44 楼
firstline78
2007-03-04
JavaInActoin 写道
robbin 写道
你这个领域模型是根本跑不起来的。数据库根本就没有department这个表,你的department的users属性根本就是null,一跑就会出错。你的user.addTask方法也执行不了,没有Dao的支持,你再调用addTask,数据库里面也不增加记录。UserManager也不应该存在,这是属于user的domain logic。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
单独的领域模型当然跑不起来,和其它层装配起来就跑的很以欢畅了。
我写的Domain Model是根据Eric Evans的观点来的,很多持久化(包括事务)的操作超越了业务逻辑,需要被安排在应用服务层。
你写的那段不是MF的充血模型,而是事务脚本。
robbin 写道
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
这个不是讨论问题的最佳方法,太累了,你写的代码同样不能运行
robbin 写道
public employee(String username, String department) {
寻找这样的错误是没有意义的,只要思路正确,在座的各位都可以把代码调试好。
OO思想或者实现不能应用到系统所有地方,JavaInActoin这么说也是很有道理的。
43 楼
newman
2007-03-04
接chinaet的话题,从java开源大全网站获取SpringXT的摘要信息如下:
“SpringXT是Spring框架的一个扩展用于开发richer domain models与richer user interfaces的应用程序。采用Domain Driven Design设计原则。为此SpringXT提供两个框架SpringXT Modeling Framework:提供一些组件来开发rich domain model(它集中了所有业务逻辑,规则和约束,完全独立于应用程序的其它部分)并能够让它们与其它应用软件分层"优雅"结合。SpringXT Ajax Framework:一个完全与Spring MVC集成在一起,基于事件的Ajax框架。”
java开源大全网址:
http://www.open-open.com/open184107.htm
springxt官方网址:
http://springxt.sourceforge.net/index.php/Main_Page
“SpringXT是Spring框架的一个扩展用于开发richer domain models与richer user interfaces的应用程序。采用Domain Driven Design设计原则。为此SpringXT提供两个框架SpringXT Modeling Framework:提供一些组件来开发rich domain model(它集中了所有业务逻辑,规则和约束,完全独立于应用程序的其它部分)并能够让它们与其它应用软件分层"优雅"结合。SpringXT Ajax Framework:一个完全与Spring MVC集成在一起,基于事件的Ajax框架。”
java开源大全网址:
http://www.open-open.com/open184107.htm
springxt官方网址:
http://springxt.sourceforge.net/index.php/Main_Page
42 楼
chinaet
2007-03-04
大牛们,研究一下SpringXT,看看SpringXT能不能解决RICH DOMAIN MODEL的问题
41 楼
newman
2007-03-04
robbin写道:
“Java难于实现充血模型的根本原因还是在于:Java是静态类型的语言,难以运行期任意的动态改变其行为,所以必须依赖外部容器例如IoC进行对象依赖组装,也必须依赖特定的ORM框架进行增强其行为,这些容器和框架本质上都是通过动态代理方式来增强类,其结果就是对象的设计必须符合容器对它的要求,从而限制你追求理论上更完美模型的可能性。至于继承不继承类,这个根本无关紧要。”
re:你能否回答一下RR的哪些动态特性支持了其优越的域对象模型?而这些动态特性是java中无可企及的?
“不知道大家有没有想过,为什么Java这么强调面向接口编程?面向接口编程为什么对Java这么重要?但是对于动态面向对象语言ruby来说,却根本不需要接口这种概念。这是因为在Java中是类型决定行为,所以类型的地位很重要,你一继承,对象的行为就被限制死了,所以Java很忌讳继承的使用;但是ruby的类型不决定行为,所以随便你怎么继承,也不会限制对象的行为。”
re:这种灵活完全是优点吗?我看未必。对于简单应用,你想怎么应用就怎么应用,但是应用复杂了之后呢?随意的继承,会是怎样的一种后果?是否会产生系统消化不良,导致运行效率问题,还有后期无法维护呢?
“Java难于实现充血模型的根本原因还是在于:Java是静态类型的语言,难以运行期任意的动态改变其行为,所以必须依赖外部容器例如IoC进行对象依赖组装,也必须依赖特定的ORM框架进行增强其行为,这些容器和框架本质上都是通过动态代理方式来增强类,其结果就是对象的设计必须符合容器对它的要求,从而限制你追求理论上更完美模型的可能性。至于继承不继承类,这个根本无关紧要。”
re:你能否回答一下RR的哪些动态特性支持了其优越的域对象模型?而这些动态特性是java中无可企及的?
“不知道大家有没有想过,为什么Java这么强调面向接口编程?面向接口编程为什么对Java这么重要?但是对于动态面向对象语言ruby来说,却根本不需要接口这种概念。这是因为在Java中是类型决定行为,所以类型的地位很重要,你一继承,对象的行为就被限制死了,所以Java很忌讳继承的使用;但是ruby的类型不决定行为,所以随便你怎么继承,也不会限制对象的行为。”
re:这种灵活完全是优点吗?我看未必。对于简单应用,你想怎么应用就怎么应用,但是应用复杂了之后呢?随意的继承,会是怎样的一种后果?是否会产生系统消化不良,导致运行效率问题,还有后期无法维护呢?
40 楼
歆渊
2007-03-04
另外说起做Web应用来, 对于单服务器环境, 看看WoW就知道TOB应用的成熟程度了, 管理界面也是JSP的, Applet的xml通信模式和AJAX没有本质差别.
基于HBI的分布式模式也会很快成熟起来.
基于HBI的分布式模式也会很快成熟起来.
39 楼
歆渊
2007-03-04
呵呵, 所以是 "主流Java" 的问题, 而不是 "Java的问题" 嘛.
TOB的应用持久类改变以后, 不需要重启应用服务器呀, 热重新部署以后就可以让数据库表结构跟着更新, 这个不是更OO Centric么? 我觉得更好啊.
TOB的应用持久类改变以后, 不需要重启应用服务器呀, 热重新部署以后就可以让数据库表结构跟着更新, 这个不是更OO Centric么? 我觉得更好啊.
38 楼
robbin
2007-03-04
to complystill:
我没有仔细看TOB的实现,TOB相当于构建一个内存当中的对象数据库,这种编程模式和主流的基于关系数据库直接驱动的web项目差别比较大。
rails是由DB schema来动态决定对象的状态。在development环境下,任何对数据库的修改都立即会改变对象的状态行为。这和Hibernate由映射文件来动态生成数据库DDL正好反过来。但不能说谁好谁不好,在TOB中你能一改数据库schema,不需要重起应用服务器就让对象的property立刻随着改变吗?也做不到不是。
我没有仔细看TOB的实现,TOB相当于构建一个内存当中的对象数据库,这种编程模式和主流的基于关系数据库直接驱动的web项目差别比较大。
rails是由DB schema来动态决定对象的状态。在development环境下,任何对数据库的修改都立即会改变对象的状态行为。这和Hibernate由映射文件来动态生成数据库DDL正好反过来。但不能说谁好谁不好,在TOB中你能一改数据库schema,不需要重起应用服务器就让对象的property立刻随着改变吗?也做不到不是。
37 楼
歆渊
2007-03-04
robbin 写道
.....
Java版本的实现代码大家都比较熟悉,因此绝大部分代码都省略了。Java版本需要3个持久对象,3个映射XML文件,3个DAO接口和实现类,4个Service和实现类,和一个IoC的bean组装文件,总共21个文件,全部逻辑写完整,代码行数至少上千行。
不要把Java一棒子打死吧, TOB上的充血模型也是Java的, 哪里不好请指点出来, 否则还是说 "主流Java实现" 比较合适.
robbin 写道
通过对比,我们可以看到Java比较流行的实现是贫血的模型,按照面向对象的基本原则,对象的状态应该和它的行为封装在一起,因此Java多出来的这些XXXService是一些从纯理论角度而言应该放入其相应的持久对象中去。但是Java实现充血模型从技术上有一定的难度,如何Service方法挪入到持久对象中呢?如何解决Dao的注入问题?如何解决domain logic方法的事务封装问题?前者可以通过AspectJ的静态织入来解决,后者也许可以通过织入或者annotation声明来解决。但不管怎么说,Java从技术上很难实现充血模型,而且即使实现充血模型,也会导致一个Java类好几百行代码的状况,其代码的可阅读性,模块解藕能力都会变得很差,因此我们认为Java不适合充血模型,在表达复杂的业务逻辑的能力上,Java要比ruby差很多:
用TOB的话, 开发者只需要关心自己的代码, 就是我给出的那么多, 没有混局的代码呀. 其余有些是在编译应用代码的时候把所有需要的额外逻辑都自动生成出来的, 不需要关心, 而且不改动应用类bytecode, 只要子类有权访问就不用反射, 可以说对运行期效率基本没有影响. 编译时速度有些影响, 但是不影响在IDE中开发时的自动提示, 重构和其它辅助功能, 编译上稍微多花点时间应该可以接受吧, 换来的是运行期比Hibernate快几倍到上千倍的效率.
robbin 写道
附件是完整的RoR版本的项目示例代码。要运行它,需要安装MySQL数据库(InnoDB表类型),Ruby和Ruby on rails环境。在MySQL数据库中分别创建demo数据库和demo_test数据库,修改demo\config\database.yml中的MySQL数据库配置,改成你的数据库密码。然后在项目跟目录下面执行:
rake db:migrate
rake db:test:clone_structure
rake test
即创建开发环境数据库,创建测试环境数据库,和执行所有的单元测试。领域模型代码位于demo\app\models目录下面;单元测试代码位于demo\test\units目录下面
用RoR数据库还要自己建, 这点我自认TOB做得更好, 只要配置好连接参数, 运行期TOB会自动创建或者扩充数据库表结构, 应用开发人员只需要创建和修改Java源码, 编译后直接运行就可以了.
36 楼
robbin
2007-03-04
fuliang 写道
我感觉java实现充血型模型有难度关键是:
一方面,如果使用ioc,则由于entity bean是不受ioc管理.
另一方面,Java实现的domain如果能够象ror的domain继承类似于ActiveRecord那样的来实现持久化,就会向ejb那样被人指责
依赖于具体的框架,具有不可携性,很难移植...
而rails则不会,因为ruby只有rails,没有形成真正的平台,况且rails足够好,框架的侵入性没有什么不可接受的.
一方面,如果使用ioc,则由于entity bean是不受ioc管理.
另一方面,Java实现的domain如果能够象ror的domain继承类似于ActiveRecord那样的来实现持久化,就会向ejb那样被人指责
依赖于具体的框架,具有不可携性,很难移植...
而rails则不会,因为ruby只有rails,没有形成真正的平台,况且rails足够好,框架的侵入性没有什么不可接受的.
Java难于实现充血模型的根本原因还是在于:Java是静态类型的语言,难以运行期任意的动态改变其行为,所以必须依赖外部容器例如IoC进行对象依赖组装,也必须依赖特定的ORM框架进行增强其行为,这些容器和框架本质上都是通过动态代理方式来增强类,其结果就是对象的设计必须符合容器对它的要求,从而限制你追求理论上更完美模型的可能性。至于继承不继承类,这个根本无关紧要。
不知道大家有没有想过,为什么Java这么强调面向接口编程?面向接口编程为什么对Java这么重要?但是对于动态面向对象语言ruby来说,却根本不需要接口这种概念。这是因为在Java中是类型决定行为,所以类型的地位很重要,你一继承,对象的行为就被限制死了,所以Java很忌讳继承的使用;但是ruby的类型不决定行为,所以随便你怎么继承,也不会限制对象的行为。
技术的进步会影响到理论的实现和普及。在Java世界ORM流行之前,要对持久层进行对象建模,根本不切实际。我在2003年之前都是采取类似iBATIS的方式建模。
03年ORM开始流行,自从ORM框架逐渐成熟以后,人们可以开始在持久层进行对象建模了,这个时候Martin Fowler又说你们的模型是贫血的,必须给模型充血。04年的时候老马这么一说,着实让我们烦躁了一阵。你说要充血,可我们手里根本就没有输血的工具阿,何况我们贫血模型也用得挺好阿,干吗要充血?
05年以后RoR开始逐渐被人关注。这个时候我们发现原来RoR才是真正适合充血模型的工具。在RoR的支持下,充血模型果然可以玩的有声有色,所以我们也开始逐渐接受充血。
35 楼
jamesby
2007-03-04
前面有一篇关于充血模型还是涨血模型的讨论我也看了,涨了不少见识. 感谢各位的精彩讨论.
34 楼
agile_boy
2007-03-04
如果单从语言层面上看,我觉得两者没有什么可比性,两者都是比较好的OO语言,不过ruby可能更灵活更动态而已。
在实现Domain model上,ruby也是借助于rails(对ror还不是很了解),那么java借助于hibernate/jdo来实现这样的模型应该也不是什么大问题
在实现Domain model上,ruby也是借助于rails(对ror还不是很了解),那么java借助于hibernate/jdo来实现这样的模型应该也不是什么大问题
33 楼
jianfeng008cn
2007-03-03
再放一箭 楼上的朋友说话和其照片让我感觉很相辅!
多谢robin等的耐心讲解,thinking
多谢robin等的耐心讲解,thinking
32 楼
newman
2007-03-03
昨天晚上就为这个话题在网上逗留了许久,今天再一看发现robbin同学很是快手,把这个话题又重新整理了一遍,真是辛苦,虽然争论依然激烈,不过很多问题也得到了澄清,看着各位大侠在场上刀来剑往,我想在这里说上几句:
1.这个问题的来源是fatzhen发的一个名为"主题: 为什么java里不能把域对象和DAO合并,rails里面就可以?",原贴子的地址是http://www.iteye.com/topic/56949。
2.在这篇贴子里,robbin还提到了另一篇精彩的文章叫“完美就是生产力”,一位老兄在半夜挑灯夜战抽烟搞出来的一篇文章,我建议参与讨论的网友如果对ruby不够了解的去看看,我看了后是很有收获的,很多背景问题(因为我是搞java的,rr只是搞了些皮毛)能搞清楚。
3.讨论的问题还是域对象模型在两种语言中的支持和实现优劣,而不是某某要取代某某。
4.域模型比oo模型要高级,对业务的描述性更好,也利于业务的计算实现,rr对域模型的支持和实现我认为是要优于java,但是,java也未必需要如rr一般的方法去实现域对象模型,正好比一个使刀的,一个用剑的,没必要说非得弃剑用刀或者弃刀用剑,尤其是java语言和rr语言在本质和风格上面相差太大。
5.代码强阅读性和LOC少是rr的最大热点,当然ActiveRecord做得也是非常不错,但是Java同样有很多出色的优点。
6.贫血模型还是涨血模型,我看还是根据实际应用来论,robbin也对这个问题做了分析,我也不多说了,我认为分析得还是很到位。
7.既然是刀来剑往,我想没有一个人能够100%保持彬彬有礼的形象,出言不逊在所难免,但是既然都是武林中人,能够互相切磋技艺心法,实在是人生之幸事,那些激昂言语也大可在一笑中抛诸脑后。
1.这个问题的来源是fatzhen发的一个名为"主题: 为什么java里不能把域对象和DAO合并,rails里面就可以?",原贴子的地址是http://www.iteye.com/topic/56949。
2.在这篇贴子里,robbin还提到了另一篇精彩的文章叫“完美就是生产力”,一位老兄在半夜挑灯夜战抽烟搞出来的一篇文章,我建议参与讨论的网友如果对ruby不够了解的去看看,我看了后是很有收获的,很多背景问题(因为我是搞java的,rr只是搞了些皮毛)能搞清楚。
3.讨论的问题还是域对象模型在两种语言中的支持和实现优劣,而不是某某要取代某某。
4.域模型比oo模型要高级,对业务的描述性更好,也利于业务的计算实现,rr对域模型的支持和实现我认为是要优于java,但是,java也未必需要如rr一般的方法去实现域对象模型,正好比一个使刀的,一个用剑的,没必要说非得弃剑用刀或者弃刀用剑,尤其是java语言和rr语言在本质和风格上面相差太大。
5.代码强阅读性和LOC少是rr的最大热点,当然ActiveRecord做得也是非常不错,但是Java同样有很多出色的优点。
6.贫血模型还是涨血模型,我看还是根据实际应用来论,robbin也对这个问题做了分析,我也不多说了,我认为分析得还是很到位。
7.既然是刀来剑往,我想没有一个人能够100%保持彬彬有礼的形象,出言不逊在所难免,但是既然都是武林中人,能够互相切磋技艺心法,实在是人生之幸事,那些激昂言语也大可在一笑中抛诸脑后。
31 楼
clamp
2007-03-03
很漂亮的实现,不过仍然有问题。
1.kind只是一个字典表,而现在却被扩充为很庞大的DomainModel,这个从业务分析的角度来说是不太自然的
2.processing_task这个业务逻辑已经在user,task,kind这三个类中都出现了,这样做是否合理?是否可以重构?重构以后是否会破坏DomainModel?
3.指定用户user的统计当月总的任务数,已完成任务数,未完成任务数
all_tasks, processed_tasks, processing_tasks = kind.tasks.current_month_tasks(user)
这个为什么是kind的领域逻辑而不是user的领域逻辑?
比如写成user.tasks.current_month_tasks(kind)
越复杂的关系运算就越难归结为某个DomainModel的领域逻辑,虽然ruby在这点上比java强,但是强的也有限。
1.kind只是一个字典表,而现在却被扩充为很庞大的DomainModel,这个从业务分析的角度来说是不太自然的
2.processing_task这个业务逻辑已经在user,task,kind这三个类中都出现了,这样做是否合理?是否可以重构?重构以后是否会破坏DomainModel?
3.指定用户user的统计当月总的任务数,已完成任务数,未完成任务数
all_tasks, processed_tasks, processing_tasks = kind.tasks.current_month_tasks(user)
这个为什么是kind的领域逻辑而不是user的领域逻辑?
比如写成user.tasks.current_month_tasks(kind)
越复杂的关系运算就越难归结为某个DomainModel的领域逻辑,虽然ruby在这点上比java强,但是强的也有限。
30 楼
fuliang
2007-03-03
我感觉java实现充血型模型有难度关键是:
一方面,如果使用ioc,则由于entity bean是不受ioc管理.
另一方面,Java实现的domain如果能够象ror的domain继承类似于ActiveRecord那样的来实现持久化,就会向ejb那样被人指责
依赖于具体的框架,具有不可携性,很难移植...
而rails则不会,因为ruby只有rails,没有形成真正的平台,况且rails足够好,框架的侵入性没有什么不可接受的.
一方面,如果使用ioc,则由于entity bean是不受ioc管理.
另一方面,Java实现的domain如果能够象ror的domain继承类似于ActiveRecord那样的来实现持久化,就会向ejb那样被人指责
依赖于具体的框架,具有不可携性,很难移植...
而rails则不会,因为ruby只有rails,没有形成真正的平台,况且rails足够好,框架的侵入性没有什么不可接受的.
29 楼
robbin
2007-03-03
见主贴贴
28 楼
JavaInActoin
2007-03-03
这里是讨论问题,不是开发一个可运行的软件,没有人真的把这些代码下载放在项目里跑,也就看看思想罢了,总共就几十行代码,作为附件上传看起来也不方便。
27 楼
robbin
2007-03-03
JavaInActoin 写道
robbin 写道
你这个领域模型是根本跑不起来的。数据库根本就没有department这个表,你的department的users属性根本就是null,一跑就会出错。你的user.addTask方法也执行不了,没有Dao的支持,你再调用addTask,数据库里面也不增加记录。UserManager也不应该存在,这是属于user的domain logic。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
单独的领域模型当然跑不起来,和其它层装配起来就跑的很以欢畅了。
我写的Domain Model是根据Eric Evans的观点来的,很多持久化(包括事务)的操作超越了业务逻辑,需要被安排在应用服务层。
你写的那段不是MF的充血模型,而是事务脚本。
robbin 写道
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
这个不是讨论问题的最佳方法,太累了,你写的代码同样不能运行
robbin 写道
public employee(String username, String department) {
寻找这样的错误是没有意义的,只要思路正确,在座的各位都可以把代码调试好。
我写的RoR充血模型代码放在项目里面立刻可以跑的。至于你所谓的和其他层装配起来就可以跑的很欢畅,那么请你把你的代码和其他层装配好,然后作为附件上传,请大家来下载测试一下你的代码究竟能不能跑!你写了一个根本在实际项目中不能用的代码出来,能说明什么问题呢?
26 楼
JavaInActoin
2007-03-03
robbin 写道
你这个领域模型是根本跑不起来的。数据库根本就没有department这个表,你的department的users属性根本就是null,一跑就会出错。你的user.addTask方法也执行不了,没有Dao的支持,你再调用addTask,数据库里面也不增加记录。UserManager也不应该存在,这是属于user的domain logic。
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
单独的领域模型当然跑不起来,和其它层装配起来就跑的很以欢畅了。
我写的Domain Model是根据Eric Evans的观点来的,很多持久化(包括事务)的操作超越了业务逻辑,需要被安排在应用服务层。
你写的那段不是MF的充血模型,而是事务脚本。
robbin 写道
请不要拿一个根本不能运行的错误代码出来,请先在你本地搭建一个实际的web项目,自己测试通过了,再贴出来。
这个不是讨论问题的最佳方法,太累了,你写的代码同样不能运行
robbin 写道
public employee(String username, String department) {
寻找这样的错误是没有意义的,只要思路正确,在座的各位都可以把代码调试好。
发表评论
-
WebObjects的来龙去脉
2012-06-08 15:30 7440在知乎上回答的一个问题:http://www.zhihu.co ... -
缓存技术浅谈
2010-09-24 18:08 21644有我在两年前写的一个培训的ppt,是介绍缓存知识的。有兴趣的可 ... -
对领域模型实现的总结性观点
2008-11-30 15:16 19416陶文发起的对领域模型 ... -
发现JBoss Seam很棒呀!有用Seam做过项目的吗?
2008-07-06 20:56 30053上周去见了一个朋友Mark,他应邀在Red Hat的研讨会上面 ... -
Spring Application Platform - SpringSource的应用服务器发布
2008-05-05 17:04 68322008年的5.1劳动节,Spring ... -
Warp framework - 一个相当有前途的Java轻量级Web开发框架
2008-03-06 15:24 22354Warp framework 是最近刚刚 ... -
Google Android会成为手机领域的微软Windows吗?
2007-11-16 17:23 9577Google gPhone手机的传言已经沸沸扬扬好几个月了,然 ... -
Java已经过时了吗?
2007-07-02 15:43 59626在四年以前,当我开始 ... -
Java开源框架发展的遐想
2007-05-23 00:04 34724上周末在杭州网侠大会做演讲的时候,我说:Java开源框架的革命 ... -
漫谈应用缓存的命中率问题
2007-05-09 14:19 26219这篇文章源自于: http://www.iteye.com/ ... -
为什么ORM性能比iBATIS好?
2007-05-06 11:16 34403缓存是有很多层次的,有web server前端缓存,有动态页面 ... -
点评Grails vs RoR
2007-03-30 17:49 8240Grails的革新和RoR相比,非常不彻底,很多地方兼容Jav ... -
缓存简述
2007-03-30 09:55 12210缓存实现的层面有很多: 1、对象缓存 由ORM框架提供,透明 ... -
JRuby0.9.8,正式宣布支持ruby on rails
2007-03-07 10:35 15597http://jruby.codehaus.org/ 自从S ... -
可以开始用Struts2.0了
2007-02-27 14:56 55985http://struts.apache.org/ Apac ... -
Google Guice - 比Spring快100倍的IoC容器
2007-02-27 14:46 58081http://code.google.com/p/google ... -
Spring2.0和EJB3.0随谈
2007-02-08 14:26 18412Spring自从2003年发布以来 ... -
Java程序员的推荐阅读书籍
2007-02-07 20:12 101216《Java程序员的推荐阅读 ... -
应该如何正确使用Quartz
2006-12-27 11:40 34089对于Web容器来说,最忌讳应用程序私自启动线程,自行进行线程调 ... -
静态类型语言的优势究竟是什么?
2006-11-13 10:03 33297在参与这个讨论的过程中,产生了一个新的话题,很想和大家探讨一下 ...
相关推荐
Domain model manual 324
lec-5 领域模型 DomainModel.ppt
python库。资源全名:domainmodel-0.12.tar.gz
python库。 资源全名:domainmodel-0.2-py2.4.egg
Java MVC framework, agile, fast, rich domain model, made e.zip
领域模型XText Domainmodel示例(按发行版)
MapperRegistry是工厂方法的变形?摘要本文通过由ActiveRecord模式到DataMapper模式(使用工厂方法)再到DataMapper模式(使用MapperRegistry)的一系列重构,探讨模式背后隐藏的思想和面向对象设计原则。...
jar包,官方版本,自测可用
ppt演讲稿 博文链接:https://taowen.iteye.com/blog/226387
propose a regularized unsupervised optimal transportation model to perform the alignment of the representations in the source and target domains. We learn a transportation plan matching both PDFs, ...
Continuous time modeling: time domain, Laplace domain, and FOPDT models Feedforward, cascade, override, and single-variable inferential control approaches One and two degree of freedom Internal ...
深入理解ApplicationDomain和SecurityDomain
'Eric Evans has written a fantastic book on how you can make the design of your software match your mental model of the problem domain you are addressing. 'His book is very compatible with XP. It is ...
The main focus of the book is how a Domain Model could be constructed to be clean, yet still be persistence-friendly. It shows what the persistence solution could look like for such a Domain Model and...
一种支持人网交互的基于领域模型的情境建模方法,何扬帆,,本文介绍了一种新型情境建模方法。该方法从领域模型中选取概念来构造情境模型。这种方法有助于减少人往交互中用户的显式输入。情
Deep generative model with domain adversarial training for predicting arterial blood pressure waveform from photoplethysmogram signal
Wavelet Transform Domain Filters
Different objects and prototypes will help you create model for your business process and see how DDD develops common language for developers and domain experts. Context map will help you manage ...