发展,需求驱动 · 一间 所见即所得

从需求不是一句空话。同样是在发展过程中真正的。

需求驱动,与极限编程的一些想法和测试驱动开发基本重合。

鉴于该网站的发展是一个比较流行的方向,我会从网站开始,阐述自己的“需求驱动的发展“认识,并扩展到更广泛的领域。

首先,我们如果一个需求:

我们须要实现一个类似google的站点,用户通过web浏览器訪问,在首页输入框中查询。返回搜索的结果。

效果例如以下图所看到的:

STEP 0,通过eclipse创建一个web项目:sitefromscratch。文件结构如图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGVsdGF0YW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

在WebRoot下新增一个jsp文件:

<%@ page pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>

  <body>
    <h1>search it!</h1>

    <form action="" method="get">
    	<input type="text" value="site from scratch" name="keywords" />    
    	<input type="submit" value="search!" />
    </form>

    <table border="1" bordercolor="grey" >
    	<tr>
    		<td>result 1</td><td>something..................</td>
    	</tr>
    	<tr>
    		<td>result 1</td><td>something..................</td>
    	</tr>
    	<tr>
    		<td>result 1</td><td>something..................</td>
    	</tr>
    	<tr>
    		<td>result 1</td><td>something..................</td>
    	</tr>
    </table>

  </body>
</html>

通过浏览器訪问 /sitefromscratch/search1.jsp 能够得到和目标一致的效果。

STEP 2,通过界面所展示的内容,我们能够大致预计出所须要的数据以及其格式,让我们增加少量的代码实现相同的效果:

<%@ page pageEncoding="UTF-8"%>
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%!
class Result {
	String title;
	String content;
	public Result(String title, String content) {
		this.title = title;
		this.content = content;
	}
}
%>
<%
	String keywords = "site from scratch";

	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.................."));
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>

  <body>
    <h1>search it!</h1>

    <form action="" method="get">
    	<input type="text" value="<%=keywords %>" name="keywords" />    
    	<input type="submit" value="search!" />
    </form>

    <%
    if(!results.isEmpty()) {
    %>
    <table border="1" bordercolor="grey" >
    	<%
    	for(int i = 0; i < results.size(); i++) {
    		Result result = (Result)results.get(i);
    	%>
    	<tr>
    		<td><%=result.title %></td><td><%=result.content %></td>
    	</tr>
    	<%
    	}
    	%>
    </table>
    <%
    }
    %>

  </body>
</html>

这里,我们构造了一批伪数据(同一时候创建了一个类),并通过相应的运行逻辑,得到了全然一致的展示效果。

STEP 3。如今,该把提交、查询、结果展示的流程走通了:

<%@ page pageEncoding="UTF-8"%>
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%!
class Result {
	public String title;
	public String content;
	public Result(String title, String content) {
		this.title = title;
		this.content = content;
	}
} 

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;
}
%>
<%
	String keywords = request.getParameter("keywords");
	if(keywords == null) keywords = "";

	List results = search(keywords);
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>

  <body>
    <h1>search it!</h1>

    <form action="" method="get">
    	<input type="text" value="<%=keywords %>" name="keywords" />    
    	<input type="submit" value="search!" />
    </form>

    <%
    if(!results.isEmpty()) {
    %>
    <table border="1" bordercolor="grey" >
    	<%
    	for(int i = 0; i < results.size(); i++) {
    		Result result = (Result)results.get(i);
    	%>
    	<tr>
    		<td><%=result.title %></td><td><%=result.content %></td>
    	</tr>
    	<%
    	}
    	%>
    </table>
    <%
    }
    %>

  </body>
</html>

这里,我们构造了一个 List search(String keywords)方法,将业务逻辑和页面展示分离开来。分别置于在jsp文件里分离的区块。

STEP 4,接着。为了保持页面的简洁,我们把定义的类和方法提取出来,用包组织起来:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGVsdGF0YW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

package cn.com.sitefromscrath.entity;

public class Result {

	public String title;
	public String content;

	public Result(String title, String content) {
		this.title = title;
		this.content = content;
	}
}
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;
	}

}

