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

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

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

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

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

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

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

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

在WebRoot下新增一个jsp文件:

  1. <%@ page pageEncoding="UTF-8"%>
  2.  
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  4. <html>
  5. <head>
  6. </head>
  7.  
  8. <body>
  9. <h1>search it!</h1>
  10.  
  11. <form action="" method="get">
  12. <input type="text" value="site from scratch" name="keywords" />    
  13. <input type="submit" value="search!" />
  14. </form>
  15.  
  16. <table border="1" bordercolor="grey" >
  17. <tr>
  18. <td>result 1</td><td>something..................</td>
  19. </tr>
  20. <tr>
  21. <td>result 1</td><td>something..................</td>
  22. </tr>
  23. <tr>
  24. <td>result 1</td><td>something..................</td>
  25. </tr>
  26. <tr>
  27. <td>result 1</td><td>something..................</td>
  28. </tr>
  29. </table>
  30.  
  31. </body>
  32. </html>

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

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

  1. <%@ page pageEncoding="UTF-8"%>
  2. <%@page import="java.util.List"%>
  3. <%@page import="java.util.ArrayList"%>
  4. <%!
  5. class Result {
  6. String title;
  7. String content;
  8. public Result(String title, String content) {
  9. this.title = title;
  10. this.content = content;
  11. }
  12. }
  13. %>
  14. <%
  15. String keywords = "site from scratch";
  16.  
  17. List results = new ArrayList();
  18. results.add(new Result("result 1", "something.................."));
  19. results.add(new Result("result 2", "something.................."));
  20. results.add(new Result("result 3", "something.................."));
  21. results.add(new Result("result 4", "something.................."));
  22. %>
  23.  
  24. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  25. <html>
  26. <head>
  27. </head>
  28.  
  29. <body>
  30. <h1>search it!</h1>
  31.  
  32. <form action="" method="get">
  33. <input type="text" value="<%=keywords %>" name="keywords" />    
  34. <input type="submit" value="search!" />
  35. </form>
  36.  
  37. <%
  38. if(!results.isEmpty()) {
  39. %>
  40. <table border="1" bordercolor="grey" >
  41. <%
  42. for(int i = 0; i < results.size(); i++) {
  43. Result result = (Result)results.get(i);
  44. %>
  45. <tr>
  46. <td><%=result.title %></td><td><%=result.content %></td>
  47. </tr>
  48. <%
  49. }
  50. %>
  51. </table>
  52. <%
  53. }
  54. %>
  55.  
  56. </body>
  57. </html>

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

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

  1. <%@ page pageEncoding="UTF-8"%>
  2. <%@page import="java.util.List"%>
  3. <%@page import="java.util.ArrayList"%>
  4. <%!
  5. class Result {
  6. public String title;
  7. public String content;
  8. public Result(String title, String content) {
  9. this.title = title;
  10. this.content = content;
  11. }
  12. }
  13.  
  14. public List search(String keywords) {
  15. List results = new ArrayList();
  16. results.add(new Result("result 1", "something.................."));
  17. results.add(new Result("result 2", "something.................."));
  18. results.add(new Result("result 3", "something.................."));
  19. results.add(new Result("result 4", "something.................."));
  20.  
  21. return results;
  22. }
  23. %>
  24. <%
  25. String keywords = request.getParameter("keywords");
  26. if(keywords == null) keywords = "";
  27.  
  28. List results = search(keywords);
  29. %>
  30.  
  31. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  32. <html>
  33. <head>
  34. </head>
  35.  
  36. <body>
  37. <h1>search it!</h1>
  38.  
  39. <form action="" method="get">
  40. <input type="text" value="<%=keywords %>" name="keywords" />    
  41. <input type="submit" value="search!" />
  42. </form>
  43.  
  44. <%
  45. if(!results.isEmpty()) {
  46. %>
  47. <table border="1" bordercolor="grey" >
  48. <%
  49. for(int i = 0; i < results.size(); i++) {
  50. Result result = (Result)results.get(i);
  51. %>
  52. <tr>
  53. <td><%=result.title %></td><td><%=result.content %></td>
  54. </tr>
  55. <%
  56. }
  57. %>
  58. </table>
  59. <%
  60. }
  61. %>
  62.  
  63. </body>
  64. </html>

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

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

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

  1. package cn.com.sitefromscrath.entity;
  2.  
  3. public class Result {
  4.  
  5. public String title;
  6. public String content;
  7.  
  8. public Result(String title, String content) {
  9. this.title = title;
  10. this.content = content;
  11. }
  12. }
  1. package cn.com.sitefromscrath.service;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import cn.com.sitefromscrath.entity.Result;
  7.  
  8. public class SearchService {
  9.  
  10. public List search(String keywords) {
  11.  
  12. List results = new ArrayList();
  13. results.add(new Result("result 1", "something.................."));
  14. results.add(new Result("result 2", "something.................."));
  15. results.add(new Result("result 3", "something.................."));
  16. results.add(new Result("result 4", "something.................."));
  17.  
  18. return results;
  19. }
  20.  
  21. }

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

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

