開發小結-雜項類

本文總結在平時開發工做中一些雜項零碎知識點。linux

SVN操做

更名操做

  1. 先把該文件從工程中排除掉
  2. 利用svn自身的Rename功能對文件進行重命名
  3. 而後將更名後的文件從新加入到VS工程中去

移動文件

  1. 從svn中,將想要移動的文件經過鼠標右鍵選中而且移動,在目的目錄選擇拷貝到這裏
  2. 從VS項目的文件裏面中,將此文件刪除
  3. 而後在VS項目的目的目錄中,將此文件從新添加進去

更新失敗處理

若在文件正在被佔用時執行svn update,svn會提示更新失敗,此時整個svn狀態不正確,右鍵點擊目錄無正確的入口菜單,能夠經過以下方法來解決:sql

  1. svn是採用sqlite3來管理數據的,所以須要下載 sqlite3 ,並將可執行文件路徑添加到系統的環境變量中
  2. 進入到 .svn的同級目錄,而後執行
  3. sqlite3 .svn/wc.db "select * from work_queue" ---> 看到不少記錄
    sqlite3 .svn/wc.db "delete from work_queue" ---> 刪除這些更新失敗的記錄
    sqlite3 .svn/wc.db "select * from work_queue" ---> 確認是否刪除完畢
  4. 在此運行 svn 的 clean up

通過如上操做,就能清除更新失敗的文件,再從新update一下。安全

查看文件版本信息

  1. 查看項目目錄的右鍵屬性多線程

  2. 查看項目修訂記錄中的記錄,當前標記爲黑色的爲當前項目的版本號異步

JIRA問題單號須要和SVN的提交編號綁定起來,那樣在查找問題時,方便雙向回溯查找。分佈式

問題搜索

看書的時候,帶着問題和本身預期的答案去在書中查找對應的知識點,或印證,或增強,或反思。對於好的東西,咱們不光要學習,並且要把它內化爲本身的東西。咱們要學習別人的先進經驗,辦事方法,但在運用中要實事求是,具體問題具體分析。svn

以尋找解決"獲取操做系統所在磁盤分區信息"方案爲例子,在剛開始時,我犯了一個錯誤具體表現爲,沒有將注意力關注於問題域,而是在網上大範圍的搜索獲取磁盤信息作法,在找到的這些通用作法中,不只會有須要的內容,也有大量不須要關係的內容。在面對這些內容,本着多學一點是一點的心態,開始寫些demo來學習,但作到後面,愈加以爲距離最原始的問題愈來愈遠。就算把整個相關知識點所有吃透,再回到原始問題上,花費的精力至關於殺雞用牛刀。雖然說最終仍是解決了問題,但從時間和效率上,還有大大的優化的空間。函數

反思下,之後在針對問題進行方案搜索時,要先定義問題域範圍而且瞭解基本背景知識。而後,針對待解決的問題,只搜索關聯度高的網頁,大體瀏覽一片,若覺的合適,則可寫些測試代碼,這裏的測試不要摻雜與待解決問題無關的代碼,只關心待解決的問題,能簡則簡。工具

效率提升點

在進行會議討論(需求討論、方案論證等)時,就討論的問題,陳述的中心思路是講解問題的背景、問題的現狀、問題的困難點,而不是講述本身對該問題心中默認的結論,咱們討論的是問題,而不是問題提出者的結論。學習

工做用到的IDE,最多隻能打開兩個,在一個IDE中完成一個任務後,若是沒有其餘的任務,要關閉它。防止在太多IDE中切換,耗費無用時間,就像進程調度同樣,進程切換的成本很高,不管是機器仍是人,都要一段時間才能進入全速運行狀態。

刪除Dll時提示被佔用

在 Windows 下面刪除dll時,提示被系統使用,沒法刪除。較好的思考路徑是:

1. 找到該 dll 被哪一個進程佔用?
   Windows下可使用 tasklist /m XXX.dll 來找
2. 在任務管理器中,暫時停止該進程(若是是窗口管理器佔用,那麼停止後,任務欄會消失)
3. 經過 dos 命令來刪除文件和文件夾(刪除文件使用 del, 刪除空文件夾使用 rd)

代碼小技巧

針對動態空間的,若已知空間大小,可使用

int nReqSize = 1024;
string strBuf(nReqSize, ' '); 
char* pReqBuf = (char*)strBuf.c_str();

do...while(false),配合break可實現相似goto的功能,用於簡化多級判斷代碼的跳出處理。

do{

    if (condition1)
        break;
    
    if (condition2)
        break;
    
}while(0)

