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

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. 这里是真实业务逻辑,为了不一下子把问题搞复杂,偏离这章的中心思想,我们先搁置不写。

 		return results;
	}
}

注意,这里需要:

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....

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

时间: 2024-10-10 08:34:52

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

开发,从需求出发 &#183; 之一 从视觉开始

从需求出发并不是一句空话,在开发过程中也是如此. 从需求出发,实质上是暗合了极限编程和测试驱动开发的一些思想. 鉴于网站开发是一个比较流行的方向,我打算从一个网站开始,阐述一下自己对"需求驱动开发"的理解,并将其引申到一个更广泛的领域. 首先,我们假设一个需求: 我们需要实现一个类似google的网站,用户通过web浏览器访问,在首页输入框中查询,返回搜索的结果. 效果如下图所示: STEP 0,通过eclipse创建一个web项目:sitefromscratch,文件结构如图所示:

开发,从需求出发 &amp;#183; 之四 春天在这里

首先,我要大字标语表达立场: 你所使用的framework & non-core features,就跟女人穿在身上的衣服一样,越少越好! 扯淡完成,说正经的. 让我们继续盯着花姐--啊,不--是 BeanFactory看. public static SearchService getSearchService() { if(MOCK) { return new SearchServiceMock(); } else { LuceneDAO luceneDAO = getLuceneDAO()

开发,从需求出发 &#183; 之三 春天在哪里

<西游降魔>里面的<儿歌三百首>里面有首儿歌叫做<春天在哪里> 歌词是这样的: 春天在哪里 春天在哪里 春天就在小朋友的眼睛里 通过俺的渣英语翻译之后是这样的: where spring is where spring is the fucking spring is in javatar's eyes yo yo check it out 我相信,java程序员已经意识到我说的春天是什么了:) 不过spring跟我们现在说的东东有关系么?暂时还没有-_-b 言归正传,

开发,从需求出发 &#183; 之四 春天在这里

首先,我要大字标语表达立场: 你所使用的framework & non-core features,就跟女人穿在身上的衣服一样,越少越好! 扯淡完毕,说正经的. 让我们继续盯着花姐--啊,不--是 BeanFactory看. public static SearchService getSearchService() { if(MOCK) { return new SearchServiceMock(); } else { LuceneDAO luceneDAO = getLuceneDAO()

办公管理支撑流程能力PaaS平台运维开发软件需求设计方案

1.概述 办公管理支撑流程能力PaaS平台(以下文中简称"能力平台")运维开发是指基于Cordys BOP 4 PaaS平台,通过二次开发,为运维开发人员提供快速支撑办公管理流程开发.实施.再造的能力,也为管理流程全生命周期管理提供数据支撑能力.管理目标及软件需求如下: (1)开发/运维人员 开发/运维人员是指系统平台管理人员.运维人员,例如:省公司与地市公司信息化系统管理员.开发/运维人员为专业信息化管理员,都是受过专业计算机教育,懂计算机软件维护.开发,但是,不是专业程序员,也就是

Scrum&amp;Kanban在移动开发团队的实践 (二)

Scrum&Kanban在移动开发团队的实践系列: Scrum&Kanban在移动开发团队的实践 (一) Scrum&Kanban在移动开发团队的实践 (二) 在第一篇分享文章中介绍了下Scrum的开发模式,介绍了Scrum中团员的角色.开发阶段.每个阶段中需要做的事情.在这篇分享我会介绍Kanban模式,相对于Scrum,Kanban比较轻量级. 首先分享些干货: Kanban和Scrum对比的Mini书:Kanban and Scrum - making the most of

【iOS开发每日小笔记(二)】gitHub上的开源“瀑布流”使用心得

这篇文章是我的[iOS开发每日小笔记]系列中的一片,记录的是今天在开发工作中遇到的,可以用很短的文章或很小的demo演示解释出来的小心得小技巧.该分类的文章,内容涉及的知识点可能是很简单的.或是用很短代码片段就能实现的,但在我看来它们可能会给用户体验.代码效率得到一些提升,或是之前自己没有接触过的技术,很开心的学到了,放在这里得瑟一下(^_^).其实,90%的作用是帮助自己回顾.记忆.复习.如果看官觉得太easy,太碎片,则可以有两个选择:1,移步[iOS探究]分类,对那里的文章进行斧正:2,在

java、python、golang等开发语言如何快速生成二维码?

免费二维码生成途径非常多!比如比较有名的草料二维码,如果只是简单的使用,用它就足够了.但是如果想大规模的生成,那就不太合适了.再者很多工具都没办法在二维码中加入logo(像微信二维码一样). 接下来,我就说说如何快速的.高质量的生成一个可高度定制的二维码. 二维码的编码算法是公开的,这就意味着大部分的开发语言都可以动图生成.但是在二维码应用如此广泛的今天,还自己去造轮子,如果不是傻,那就是正真的技术极客了. Java有开源的二维码生成库:com.google.zxing,这是谷歌大佬为andro

[Axis2与Eclipse整合开发Web Service系列之二] Top-Down方式,通过WSDL逆向生成服务端(续)

前言 本篇是承接上一篇: [Axis2与Eclipse整合开发Web Service系列之二] Top-Down方式,通过WSDL逆向生成服务端 在上一篇粗略地介绍了如何使用Top-Down的方式创建一个web service .  但是对于如何部署及调用,以及一些细节的部分基本上没有介绍. 应某些博友的要求, 也适逢自己有空, 接下来就详细介绍一下整个部分如何进行. 环境准备 JDK 肯定要安装了, 这个就不多讲了. 1. eclipse  3.5.2 对eclipse 版本的要求其实不是很严