例如以下所看到的:

  1. package cn.com.sitefromscrath;
  2.  
  3. import cn.com.sitefromscrath.service.SearchService;
  4.  
  5. public class BeanFactory {
  6.  
  7. public static Object getBean(String id) {
  8. if("searchService".equals(id)) {
  9. return new SearchService();
  10. }
  11.  
  12. throw new RuntimeException("cannot find the bean with id :" + id);
  13. }
  14.  
  15. }

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

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

  1. <%@ page pageEncoding="UTF-8"%>
  2. <%@page import="java.util.List"%>
  3. <%@page import="cn.com.sitefromscrath.service.SearchService"%>
  4. <%@page import="cn.com.sitefromscrath.BeanFactory"%>
  5. <%@page import="cn.com.sitefromscrath.entity.Result"%>
  6. <%
  7. String keywords = request.getParameter("keywords");
  8. if(keywords == null) keywords = "";
  9.  
  10. SearchService searchService = (SearchService)BeanFactory.getBean("searchService");
  11. List results = searchService.search(keywords);
  12. %>
  13.  
  14. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  15. <html>
  16. <head>
  17. </head>
  18.  
  19. <body>
  20. <h1>search it!</h1>
  21.  
  22. <form action="" method="get">
  23. <input type="text" value="<%=keywords %>" name="keywords" />    
  24. <input type="submit" value="search!" />
  25. </form>
  26.  
  27. <%
  28. if(!results.isEmpty()) {
  29. %>
  30. <table border="1" bordercolor="grey" >
  31. <%
  32. for(int i = 0; i < results.size(); i++) {
  33. Result result = (Result)results.get(i);
  34. %>
  35. <tr>
  36. <td><%=result.title %></td><td><%=result.content %></td>
  37. </tr>
  38. <%
  39. }
  40. %>
  41. </table>
  42. <%
  43. }
  44. %>
  45.  
  46. </body>
  47. </html>

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

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

  1. package cn.com.sitefromscrath.web;
  2.  
  3. import java.io.IOException;
  4. import java.util.List;
  5.  
  6. import javax.servlet.ServletException;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10.  
  11. import cn.com.sitefromscrath.BeanFactory;
  12. import cn.com.sitefromscrath.service.SearchService;
  13.  
  14. public class SearchServlet extends HttpServlet {
  15.  
  16. public void doGet(HttpServletRequest request, HttpServletResponse response)
  17. throws ServletException, IOException {
  18. doPost(request, response);
  19. }
  20.  
  21. public void doPost(HttpServletRequest request, HttpServletResponse response)
  22. throws ServletException, IOException {
  23.  
  24. String keywords = request.getParameter("keywords");
  25. if(keywords == null) keywords = "";
  26.  
  27. SearchService searchService = (SearchService)BeanFactory.getBean("searchService");
  28. List results = searchService.search(keywords);
  29.  
  30. request.setAttribute("keywords", keywords);
  31. request.setAttribute("results", results);
  32.  
  33. request.getRequestDispatcher("/search5.jsp").forward(request, response);
  34. }
  35.  
  36. }

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

  1. <%@ page pageEncoding="UTF-8"%>
  2. <%@page import="java.util.List"%>
  3. <%@page import="cn.com.sitefromscrath.entity.Result"%>
  4. <%
  5. String keywords = (String)request.getAttribute("keywords");
  6. List results = (List)request.getAttribute("results");
  7. %>
  8.  
  9. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  10. <html>
  11. <head>
  12. </head>
  13.  
  14. <body>
  15. <h1>search it!</h1>
  16.  
  17. <form action="" method="get">
  18. <input type="text" value="<%=keywords %>" name="keywords" />    
  19. <input type="submit" value="search!" />
  20. </form>
  21.  
  22. <%
  23. if(!results.isEmpty()) {
  24. %>
  25. <table border="1" bordercolor="grey" >
  26. <%
  27. for(int i = 0; i < results.size(); i++) {
  28. Result result = (Result)results.get(i);
  29. %>
  30. <tr>
  31. <td><%=result.title %></td><td><%=result.content %></td>
  32. </tr>
  33. <%
  34. }
  35. %>
  36. </table>
  37. <%
  38. }
  39. %>
  40.  
  41. </body>
  42. </html>