在一系列計算的中間過程,只要有一處臨時變量在計算過程當中,可能超過相關數據類型可以表達的最大範圍,那麼最終結果就極可能會出錯,這種錯誤很難發現,要知足特定的場景纔會發現,在後續涉及到較大數量的計算時,必定要注意。

利用靜態代碼檢查工具cppcheck,cpplint來輔助檢查你的代碼。針對資源泄露的問題,注意相關資源申請和釋放函數的配對使用

調試經驗

  • 在須要查看數據發送內容,而又不想經過斷點來中斷執行流程,能夠經過 VS 的 條件斷點 配合特定的條件,在調試輸出窗口中查看收發內容。

  • 找內存泄漏:根據vld輸出的信息,找到泄露內存的具體字節數和內存分配序號,而後在 dbgheap.c 文件中的 391 行出 打上條件斷點,經過申請的具體字節數來大體定位是哪個文件上申請了內容,能夠大體定位內存泄漏的源頭。

  • 描述類與類,窗體與窗體之間的相互交互的關係,最好用序列圖來描述。流程圖中異步處理,可經過帶箭頭的虛線來表示異步響應的流程。

  • 永遠不要混合Tab鍵和Space鍵。 VS設置,將TAB鍵轉換爲4個空格
  • 在程序中,全角和半角英文混用,容易形成顯示不一致,在設計的時候要注意。

  • 在工程實踐中,多線程開始初始化以前,對整個工程中所涉及到的單例按照先後的邏輯順序,完成手動的初始化,這可避免首次調用時的不肯定性,簡單明確。

  • 當一個條件判斷(if,while)比較複雜,而且是隱含有必定的業務背景知識的,必定要寫好註釋,不只是給本身方便,也是給其餘人方便.

  • 從接口中返回const char*指針給外部的string變量,所對應的一塊內存是如何響應外部變化的?其實是調用 string::operator=(const _Elem* _Ptr) 賦值構造函數來完成對應地址內容的拷貝的.

  • 提示:在VS調試,沒法進入到stl的內部函數中去,由於用到 破解的VS助手,把VS助手給禁用掉,從新啓動VS,就能夠調試進入stl內部。

  • 發佈給別人的軟件,必定要先在本身虛擬機上面跑一次,防止一些軟件依賴的dll在用戶機器上沒有,啓動時爆出「未找到 mfc100.dll」的問題。多在本身本地測試下,確保在各類狀況下正確後,再交付給用戶。

  • C++自己提供了四種標準異常: 只能經過 傳值 或者 引用 來捕獲, 傳值捕獲異常,會將異常對象拷貝兩次,效率較低。

    bad_alloc --> operator new 不能分配足夠內存時拋出
    bad_cast --> 當 dynamic_cast 針對一個引用reference操做失敗時,拋出
    bad_typeid --> 當 dynamic_cast 對空指針進行操做時,拋出
    bad_exception --> 用於 unexcepted 異常

    總結:優先使用傳引用來傳遞異常

  • 對象構造要作到線程安全,要求在構造函數期間,不對外暴露this指針。做爲class數據成員的mutex,只能用於同步本class的其餘數據成員的讀和寫,它不能安全的保護析構.由於類成員的生命週期最多與對象同樣長,而析構動做發生在對象銷燬之時。

二進制兼容性

二進制兼容性指的是在升級庫文件時,沒必要從新編譯使用了這個庫的可執行文件或者其餘庫文件,程序的功能不被破壞。

C++二進制兼容性,在於以虛函數做爲庫接口時,更新庫接口後調用的不肯定性。本質在於虛函數是以vtable[offset]方式實現虛函數調用,offset又是根據虛函數聲明的位置隱式肯定,一旦新舊版本的虛函數相對位置有變化,就可能帶來兼容性問題。

解決方法:

  1. 可使用 靜態連接

  2. 用 pimpl 技法: 在頭文件中只暴露 non-virtual 接口,而且class的大小固定爲 sizeof(Impl*),這樣能夠隨意更新庫文件而不影響可執行文件。

在什麼場景下,須要考慮二進制兼容性? 當你是一個shared library的維護者,你提供的庫被其餘團隊、其餘公司、其餘社區所使用時,須要考慮。這裏面有兩點:共享庫的維護者,而且該庫被不受你控制的團隊所使用。

若是隻是開發團隊內部特定場景下特定功能的庫,使用範圍較窄能夠不用太在乎二進制兼容性,發佈新版本(修復Bug或者增長功能),通知外部使用者從新編譯,使用便可。

