[TOC] 。。博客園不支持目錄。。安全
在個人三次電梯做業裏,追求的目標都是讓電梯運行與調度器分離,電梯只負責按照指令運行,目前的最終版本中,指令有UP、DOWN、OPEN、CLOSE、STILL、STOP六條。數據結構
從第二次做業開始,我創建了Stage類,負責保存樓層信息;多線程
創建了Instruction類,負責描述電梯運行的指令以及對應的Stage的變化,Instruction類中有一個枚舉類型表示指令類型,一個IntFunction類型函數表示樓層索引的變化。架構
從第二次到第三次,個人調度器的邏輯部分都是解耦成以下4個部分:app
這是一個輪詢機制,順序循環並分發指令,控制電梯。ide
返回目錄函數
Method | ev(G) | iv(G) | v(G) |
---|---|---|---|
"Main.main(String[])" | 1 | 1 | 1 |
"elevator.Dispatcher.Dispatcher()" | 1 | 1 | 1 |
"elevator.Dispatcher.getWaitingQueue()" | 1 | 1 | 1 |
"elevator.Dispatcher.printQueue()" | 1 | 1 | 1 |
"elevator.Dispatcher.run()" | 1 | 3 | 4 |
"elevator.Elevator.Elevator(int|int|int)" | 1 | 1 | 1 |
"elevator.Elevator.OutPersonThread.OutPersonThread(int|Vector
|
1 | 1 | 1 |
"elevator.Elevator.OutPersonThread.run()" | 1 | 3 | 3 |
"elevator.Elevator.addPassenger(int|int)" | 1 | 1 | 1 |
"elevator.Elevator.getStage()" | 1 | 1 | 1 |
"elevator.Elevator.getStatus()" | 1 | 1 | 1 |
"elevator.Elevator.moveDown()" | 1 | 2 | 3 |
"elevator.Elevator.moveTo(int)" | 1 | 5 | 5 |
"elevator.Elevator.moveUp()" | 1 | 2 | 3 |
"elevator.Elevator.release()" | 1 | 1 | 1 |
"elevator.ElevatorOutput.formatOutput(Format|int)" | 2 | 2 | 4 |
"elevator.ElevatorOutput.formatOutput(Format|int|int)" | 2 | 2 | 4 |
"elevator.Person.Person(int|int|int)" | 1 | 1 | 1 |
"elevator.Person.getFrom()" | 1 | 1 | 1 |
"elevator.Person.getId()" | 1 | 1 | 1 |
"elevator.Person.getTo()" | 1 | 1 | 1 |
"elevator.TransferPersonRequest.TransferPersonRequest(Dispatcher)" | 1 | 1 | 1 |
"elevator.TransferPersonRequest.run()" | 3 | 2 | 5 |
"util.MultiMap.MultiMap()" | 1 | 1 | 1 |
"util.MultiMap.get(K)" | 1 | 1 | 1 |
"util.MultiMap.put(K|V)" | 1 | 1 | 2 |
"util.MultiMap.remove(K)" | 1 | 1 | 1 |
"util.MultiMap.toString()" | 1 | 1 | 1 |
可見的是,個人方法複雜度都很低,由於類也比較少,沒什麼衡量價值工具
返回目錄spa
從第二次電梯開始,個人電梯是按照如上的設計架構完成的,這是讓我以爲比較舒服的架構設計,其設計方向是在於模擬,而不是爲最優解設計的。線程
Method | ev(G) | iv(G) | v(G) |
---|---|---|---|
"Main.main(String[])" | 1 | 1 | 1 |
"machine.Dispatcher.Dispatcher()" | 1 | 2 | 2 |
"machine.Dispatcher.exec(Instruction)" | 1 | 7 | 7 |
"machine.Dispatcher.getNewInstruction()" | 6 | 4 | 9 |
"machine.Dispatcher.getNewMajorRequest()" | 8 | 4 | 11 |
"machine.Dispatcher.run()" | 1 | 5 | 5 |
"machine.Dispatcher.updatePersonMap()" | 1 | 3 | 3 |
"machine.elevator.Elevator.Elevator(ReentrantLock)" | 1 | 1 | 1 |
"machine.elevator.Elevator.close()" | 1 | 1 | 1 |
"machine.elevator.Elevator.move()" | 1 | 1 | 1 |
"machine.elevator.Elevator.open()" | 1 | 1 | 1 |
"machine.elevator.Elevator.run()" | 2 | 5 | 8 |
"machine.elevator.Elevator.setOutsideQueue(MapVisitor<Integer| Person>)" | 1 | 1 | 1 |
"machine.elevator.Elevator.setStage(Stage)" | 1 | 1 | 1 |
"machine.elevator.Elevator.setToBeExec(List<Instruction>)" | 1 | 1 | 1 |
"machine.elevator.Elevator.setToBeRemoved(Queue<Person>)" | 1 | 1 | 1 |
"machine.elevator.ElevatorOutput.formatOutput(Format|int)" | 2 | 2 | 5 |
"machine.elevator.ElevatorOutput.formatOutput(Format|int|int)" | 2 | 2 | 4 |
"machine.elevator.Stage.Stage()" | 1 | 1 | 1 |
"machine.elevator.Stage.Stage(int)" | 1 | 1 | 2 |
"machine.elevator.Stage.apply(IntFunction)" | 1 | 1 | 2 |
"machine.elevator.Stage.checkIndex(int)" | 1 | 1 | 2 |
"machine.elevator.Stage.checkStage(int)" | 3 | 1 | 3 |
"machine.elevator.Stage.getStage()" | 1 | 1 | 1 |
"machine.input.Person.Person(int|int|int)" | 1 | 1 | 2 |
"machine.input.Person.equals(Object)" | 2 | 1 | 2 |
"machine.input.Person.getFrom()" | 1 | 1 | 1 |
"machine.input.Person.getId()" | 1 | 1 | 1 |
"machine.input.Person.getSide()" | 1 | 1 | 1 |
"machine.input.Person.getStatus()" | 1 | 1 | 1 |
"machine.input.Person.getTo()" | 1 | 1 | 1 |
"machine.input.Person.transSide()" | 1 | 1 | 2 |
"machine.input.TransferPersonRequest.TransferPersonRequest(Queue<Person>)" | 1 | 1 | 1 |
"machine.input.TransferPersonRequest.run()" | 3 | 2 | 4 |
"machine.input.TransferRequest.TransferRequest(PersonMap)" | 1 | 1 | 1 |
"machine.input.TransferRequest.run()" | 3 | 2 | 4 |
"machine.instr.Instruction.Instruction(Instr|IntFunction)" | 1 | 1 | 1 |
"machine.instr.Instruction.getFunc()" | 1 | 1 | 1 |
"machine.instr.Instruction.getInstr()" | 1 | 1 | 1 |
"util.MultiMap.MultiMap()" | 1 | 1 | 1 |
"util.MultiMap.get(K)" | 1 | 1 | 1 |
"util.MultiMap.put(K|V)" | 1 | 1 | 2 |
"util.MultiMap.removeByKey(K)" | 1 | 1 | 1 |
"util.MultiMap.removeValue(K|V)" | 1 | 2 | 2 |
"util.MultiMap.toString()" | 1 | 1 | 1 |
"util.PersonMap.PersonMap()" | 1 | 1 | 1 |
"util.PersonMap.getFromPerson(int|Status)" | 2 | 2 | 2 |
"util.PersonMap.getToPerson(int|Status)" | 2 | 2 | 2 |
"util.PersonMap.hasElement(Person)" | 3 | 3 | 4 |
"util.PersonMap.isEmpty()" | 5 | 4 | 7 |
"util.PersonMap.putPerson(Person)" | 2 | 2 | 3 |
"util.PersonMap.removePerson(Person)" | 2 | 4 | 4 |
"util.PersonMap.toEnd()" | 2 | 2 | 2 |
"util.PersonMap.toString()" | 1 | 1 | 1 |
能夠看出加粗的三個方法複雜度較高,分別是獲取主請求、根據主請求生成新命令、還有personMap的isEmpty方法。
獲取主請求因爲personMap的不合理,得在遍歷時分別獲取personMap的兩個子map,即fromUp和fromDown兩個map,因此複雜度很高。
根據主請求生成命令複雜度高跟上一個函數同理。
personMap的isEmpty方法就是由於personMap內部成員是4個map,對每個都isEmpty而後與起來,複雜度就高了。
Class | OCavg | WMC |
---|---|---|
"Main" | 1.00 | 1 |
"machine.Dispatcher" | 5.17 | 31 |
"machine.elevator.Elevator" | 2.22 | 20 |
"machine.elevator.Elevator.Format" | n/a | 0 |
"machine.elevator.Elevator.Status" | n/a | 0 |
"machine.elevator.ElevatorOutput" | 4.50 | 9 |
"machine.elevator.Stage" | 1.67 | 10 |
"machine.input.Person" | 1.38 | 11 |
"machine.input.Person.Side" | n/a | 0 |
"machine.input.Person.Status" | n/a | 0 |
"machine.input.TransferPersonRequest" | 2.00 | 4 |
"machine.input.TransferRequest" | 2.00 | 4 |
"machine.instr.InstrFac" | n/a | 0 |
"machine.instr.InstrFac.Instr" | n/a | 0 |
"machine.instr.Instruction" | 1.00 | 3 |
"util.MultiMap" | 1.33 | 8 |
"util.PersonMap" | 2.44 | 22 |
能夠看出,加粗的Dispatcher類和ElevatorOutput類複雜度較高,後者不說了,這個很難避免,前者複雜度高的緣由是,目前大部分的邏輯處理部分在這一層,實現了輪詢生成指令並分發,又有前述的兩個方法加成,因此複雜度很高,固然,這個還與個人數據結構設計有必定的關係,personMap設計得很糟糕,若是改進數據結構並分離一些邏輯,想必複雜度會降下去的吧。
這裏實際上scheduler是給三個Dispatcher發送不一樣的人員請求可是爲了說明的簡易,只畫了一個Dispatcher、Stage、Elevator組。
Method | ev(G) | iv(G) | v(G) |
---|---|---|---|
"Main.main(String[])" | 1 | 1 | 1 |
"machine.Scheduler.Scheduler()" | 1 | 1 | 1 |
"machine.Scheduler.dispatchPerson()" | 1 | 1 | 1 |
"machine.Scheduler.putPersonToElevator(Person)" | 1 | 2 | 2 |
"machine.Scheduler.run()" | 1 | 4 | 4 |
"machine.elevator.Dispatcher.Dispatcher(Stage,String,long,int,ReentrantLock)" | 1 | 1 | 1 |
"machine.elevator.Dispatcher.exec(Instruction)" | 1 | 5 | 5 |
"machine.elevator.Dispatcher.getNewInstruction()" | 11 | 7 | 13 |
"machine.elevator.Dispatcher.getNewMajorRequest()" | 1 | 3 | 5 |
"machine.elevator.Dispatcher.getPeopleMap()" | 1 | 1 | 1 |
"machine.elevator.Dispatcher.run()" | 1 | 5 | 5 |
"machine.elevator.Dispatcher.setToBePut(PeopleVector)" | 1 | 1 | 1 |
"machine.elevator.Dispatcher.update()" | 1 | 3 | 3 |
"machine.elevator.Elevator.Elevator(ReentrantLock,String,long,int)" | 1 | 1 | 1 |
"machine.elevator.Elevator.close()" | 1 | 1 | 1 |
"machine.elevator.Elevator.move()" | 1 | 1 | 1 |
"machine.elevator.Elevator.open()" | 1 | 1 | 1 |
"machine.elevator.Elevator.processInside()" | 1 | 1 | 1 |
"machine.elevator.Elevator.processOutside()" | 2 | 1 | 2 |
"machine.elevator.Elevator.run()" | 2 | 5 | 8 |
"machine.elevator.Elevator.setOutsideQueue(MapVisitor<Integer, Person>)" | 1 | 1 | 1 |
"machine.elevator.Elevator.setStage(Stage)" | 1 | 1 | 1 |
"machine.elevator.Elevator.setToBeExec(List<Instruction>)" | 1 | 1 | 1 |
"machine.elevator.Elevator.setToBeRemoved(Queue<Person>)" | 1 | 1 | 1 |
"machine.elevator.Stage.Stage(int[])" | 1 | 2 | 3 |
"machine.elevator.Stage.apply(IntFunction)" | 1 | 2 | 2 |
"machine.elevator.Stage.checkIndex(int)" | 1 | 1 | 2 |
"machine.elevator.Stage.couldStall()" | 1 | 1 | 1 |
"machine.elevator.Stage.getStage()" | 1 | 1 | 1 |
"machine.elevator.Stage.initStage(int)" | 1 | 2 | 2 |
"machine.elevator.Stage.isReachable(int)" | 1 | 1 | 1 |
"machine.elevator.Stage.isReachableByIndex(int)" | 2 | 2 | 2 |
"machine.elevator.Stage.stageToIndex(int)" | 3 | 1 | 4 |
"machine.elevator.Stage.toString()" | 1 | 1 | 1 |
"machine.input.Person.Person(int,int,int)" | 1 | 1 | 2 |
"machine.input.Person.equals(Object)" | 2 | 1 | 2 |
"machine.input.Person.getDestination()" | 2 | 1 | 2 |
"machine.input.Person.getFrom()" | 1 | 1 | 1 |
"machine.input.Person.getId()" | 1 | 1 | 1 |
"machine.input.Person.getSide()" | 1 | 1 | 1 |
"machine.input.Person.getStatus()" | 1 | 1 | 1 |
"machine.input.Person.getTo()" | 1 | 1 | 1 |
"machine.input.Person.hashCode()" | 1 | 1 | 1 |
"machine.input.Person.isOutside()" | 1 | 1 | 1 |
"machine.input.Person.isUp()" | 1 | 1 | 1 |
"machine.input.Person.needGetInside(int)" | 1 | 1 | 2 |
"machine.input.Person.needGetOutside(Stage)" | 3 | 2 | 3 |
"machine.input.Person.setMid(Stage,Stage)" | 6 | 6 | 12 |
"machine.input.Person.toString()" | 1 | 1 | 1 |
"machine.input.Person.transSide()" | 1 | 1 | 2 |
"machine.input.Person.wantOne()" | 3 | 4 | 7 |
"machine.input.TransferRequest.TransferRequest(PeopleVector,ReentrantLock)" | 1 | 1 | 1 |
"machine.input.TransferRequest.run()" | 3 | 3 | 5 |
"machine.instr.Instruction.Instruction(Type,IntFunction)" | 1 | 1 | 1 |
"machine.instr.Instruction.getFunc()" | 1 | 1 | 1 |
"machine.instr.Instruction.getType()" | 1 | 1 | 1 |
"machine.output.Output.format(Format,int,String)" | 2 | 2 | 5 |
"machine.output.Output.format(Format,int,int,String)" | 2 | 2 | 4 |
"machine.util.PeopleMap.PeopleMap()" | 1 | 2 | 2 |
"machine.util.PeopleMap.getCapcity()" | 1 | 1 | 1 |
"machine.util.PeopleMap.getMap(Type)" | 1 | 1 | 1 |
"machine.util.PeopleMap.getPerson(Type,int)" | 1 | 1 | 1 |
"machine.util.PeopleMap.hasElement(Person)" | 3 | 4 | 5 |
"machine.util.PeopleMap.isEmpty()" | 1 | 2 | 2 |
"machine.util.PeopleMap.put(Type,Integer,Person)" | 1 | 1 | 1 |
"machine.util.PeopleMap.putPerson(Person)" | 3 | 2 | 5 |
"machine.util.PeopleMap.remove(Type,Integer,Person)" | 1 | 1 | 1 |
"machine.util.PeopleMap.removePerson(Person)" | 2 | 2 | 4 |
"machine.util.PeopleMap.toEnd()" | 1 | 2 | 2 |
"machine.util.PeopleMap.toString()" | 1 | 1 | 1 |
"machine.util.PeopleVector.PeopleVector()" | 1 | 1 | 1 |
"machine.util.PeopleVector.putPerson(Person)" | 1 | 2 | 2 |
"machine.util.PeopleVector.putPerson(Person,String)" | 1 | 2 | 3 |
"machine.util.PeopleVector.toEnd()" | 1 | 3 | 3 |
"util.MultiMap.MultiMap()" | 1 | 1 | 1 |
"util.MultiMap.get(K)" | 1 | 1 | 1 |
"util.MultiMap.isEmpty()" | 1 | 1 | 1 |
"util.MultiMap.put(K,V)" | 1 | 2 | 3 |
"util.MultiMap.removeByKey(K)" | 1 | 1 | 1 |
"util.MultiMap.removeValue(K,V)" | 1 | 2 | 2 |
"util.MultiMap.toString()" | 1 | 1 | 1 |
"util.MultiMap.values()" | 1 | 1 | 1 |
加粗的兩個方法複雜度飄紅了,仍是蠻高的,一個是與以前同樣的getNewMajorRequest方法,獲取新的主請求,由於遍歷對象,還有判斷person的邏輯比較複雜,因此複雜度很高;
相比上回的改進是getNewInstruction方法複雜度已經沒那麼高了,由於將一部分邏輯引導到了person類中。
另外一個是person類的setMid方法,其做用是設置person的中轉目的地,由於拿取了兩個stage對象並循環調用對象isReachable函數判斷,因此複雜度較高,但並非過高,只是剛剛超出。
Class | OCavg | WMC |
---|---|---|
"Main" | 1.00 | 1 |
"machine.Scheduler" | 1.75 | 7 |
"machine.elevator.Dispatcher" | 3.88 | 31 |
"machine.elevator.Elevator" | 1.91 | 21 |
"machine.elevator.Elevator.Format" | n/a | 0 |
"machine.elevator.Stage" | 1.70 | 17 |
"machine.elevator.StageFac" | n/a | 0 |
"machine.input.Person" | 1.94 | 33 |
"machine.input.Person.Side" | n/a | 0 |
"machine.input.Person.Status" | n/a | 0 |
"machine.input.TransferRequest" | 2.00 | 4 |
"machine.instr.Instr" | n/a | 0 |
"machine.instr.Instr.Type" | n/a | 0 |
"machine.instr.Instruction" | 1.00 | 3 |
"machine.output.Output" | 4.50 | 9 |
"machine.util.PeopleMap" | 1.92 | 23 |
"machine.util.PeopleMap.Type" | n/a | 0 |
"machine.util.PeopleVector" | 1.50 | 6 |
"util.MultiMap" | 1.38 | 11 |
Dispatcher類有點積重難返的意思,目前架構是這樣了,固然,Dispatcher類徹底能夠把功能分散到其餘類中,最後讓他起組合搭橋的做用,就是把以前就描述的DIspatcher類的四個函數分離開來,變成新的類的處理邏輯,這樣,應該能夠顯著減小他的複雜度把;
Person類WMC太高的緣由是方法太多了,獲取成員、判斷進出、判斷上哪個電梯,這麼多內容夾雜在一塊兒,內部還有其餘的工具函數,致使Person類複雜度很高,若是重構,能夠把新的person類變成幾個接口的組合,一個獲取ID、FROM、TO的藉口,一個判斷進出相關工具函數的接口,或者單獨開個類,處理人員是否須要進出和向上哪個電梯的類,後者讓person專職其責,也能下降複雜度,更好一點把。
Output類。。不用說了。
從架構上來講,個人程序在線程間的數據安全上,是沒有問題的,因此bug主要出如今我某一個步驟沒有完成,好比在寫的過程當中de出的一個bug,人從電梯裏出來要從電梯內部的隊列中刪除,若是沒有刪除,致使一我的會出電梯數次,諸如此類,我犯得bug都是這樣的錯誤,這些bug的主要緣由是個人數據結構類設計的不夠好,使用時頭腦也不清晰,可變數據的壞處就在這,必須時時考慮數據該怎麼變化遷移,或是添加或是刪除。
除了上述說的,我還犯得的一個bug就是主請求選擇bug,第三次電梯裏,主請求選擇沒有考慮人滿員的情況,選了outside的人,致使電梯日門,哭。/(ㄒoㄒ)/~~
我從表達式求導做業完成後,就一直比較在乎這個問題,就是程序的架構,還有代碼的複雜度,因此在電梯做業的編寫中,我就一直作着我反覆說的東西,就是分離分離再分離,將邏輯分散開來,固然,不能是隨意地平行散列邏輯,應該是有所關聯結構,按照層次化的方式構建起來的,不斷將邏輯解耦,就是我在寫程序中反覆思考的內容,爲此,我寫這部分程序動輒刪除或者重寫,可是因爲經驗和能力的不足,依然沒有設計出真正健壯、低耦合、複雜度低的架構,好比個人數據結構類,設計的仍是讓我很不滿意,也增添了我其餘使用該類的方法的複雜度,這是從此須要改進的,另外個人OO工程寫得實在是太慢了,從週六晚寫到週二早,第二次電梯第三次電梯都是這樣,第一次也少不了多少,,仍是小將想指揮全軍,能力不足啊。