您的位置:首页 > 其它

开发,从需求出发 · 之二 造飞机的工厂

2014-07-23 22:38 232 查看
CD镇楼~~!



现在,让我们切换到后端开发人员的角度看问题。我们需要做的是实现一下这个类,让它返回真实的业务数据。

package cn.com.sitefromscrath.service;

import java.util.ArrayList;
import java.util.List;

import cn.com.sitefromscrath.entity.Result;

public class SearchService{

public List search(String keywords) {

List results = new ArrayList();
results.add(new Result("result 1", "something.................."));
results.add(new Result("result 2", "something.................."));
results.add(new Result("result 3", "something.................."));
results.add(new Result("result 4", "something.................."));

return results;
}

}


由于需要重写这个方法,原来费劲手工录入的模拟数据就得删除掉,显得有点儿可惜,因此,我决定重新定义一个类,

package cn.com.sitefromscrath.service;

import java.util.ArrayList;
import java.util.List;

import cn.com.sitefromscrath.entity.Result;

public class SearchServiceInRealBiz extends SearchService{

public List search(String keywords) {

List results = new ArrayList();

//do sth. 这里是真实业务逻辑,为了不一下子把问题搞复杂,偏离这章的中心思想,我们先同样采用Mock中的返回数据。
results.add(new Result("result 1", "something.................."));
results.add(new Result("result 2", "something.................."));
。。。。。。。。。。。。。。。。。。。。。
 return results;}}
<pre>


注意,这里需要:

SearchServiceInRealBiz extends SearchService


以此来迎合java的恶趣味,否则,我们的SearchServlet中的代码:

SearchServicesearchService = (SearchService)BeanFactory.getBean("searchService");


会抛出cast异常。

插一句,之所以”恶趣味“,主要是个人更偏好”Duck Typing“,比如python。

现在我可以说明我的标题了,因为我们在第一章 建造了一个工厂,因此,我们只需要调整很少的代码,就可以让整个系统从模拟状态切换到真实业务状态。

package cn.com.sitefromscrath;

import cn.com.sitefromscrath.service.SearchService;
import cn.com.sitefromscrath.service.SearchServiceInRealBiz;

public class BeanFactory {

public static Object getBean(String id) {
if("searchService".equals(id)) {
//			return new SearchService();
return new SearchServiceInRealBiz();
}

throw new RuntimeException("cannot find the bean with id :" + id);
}

}


我们注释掉了

return new SearchService();


而返回新定义的类:

return new SearchServiceInRealBiz();


现在,我确信前端页面会展示真实的数据——这种确信不需要建立在和前端开发人员协调,甚至不需要运行tomcat操作一遍web。

当然,口说无凭,本着”没有做过测试的代码一定会出问题“的原则,

public class BeanFactory {

public static Object getBean(String id) {
if("searchService".equals(id)) {
//			return new SearchService();
return new SearchServiceInRealBiz();
}

throw new RuntimeException("cannot find the bean with id :" + id);
}

public static void main(String ... arg) {
String keywords = "test";
SearchServicesearchService = (SearchService)BeanFactory.getBean("searchService");
List results = searchService.search(keywords);
for(int i = 0; i < results.size(); i++) {
Result result = (Result) results.get(i);
System.out.print("[" + result.title + "]");
System.out.println(result.content);
}
}

}



运行,得到输出结果:

[result 1]something..................
[result 2]something..................
[result 3]something..................
[result 4]something..................
bingo!测试通过。——为了不把问题搞复杂,这里就不采用Junit鸟。:)

出于java程序员的”模式“,我决定设计一个接口,这样看起来更java style 一点儿。

package cn.com.sitefromscrath.service;

import java.util.List;

public interface SearchService{

public List search(String keywords);

}
注意,这里我们为了不修改jsp,将接口命名为
SearchService


然后,是一个模拟数据实现类和一个业务数据实现类

真实:

package cn.com.sitefromscrath.service;

import java.util.ArrayList;
import java.util.List;

import cn.com.sitefromscrath.entity.Result;

public class SearchServiceInRealBiz implements SearchService{

public List search(String keywords) {

List results = new ArrayList();

//do sth.

return results;
}
}


模拟:

package cn.com.sitefromscrath.service;

import java.util.ArrayList;
import java.util.List;

import cn.com.sitefromscrath.entity.Result;

public class SearchServiceMockimplements SearchService{

public List search(String keywords) {

List results = new ArrayList();
results.add(new Result("result 1", "something.................."));
results.add(new Result("result 2", "something.................."));
results.add(new Result("result 3", "something.................."));
results.add(new Result("result 4", "something.................."));

return results;
}

}


好了,现在看看工厂类,没有什么比工厂更能满足程序员的控制欲了:)

package cn.com.sitefromscrath;

import cn.com.sitefromscrath.service.SearchServiceMock;
import cn.com.sitefromscrath.service.SearchServiceInRealBiz;

public class BeanFactory {

public static boolean MOCK = false;

public static Object getBean(String id) {
if("searchService".equals(id)) {
if(MOCK) {
return new SearchServiceMock();
} else {
return new SearchServiceInRealBiz();
}
}

throw new RuntimeException("cannot find the bean with id :" + id);
}

}


这里我们放了一个开关 :

public static boolean MOCK = false;


这样,通过控制这个开关,我们就能实现一个便捷的切换。

————————————————————————————————————————————————————————————————————————————

本章该收尾了,俺也恶趣味一把,重复第一章的结束部分:

嗯,到这里,我们到底达到了什么目的?有这个必要吗?有这个必要吗?



除了通过一个开关,保证了对前端恒定(模拟)的数据输出,因此保证了自己的开发工作不干扰前端开发人员的开发和测试之外,貌似确实没什么必要。

BUT...请注意,我们在实现和测试代码的过程中,没有启动tomcat,但是同样达到了”代码/模块可靠性“的保证——我相信,很多web开发人员在开发过程中,最常干的一件事情就是重启tomcat,手工执行表单操作,肉眼查看页面输出结果——太慢了,太慢了啊,亲!

(补充一句,上文提到了junit,我们所做的模拟服务:

SearchServiceMock


也可以使用工具easyMock,有兴趣的同学可以尝试试用一下。)

当然,如果你还是觉得看不出必要性,那是因为我们的业务逻辑还不够复杂。



下一章,我们会试着模拟一个业务流程,把简单的事情搞的更复杂一点儿。

to be continued....


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