JAVA专家Robbin: 谈domain model的延伸
domain model,又称为领域模型,是Java企业应用讨论的一个热门话题,下面举例说明:
引用
一个简单的公司工时管理系统,记录员工的个人信息,每个员工的工作任务分配,以及工作所属类别(例如开发,还是测试,还是培训等等),其中每个员工有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如何实现系统的领域模型:
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