本文在中科大軟件學院孟寧老師的指導下完成,意在經過對小型程序的分析來幫助體會軟件工程方法、思想。git
本文的參考資料及資源來自:軟件工程——碼農的自我修養。程序員
有關VS Code的安裝配置能夠參考該資料:https://mp.weixin.qq.com/s/sU9Wh12JZqQyJfEBBafFAQshell
在本文中,咱們對此進行簡單介紹。咱們能夠在VS Code官網下載,它是一款免費的輕量級IDE,經過擴展插件能夠支持多種語言。編程
下載地址:https://code.visualstudio.com/#alt-downloadsjson
在VS Code中,當咱們經過加載擴展插件來實現支持時,它並不會包含語言的編譯器與調試器。這裏所說的編譯器與調試器,對於C++而言,即爲MinGw。安全
C/C++編譯器則爲MinGw: http://www.mingw.org/數據結構
下載完成並安裝後,咱們能夠獲得如下目錄:併發
一般狀況下,在安裝MinGw時,會建議或者要求咱們將其添加到環境變量中。但若是咱們忘記了配置,也能夠經過如下方法手動進行配置。模塊化
首先,咱們須要獲取到MinGw在咱們系統中的安裝位置,如上所示,即爲:C:\MinGw 。函數
以後,右鍵點擊此電腦 -> 選擇屬性 -> 高級系統設置 -> 環境變量,在此處能夠管理咱們計算機的環境變量。咱們找到下方系統變量中的Path選項:
經過編輯Path選項,新建添加新環境變量地址,填入上述安裝位置。須要注意的是,咱們此時需填入C:\MinGw\bin。
以上即爲C/C++編譯器的環境安裝配置過程。對於其餘語言,如Java、Python、Golang,咱們都可以採用此種方法。
咱們能夠經過命令提示符查看MinGw的安裝是否成功,使用gcc -v指令:
在VS Code左側擴展選項中,咱們搜索C++便可搜索到插件,點擊Install後便可安裝完成:
VS Code經過 task.json 配置文件來獲取編譯程序的方式,經過修改task.json就能夠利用VS Code進行gcc編譯源碼了。
一個參考的task.json文件配置以下:
{ "version": "2.0.0", "tasks": [ { "type": "shell", "label": "gcc build active file", "command": "gcc", "args": [ "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}"// ], "group": { "kind": "build", "isDefault": true } } ] }
關於task.json的格式,能夠參考如下文檔:https://go.microsoft.com/fwlink/?LinkId=733558
VS Code經過launch.json配置文件中的配置來調用調試器對程序進行調試。經過快捷鍵Ctrl+Shift+P,搜索launch.json,能夠打開launch.json進行配置。
一個參考的launch.json的配置文件以下:
{ "version": "0.2.0", "configurations": [ { "name": "gcc build and debug active file", "type": "cppdbg", "request": "launch", "program": "${fileDirname}/${fileBasenameNoExtension}", "args": [], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ], "preLaunchTask": "gcc build active file", "miDebuggerPath": "C:\\MinGW\\bin\\gdb.exe" // 此處爲上述的MinGw安裝地址 } ] }
關於launch.json文件的配置,能夠參考如下文檔:https://go.microsoft.com/fwlink/?linkid=830387
能夠看到,運行如下示例成功,說明環境配置成功!
良好的註釋風格,能夠幫助代碼閱讀者、維護者等人員快速明確地瞭解到代碼所實現的功能等,方便Debug。一個優秀的代碼註釋風格以下,這是孟寧老師所給出的案例,很是值得學習:
從中,能夠清楚地看到,這個文件中的代碼的文件名、做者、模塊名、語言類型、運行環境、版本時間以及描述等,對咱們理解代碼十分有幫助。
模塊化(Modularity)是指,在指軟件系統設計時保持系統內各部分相對獨立,以便每個部分能夠被獨立地進行設計和開發。這樣使得咱們在開發過程當中,每個模塊都執行本身單一的功能目標,能夠獨立於其餘軟件模塊,這樣也就方便了開發人員之間的配合。
模塊化的基本原理是關注點的分離(Soc,Separation of Concerns),翻譯成中文其實大概即是「分而治之」。
在實際的軟件設計開發中,咱們通常使用耦合度(Coupling)和內聚度(Cohesion)來做爲軟件模塊化程度的高低,它們一樣是判斷一個軟件設計優良程度的重要參考。
耦合度,是指一個軟件中各個模塊之間的依賴程度,從高到低在大體上能夠分爲緊密耦合(Tightly Coupled)、鬆散耦合(Loosely Coupled)。咱們所追求的是鬆散耦合,它代表咱們所設計的軟件各個模塊的依賴程度較低,是比較好的設計。
內聚度,是指一個軟件模塊內部各類元素之間互相依賴的程度。理想的內聚是功能內聚,也即一個模塊只作一件事,只完成一個主要功能。
在實現模塊化設計時,咱們能夠將多種數據封裝成結構體、將實現功能封裝成一個文件,能夠幫助咱們簡化代碼:
在上圖中,咱們將數據結構以及函數聲明放在一個linklist.h的頭文件中,其實現放在linklist.c文件,須要調用時再在main函數中去調用,這樣就實現了較低的耦合度,也方便咱們做爲程序員去debug。
接口是通訊雙方共同遵照的一種規範,在軟件系統內部通常的接口方式是經過一組API函數來約定軟件模塊之間的溝通方式。面向對象與面向過程的語言在對接口的是實現通常不相同。前者的接口是對象對外開放的一組屬性和方法的集合;後者則是數據結構和操做這些數據結構的函數等。
上圖借用了孟寧老師提供的工程源碼文件中的某個源碼文件。在這個文件中,能夠看到其聲明瞭許多接口,這些接口的實現會放在.c文件中。但不經過具體的實現代碼,咱們依然能夠經過接口的名稱、參數、返回值以及相關描述瞭解到大概的功能,這些接口的也能夠被屢次重複使用,提升了代碼的複用性。
線程(thread)是操做系統可以進行運算調度的最小單位。它包含在進程之中,是進程中的實際運做單位。一個線程指的是進程中一個單一順序的控制流,一個進程中能夠併發多個線程,每條線程並行執行不一樣的任務。
線程安全問題都是由全局變量及靜態變量引發的。若每一個線程中對全局變量、靜態變量只有讀操做,而無寫操做,通常來講,這個全局變量是線程安全的;如有多個線程同時執行讀寫操做,通常都須要考慮線程同步,不然就可能影響線程安全。
可重入(reentrant)函數能夠被多個線程併發執行,而一般不會致使因爲共享數據而致使結果錯誤;不可重入函數則在多個線程併發執行時,若是不能保持線程互斥,那麼就會致使結果的錯誤。對於軟件工程而言,咱們應該以比較悲觀的方式去評估函數:便可重入函數不必定是線程安全的,多是線程安全的函數就不是線程安全的函數,不可重入函數必定不是線程安全的函數。
首先,對於線程安全,咱們所關注的焦點通常在如下幾個方面:
i. 全部的函數是否是都是可重入函數:分析函數有沒有訪問臨界資源,如有則必須仔細分析其互斥的處理過程;
ii. 不一樣的可重入函數有沒有可能同時進入臨界區:讀寫互斥應該如何去考慮;
下面,一樣地,經過孟寧老師所給出的代碼,咱們選擇一段代碼來加以解釋:
在須要進入臨界區時,咱們對代碼進行了加鎖操做以確保其餘函數沒法使用臨界區的資源,當咱們退出臨界區後及時解鎖供以其餘函數訪問,最後銷燬互斥鎖,這就是一個典型的線程安全代碼。
孟寧老師於課堂上講解的各個知識點,使我對軟件工程中的開發思想、方法有了更深一步地理解。同時,通過這篇博客的書寫,我對這些知識的理解更上一層樓了,更爲重要的是,動手能力也有所提升,在此深表感謝。
最後,再次強調,參考資料於此:軟件工程——碼農的自我修養