web.xml中配置:

  1. <?
  2.  
  3. xml version="1.0" encoding="UTF-8"?>
  4. <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  7. http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  8. <servlet>
  9. <servlet-name>SearchServlet</servlet-name>
  10. <servlet-class>cn.com.sitefromscrath.web.SearchServlet</servlet-class>
  11. </servlet>
  12.  
  13. <servlet-mapping>
  14. <servlet-name>SearchServlet</servlet-name>
  15. <url-pattern>/search</url-pattern>
  16. </servlet-mapping>
  17.  
  18. <welcome-file-list>
  19. <welcome-file>index.jsp</welcome-file>
  20. </welcome-file-list>
  21.  
  22. </web-app>

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

binggo。效果跟目标无差!

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

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

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

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

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

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

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

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

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

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

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

  1. package cn.com.sitefromscrath.service;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import cn.com.sitefromscrath.entity.Result;
  7.  
  8. public class SearchService {
  9.  
  10. public List search(String keywords) {
  11.  
  12. List results = new ArrayList();
  13. results.add(new Result("result 1", "something.................."));
  14. results.add(new Result("result 2", "something.................."));
  15. results.add(new Result("result 3", "something.................."));
  16. results.add(new Result("result 4", "something.................."));
  17.  
  18. return results;
  19. }
  20.  
  21. }

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

WEB开发那些事儿

第一部分:从需求出发

所见即所得

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

造飞机的工厂

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

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

春天在哪里

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

春天在这里

对spring的吐槽

麦克斯韦妖

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

扒皮MVC

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

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

序言

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

再造一个dom4j

标题说明了一切

再造一个spring

标题说明了一切

再造一个jsp

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

再造一个struts

标题说明了一切

再造一个lucene

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

再造一个hibernate

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

Final Fantasy

