代码中的软件工程——小型命令行项目menu分析
本文基于中科大软件学院孟宁老师的教学指导下,分析小型命令行项目menu中的软件工程方法、规范或软件工程思想。此文将结合源码进行以下几方面的分析:
① 编译和调试环境配置;
② 模块化设计、可重用接口、线程安全
一、编译和调试环境配置
1. 在vscode中安装c/c++插件

2. 下载安装C/C++编译器:MinGW

3. 验证C/C++编译器配置成功
①右键单击“此电脑”,点击“属性”->“高级系统设置”->“环境变量”进入环境变量页面。在下方的系统变量列表中找到“Path”变量并双击进入编辑界面。单击“新建”并将刚刚复制的路径名粘贴上后点击确定,完成环境配置。
②在开始菜单上单击右键,选择“命令提示符”进入命令窗口。输入“gcc -v”查看是否安装成功,若成功显示“gcc version”则表示配置成功。

4. 配置launch.json和task.json文件
tasks.json文件是用来配置编译的,launch.json文件是用来配置调试的

二、模块化设计
1. 模块化的基本原理
模块化(Modularity)是指,在软件系统设计时保持系统内各部分相对独立,以便每一个部分可以被独立地进行设计和开发。最终追求是每一个软件模块都将只有一个单一的功能目标,并相对独立于其他软件模块。
关注点的分离在软件工程领域是最重要的原则,我们习惯上称为模块化,翻译成我们中文的表述其实就是“分而治之”的方法。
关注点的分离的思想背后的根源是由于人脑处理复杂问题时容易出错,把复杂问题分解成一个个简单问题,从而减少出错的情形。
2. 模块化程度
一般通过“耦合度”和“内聚度”来衡量模块化的程度。
①耦合度:耦合度是指软件模块之间的依赖程度,一般可以分为紧密耦合、松散耦合和无耦合。一般在软件设计中我们追求松散耦合。

②内聚度:内聚度是指一个软件模块内部各种元素之间互相依赖的紧密程度。理想的内聚是功能内聚,也就是一个软件模块只做一件事,只完成一个主要功能点或者一个软件特性(Feather)。
3. 源码分析——模块化设计
① 使用数据结构和函数来简化主函数中的代码

② 将数据结构以及其相关的函数单独从主函数所在的C文件中分离出来成为单独的文件


三、软件模块接口
软件模块接口在面向过程的语言中一般是定义一些数据结构和函数接口API,在面向对象的编程语言中一般在类或接口类中定义一些公有的(public)属性和方法。两类编程语言中接口形式上有很大不同,但是不管是函数接口API还是公有的方法本质上都是函数定义。这里我们将对比采用通用链表模块的接口设计和Callback方式的函数接口设计
1. 通用链表模块的接口设计

2. Callback方式函数接口
callback接口方式非常像谍战剧里派遣卧底,这里SearchLinkTableNode函数派遣了一个卧底Conditon并指定了卧底负责收集的情报范围tLinkTableNode * pNode,一旦发现目标情报卧底就被激活return pNode。

四、线程安全
1. 线程的概念:
线程(thread)是操作系统能够进行运算调度的最小单位。它包含在进程之中,是进程中的实际运作单位。一个线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。一般默认一个进程中只包含一个线程。
2. 什么是线程安全
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行读写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
3. Linktable软件模块的线程安全分析
① 逐一分析所有的函数是不是都是可重入函数
a. 函数有没有访问临界资源(全局变量、静态存储区等),如果有访问临界资源的话需要仔细分析竞争互斥的处理能不能有效避免临界资源冲突问题
b. 对于不可重入函数要具体分析其对线程安全带来的影响,有没有潜在的破坏性。
② 研究不同的可重入函数有没有可能同时进入临界区
a. 写互斥
b. 读写互斥
③ Linktable链表的数据结构中包含pthread_mutex_t mutex用于临界区的互斥,在创建Linktable链接时使用了pthread_mutex_init初始化来mutex,清空链表之后彻底删除链表之前使用pthread_mutex_destroy销毁了mutex。以DeleteLinkTable函数为例

④ 读写并行的可行性分析
a. 插入链接节点是从尾部插入,而查询链表节点是从依次查找,不会出现链表在插入节点的过程中断链的瞬间

b. 删除节点的过程是把待删除的节点的下一个节点指针赋给上一个节点的pNext,一个指令周期内完成,也不会造成链表在删除节点的过程中断链的瞬间。

五、总结
通过这次学习,利用孟老师课堂讲的知识点结合menu项目代码分析各个知识点的具体实现,使我对软件工程开发方法有了更深的理解,在以后的学习中希望有更多的机会可以深入接触更多的软件工程开发方法和技巧,不断进步。
浙公网安备 33010602011771号