代碼中的軟件工程

本文在中科大軟件學院孟寧老師的指導下完成,意在經過對小型程序的分析來幫助體會軟件工程方法、思想。git

本文的參考資料及資源來自:軟件工程——碼農的自我修養程序員

 1. VS Code開發環境配置

1.1 VS Code 安裝

    有關VS Code的安裝配置能夠參考該資料:https://mp.weixin.qq.com/s/sU9Wh12JZqQyJfEBBafFAQshell

    在本文中,咱們對此進行簡單介紹。咱們能夠在VS Code官網下載,它是一款免費的輕量級IDE,經過擴展插件能夠支持多種語言。編程

    下載地址:https://code.visualstudio.com/#alt-downloadsjson

1.2 C/C++編譯器下載

    在VS Code中,當咱們經過加載擴展插件來實現支持時,它並不會包含語言的編譯器與調試器。這裏所說的編譯器與調試器,對於C++而言,即爲MinGw。安全

    C/C++編譯器則爲MinGw: http://www.mingw.org/數據結構

    下載完成並安裝後,咱們能夠獲得如下目錄:併發

    

1.3 環境變量配置

    一般狀況下,在安裝MinGw時,會建議或者要求咱們將其添加到環境變量中。但若是咱們忘記了配置,也能夠經過如下方法手動進行配置。模塊化

    首先,咱們須要獲取到MinGw在咱們系統中的安裝位置,如上所示,即爲:C:\MinGw 。函數

    以後,右鍵點擊此電腦 -> 選擇屬性 -> 高級系統設置 -> 環境變量,在此處能夠管理咱們計算機的環境變量。咱們找到下方系統變量中的Path選項:

    

    經過編輯Path選項,新建添加新環境變量地址,填入上述安裝位置。須要注意的是,咱們此時需填入C:\MinGw\bin。

    以上即爲C/C++編譯器的環境安裝配置過程。對於其餘語言,如Java、Python、Golang,咱們都可以採用此種方法。

    咱們能夠經過命令提示符查看MinGw的安裝是否成功,使用gcc -v指令:

    

1.4 VS Code中配置C/C++開發環境

1.4.1 加載C/C++擴展

    在VS Code左側擴展選項中,咱們搜索C++便可搜索到插件,點擊Install後便可安裝完成:

    

1.4.2 task.json與launch.json配置

    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

1.4.3 驗證安裝

    能夠看到,運行如下示例成功,說明環境配置成功!

    

    

2. 代碼中的軟件工程思想

2.1 代碼註釋風格

    良好的註釋風格,能夠幫助代碼閱讀者、維護者等人員快速明確地瞭解到代碼所實現的功能等,方便Debug。一個優秀的代碼註釋風格以下,這是孟寧老師所給出的案例,很是值得學習:

    

    從中,能夠清楚地看到,這個文件中的代碼的文件名、做者、模塊名、語言類型、運行環境、版本時間以及描述等,對咱們理解代碼十分有幫助。

2.2 模塊化設計

2.2.1 模塊化原理

    模塊化(Modularity)是指,在指軟件系統設計時保持系統內各部分相對獨立,以便每個部分能夠被獨立地進行設計和開發。這樣使得咱們在開發過程當中,每個模塊都執行本身單一的功能目標,能夠獨立於其餘軟件模塊,這樣也就方便了開發人員之間的配合。

    模塊化的基本原理是關注點的分離(Soc,Separation of Concerns),翻譯成中文其實大概即是「分而治之」。

2.2.2 模塊化程度

    在實際的軟件設計開發中,咱們通常使用耦合度(Coupling)和內聚度(Cohesion)來做爲軟件模塊化程度的高低,它們一樣是判斷一個軟件設計優良程度的重要參考。

    耦合度,是指一個軟件中各個模塊之間的依賴程度,從高到低在大體上能夠分爲緊密耦合(Tightly Coupled)、鬆散耦合(Loosely Coupled)。咱們所追求的是鬆散耦合,它代表咱們所設計的軟件各個模塊的依賴程度較低,是比較好的設計。

 

     內聚度,是指一個軟件模塊內部各類元素之間互相依賴的程度。理想的內聚是功能內聚,也即一個模塊只作一件事,只完成一個主要功能。