终于的成品

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

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

  1. 解析图书 XML

    Java代码: package com.thinkgem.jeesite.test; import org.dom4j.Attribute; import org.dom4j.Document; im ...

  2. 基于低代码平台(Low Code Platform)开发中小企业信息化项目

    前言:中小企业信息化需求强烈,对于开发中小企业信息化项目的软件工作和程序员来说,如何根据中小企业的特点,快速理解其信息化项目的需求并及时交付项目,是一个值得关注和研讨的话题. 最近几年来,随着全球经济 ...

  3. IT项目管理十大要素

    1.项目需求PgMp.mypm.net 当项目混乱和不可控的时候,往往是源头出了问题,解决源头才能治本.项目管理者联盟文章 软件项目中的范围管理重点就是项目需求,需求包括原始需求,用户需求,产品需求和 ...

  4. CIO在数字化转型中如何正确定位?

    在数字化转型的大潮下,CIO和传统企业应如何抓住数字生态系统中的机遇?CIO该如何面对领导力.资金.技术和人才的挑战? Gartner研究总监陈勇表示:IT部门在企业中应转变成为一个引领创新的部门,C ...

  5. 054 Python程序设计思维

    目录 一.单元开篇 二.计算思维与程序设计 2.1 计算思维 2.1.1 第3种人类思维特征 2.1.2 抽象和自动化 2.1.3 计数求和:计算1-100的计数和 2.1.4 圆周率的计算 2.1. ...

  6. HANA到MySQL数据同步方法!

    随着各行各业信息化建设的不断发展,异构数据库间的互通.汇聚,挖掘,分析逐渐被提上日程, TreeSoft数据库管理系统,实现了异构数据库的维护.监控.可视化.自动交换同步.目前支持MySQL,Orac ...

  7. 阿里云场景化阿里云企业数字化转型售前方法PSA

    阿里云场景化阿里云企业数字化转型售前方法PSA 目录 01 课程收获 理解企业数字化转型的概念.内涵.本质 了解企业数字化转型的要点.目标和切入点 掌握数字化转型项目售前阶段实践方法 场景化方案 阿里 ...

  8. 初学者应该怎么学习前端?web前端的发展路线大剖析!

    写在最前: 优秀的Web前端开发工程师要在知识体系上既要有广度和深度!应该具备快速学习能力. 前端开发工程师不仅要掌握基本的Web前端开发技术,网站性能优化.SEO和服务器端的基础知识,而且要学会运用 ...

  9. 星浩资本快速发展引擎:IT就是生产力

    星浩资本成立于2010年,是一家涵盖私募基金.开发管理.商业与现代服务业三大业务范围的综合性管理公司,专注于投资中国首创.高成长性.高回报率的创新型城市综合体. 年轻的星浩资本在商业投资上有其独到的商 ...

随机推荐

  1. hdu1059(多重背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1059 题意 : 按顺序读入一些列数,所对应的序列代表价值,数值代表个数(如a[5]=6 ,代表价值为五 ...

  2. Cygwin下vim按方向键出现ABCD;

    1:乱码解决Option->Text设置编码 2:vim按方向键出现A.B.C.D 解决:--$ cd /usr/share/vim/vim73 (ps:看你的版本号.假设没有这个文件可能是/u ...

  3. Cocos2d-x v3.0正式版尝鲜体验【3】 Label文本标签

    Cocos2d-x在新版本号中增加了新的Label API.和以往不同的是,2.x的版本号是通过三个不同的类来创建不同的文本标签,而如今是模仿着精灵的创建方式.一个类创建不同形式的文本,只是核心内容还 ...

  4. Codeforces Round #269 (Div. 2) A B C

    先说C 题目链接:http://codeforces.com/problemset/problem/471/C 题目意思:有 n 张卡,问能做成多少种不同楼层(floor)的 house.注意这 n ...

  5. I2C操作笔记——以 AT24C04为例

    1.前言     对于大多数project师而言,I2C永远是一个头疼的问题.相比UART和SPI而言,I2C的时序要复杂一些,I2C组合变化也丰富一些.在这里以AT24C04为例说明I2C使用过程中 ...

  6. jQuery cxSelect 多级联动下拉菜单

    随着电商热门,这种多层次的互动更充分地体现在下拉菜单,最明显的是多级联动地址下拉选择,因此,这里是一个简单的分享 jQuery cxSelect 多级联动下拉菜单 cxSelect 它是基于 jQue ...

  7. ECshop lib_base.php on line 1241 错误解决方法

    ECSHOP做的一个网站,突然报这个错误,整个网站打不开,后来找了很久,终于找到这个方法,亲测可用 Notice: Undefinedvariable: data in D:\wwwroot\KISS ...

  8. 21天教你学会C++

  9. linux查看某个进程CPU消耗较高的具体线程或程序的方法

      目前我们的监控,可以发现消耗较高CPU的进程(阀值为3个CPU),通过监控我们可以找到消耗较高CPU的进程号: 通过进程号pid,我们在linux上可以通过top –H –p <pid> ...

  10. 【LaTeX排版】LaTeX论文排版&lt;三&gt;

    A picture is worth a thousand words(一图胜千言).图在论文中的重要性不言而喻,本文主要解说图的制作与插入. 1.图像的插入     图像能够分为两大类:位图和向量图 ...