《编写可读代码的艺术》,艺术是表达自己内在的欲望
再看看我毕设中的代码,写的真是烂啊
可读代码的艺术包含:
- 名副其实的命名
- 子解释的注释
- 言简意赅的控制结构
在毕设中遇到的实际问题:
/**
* 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里面的控制言简意赅的控制结构的案例