不出意料。SearchService.java 和 Result.java的代码就是直接从search.jsp中copy过去的。

值得一提的是,我们新增了一个BeanFactory类,作为工厂模式的一个实现,它简单的通过指定的ID所相应的类返回产生的实例。

例如以下所看到的:

package cn.com.sitefromscrath;

import cn.com.sitefromscrath.service.SearchService;

public class BeanFactory {

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

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

}

尽管它如今看来显得画蛇添足了一些,可是在我之后的展开论述中,它将占有非常重要的位置。

如今。jsp文件的内容看起来简洁多了:

<%@ page pageEncoding="UTF-8"%>
<%@page import="java.util.List"%>
<%@page import="cn.com.sitefromscrath.service.SearchService"%>
<%@page import="cn.com.sitefromscrath.BeanFactory"%>
<%@page import="cn.com.sitefromscrath.entity.Result"%>
<%
	String keywords = request.getParameter("keywords");
	if(keywords == null) keywords = "";

	SearchService searchService = (SearchService)BeanFactory.getBean("searchService");
	List results = searchService.search(keywords);
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>

  <body>
    <h1>search it!</h1>

    <form action="" method="get">
    	<input type="text" value="<%=keywords %>" name="keywords" />    
    	<input type="submit" value="search!" />
    </form>

    <%
    if(!results.isEmpty()) {
    %>
    <table border="1" bordercolor="grey" >
    	<%
    	for(int i = 0; i < results.size(); i++) {
    		Result result = (Result)results.get(i);
    	%>
    	<tr>
    		<td><%=result.title %></td><td><%=result.content %></td>
    	</tr>
    	<%
    	}
    	%>
    </table>
    <%
    }
    %>

  </body>
</html>

STEP 5,听说MVC是个非常高科技的东西,我们也来实现一下:

新增一个servlet,作为 控制层 Controller

package cn.com.sitefromscrath.web;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

public class SearchServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String keywords = request.getParameter("keywords");
		if(keywords == null) keywords = "";

		SearchService searchService = (SearchService)BeanFactory.getBean("searchService");
		List results = searchService.search(keywords);	

		request.setAttribute("keywords", keywords);
		request.setAttribute("results", results);

		request.getRequestDispatcher("/search5.jsp").forward(request, response);
	}

}

新增一个jsp文件。search5.jsp,作为视图层 Viewer。

<%@ page pageEncoding="UTF-8"%>
<%@page import="java.util.List"%>
<%@page import="cn.com.sitefromscrath.entity.Result"%>
<%
	String keywords = (String)request.getAttribute("keywords");
	List results = (List)request.getAttribute("results");
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>

  <body>
    <h1>search it!</h1>

    <form action="" method="get">
    	<input type="text" value="<%=keywords %>" name="keywords" />    
    	<input type="submit" value="search!" />
    </form>

    <%
    if(!results.isEmpty()) {
    %>
    <table border="1" bordercolor="grey" >
    	<%
    	for(int i = 0; i < results.size(); i++) {
    		Result result = (Result)results.get(i);
    	%>
    	<tr>
    		<td><%=result.title %></td><td><%=result.content %></td>
    	</tr>
    	<%
    	}
    	%>
    </table>
    <%
    }
    %>

  </body>
</html>

web.xml中配置:

<?

xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<servlet>
		<servlet-name>SearchServlet</servlet-name>
		<servlet-class>cn.com.sitefromscrath.web.SearchServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>SearchServlet</servlet-name>
		<url-pattern>/search</url-pattern>
	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

</web-app>

如今,让我们再来run一次,http://localhost:8080/sitefromscratch/search

binggo。效果跟目标无差!

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

嗯,到这里。我们究竟达到了什么目的?数据还是假的啊,有这个必要吗?有这个必要吗?

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGVsdGF0YW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

看看,葛大爷已经被拍了一脸血了。我希望您还没到这地步。

到了这一步。我们事实上完毕了跟前端页面制作人员的握手协议:

您写js的也好,html5的也好,随便整,我返回的数据格式和内容您也看见了,就这样。格式不会变,内容也不会出错。

数据怎么嵌,那是您的事儿,俺就不侍奉了。

