代码中的软件工程

本文基于孟宁老师所授课程——高级软件工程,以VS Code + GCC工具集为主要环境编译调试课程项目案例,结合代码分析其中的软件工程方法、规范或软件工程思想。

参考资料:https://gitee.com/mengning997/se/blob/master/README.md#%E4%BB%A3%E7%A0%81%E4%B8%AD%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B

一、vscode配置c++环境

1、下载vscode

下载链接:https://code.visualstudio.com/Download

安装过程:傻瓜式安装,由于本人已安装vscode,安装过程不再赘述

2、安装cpptools工具

打开vscode,按以下步骤操作

1、点击扩展图标(extensions)

2、在搜索栏里搜索c++

3、点击install,安装cpptools

3、下载Mingw

下载地址:https://sourceforge.net/projects/mingw-w64/files/

下载的文件:进入网站后不要点击 "Download Lasted Version",往下滑,32位的选择i686开头的文件,64位选择 x86_64位文件,由于我的电脑时64位的,所以我选择的是最新版的 "x86_64-posix-seh"。

安装Mingw

4、配置环境变量

配置好环境变量后重启vscode,

win+R打开,键入cmd,打开控制台,输入gcc -v,验证环境变量是否已经配置成功

如下显示则已配置成功

5、使用简单的.cpp文件配置C++环境

1、新建一个test.cpp文件

2、进入调试界面添加配置环境,选择C++(GDB/LLDB),再选择g++.exe,之后会自动生成launch.json配置文件

3、编辑launch.json文件

 

 

4、返回.cpp文件,按F5进行调试,会弹出找不到任务"task g++",选择 "配置任务",会自动生成 tasks.json 文件

5、编辑tasks.json文件

 

 

 6、运行

  按F5调试,发现完全OK了! 

 

 

二、模块化设计

写代码要小步快跑不断迭代,罗马不是一天建成的,不要期望一撮而就。我们应该采取这种思路,从 hello world 开始不断迭代调试使代码长的越来越像一个命令行的菜单小程序。在孟宁老师的代码中,就充分体现了这种思想。下图为menu代码的各个不同阶段,从简单的输出hello world,到最终形成菜单。

   模块化(Modularity)是在软件系统设计时保持系统内各部分相对独立,以便每一个部分可以被独立地进行设计和开发。这个做法背后的基本原理是关注点的分离 (SoC, Separation of Concerns),是由软件工程领域的奠基性人物Edsger Wybe Dijkstra(1930~2002)在1974年提出,没错就是Dijkstra最短路径算法的作者。

  模块化软件设计应使每一个软件模块都将只有一个单一的功能目标,并相对独立于其他软件模块,使得每一个软件模块都容易理解容易开发。从而整个软件系统也更容易定位软件缺陷bug,因为每一个软件缺陷bug都局限在很少的一两个软件模块内。而且整个系统的变更和维护也更容易,因为一个软件模块内的变更只影响很少的几个软件模块。

  为了体现模块化的思想,孟宁老师在代码lab3-3中引入了接口,将功能的实现与主代码程序分离开来。

   在这个文件夹中,menu.c为主程序,linklist.h为功能实现程序的接口,linklist.c为功能实现的具体代码。主程序通过调用接口中的函数实现自己所需要的功能。好的代码应该实现了松散耦合和功能内聚。

三、可重用接口

  在一个系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。因此接口的设计好坏与泛化能力直接可以体现一个项目的优秀程度。

  如下代码块,MENU程序也设计了好的接口

//linktable.h文件
//LinktableNode结构体只保留了最基本的结点指针,具体的data数据并没有包含,面向抽象不依赖具体
typedef struct LinkTableNode
{
    struct LinkTableNode * pNext;
}tLinkTableNode;
 
/*
 * LinkTable Type
 */
//而inktable这个结构体则在引入头文件的情况下,嵌入了LinkTableNode结构体,并且另外定义了数据头//尾指针以及互斥量,相当于实现了遍历功能和线程保护
typedef struct LinkTable
{
    tLinkTableNode *pHead;
    tLinkTableNode *pTail;
    int            SumOfNode;
    pthread_mutex_t mutex;
}tLinkTable;
 
/*
 * Create a LinkTable
 */
tLinkTable * CreateLinkTable();
/*
 * Delete a LinkTable
 */
int DeleteLinkTable(tLinkTable *pLinkTable);
/*
 * Add a LinkTableNode to LinkTable
 */
int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
/*
 * Delete a LinkTableNode from LinkTable
 */
int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
/*
 * get LinkTableHead
 */
tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);
/*
 * get next LinkTableNode
 */
tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);

四、线程安全

  线程(thread)是操作系统能够进行运算调度的最小单位。它包含在进程之中,是进程中的实际运作单位。一个线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

  线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行读写操作,一般都需要考虑线程同步,否则就可能影响线程安全。

  在代码lab5.2中,我们可以看到代码引入了线程模块。

#include<stdio.h>
#include<stdlib.h>
#include <pthread.h>
#include"linktable.h"

/*
 * LinkTable Type
 */
struct LinkTable
{
    tLinkTableNode *pHead;
    tLinkTableNode *pTail;
    int            SumOfNode;
    pthread_mutex_t mutex;

};

  并且在后续代码中运用到了同步与互斥的思想,从而达到对线程的保护,实现线程安全。

/*
 * Delete a LinkTable
 */
int DeleteLinkTable(tLinkTable *pLinkTable)
{
    if(pLinkTable == NULL)
    {
        return FAILURE;
    }
    while(pLinkTable->pHead != NULL)
    {
        tLinkTableNode * p = pLinkTable->pHead;
        pthread_mutex_lock(&(pLinkTable->mutex));   //P操作
        pLinkTable->pHead = pLinkTable->pHead->pNext;
        pLinkTable->SumOfNode -= 1 ;
        pthread_mutex_unlock(&(pLinkTable->mutex)); //V操作
        free(p);
    }
    pLinkTable->pHead = NULL;
    pLinkTable->pTail = NULL;
    pLinkTable->SumOfNode = 0;
    pthread_mutex_destroy(&(pLinkTable->mutex));
    free(pLinkTable);
    return SUCCESS;
}

五、总结

  通过学习孟宁老师的课程,我明白平时在进行开发时,要时刻注意、深入理解模块化设计、可重用接口、线程安全等方面。这些思想能够指导我写出更加规范可靠的代码。

posted @ 2020-11-10 22:45  木子立口儿  阅读(249)  评论(0)    收藏  举报