智能领域对象设计(演绎革命)-1/2

10-08-08 cuwkuhaihong
请先看看:智能领域对象设计

本文源代码

关于智能领域对象的设计,一直没有拿出确实的例子来说明这样编程的好处和优点,以及如何正确地理解这种编程方式。接下来我开始从传统Service + DAO开发模式开始改造和发展,直到变化成智能领域对象设计的开发模式上来,对于每一种变化,我会统计出手工代码编写行数(setter 、getter和import等就不在统计范围内了),看看生产力的变化。任何生产力的提高都是体现在机械代替重复而又规律的工作上,我们选择的案例同样是本应该被工业化掉的东西,但还在手工劳作。

传统的Service + DAO包括三个核心类,以“用户”对象为例,通常包括的类:User, UserService, UserDAO。通常需要的外部支持是:hibernate/jpa,spring。为了演示方便忽略掉接口(如IUserService),也不再区分PO和VO。事实上案例演示完成后,你会发觉这两个东西确实很少使用。

这个实例中包含了一个持久层框架Thin,我先将有关持久的论述写在这里,你可以先看实例回头有兴趣再这段内容:所谓对象的持久就是把对象的属性登记在数据库中,在现实生活是经常发生的,如我们去银行办一个储蓄卡,需要填表,而填表的过程就是持久化的过程。看看这张表格,便会发现所有填写项都可以用key-value表示,再考察我们是如何区分现实对象,便会发现同样是以对象的属性为区分依据,属性就可以用key-value表示,所以无论任何对象只要被持久必然可转化成key-value,唯一的不同就是key-value的存储方法不同而已,即:key-value是一切对象持久的接口。如果应用程序的持久方式是基于key-value的,那么这种应用不仅便于更换不同的关系数据库,即使是往NO-SQL数据库上移植,纵然我对No-SQL数据库不甚了解,但它绝不会偏离本质。Thin就是这么一个工具,把对象转化成key-value,然后存入对应的表,反之亦可。科学家通常用习惯用“美”来衡量结论正确性,虽然没有什么科学依据,但也屡试不爽。key-value是一切对象持久的接口,这个结论是美的,大家可以顺便考量一下thin的短小精干是否也符合美的标准。”大道若简”,我相信基于key-value的持久方式,正是持久层的“大道”。

User类改动前User.java:

@Entity
@Table(name=”user”)
public class User{
	@Id
	private String uid;
	private String uname;
	private String password;
	private String gid;//机构ID
	private String gname;//机构名称
	private String rid;//角色ID
	private String rname;//角色名称

	//setter and getter	
}

UserService.java

/**
 * spring的配置忽略
 * 
 * <bean id="UserService" class="com.icitic.zero.service.impl.UserService">
      <property name="userDao" ref="userDao"/>
   </bean>    
    
 * @author haihong
 *
 */
