
DVDFab PlatinumV9.2.0.1 Final 多國(guó)語(yǔ)言官方安裝版
- 類型:光盤(pán)工具大小:74.4M語(yǔ)言:中文 評(píng)分:6.0
- 標(biāo)簽:
在我的編程生涯中,碰到類似Copy-Paste的情況簡(jiǎn)直不勝枚舉。在一次項(xiàng)目中,我們對(duì)開(kāi)源項(xiàng)目Jasper Report進(jìn)行了擴(kuò)展。我們加入了對(duì)新報(bào)表類型(CJT_REPORT)的支持。在ReportParameterAction類中,我們需要對(duì)報(bào)表對(duì)象ReportUnit判斷報(bào)表類型。于是,我在ReportParameterAction類中定義了如下的私有方法:
private void setReportUnitTypeByFileResource(ReportUnit reportUnit) {
final String JS_FILE_TYPE = "jrxml";
ResourceReference reference = reportUnit.getMainReport();
if (reference.isLocal()) {
FileResource resource = (FileResource)reference.getLocalResource();
String fileType = resource.getFileType();
if (fileType.toLowerCase().equals(JS_FILE_TYPE)){
reportUnit.setReportType(ReportUnit.JS_REPORT);
} else {
reportUnit.setReportType(ReportUnit.CJT_REPORT);
}
}
}
該方法根據(jù)FileResource中的文件類型獲得對(duì)應(yīng)的報(bào)表類型。這一方法在ReportParameterAction類的createWrappers()方法中被調(diào)用。
protected Event createWrappers(RequestContext context) {
ReportUnit reportUnit = loadReportUnit(context);
setReportUnitTypeByFileResource(reportUnit);
InitialRequestContext(context, reportUnit);
int reportType = reportUnit.getReportType();
if (reportType == ReportUnit.CJT_REPORT) {//……}
//……
}
后來(lái),我發(fā)現(xiàn)在EngineServiceImpl類中同樣需要判斷報(bào)表的類型。然而,setReportUnitTypeByFileResource()方法卻被定義為ReportParameterAction的私有方法,無(wú)法被EngineServiceImpl對(duì)象調(diào)用。最簡(jiǎn)單的做法是采用復(fù)制的方式,將這段代碼復(fù)制到EngineServiceImpl中。好了,如果此時(shí)我們不能忍住copy-paste的簡(jiǎn)便所帶來(lái)的誘惑,或許就會(huì)陷入重復(fù)的泥沼了。Copy的動(dòng)作絕對(duì)應(yīng)該鳴起刺耳的警聲。我們需要對(duì)這一做法保持足夠的警惕。
通過(guò)分析setReportUnitTypeByFileResource()方法,我發(fā)現(xiàn)該方法需要操作的對(duì)象均與ReportUnit有關(guān),而本身該方法的職責(zé)就是要獲得ReportUnit的類型,并對(duì)其字段reportType進(jìn)行設(shè)置,因此,完全可以將它搬移到ReportUnit中(Move Method重構(gòu),不是嗎?)。由于ReportUnit已經(jīng)增加了對(duì)reportType字段的get和set訪問(wèn)方法,我發(fā)現(xiàn)它們與我要重構(gòu)的方法實(shí)有異曲同工之處,因而決定將其搬移到getReportType()方法中:
public int getReportType() {
if (hasReportTypeBeenSet()) {
return reportType;
}
return getReportTypeByFileResource();
}
private int getReportTypeByFileResource() {
final String CJT_FILE_TYPE = "cjtxml";
int reportType = ReportUnit.JS_REPORT;
ResourceReference reference = this.getMainReport();
if (reference != null) {
if (reference.isLocal()) {
FileResource resource = (FileResource) reference
.getLocalResource();
if (resource != null) {
String fileType = resource.getFileType();
if (fileType.toLowerCase().equals(CJT_FILE_TYPE)) {
reportType = ReportUnit.CJT_REPORT;
}
}
}
}
return reportType;
}
private boolean hasReportTypeBeenSet(){
if (reportType != ReportUnit.JS_REPORT
&& reportType != ReportUnit.CJT_REPORT) {
return false;
} else {
return true;
}
}
注意,在以上過(guò)程中,除了使用Move Method之外,我還運(yùn)用了Rename Method以及Extract Method等重構(gòu)手法。
現(xiàn)在,對(duì)報(bào)表類型的獲取與調(diào)用就變得簡(jiǎn)單了,在ReportParameterAction與EngineServiceImpl類中,也規(guī)避了重復(fù)代碼的產(chǎn)生。例如,在createWrappers()方法中的調(diào)用被更改為:
protected Event createWrappers(RequestContext context) {
ReportUnit reportUnit = loadReportUnit(context);
setReportUnitTypeByFileResource(reportUnit);
InitialRequestContext(context, reportUnit);
int reportType = reportUnit.getReportType();
if (reportType == ReportUnit.CJT_REPORT) {//……}
//……
}