关于”内容不会出错“这句,补充一点儿,这是指的前端页面人员(或许是你自己兼任)无需启动一大堆复杂的应用程序,比方mysql、memcache,就能调试自己的html或者js代码。同一时候,也避免了其它异常(数据库down了。数据表毁坏了,网络断了,memcache连接不上了等等等等)对前端开发的干扰。

特别是debug阶段,假设你不能确保哪些是正确的。你就无法找到错误的

非常多程序猿在debug排查某个问题的时候。最常犯的错误就是迷失在一大堆的模块中间,找不到出路,造成这样的情况的根本原因就在于:在当事人看来,每一个模块都是可疑的,不确定的。要么猜要么一个个查,精力和时间就此白白浪费。

而对于后端开发者来说,如今面临的就仅仅剩一个任务:让以下的类方法返回真实的业务结果吧。

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;
	}

}

我们将在下一章讨论这个问题。


WEB开发那些事儿


第一部分:从需求出发



所见即所得


这里从一个静态html页面说起。逐步抽离出展示层面和数据层面的东西。



造飞机的工厂


这里主要说的是工厂方法。

当然,工厂不是目的,而是结果,需求才是源起。



春天在哪里


这里開始扯到了spring和《儿歌三百首》



春天在这里


对spring的吐槽



麦克斯韦妖


让我们充当一次麦克斯韦妖。探測和控制单个模块/方法的工作



扒皮MVC


MVC模式的得失。开发的时候。别由于迷失才过程里尔忘记了我们的目的。


第二部分:拿起笔来做刀枪



序言


拿起笔来做刀枪,开发路上当闯将



再造一个dom4j


标题说明了一切



再造一个spring


标题说明了一切



再造一个jsp


标题说明了一切,这里的 jsp 不是 java server pages,而是java sign pages :)



再造一个struts


标题说明了一切



再造一个lucene


标题说明了一切,lucene的原理仅仅须要一句话说清楚,这个就是我喜欢他的原因



再造一个hibernate


事实上我在意的是HQL怎样映射到多种sql查询语言上



Final Fantasy


终于的成品

版权声明:本文博客原创文章,博客,未经同意,不得转载。

发展,需求驱动 · 一间 所见即所得

时间: 2024-11-09 22:09:18

发展,需求驱动 &#183; 一间 所见即所得的相关文章

linux_c开发(5-1)进程间通讯_进程间通讯概念

目的:为什么进程间需要通信? 1.数据传输 一个进程需要将他的数据发送给另外一个进程. 2.资源共享 多进程之间共享同样的资源. 3.通知事件 一个进程需要向另一个或一组进程发送消息,通知他们发生了某种事件. 4.进程控制 有些进程希望完全控制另一个进程的执行(eg:debug进程),此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道他的状态改变. 发展: linux进程间通讯(IPC)由以下及部分发展而来: 1.UNIX间进程通讯 2.基于system v进程间通讯 3.POSIX进

进程之间通信之有名管道、无名管道(pipe),笔记

             进程之间的通信作用1.数据传输   :一个进程需要将他的数据传到其他进程2.资源共享3.进程通知事件4.进程控制 :有些进程完全控制另一个进程的执行,如调试状态啊我们需要完全控制他的每一步操作: 通信发展历史Linux进程间的通信IPC由以下几个部分发展而来:1.UNIX进程之间的通信2.基于system v进程间的通信3.POSIX进程之间的通信(portable operating system interface) 现在Linux使用的进程间的通信方式包括:1.管

HTML5开发培训学院

兄弟连IT教育-www.itxdl.cn    免费教程光盘领取- http://www.hdb.com/party/v7m3u.html HTML5中,大家一直在探讨的问题就是我们到底要用它去开发web好一点还是原生应用好一点,随着h5的发展,这两者间的差异渐渐的融合起来.那么HTML5未来的发展趋势是怎样的呢?选择HTML5开发学院又有那些好处呢? 首先要说的就是移动应用了,如今的手机对生活的重要性甚至高过了电脑,这种优先性的趋势也在慢慢的扩大.如今无论进行什么开发,都会有它的身影,而且一部

迷失的心,不愿回头

