开发,从需求出发 · 之二 造飞机的工厂
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中的代码:
SearchService searchService = (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";
SearchService searchService = (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 SearchServiceMock implements 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....
开发,从需求出发 · 之二 造飞机的工厂的更多相关文章
- 开发,从需求出发 · 之四 春天在这里
首先,我要大字标语表达立场: 你所使用的framework & non-core features,就跟女人穿在身上的衣服一样,越少越好! watermark/2/text/aHR0cDovL ...
- 开发,从需求出发 · 之三 春天在哪里
<西游降魔>里面的<儿歌三百首>里面有首儿歌叫做<春天在哪里> 歌词是这种: 春天在哪里 春天在哪里 春天就在小朋友的眼睛里 通过俺的渣英语翻译之后是这种: whe ...
- 吴裕雄--天生自然PythonDjangoWeb企业开发:需求
开发或者做一个项目,是要有一个需求过来的,而不是无缘无故的,启动一个项目,或者推动整个项目进行下一步迭代.这个需求可能是根据用户反馈增加的,可能是老板提出来的,也有可能是产品经理提出来的,但是无论是什 ...
- iOS开发-UI 从入门到精通(二)
iOS开发-UI 从入门到精通(二)是对 iOS开发-UI 从入门到精通(一)知识点的巩固,主要以习题练习为主,增强实战经验,为以后做开发打下坚实的基础! ※开发环境和注意事项: 1.前期iOS-UI ...
- iOS开发UI篇—Quartz2D简单使用(二)
iOS开发UI篇—Quartz2D简单使用(二) 一.画文字 代码: // // YYtextview.m // 04-写文字 // // Created by 孔医己 on 14-6-10. // ...
- 实验一《开发环境的熟悉》&实验二《固件设计》
20145312&20145338 实验一<开发环境的熟悉>&实验二<固件设计> 合作博客链接:http://www.cnblogs.com/yx2014531 ...
- 第1章 开发环境安装和配置(二)安装JDK、SDK、NDK
原文 第1章 开发环境安装和配置(二)安装JDK.SDK.NDK 无论是用C#和VS2015开发Androd App还是用Java和Eclipse开发Androd App,都需要先安装JDK和Andr ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(二)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(二) 4.3 表达式用户搜索,只会输入一个或几个词,也可能是一句话.输入的语句是如何变成搜索条件的上一篇已经略有提及. 4.3.1 观察 ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(二)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(二) 2.索引中用到的核心类 在Lucene.Net索引开发中,用到的类不多,这些类是索引过程的核心类.其中Analyzer是索引建立的 ...
随机推荐
- Day 14A 网络编程入门
---恢复内容开始--- 计算机网络基础 计算机网络是独立自主的计算机互联而成的系统的总称,组建计算机网络最主要的目的是实现多台计算机之间的通信和资源共享.今天计算机网络中的设备和计算机网络的用户已经 ...
- Lua表(table)的用法_个人总结
Lua表(table)的用法_个人总结 1.表的创建及表的介绍 --table 是lua的一种数据结构用来帮助我们创建不同的数据类型.如:数组和字典--lua table 使用关联型数组,你可以用任意 ...
- Python --- 二叉树的层序建立与三种遍历
二叉树(Binary Tree)时数据结构中一个非常重要的结构,其具有....(此处省略好多字)....等的优良特点. 之前在刷LeetCode的时候把有关树的题目全部跳过了,(ORZ:我这种连数据结 ...
- tinyXml输出utf-8文档
TiXmlDocument虽然能读取utf-8的xml文件,但读入后在内存中是以多字节存储.如果新建一个TiXmlDocument,即使定义头为utf-8编码,直接调用SaveFile方法保存的文档仍 ...
- [BZOJ] 1037 [ZJOI2008]生日聚会
Time Limit: 10 Sec Memory Limit: 162 MB Submit: 3007 Solved: 1795 [Submit][Status][Discuss] Descript ...
- python 博客开发之散乱笔记
博客开发之旅: # 回滚,数据存储失败时,还原修改操作 from django.db import transaction with transaction.atomic(): do... ... # ...
- HDU 4747 Mex【线段树上二分+扫描线】
[题意概述] 一个区间的Mex为这个区间没有出现过的最小自然数,现在给你一个序列,要求求出所有区间的Mex的和. [题解] 扫描线+线段树. 我们在线段树上维护从当前左端点开始的前缀Mex,显然从左到 ...
- UVA 230 Borrowers (STL 行读入的处理 重载小于号)
题意: 输入若干书籍和作者名字,然后先按作者名字升序排列,再按标题升序排列,然后会有3种指令,BORROW,RETURN, SHELVE. BORROW 和 RETURN 都会带有一个书名在后面,如: ...
- bootloader的移植
jz2440开发板 在介绍bootloader里边的内容的时候,需要知道的是: bootloader的引入的目的就是启动linux内核,一个简单的bootloader编写需要以下的步骤: ①初始化硬件 ...
- c语言基础--数据类型
一.整型数据: 1.表格: 类型名称 可简写 占用字节 数值范围 signed int int -2147483648(-2^31)~2147483647(2^31-1) unsigned int u ...