修補Bug的patch應該作到二進制兼容,好比1.1.1應該和1.1.0,兼容,修復了一些bug,或者增長不影響二進制兼容的功能若是新增功能與原有版本的二進制不兼容,那就應該發佈到1.3.0版本上去。

若是須要hot fix,那麼必定要發佈爲動態庫,不然,在分佈式系統中使用靜態庫更容易部署。

做爲一個庫來講,以什麼方式暴露庫的接口?通常來講有如下三種方式:

  1. 以全局(含namespace級別)的函數爲接口

  2. 以class的non-virtual成員函數爲接口,內部輔以 pimpl(pointer to implementation) 來提供具體實現。<-- 推薦採用這種方式,能夠確保二進制兼容性
    並考慮多采用 non-member,non-firend function in namespace 做爲接口,對外暴露的接口不要有虛函數,不要有數據成員。

  3. 以class的virtual函數爲接口(interface),客戶端繼承這個interface,而後將對象實例註冊到庫中,由庫來回調本身

Debug和Release庫兼容性

  • 在Windows上,好比Visual C++編譯的時候要選擇Debug或者Release模式,並且Debug模式編譯出來的library一般不能在Release binary中使用,反之亦然。這是由於在這兩種模式下的CRT二進制不兼容,主要是內存分配方面的,Debug有本身的堆。

在linux下,編譯時涉及到調試的選項爲 -g,增長調試開關宏-DDEBUG,編譯發佈版本時,通常加上 -O3 ,而後利用strip,去掉調試信息.
從這上面來看,linux下的庫是不區分Debug模式和Release模式,只不過是運行效率的不一樣而已。

配置文件實時更新讀取

要作到修改配置文件可以實時生效,要作到兩點:

  1. 當配置文件被外部修改時,要主動向外投遞"配置已改動"的消息,相關進程要被動。

  2. 本模塊針對得到配置文件數據的數據時,在本地不維護配置屬性副本,每次使用時,主動從配置文件接口中去讀取。

字體配置

好比,目前A處和B處目前顯示字體都是微軟雅黑字體ID,如今來需求了:要求B處顯示爲微軟雅黑加粗字體,怎麼作比較好?

方案一:每個字體ID都在配置文件裏,若要顯示爲對應加粗字體,那就新增一個字體配置。若是存在多種字體風格配置文件,那麼在每一個配置文件中都須要添加該新增字體。

優勢:現有獲取字體邏輯不變,新增字體對應新增字體ID而已。

缺點:每新增一個與現有字體樣式風格差異很小的字體,都要在衆多配置文件中新增。

方案二: 基礎默認字體這三五種,在不新增字體種類的狀況下,提供一個 GetBoldFont(nFondId, BoldFont)接口函數,可將基礎字體顯示風格微調,有其餘屬性,能夠增長其餘微調接口。

優勢:在不新增字體種類的狀況下,增長靈活性,若是有其餘風格類型的字體需求,直接使用該函數便可。

缺點:在得到加粗字體,須要使用特定的函數來實現。

我的認爲,方案二是較好的方式。基礎數據提供一套,微調接口提供一套,外部可任意組合實現自定義需求。

界面數據請求

當有一個界面,須要請求數據A,數據B。又有一個新界面,也要請求數據A,數據B,再來了一個新界面,也要請求數據A,數據B。如何減小重複請求代碼?

整體思想:將各個界面重複性的請求代碼邏輯抽離出來,抽離出來放在哪裏呢?
有兩個選擇,一是放到基類中去,二是放置在獨立實現中。

方案一會在基類業務中混雜具體的業務數據請求邏輯,原本基類應該是業務無關的,加上去會混淆職責,之後有新的通用數據需求,可能還會增長到基類中,久而久之,基類會愈來愈龐大,不利於維護。

方案二,將通用的操做放到獨立數據收發類中去,對外提供統一接口,具體來講,各種數據的請求接口是相似的,細分需求可經過傳參來區分。不一樣界面對數據的響應處理是互不相同的,所以,響應的處理要抽離成虛函數,留給各個界面去處理。各個業務界面繼承該數據收發類,重載響應虛函數便可。

方案三:將通用的操做放到獨立數據收發類中去,對外提供統一接口,可是,數據收發類和具體的業務類之間是經過注入的方式完成關聯,每一個請求關聯一個發送請求頁面的指針,當數據返回時,請響應數據回調給發送請求頁面便可。

我的認爲,方案二和方案三都有適用場景,須要具體問題具體分析。

相關文章
相關標籤/搜索