2.2.3 模塊化設計:源碼分析

    在實現模塊化設計時,咱們能夠將多種數據封裝成結構體、將實現功能封裝成一個文件,能夠幫助咱們簡化代碼:

    

    

    

    在上圖中,咱們將數據結構以及函數聲明放在一個linklist.h的頭文件中,其實現放在linklist.c文件,須要調用時再在main函數中去調用,這樣就實現了較低的耦合度,也方便咱們做爲程序員去debug。

2.3 軟件模塊接口

2.3.1 接口的定義

    接口是通訊雙方共同遵照的一種規範,在軟件系統內部通常的接口方式是經過一組API函數來約定軟件模塊之間的溝通方式。面向對象與面向過程的語言在對接口的是實現通常不相同。前者的接口是對象對外開放的一組屬性和方法的集合;後者則是數據結構和操做這些數據結構的函數等。

2.3.2 接口的應用

    

    上圖借用了孟寧老師提供的工程源碼文件中的某個源碼文件。在這個文件中,能夠看到其聲明瞭許多接口,這些接口的實現會放在.c文件中。但不經過具體的實現代碼,咱們依然能夠經過接口的名稱、參數、返回值以及相關描述瞭解到大概的功能,這些接口的也能夠被屢次重複使用,提升了代碼的複用性。

2.4 線程安全

2.4.1 線程的基本概念

    線程(thread)是操做系統可以進行運算調度的最小單位。它包含在進程之中,是進程中的實際運做單位。一個線程指的是進程中一個單一順序的控制流,一個進程中能夠併發多個線程,每條線程並行執行不一樣的任務。

2.4.2 可重入與線程安全

    線程安全問題都是由全局變量及靜態變量引發的。若每一個線程中對全局變量、靜態變量只有讀操做,而無寫操做,通常來講,這個全局變量是線程安全的;如有多個線程同時執行讀寫操做,通常都須要考慮線程同步,不然就可能影響線程安全。

    可重入(reentrant)函數能夠被多個線程併發執行,而一般不會致使因爲共享數據而致使結果錯誤;不可重入函數則在多個線程併發執行時,若是不能保持線程互斥,那麼就會致使結果的錯誤。對於軟件工程而言,咱們應該以比較悲觀的方式去評估函數:便可重入函數不必定是線程安全的,多是線程安全的函數就不是線程安全的函數,不可重入函數必定不是線程安全的函數。

2.4.3 線程安全:代碼分析

    首先,對於線程安全,咱們所關注的焦點通常在如下幾個方面:

      i. 全部的函數是否是都是可重入函數:分析函數有沒有訪問臨界資源,如有則必須仔細分析其互斥的處理過程;

      ii. 不一樣的可重入函數有沒有可能同時進入臨界區:讀寫互斥應該如何去考慮;

    下面,一樣地,經過孟寧老師所給出的代碼,咱們選擇一段代碼來加以解釋:

    

    在須要進入臨界區時,咱們對代碼進行了加鎖操做以確保其餘函數沒法使用臨界區的資源,當咱們退出臨界區後及時解鎖供以其餘函數訪問,最後銷燬互斥鎖,這就是一個典型的線程安全代碼。

3. 總結

    孟寧老師於課堂上講解的各個知識點,使我對軟件工程中的開發思想、方法有了更深一步地理解。同時,通過這篇博客的書寫,我對這些知識的理解更上一層樓了,更爲重要的是,動手能力也有所提升,在此深表感謝。

    最後,再次強調,參考資料於此:軟件工程——碼農的自我修養

相關文章
相關標籤/搜索