《編寫可讀代碼的藝術》,藝術是表達自己內在的慾望
再看看我畢設中的代碼,寫的真是爛啊
可讀代碼的藝術包含:
- 名副其實的命名
- 子解釋的註釋
- 言簡意賅的控制結構
在畢設中遇到的實際問題:
/**
* This method evaluates an event against a run, for skip-till-any-match
* @param e The event which is being evaluated.
* @param r The run which the event is being evaluated against.
* @throws CloneNotSupportedException
*/
public void evaluateEventForSkipTillAny(Event e, Run r) throws CloneNotSupportedException{
boolean checkResult = true;
checkResult = this.checkPredicate(e, r);// check predicate
if(checkResult){ // the predicate if ok.
checkResult = this.checkTimeWindow(e, r); // the time window is ok
if(checkResult){// predicate and time window are ok
this.buffer.bufferEvent(e);// add the event to buffer
int oldState = 0;
int newState = 0;
Run newRun = this.cloneRun(r); // clone this run
oldState = newRun.getCurrentState();
newRun.addEvent(e); // add the event to this run
newState = newRun.getCurrentState();
if(oldState != newState){
this.activeRuns.add(newRun);
}else{//kleene closure
if(newRun.isFull){
//check match and output match
if(newRun.checkMatch()){
this.outputMatch(new Match(newRun, this.nfa, this.buffer));
Profiling.totalRunLifeTime += (System.nanoTime() - r.getLifeTimeBegin());
}
}else{
//check proceed
if(this.checkProceed(newRun)){
Run newerRun = this.cloneRun(newRun);
this.activeRuns.add(newRun);
newerRun.proceed();
if(newerRun.isComplete()){
this.outputMatch(new Match(r, this.nfa, this.buffer));
Profiling.totalRunLifeTime += (System.nanoTime() - r.getLifeTimeBegin());
}else {
this.activeRuns.add(newerRun);
}
}
}
}
}else{
this.toDeleteRuns.add(r);
}
}
}
- 先觀察上面的代碼,計算代碼的複雜度
Cyclomatic Complexity(CC循環複雜度)=edges-nodes+2 代碼的作用
分析上面方法的作用
- 檢查事件滿足NFA當前狀態的起始邊,如果滿足再檢查當前狀態是否爲克林閉包狀態,再檢查是否要前進
修改爲evaluateEventForSkipTillAny(Event e,Run run)的作用是移除/添加/前進對run的三個操作
checkPredicateOptimized(Event e,Run run)的作用是檢查事件對run當前狀態的所有謂詞的檢查
public void evaluateEventOptimizedForSkipTillAny(Event e, Run r) throws CloneNotSupportedException{
int checkResult = this.checkPredicateOptimized(e, r);
switch(checkResult){
case 1:
boolean timeWindow = this.checkTimeWindow(e, r);
if(timeWindow){
Run newRun = this.cloneRun(r);
this.addRunByPartition(newRun);
this.addEventToRun(r, e);
}else{
this.toDeleteRuns.add(r);
}
break;
case 2:
Run newRun = this.cloneRun(r);
this.addRunByPartition(newRun);
r.proceed();
this.addEventToRun(r, e);
}
}
/**
* Checks the predicate for e against r
* 對於run,檢測e的謂詞,檢測結果是0爲false,1是take或begin,2是proceed
* @param e The current event
* @param r The run against which e is evaluated
* @return The check result, 0 for false, 1 for take or begin, 2 for proceed
*/
public int checkPredicateOptimized(Event e, Run r){//0 for false, 1 for take or begin, 2 for proceed
int currentState = r.getCurrentState();//當前run的狀態
State s = this.nfa.getStates(currentState);//例子會返回run的克林閉包a狀態
//檢測事件類型
if(!s.getEventType().equalsIgnoreCase(e.getEventType())){// event type check;
return 0;
}
//非克林加檢測
if(!s.isKleeneClosure()){
Edge beginEdge = s.getEdges(0);
boolean result;
//result = firstEdge.evaluatePredicate(e, r, buffer);
result = beginEdge.evaluatePredicate(e, r, buffer);//
if(result){
return 1;
}
}else{//克林加情況
//克林加初始化檢測,true
if(r.isKleeneClosureInitialized()){
boolean result;
//當將e加入r當中時,檢測run是否需要proceed,他是通過將該事件放入下一個狀態中進行計算,
//得到下一個狀態,如果這個事件滿足下個狀態的所有謂詞,狀態從克林閉包狀態前進
//例如第一次匹配中,2和3事件到來時返回的false,因爲它的volume不滿足狀態1中的謂詞。4事件滿足,返回true
result = this.checkProceedOptimized(e, r);//proceedEdge.evaluatePredicate(e, r, buffer);
if(result){
return 2;//前進
}else{
//take邊
Edge takeEdge = s.getEdges(1);
//計算take邊
result = takeEdge.evaluatePredicate(e, r, buffer);
if(result){
//在第一個匹配中,ID爲2和3的事件滿足,take邊
return 1;
}
}
}else{//克林加初始化檢測,false
Edge beginEdge = s.getEdges(0);
boolean result;
result = beginEdge.evaluatePredicate(e, r, buffer);//
if(result){
return 1;
}
}
}
return 0;
}
兵哥PPT上編寫可讀代碼的藝術其中包含->言簡意賅的控制結構
1. 打平條件分支:用if-else if -else 代替嵌套if
2. 提前返回
3.使用continue
根據這個理論,checkPredicateOptimized()方法可以改爲
else if(r.isKleeneClosureInitialized()){}
else{}
的結構。
只是一個簡單的改進,15行的方法還沒做好呢
附上PPT裏面的控制言簡意賅的控制結構的案例