|
楼主 |
发表于 2005-3-18 12:18:11
|
显示全部楼层
一、《重构》-- 改善既有代码的设计
1、TTD 、XP与Refactoring
XP(极限编程)获得了14届软件工程方法学JOLT大奖。它被候捷认为是重型开发与轻型开发之间的区别。XP认为中小型项目不适合按传统的软件工程方法进行--汗牛充栋的文档,需求的错误被持续等。这损害了软件需求的快速变化的适应能力。
XP中的核心是TTD与Refactoring。很多人都己经知道测试的重要,各种语言也有相应的测试工具使用。XP更强调测试,因为软件处在不断的变化(既所谓Refactoring)中,Refactoring这个词应该是伴随着XP这个概念一起流行的。虽然在《重构》这本书中Refactoring这个概念来自于SmallTallk。
只是很多经理都不太赞成结对编程。对它所描述的美好图景将信将疑。
我记得我的前任经理认为,要实现结对编程,真正的提高效率,需要较为优秀的程序员。不然的话,有人会偷懒。呵呵。你看Driver与Navigator哪个不是身怀绝技?
2、《重构》这本书
这本书熊节不认为它应该成为经典,经典应该成为一种高山仰止的东西,例如《设计模式》。而它应该成为程序员的空气与水。我们必须时刻重构代码,特别是当有了坏味道(bad smell)的时候。
必须有测试。你的测试用例将不必修改,因为重构将不改变现有可查功能。必须小步前进,确保不带来臭虫(bug)。
它是在实践中获得的经验。如果你要掌握它,你必须去实践。熊节说,从最简单的Extract Method开始吧。
我们比较幸运,因为那么多IDE有了Refactoring这样一个专门的菜单。至少Java的IDE是这样。
3、这本书重要的概念与章节
关键词:概念、坏味道、测试体系、步进,小规模、工具
什么是重构?去看这本书吧,我起先也不知道。在不知道的情况下,我使用了Extract Method。可是,读了这本书才知道pull up xxx、pull down xxx是什么。
在Martin Fowler写这本书的时候,没有IDE上有Refactoring这项菜单,JB9没有,Eclipse2也没有。
本书体例上模仿了《设计模式》,你可以按《设计模式》的读者指南去研究这本书。
我赞成熊节的话,它应该成为程序员的日常的面包与黄油。
4、实际的例子
Duplicate Code与Long Method(重复代码与过长方法)
这是软件内部实现两种最为典型的坏味道。
重复代码的例子可以参考我所说过的文件上传与取下拉框架的例子。
以下是对一个过长方法的处理过程:
旧代码片断
else if (act.equals("list")) {
String temppath = this.getServlet().getServletContext()
.getRealPath("/")
+ "roadmanage/reports/xlsfile/xlstemplate/";
String _path = this.getServlet().getServletContext().getRealPath(
"/")
+ "roadmanage/reports/xlsfile/";
String _file = "roadManageMonthReport.xls";
String to_file = "roadManageMonthReport.xls";
if (!ReportUtil.copy_template_file(temppath + _file, _path
+ to_file)) {
log.error("拷贝文件出现错误,,,,,,,,,,,,,,,,,,");
throw new ReportException();
}
//检查月报选择情况
String report_select[] = request
.getParameterValues("select_report");
int start_line = 1;
//报表数据参数对象
GetDataPara r_data_para = new GetDataPara();
//得到机构
r_data_para.setOrg_id(user.getOrgID());
//按月查询
r_data_para.setYear(year);
r_data_para.setMonth(month);
//如果是期间查询
//${FIXME} 增加期间查询参数
//
String period = null;
if (is_period){//是期间查询
String start_date = request.getParameter("start_date");
String end_date = request.getParameter("end_date");
if (start_date!=null&&end_date!=null){
period = start_date+" 到 "+end_date;
try{
r_data_para.setStart_date(new java.sql.Date(DateUtil.parse(start_date).getTime()));
r_data_para.setEnd_date(new java.sql.Date(DateUtil.parse(end_date).getTime()));
}catch(Exception ex){
log.error("期间查询时,查询参数有误!",ex);
throw new ReportException();
}
}else{
log.error("期间查询时,查询参数有误!");
throw new ReportException();
}
//是期间查询 ,并且开始时间小于结束时间
if (DateUtil.parse(start_date).before(DateUtil.parse(end_date))){
r_data_para.setIs_period(true);
}else{
//互换时间
r_data_para.setStart_date(new java.sql.Date(DateUtil.parse(start_date).getTime()));
r_data_para.setEnd_date(new java.sql.Date(DateUtil.parse(end_date).getTime()));
r_data_para.setIs_period(true);
}
}
if (report_select != null && report_select.length > 0) {
log.info("所选择的月报个数:" + report_select.length);
int size = report_select.length;
String period_str = this.getCountPeriod(r_data_para);
for (int i = 0; i < size; i++) { //逐个检查选择值
log.info("月报名:" + report_select);
if (report_select.equals("month_report1")) {
//得到路政申请事项统计表数据 己加上公路占用数据 wangsy 2004-11-11
HashMap roadPermitMap = RoadPermitReportDataMap
.getRoadPermitData(r_data_para);
//加上期间字符串 2005-01-31 wangsy
roadPermitMap.put("F2",period_str);
ReportUtil.toXlsFile(_path, to_file, start_line, 0,
roadPermitMap);
} else if (report_select.equals("month_report2")) {
//得到路政案件综合报表
HashMap dataMap = RoadCaseReportDataMap
.getRoadPermitData(r_data_para);
//加上期间字符串 2005-01-31 wangsy
dataMap.put("F2",period_str);
ReportUtil.toXlsFile(_path, to_file, start_line, 1,
dataMap);
} else if (report_select.equals("month_report3")) {
//得到施工安全管理统计表数据
HashMap constructionSafeMap = ConstructionSafeManageDataMap
.getConstructionSafeData(r_data_para);
//加上期间字符串 2005-01-31 wangsy
constructionSafeMap.put("E4",period_str);
ReportUtil.toXlsFile(_path, to_file, start_line, 2,
constructionSafeMap);
} else if (report_select.equals("month_report4")) {
//得到交通事故案件综合报表
HashMap dataMap = CaseSumReportDataMap.getRoadCaseData(r_data_para);
//加上期间字符串 2005-01-31 wangsy
dataMap.put("F2",period_str);
ReportUtil.toXlsFile(_path, to_file, start_line, 3,
dataMap);
} else if (report_select.equals("month_report5")) {
//得到交通事故案件登记表数据
HashMap accidentCaseRegisterMap = AccidentCaseRegisterDataMap
.getAccidentCaseData(r_data_para);
//加上期间字符串 2005-01-31 wangsy
accidentCaseRegisterMap.put("F2",period_str);
ReportUtil.toXlsFile(_path, to_file, start_line, 4,
accidentCaseRegisterMap);
} else if (report_select.equals("month_report6")) {
//得到资源文件
String file = this.getServlet().getServletContext()
.getRealPath(Constants.PROPERTIES_FILE_PATH);
r_data_para.setProperties_file(file);
//交通事故案件分析表
HashMap dataMap = CaseAnalyseReportDataMap
.getRoadCaseData(r_data_para);
//加上期间字符串 2005-01-31 wangsy
dataMap.put("D2",period_str);
ReportUtil.toXlsFile(_path, to_file, start_line, 5,
dataMap);
} else if (report_select.equals("month_report7")) {
//得到事故案件待处登记表数据
HashMap accidentCaseWaitingRegisterMap = AccidentCaseWaitingRegisterDataMap
.getAccidentCaseWaitingData(r_data_para);
//加上期间字符串 2005-01-31 wangsy
accidentCaseWaitingRegisterMap.put("F2",period_str);
ReportUtil.toXlsFile(_path, to_file, start_line, 6,
accidentCaseWaitingRegisterMap);
} else if (report_select.equals("month_report8")) {
//指路产修复表,暂未加上
;
}
}
}
String _reportname = org_name+year+"年"+month+"月管理报表.xls";
if (r_data_para.isPeriod_Query()){
_reportname = org_name+"期间("+period+")管理报表.xls";
}
ReportUtil.getReturnPage(_path + to_file, response, _reportname);
return null;
}
它太长了,很累吧。看看缩减后的情况
新代码片断
else if(act.equals("list")){
//拷贝excel模板文件
copyExcelFile(new_temppath, new_path, _file, to_file);
//得到参数对象
GetDataPara r_data_para = getDataPara(
request, year, month, isPeriod(request), UserMap.getUserFromRequest(request));
//月报选择情况
String report_select[] = request.getParameterValues("select_report");
//处理报表
genReport(new_path, to_file, report_select, r_data_para);
//Report Name
String _reportname = org_name + year + "年" + month + "月管理报表.xls";
if(r_data_para.isPeriod_Query()){
_reportname = org_name + "期间(" + getCountPeriod(r_data_para) +
")管理报表.xls";
}
//return client
ReportUtil.getReturnPage(new_path + to_file, response, _reportname);
return null;
}
[此贴子已经被作者于2005-3-18 12:19:16编辑过]
|
|