为什么说二进制依赖一个组件时不准调用它的内部API?

为什么说二进制依赖一个组件时不准调用它的内部API? 比如说,对bean-biz.jar,应用层只准调用BeanService.getBean(),而不准调用BeanDAO.getBean()?

你会说这是为了“封装性”,以“避免不必要的耦合”。但直接耦合BeanDAO.getBean()和BeanDAO.deleteBean()有什么“具体”的坏处呢? 

我的结论是:

    1.
如果同时依赖BeanService.getBean()和BeanDAO.getBean(),就意味着对同一个操作形成了“调用上的冗余”; 当一个发生变化时,另一个也要跟着变,而且变得很尴尬。

    2.
如果绕过BeanService直接调用BeanDAO.deleteBean(),就意味着依赖了组件的内部实现;而内部实现往往是不稳定的,当内部实现改变时,应用层也要发生改变,一种本可以避免的改变。

代码阐述:

1. 调用的冗余

   

//改变发生前
public class BeanService {

	public Bean getBean(Long id) {
		return beanDAO.getBean(id);
	}
}	

public class WiseAction {	
	
	public void showBeanDetail(){
		
		Bean bean = beanService.getBean(id);
	 
	}
}	

public class RogueAction {

	public void showBeanDetail() {

		Bean bean = beanDAO.getBean(id);

	}
}	
//改变:后来出了规定,对Bean的获取必须走缓存
public class BeanService {
	
	public Bean getBean(Long id) {
		Bean bean = Cache.get(id);
		if (bean == null) {
			bean = beanDAO.getBean(id);
		}
		return bean;
	}
}	

////只依赖了BeanService的应用层代码无须改变
public class WiseAction {	
	
	public void showBeanDetail(){
		
		Bean bean = beanService.getBean(id);
	 
	}
}	

////依赖了BeanDAO的应用层代码需要改变以加入缓存逻辑;同时,这也导致了缓存逻辑的重复
public class RogueAction {

	public void showBeanDetail() {
		Bean bean = Cache.get(id);
		if (bean == null) {
			bean = beanDAO.getBean(id);
		}
		return bean;
	}
}

2. 依赖了不稳定的内部实现

//改变发生前
public class BeanService {
	
	public void deleteBean(Long id) {
		beanDAO.deleteBean(id);
	}
}

public class WiseAction {

	public void removeBean(){
		
		 beanService.deleteBean(id);
		 
	}
}

public class RogueAction {
	
	public void removeBean() {

		beanDAO.deleteBean(id);

	}
}

//改变:后来规定对Bean不能物理删除,只允许逻辑删除(把某个标志位设置为false)
public class BeanService {
	
	public void deleteBean(Long id) {
		Bean bean = getBean(id);
		bean.setValid(false);
		beanDAO.updateBean(bean);
	}
}
 

//同时,为了防卫,BeanDAO.deleteBean()方法应该删除

 
////只依赖了BeanService的应用层代码不用变
public class WiseAction {

	public void removeBean(){
		
		 beanService.deleteBean(id);
		 
	}
}	


////依赖了BeanDAO的应用层代码必须改变,因为BeanDAO.deleteBean()已经不存在了
public class RogueAction {

	public void removeBean(){
		
		 beanService.deleteBean(id); //这时应用层代码也只好改成依赖BeanService,早知今日,何必当初?
		 
	}
}	

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.