組員:陳鴻超
程富瑞
代碼:https://github.com/ChengFR/PairProgramming_SubwayRoute-
一.結對程式設計分析
照片:
(忘了照了,十一大家都回家就算了)
結對程式設計的優缺點:
優點:
- 毫無疑問,兩個人在一起解決一個問題想法更多。比如這次作業站點坐标的确定,之前一個人的時候,想法是手輸或者寫個算法自動計算,當然這個算法就會很難,不一定做的出來。而兩個人在一起商讨時,他突然找到了一張北京站點的經緯表,看到這個我就想到了找一個站點做為中心點(0,0),再找兩個最遠站點,這樣根據他們三個就可以換算出所有站點的坐标。很準确,而且最重要的是簡單多了。
- 配置設定好任務之後,每個人的工作量就比較輕了。
- 互相借鑒學習對方的編碼風格。
缺點:
- 自己的一些想法不能快速準确的傳達給對方。
- 就這次而言,我們兩個人都通讀了完整的代碼,在看到對方代碼時效率難免有些低。
- 畢竟程式設計時不在一起,溝通起來有些麻煩。
個人優缺點:
因為之前用java比較多,是以寫代碼比較注意按功能進行封裝。不過除了課上學到的知識以外,課外知識太匮乏,真的是感覺什麼都不會。
二.如何利用好的設計方法
Information Hiding
對于資訊隐藏,應該在資料建立的階段就建立一種規則,使用一些ID來代表這些資料,當然也要記錄下ID與相應資料的對應關系。在後面的操作中,對輸入都可以轉換為ID,然後對ID進行操作,輸出也用ID表示。隻有在最終展現給使用者的階段才将其轉換為具體的資料。
Interface Design
接口的設計包括兩個方面,一個是在程式設計時為了規範功能相似的類而定義的接口,這類接口的實作重點在于總結出相似類的共同點,然後将共同點其封裝在接口中,讓這些相似的類都根據自身情況去實作這些共同點;另一方面的接口設計則是為了提供給測試和外部程式使用,這方面就要做好封裝的工作,讓每個功能都能獨立運作,不依賴與其他子產品,有正确的輸入就能出正确的結果。
Loose Coupling
對于這一點,主要還是盡量的對各種功能,實作這些功能需要用到的一些代碼都進行封裝,各司其職,盡量減少功能之間的依賴性。讓每一個功能子產品在輸入正确的情況下就能夠産生正确的輸出,而不關心其他子產品是否正确。這樣才能在修改某一功能時盡量不對其他功能的代碼造成影響。
三.契約式程式設計
其實契約式程式設計在大二下的OO課上接觸過,感覺他其實更像是一種程式設計習慣。按照契約式程式設計的要求,每個方法都得有明确的前置條件,後置條件和不變式,其實也就是明确他的輸入、輸出已經中間的實作過程。
優點:通過這種格式化的規定,使用契約式程式設計寫出來的程式,每個方法都會非常容易測試、Debug以及功能修改。而且這樣寫出來的代碼清晰易懂,非常友善以後的維護與功能更新。同時,在最初的程式設計過程中,隻有确定好了這三個條件,代碼寫起來也會簡單很多。
缺點:麻煩,這種程式設計方式限制了方法的靈活度,必需要按照這種統一的格式,有時候還會帶來記憶體和時間的額外開銷。
這我們的作業中,對于那些封裝在内部的各種功能函數,我們沒有使用契約式程式設計這種方式,因為這是我們内部可見的,對格式的要求不高。而在包裝提供給外部調用和測試用的API功能接口時,我們使用了契約式程式設計的方式,前置、後置和不變式都比較統一,這樣友善了對這些接口的了解與使用。
四.Unit test
單元測試這一塊,在寫測試程式時遇到兩個問題,始終是不知道什麼原因,也無法解決,被卡了兩天,雖然寫了測試樣例,但是沒有成功運作過,也不太清楚代碼覆寫率怎樣。
在這裡,無法介紹單元測試的結果,隻能說一下我們遇到的問題與分析。
問題:
在寫好測試程式運作時,一直在報下面這個錯誤。
測試名稱: TestMethod1
測試全名: UnitTest1::UnitTest1::TestMethod1
測試源: g:\軟工\結對項目\pairprogramming_subwayroute--newversion\subwayroute\unittest1\unittest1.cpp:第 12 行
測試結果: 未通過
測試持續時間: 0:00:00.409065
結果 的堆棧跟蹤:
位于 subwayNet::getRouteB() (第 g:\軟工\結對項目\pairprogramming_subwayroute--newversion\subwayroute\subwayroute\subwaynet.cpp: 行中) 42
位于 UnitTest1::UnitTest1::TestMethod1() (第 g:\軟工\結對項目\pairprogramming_subwayroute--newversion\subwayroute\unittest1\unittest1.cpp: 行中) 28
結果 的消息: 未處理的 C++ 異常
在網上找了很多文章,講的都是C#的單元測試,幾乎沒有介紹VS2015中C++單元測試的,更不要說這種問題了,是以隻能自己分析。
分析:
1. 首先我根據他的提示找到了subwayNet::getRouteB()的第42行,這一行隻是調用了calculateRoute類中的一個計算方法。我想是不是這個方法有問題,于是又把測試程式修改了一下,調用了calculateRoute類另外一個不相關的函數,可還是這樣的錯誤,這樣看來就不是函數的原因,而是有其他原因,不過沒找到相關的文章,就先放了放。
2.然後我又注意了一下 未處理的 C++ 異常 這個提示,正好這次我們自己封裝了異常,會不會是因為我們封裝的異常有問題才導緻的這個錯誤?于是我找到較早版本的程式,那裡面還沒有使用異常,建立一個測試程式之後有出現了新的問題,這次竟然連編譯都過不去,錯誤提示如下:LNK 2019 無法解析的外部符号。 我在測試程式中所有調用正常程式的函數都報了這個錯誤。
3. 對于這個LNK 2019錯誤,我在網上看到了很多不同的原因,發現其中一個和單元測試有點關系,講的是什麼函數内聯的問題。不過講的非常少,我隻能大緻推測。因為我們的程式為了防止多次編譯,是以.h檔案中都有#pragma once 。是以在測試程式中所要調用到的類都在正常程式的Main類中編譯過了,而我們的測試程式運作時也要編譯一次。而這些類又隻能編譯一次,是以才帶來了各種各樣的問題。
4. 為了檢測是不是上述編譯問題,我就天真的把#pragma once去掉了,結果連正常程式的編譯都過不去(這裡我也有疑問,我運作的是測試程式,隻調用了幾個功能類,運作時為什麼會提示Main類錯誤呢?難道運作測試程式時也要把原程式運作一遍)。
5. 上述分析就是我這兩天找到的,不過大都是我不太懂的層面的東西,這個單元測試也做不出來了,明天就要回家了,這就算了,國慶快樂\(^o^)/
五.UML
六.程式介紹
(一) 資料的讀取
1. 首先我們定義了兩個結構route和station分别儲存線路和地鐵站的相關資訊。
2. 通過讀取地圖檔案,判斷并儲存下各個線路包含的所有站點,站點的鄰近站點,站點所屬的線路等資訊。
3. 因為要做界面,是以我們要确定各個站點的坐标。這一點我們是寫了一個函數,以天安門東為中心,根據一個站點經緯度表換算出各個站點的大緻坐标,得到一個坐标檔案。然後讀取該坐标檔案儲存各站點的坐标。
(二) 路線的計算
1. 最短路線采用的是廣搜,從起點搜到終點之後再倒推出路線。
2. 對于最短換乘,是通過先周遊目前線路上所有點,沒有的話再從目前路線上第一個點開始進行這樣的循環,找到終點之後倒推出所有最少換乘,然後從中選擇站點數最少的。
3. 對于偏好,我們是記錄下之前調用-b和-c的次數,通過這兩個數判斷-g采用最短路線還是最短換乘。
(三) 異常的封裝
1. 将檔案錯誤,參數錯誤等分裝成異常,在程式中抛出。
(四) API封裝
1. 為了單元測試,我們專門建了一個類subwayNet封裝好了需要用到的幾個功能接口,上述UML圖中有詳細介紹。不過因為測試程式始終運作不起來的原因,這點也沒用到。
(五) 界面設計
1. 因為我倆都是小白,不懂GUI設計。從同學那了解到openGL最簡單之後我們就選擇它。不過還是因為第一次接觸,做的有點醜。
(六) 對不同城市地圖的支援
1. 對于不同城市,隻有按要求提供給我們兩個檔案--地圖檔案和經緯度表,然後指定坐标的中心站點和兩個邊界站點。我們的程式就能夠支援其他城市的地鐵線路查詢,不需要再做什麼太大的修改。