曾以为,只有心的自由,才能赋予笔下文字的灵性,就放任了心的漂流,独步于寂寞的荒原,等候一朵花开. 曾以为,只有情的温暖,才能融化封锁心灵门窗的冰霜,就纵容了心火的燃烧,燃情于忧伤的国度,期待着一扇为我打开的窗. 曾以为,只有灵魂的交融,才能点燃平淡生活的激情,就放飞了相思的触手,飞翔于梦的夜空,找寻心底的那个坐标. 只是,走得久了,累了,才发现已经回不去了.哭得久了,痛了,才明白已经停不下来了.飞得久了,冷了,才知道已经迷失方向了. 走到现在才发觉,已经回不去了.感觉像个孩子在夜晚迷了路,周围只

《具身认知》听书笔记

具身认知是在反对传统认知科学之偏误的基础上出现的.在传统的认知科学中,人的心智遭以简化为对自然.世界的准确镜像,认知活动在于摒弃.剔除身体的生理参与及经验的嵌入.具身认知真正把人视作“整全的人”,主张认知是大脑.身体与环境交互作用的产物,强调人的身心整全意义上的发展.它强调“具身性”与“情境化”,将对认知的认识从个体加工机制的探讨转向社会实践活动的分析:并认为认知结构具有时间属性,某一时刻的认知状态只是连续动态变化中的一个即时状态,因此主张把实验法和自然法融通起来,在真实.自然的情境中对认知过程

做了一个漂亮的项目,啧啧

选择android的缘由 我叫刘**,来自黑龙江省哈尔滨市,在学习安卓之前做过一段时间的web前端,但总感觉不是自己未来的方向,这两年移动互联网行业的大力发展,我仿佛间看到了这才是我未来要找寻的路,在半年前,我开始自学安卓.主要学安卓还是因为开源和市场的巨大,通过在网站了解和朋友的了解,根据我自身的情况,0基础的课程我肯定是不会选择的,因为不适合我,所以我选择好程序员班,很适合我这种有一定基础的人.于是乎我来到了这里,在这期间我反复对比了下各机构的课程大纲,只有这边的课程深度是最让我满意的.也是

无名管道通信

一.核心理论 1.进程通信方式(IPC) (1).通讯的目的: 数据传输,资源共享,通知事件,进程控制 (2).通讯的发展:UNIX进程间的通信.基于System V进程间的通信.POSIX进程间通信 (3).通信方式 : 无名管道(pipe),有名管道(FIFO),信号(signal), 消息队列, 共享内存, 信号量, 套接字(socket) 2.管道通信方式(特点) (1).管道通讯是单向的,有固定的读端和写端 (2).数据被进程从管道读出后,在管道中该数据就不存在了 (3).当进程去读取

业界文章【马云】

从北京茶馆到杭州“太极禅苑”的十年喝茶史. 作为浙江人,我频繁地回到杭州,与杭州的诸多互联网创业者交往颇多,但是,我第一次和马云见面,还是在北京. 大约是1999年,有人联系我,说马云约我喝茶.喝茶的地点就是北大南门外的一个茶馆.听说,那一次马云约了不少人,但是很多人都没有赴约.而我对这位老乡充满好奇,所以准时到了.今天,见面的细节和谈论的内容,早已被健忘的我忘得一干二净.但是,我还是记着那一次两个小时的喝茶时间,谈得非常热烈.马云对于互联网的见地,的确不比京城互联网界最牛的大佬来得差. 因为相

用开发平台快速开发中小企业信息平台

第一章 行业特点及需求概述 1.1.移动公司介绍 中国移动通信集团公司,是中国规模最大的移动通信运营商,主要经营移动话音.数据.IP电话和多媒体业务,并具有计算机互联网国际联网单位经营权和国际出入口局业务经营权. 1.2.中小企业行业特点 企业业务不规范,信息化需求柔性大.中小企业相对大型企业而言,其业务的随意性比较大,职能分工比较粗放,决定了信息化应用必须能够满足业务变动的节奏,有效匹配新的业务模式.信息系统要做到有高度,且必须要便捷.灵活.这是一对矛盾,对于信息化基础并不好的企业,其挑战性更