public class UserService {
    private UserDAO userDao;
    public void addUser(User user) {
		try {
			this.userDao.add(user);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
   public User getUser(String id) {
		try {
			this.userDao.getUserById(id);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return null;
	}

	public void updateUser(User user) {
		try {
			this.userDao.update(user);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void deleteUser(Collection<User> users) {
		try {
			User[] us = new User[users.size()];
			users.toArray(us);
			this.userDao.delete(us);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void saveOrUpdate(User user) {
		try {
			this.userDao.save(user);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public UserDAO getUserDao() {
		return userDao;
	}
	public void setUserDao(UserDAO userDao) {
		this.userDao = userDao;
	}	
}
UserDAO.java
/**
 *  <bean id="UserDAO" class="com.icitic.zero.dao.UserDAO">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
 * 
 * 
 * @author haihong
 *
 */
public class UserDAO extends HibernateDaoSupport{
	public void add(User user) {
		getHibernateTemplate().save(user);
	}
    public User getUserById(String id) {
		return (User) getHibernateTemplate().load( User.class, id);
	}
	public void update(User user) {
		getHibernateTemplate().update(user);
	}
	public void delete(User... user) {
		getHibernateTemplate().delete(user);
	}
	public void deleteById(String uid) {
		User user = this.getUserById(uid);
		getHibernateTemplate().delete(user);
	}
	public void save(User user) {
		getHibernateTemplate().saveOrUpdate(user);
	}
}

<p>

1.编码量统计:

User.java 11行

UserService.java 56行

UserDAO.java 21行

共88行

开始用thin(基于key-value的持久层框架)改造:

User.java

@BeanTableName(name="z_user")
public class User{
	@Primary
	private String uid;
	private String uname;
	private String password;
	private String gid;//机构ID
	private String gname;//机构名称
	private String rid;//角色ID
	private String rname;//角色名称
//setter and getter
}

<p>

替换类和主键的注解换成thin的注解,其他不变.

UserService.java

public class UserService extends BaseService  {
	public void addUser(User user) {
		try {
			this.add(user);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public User getUser(String id) {
		try {
			List users = this.getObject(User.class,SQLCriterion.get("uid", id));
			if(users.isEmpty()){
				return (User)users.get(0);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	public void deleteUser(User user) {
		try {
			this.deleteObject(user);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void deleteUser(String uid) {
		try {
			User user = (User)this.getObject(User.class, SQLCriterion.get("uid", uid));
			this.deleteUser(user);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void deleteUser(Collection<User> users) {
		Collection<String> uids = new ArrayList();
		for (User u : users) {
			uids.add(u.getUid());
		}
		try {
			getBeanTable(User.class).delete(SQLCriterion.get("uid", Operator.IN, uids));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void saveOrUpdate(User user) {
		try {
			ThinContext.ctx.beginTransaction();
			this.deleteUser(user);
			this.addUser(user);
			ThinContext.ctx.commitTransaction();
		} catch (SQLException e) {
			try {
				ThinContext.ctx.rollback();
			} catch (SQLException e1) {
			}
			throw new RuntimeException(e);
		}
	}
}

<p>

UserDAO.java不再需要,所有类似与此的DAO都不需要了,BaseService 已经为对象的持久提供好了接口,只需要调用即可。

2.编码量统计:

User.java 11行

UserService.java 60行

UserDAO.java 0行

编码量合计:71行

如此改进会减少88-71=17行代码和一个Dao类。

同时可以放一放hibernate/jpa这个朋友了,而且可以减少与spring的瓜葛。说真的,使用Service+DAO这种方式编程,有类似spring这样的管理工具,还是真是轻松了不少,但是spring所提供的依赖管理方式只是让我们更加舒适地适应了传统,但是原来要写程序现在几乎还要写。

我们再进一步用采用面向对象的思想(智能领域对象设计)来改造这个模块,让有User继承ThinObject:

@BeanTableName(name="z_user")
public class DomainUser extends ThinObject{
	@Primary
	private String uid;
	private String uname;
	private String password;
	private String gid;//机构ID
	private String gname;//机构名称
	private String rid;//角色ID
	private String rname;//角色名称	
	//所有的增删改查父类已经提供了
   //setter and getter
}
<p>

不再需要UserServiceT.java了,像这种增删改查的功能,ThinObject已经提供了。

3.编码量统计:

DomainUser.java 11行

UserServiceT.java 0行

UserDAO.java 0行

合计:11行

代码编写量从88行降到11行。减少87.5%的工作量。以30类为例,就少写2310行代码,少建60个类.

大家可以根据自己的工作效率算算,会节省多少天的工作量。从此单表的DAO操作就可以不用再写,也不用建立对应增删改查的类了。

当然这个例子有些极端,但是并不影响它在提高生产力的方面的不错表现。读到这里你可以会有一个疑问,我们应该如何处理对象之间的关系,如一对多,或者多对多。复合对象是由简单对象组成的,既然简单的存储已经很方便地解决了,复合对象也水到渠成地解决了。

智能领域对象设计还有个特性,是支持因果事件模式,模拟因果传递。我在下一篇实例中详解!

下一篇:智能领域对象设计(实例讲解)

[该贴被cuwkuhaihong于2010-08-09 13:20修改过]

    

3
cuwkuhaihong
2010-08-11 11:19
这么经典的东西,竟然沉底了

banq
2010-08-11 11:26
2010年08月08日 18:45 "cuwkuhaihong"的内容
我相信基于key-value的持久方式,正是持久层的“大道”。 ...

这个我同意,其实万事万物都有ID标识,一个ID标识一个对象,MT的分析模式中以及DDD中都开篇肯定了这点,是基本规律。

cuwkuhaihong
2010-08-11 15:50
2010年08月11日 11:26 "banq"的内容
2010年08月08日 18:45 "cuwkuhaihong"的言论

我相信基于key-value的持久方式,正是持久层的“大道”。 ...

这个我同意,其实万事万物都有ID标识,一个ID标识一个对象,MT的分析模式中以及DDD中都开 ...

banq很会赞扬人。

其实我想知道你对此不同的看法。

yananay
2010-08-11 22:09
看起来很不错哦!

有几个问题:

1、数据库链接怎么控制?

2、事务方面怎么控制?

3、一些场合肯定是需要sql语句的,写到 service 或者 domain object 里?

当然,最不爽的是,领域对象必须继承一个 ThinObject,这就不是领域对象了,

换句话说,离开 thin,这个领域对象就玩不转了,这并非领域对象的初衷。

猜你喜欢
3Go 1 2 3 下一页