摘要:不要小看乙份程式設計指南,它真的很有講究……
開發人員往往只關注程式的功能是否正確,而忽視質量的其它屬性。至於程式設計指南(或者程式設計規範),很多程式設計師更是覺得沒有必要遵循:我不遵守這些指南,程式不是執行的也很好嗎?
實際上,**不僅僅是被機器執行的,還是給人看的。不遵循指南的**,可讀性差,不利於理解,因此不利於維護。而軟體維護成本通常佔整個生命週期成本的40%~80%。
反對程式設計指南的人還可能會提出如下的一些理由:
剛開始的時候會帶來這樣的感覺,但長期來看,無論從團隊協作還是長期收益來看,遵循指南是非常有益的。可以模擬一下交通規則:從個體上看,許多交通規則是非常煩人的,浪費時間。但從群體角度看,這些交通規則不僅可以提公升總體效率,還可以避免交通事故,保障人身安全。許多交通規則,都是在初期引起人們的反感,但較長一段時間之後,才體會到了它的好處。
2)程式設計是藝術創造,不能約束太多:前半句可是演算法的上帝donald knuth講的。
程式設計過程具有雙重性:微觀上的藝術性,與巨集觀上的工程性,期間不僅需要有創新,還需要有約束。尤其當軟體逐步成為人類文明的載體時,巨集觀上的工程需求更加重要。個性再明顯的程式設計師,也需要逐步適應。python發明人加入谷歌後,也曾經因為**可讀性不足被拒絕將**合入**庫。
3)程式設計指南本身有意義,但實施太困難:要讓企業中所有的開發人員都完全掌握程式設計指南,是一件困難的事情。尤其是企業裡的人員通常處於變動狀態,總有程式設計新手持續加入。這給指南的實施帶來了非常大的困難。
近年來,隨著**分析技術的不斷進步,通過**檢查工具自動發現違反程式設計指南的**,進而推動程式設計指南的落實,正在成為乙個大趨勢。許多公司的實施效果非常顯著,大大提公升了**的質量。
正因為程式設計指南如此重要,一些大型公司紛紛頒布了程式設計方面的系列指南。不僅如此,一些行業組織也制定了行業特有的指南。例如:misra c是由汽車產業軟體可靠性協會(misra:motor industry software reliability association)提出的c語言開發標準指南,以增進嵌入式系統的安全性及可移植性。只有符合misra 指南的軟體才可以在汽車領域進行應用。misra c一開始主要是針對汽車產業,後來許多其他行業也逐漸開始使用misra c,包括航空、電信、國防、醫療裝置、鐵路等領域中都已有廠商使用misra c。
程式設計指南主要可以分為兩大類:風格類與程式設計實踐類。
風格類指南包括識別符號的命名、格式以及注釋風格等。此類指南引導開發團隊使用統一的**風格進行開發。一致的編碼習慣與風格,會使**更容易閱讀、理解,也更容易維護。需要注意的是,對於開源專案,如果在**風格類指南上有衝突,原則上遵從開源專案原本的**風格要求。
• 命名類條款要求識別符號的命名要清晰、明了,含義明確容易理解,軟體專案內部應具有統一的命名風格。例如駝峰風格的命名是近年來多數企業推薦的命名方式。符合閱讀習慣的命名將明顯提高**可讀性,統一的命名風格更加有利於**的理解和維護。
• 格式類條款建議在同乙個專案中使用統一的排版格式風格,以便所有人都能夠輕鬆的閱讀和理解**,增強**的可維護性。例如使用空格進行縮排,每次縮排4個空格。
• 注釋類條款建議在需要的時候,對邏輯較為複雜或者易於讓讀者產生困惑的**,輔以注釋加以說明。注釋是為了幫助閱讀者理解**,所以要從閱讀者的角度出發按需注釋。例如「**注釋置於對應**的上方或右邊」。注釋內容要簡潔、明了、無歧義,資訊全面而不冗餘。注釋跟**一樣重要,修改**時也要保證其相關注釋的一致性。只改**,不改注釋是一種不文明行為,破壞了**與注釋的一致性,讓閱讀者迷惑、費解,甚至誤解。
程式設計實踐類指南包含程式語言特性相關的條款,比如資料型別、常量與變數的使用,表示式、語句,函式設計與使用,資源管理以及錯誤處理等。這類程式設計實踐有些具有一定的時效性,比如語言的新特性。對於趨於成熟的語言新特性,程式設計指南會引導開發人員從使用舊特性的程式設計方式向使用新特性轉變,對於這類場景給出最佳實踐作為參考,其中引導、建議的成分居多。但是,隨著時間的推移,新特性的使用也可能逐步轉變成更加嚴格的要求條款。程式設計實踐類指南中,健壯性與安全性尤其受到人們的關注。
• 健壯類條款側重於提公升軟體產品本身的質量屬性,比如健壯性、可維護性、執行效能等。這類指南通過在語言本身的語法之外新增額外的合理限制,來避免語言本身或者開發人員無意疏漏導致的意外錯誤。比如「」確保列舉常量對映到唯一值」這一條款,雖然程式語言本身可能允許乙個列舉中的項具有重複的值,但是這違反了人們對於列舉的自然期望,而且往往意味著不良的設計,進而導致一些不易發現的錯誤。
• 安全類條款側重於軟體的安全性,主要通過列舉可能導致安全隱患的危險場景,結合導致安全風險的示例,要求開發人員避免使用不安全的方式編寫**。比如「禁止外部可控資料作為程序啟動函式的引數」這一條款,舉例說明了將外部可控輸入資料直接傳遞給程序啟動函式,導致程式產生注入漏洞。隨後給出了如何避免此類風險的多種可行方案,引導開發人員正確進行安全編碼。
針對不同的場景,每一條程式設計指南條款的目標、範圍以及適用性都略有不同。總體上來說,程式設計指南把所有的指南條款分為原則類和規則類兩個類別。
原則類條款通常是對適用於某個較典型的開發場景或語言特性中的一類指南條款的概括,或者是對於不存在明確的標準的場景,給出指導性建議。比如「識別符號命名應符合閱讀習慣」這樣的原則,是否符合閱讀習慣是比較主觀,但是盡量讓識別符號命名有意義,符合自然語言使用習慣可以極大地提高**的可讀性和可維護性。
• 要求:表示開發團隊原則上應該遵從,違反要求類條款往往會導致軟體產品的潛在質量、安全以及可移植性等問題。比如「定義巨集時,要使用完備的括號」這條要求條款,如條款所言「巨集展開時只做文字替換,在編譯時再求值。文字替換後,巨集包含的語句跟呼叫點**合併。合併後的表示式因為操作符的優先順序和結合律,可能會導致計算結果跟期望的不同」。違反此條款往往意味著程式的正確性無法保證。
• 建議:**風格類多屬於這類條款,除此之外通常表示條款屬於最佳實踐,有助於進一步降低風險或優化**。建議類條款作為優秀的實踐經驗的總結,通常是被廣為接受的,但也並非就是唯一的正確選擇,開發團隊可結合具體實際情況考慮是否採納。比如「行寬不超過120個字元」這條建議條款,從最早的行寬80到現在的120,具體的行寬要求也是順應著開發人員的顯示器或編輯器的可顯示能力的變化而調整的。具體採用行寬80、120還是其他合理的值都是可以的,具體要看開發團隊的實際情況。
最理想的情況,是所有的開發人員都通過學習,掌握了程式設計指南的內容,然後編寫出的**都符合指南。但上述場景終歸只是個理想。因為開發人員很難完全掌握內容繁雜的程式設計指南,尤其對於新手,經常會忘記部分指南的內容。這導致他們編寫的**裡面不可避免的存在或多或少的違反程式設計指南的內容。
對於這些違反程式設計指南的**,**檢視是發現它們的重要手段。可以說,審核**是否符合程式設計指南,是**檢視的核心內容之一。開展**檢視的人員,通常是經驗豐富的開發人員,對於指南內容的掌握也更加深入。
對於**檢視人員,其實他們也很難掌握指南的全部。尤其是對於資源洩漏等複雜的場景,人工檢查效率很低。這時候,自動檢查工具就可以發揮較大的作用了。當然,部分指南的內容過於籠統,還是需要人工檢視人員。例如,類似「識別符號命名應符合閱讀習慣」這樣的內容,目前工具識別的準確率還不夠高,主要需要依賴檢視人員來發現。
基於現有的**分析技術,研發人員綜合運用語法樹、資料流分析、控制流分析、指標分析、符號執行、約束求解等技術,開發出了許多**檢查工具,以自動地發現違反程式設計指南等規則的缺陷**。華為公司在長期的**檢查實踐過程中,結合研發側對程式設計指南落地的訴求,研發了自己的**檢查系統codecheck( codecheck.html),並在檢查引擎的選擇、研發上積累了大量的經驗和教訓。
**檢查工具是否能融洽地整合到開發人員的工作流程中,往往會成為**檢查工具落地的門檻。華為倡導根據開發人員在編碼、入庫、持續整合階段對檢查速度與能力的要求不同,在不同階段配置不同的檢查規則,以較好地兼顧開發人員對檢查時間與檢查能力的要求。
• ide:編碼階段是最早的缺陷檢查時機,可以利用ide外掛程式實現檢查功能。但由於一些缺陷的檢查(例如資源洩露)需要對**進行全量分析才能準確發現,而且耗時很多,因此這個階段不用對所有的規則進行檢查。
• 門禁:在門禁上做檢查是最重要的時機。一方面,很難保證所有的開發人員都自覺地在編碼階段進行檢查;另一方面,**一旦通過了門禁,進入了**庫,就成為公司資產的一部分,並可能被大量地複製。這個階段的檢查,也可以被稱為「檢視機械人」,可以幫助 committer 發現一些共性的問題,分擔committer的一些低階工作。由於程式設計師對**合入時間比較敏感,因此,非常耗時的檢查規則也不適合在這裡部署。另外,在門禁階段,便於進行增量式檢查,即只檢查新寫的**。
• ci:ci(持續整合)由於頻率低一些,有些甚至可以放在晚上等非工作時間,因此對**檢查時間的容忍度相對高一些,適合部署所有的檢查規則,並對**進行全量檢查。
面對不同的目標受眾,檢查報告內容的角度也是同等重要的!例如普通開發人員需要盡可能多的缺陷詳細資訊;管理人員專注於問題概覽,關注目前的產品是否可以發布,關於整體的問題分布;安全人員專注於**裡漏洞等。
檢查報告裡面通常列出針對某個專案發現的問題資訊。例如:總共發現了多少個問題。這些問題中,致命的有多少,嚴重的有多少,一般的有多少,提示性的有多少,以及問題最多的top檢查規則,等等。點選相關的鏈結,可以進一步檢視更為具體的問題資訊。
針對檢查報告裡面的列出的缺陷內容,通常情況下,開發人員需要逐條修復,然後再次提交審核。
對於部分檢查結果,開發人員可能不採取修復動作,而是對其進行遮蔽。遮蔽的主要原因包括:1)檢查報告中可能存在誤報;2)部分**不適合修改;3)提示性的問題;4)開源**;等等
• 誤報:軟體分析技術面臨的核心挑戰之一是精確性與**規模不可兼得。例如,為了在有限的時間內返回檢查結果,許多任務具不進行路徑敏感等深度的分析。這將導致結果中包含一些漏報與誤報。因此開發人員發現某條報告中列出的檢查結果是誤報時,可以對其進行遮蔽。
• 不適合修改的**:多數是為了避免執行效率的降低,對於不嚴重的問題,可以不做修改。
開發人員基於**檢查系統提供的「申請遮蔽」入口,可以在系統中記錄下遮蔽資訊,下次系統就不再報出這個問題了,以減少對開發人員的干擾。對於開發人員提交的申請遮蔽資訊,通常需要有專門的人員進行審核,以保障遮蔽的合理性。
點選關注,第一時間了解華為雲新鮮技術~
這可能是不可取的!
雖然消極期望功能的一部分,我們給它乙個整數而不是。然而,由於分數具有建構函式的願意接受乙個整數,編譯器將使用此建構函式隱式轉換為整數6轉化為分數的物件,然後將其複製到makenegative 初始化引數f.因此,上面的程式列印 6 1 這種隱式轉換為各種初始化 直接 統一和複製 用於隱式會話的建構函...
福利丨所有AI安全的講座裡,這可能是最實用的一場
安全領域攻與防之間的博弈一刻也沒有停止過 無論是實現思路還是技術方法 都在不斷的公升級和突破 如今,將ai應用到雲安全的思路逐漸受到認可 那麼,有沒有一些更加具體方案和落地實踐 告訴安全工程師該如何做?10月21日行業頂級安全技術專家將與你相約深圳 解碼ai與大資料驅動下雲安全的防禦公升級 教你如何...
這可能是退出Activity最優雅的方式了
最近複習安卓的基礎知識,準備面試,發現以前榮哥說過的一種退出所有activity的方法,拿出來和大家分享以下。在網路上找了一下,關閉所有的activity的方式無非以下幾種 記錄每個開啟的activity,退出的時候,關閉每個activity 傳送特定廣播,當應用程式需要關閉的時候關閉乙個廣播告訴a...