Monthly Archives: April 2012

为什么说SOA环境下Service Registry很重要?

为什么说SOA环境下Service Registry很重要?

有了Service Registry,consumer不必通过IP找到provider,而只需通过服务名。但这又有什么好处呢?

个人观点:

    开发人员和运维人员不必互相询问和通知了。开发人员不必向运维人员打听某服务器的IP,运维人员如果把某服务转移到了另一台机上,也不必通知开发人员。  也就是说,基于名字的耦合(connascence)会弱于基于网络地址的耦合

另一个好处是方便依赖关系的监控。Service Registry集中地保存了consumer/provider之间的逻辑依赖关系,以及consumer机器和provider机器之间的物理依赖关系。 如果有一个界面,就可以一目了然地监控这些依赖。

初识Http Push技术

以下基本抄自维基百科(词条:Push Technology)

Push技术

从交互模型上来说是一种publisher/subscriber机制,两者通过事件通知来发生关系

Http Push

HTTP server push (also known as HTTP streaming) is a mechanism for sending data from a web server to a web browser. HTTP server push can be achieved through several mechanisms.

Http Push的几种实现

Generally the web server does not terminate a connection after response data has been served to a client. The web server leaves the connection open such that if an event is received, it can immediately be sent to one or multiple clients.

服务端改http头

如:Non-Parsed Headers scripts on Apache

是否需要浏览器支持? 待研究

使用特殊的MIME类型

即“multipart/x-mixed-replace”

这种机制需要浏览器支持

Pushlet

The server never terminates the response, effectively fooling the browser into continuing in "loading" mode after the initial page load would normally be complete

这种机制不需要客户端支持,但在http超时后无法自动恢复

Long polling

With long polling, the client requests information from the server in a similar way to a normal poll. However, if the server does not have any information available for the client, instead of sending an empty response, the server holds the request and waits for some information to be available. commet就是这么玩的。

可以看出,这不是真正的server push.

Flash XMLSocket relays

待研究

BOSH

待研究

模块化及组件化的一些概念

模块化是什么:

      In software design, modularity refers to a logical partitioning of the "software design" that allows complex software to be manageable for the purpose of implementation and maintenance. The logic of partitioning may be based on related functions, implementation considerations, data links, or other criteria.

  

模块化编程的好处:

   Modular programming improve maintainability by enforcing logical boundaries between components

模块化还可以促进开发团队的拆分

 

     Theoretically, a modularized software project will be more easily assembled by large teams, since no team members are creating the whole system, or even need to know about the system as a whole.  They can focus just on the assigned smaller task

 

    Several programmers can work on individual programs at the same time, thus, making development of program faster. It easer to debug, update and modify. It leads to a structured approach as a complex problem can be broken into simpler tasks.

基于组件的开发是模块化思想的一种具体实践

组件应该是“面向服务”的:

       The Software engineers regard components as part of the starting platform for service-orientation.

组件化跟面向对象是两种不同的paradigm:

      OOP and the related disciplines of object-oriented analysis and object-oriented design focus on modeling real-world[citation needed] interactions and attempting to create "nouns" and "verbs" that can be used in more human-readable ways, ideally by end users as well as by programmers coding for those end users.

 

       Component-based software engineering, by contrast, makes no such assumptions, and instead states that developers should construct software by gluing together prefabricated components – much like in the fields of electronics or mechanics. Some peers[who?] will even talk of modularizing systems as software components as a new programming paradigm.   

收集一些关于Software Modularity & Component-Based Development的文献 

如何理解“每个组件只应提供单一的API调用入口”

每个组件只应提供单一的API调用入口,这句话的意思是什么?

我的看法:

1.
正解:组件中的每个操作都应该只有一个入口;应用层不能既调用BeanService.getBean(),又调用BeanDAO.getBean(). 原因可见这里

2.
误解:每个模块只能使用一个类作为API. 像bean-biz.jar这种组件,可以同时提供BeanService作为CRUD、业务逻辑入口,以及BeanSearchService作为搜索查询入口;否则,如果把所有操作都丢给单一的BeanService,那 BeanService 这个类本身的内聚性就很差。

其实,关于“组件中的每个操作都应该只有一个入口”也可以有例外情况。 比如一个缓存客户端 cache-client.jar中,可以同时提供CommonCacheTemplate作为通用的、灵活性高的API,以及SimpleCacheOperations作为最常用的、极其易用(比如可以少传几个参数)的的API。不过,后者必须建立在前者基础上,只作为前者的易用版本来使用,不准附加任何与前者冲突的业务逻辑

为什么说二进制依赖一个组件时不准调用它的内部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,早知今日,何必当初?
		 
	}
}