论代码中的软件工程 ——Menu项目
------------恢复内容开始------------
代码中的软件工程
课上,孟宁老师向我们讲述了有关软件工程的思想方法,加以实例介绍,让我深刻认识到软件工程在实际编程工作项目中的重要性,并有了许多体会。
本文主要总结老师课上讲述的知识,并基于Menu项目进行代码中软件工程项目的案例分析。非常感谢孟宁老师的教学指导。
一.完成编译和调试环境配置
在本次实验项目中,我们采用Vscode+gcc的模式进行实现,因此需要完成相关环境的配置。
首先我们需要下载Vscode
进入Vscode官方网站下载:https://code.visualstudio.com/docs/setup/windows

下载完成后,我们进入Vscode界面,建议先在商店中下载中文扩展包。(在搜索界面输入Language,第一项就是)

接下来我们需要配置C/C++的扩展包,在商店中查找C/C++(搜索C++ extension),并下载安装,重启Vscode即可。

由于Vscode只是一个单纯的文本编译器,无法直接执行C/C++文件,因此我们需要下载跨平台的编译器和调试器,在本文中我们选择的是运用广泛的MinGW-w64编译器。
MinGW(Minimalist GNU for Windows), 是一个适用于微软 windows 应用程序的极简开发环境。MinGW 提供了一个完整的开源编程工具集,适用于原生 MS-Windows 应用程序的开发,并且不依赖于任何第三方 C 运行时 DLL。MinGW 主要供在 MS-Windows 平台上工作的开发人员使用,也可以跨平台使用。Mingw-w64 是原始 mingw.org 项目的升级版,该项目旨在支持 Windows 系统上的 GCC 编译器。它在 2007 年进行了分支,以便为 64 位和新 API 提供支持。从那以后,它得到了广泛的使用和分发。
首先去MinGW官方网址进行下载:https://sourceforge.net/projects/mingw-w64/files/?source=navbar
若是挂有外网VPN,可以直接下载;没有则最好下载离线压缩安装包。在此笔者选择下载压缩包。

解压完成后,我们需要在电脑中配置环境变量:

我们将minw64中的bin文件配置到系统变量Path的路径下:

这样我们就完成了MinGW编译环境的配置。
在控制台键入
gcc -v
查看Gcc版本,即可看到当前版本号与版本信息。

接下来,我们打开Vscode,并选择环境配置:

我们创建一个工作文件夹VS_TEST,并拖拽入Vscode中

我们发现在VS_TEST文件目录下生成了launch.json、settings.json、tasks.json三个文件

接下来我们打开launch.json文件,并更改工作区配置如下。

新建一个C++文件,执行:

即可在控制台终端看到输出结果。这样第一个程序即在Vscode上运行成功了。

二.Menu项目代码中软件工程思想的理解分析
首先我们下载孟宁老师的Menu项目,并将它拖入我们的工作区中。

1.模块化设计
模块化程序设计是指在进行程序设计时将一个大程序按照功能划分为若干小程序模块,每个小程序模块完成一个确定的功能,并在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计方法。
模块化程序设计的基本思想是自顶向下、逐步分解、分而治之,即将一个较大的程序按照功能分割成一些小模块,各模块相对独立、功能单一、结构清晰、接口简单。通常采用内聚度和耦合度来衡量模块化的程度。
2.可重用接口设计
接口具体定义了软件模块对系统的其他部分提供了怎样的服务,以及系统的其他部分如何访问所提供的服务。在面向过程的编程中,接口一般定义了数据结构及操作这些数据结构的函数;而在面向对象的编程中,接口是对象对外开放的一组属性和方法的集合。
我们希望这一个软件模块与其他软件模块之间松散耦合,就需要定义简洁、清晰、明确的接口,在Menu项目中,同样有接口的运用。
在lab4的linktabel.h中,即对各个函数接口进行了相关的定义。同时增加了testlinktable.c开发者指南程序,告诉用户和其他开发者怎么使用linktable,方便对整个项目进行延伸扩展。

lab4定义了一组链表的操作,并独立成函数,完成了数据结构与操作数据结构的函数与具体实现的解耦。
linktable.c其中一个函数具体实现部分:

而在menu.c中,只调用了了“linktable.h",其余具体的实现全部在linktable.c中,这样只留接口给c文件,既保证了函数体的安全性,又使内聚性提高,使开发人员专注自己的事情上,不需要关心函数内部的细节实现。

在lab5.1中,孟宁老师采用了callback机制为其他程序员提供了一个遍历链表的函数接口linktable.h,用户可以直接去主程序中关注实现即可。
利用callback函数参数使Linktable的查询接口更加通用,这样可以有效地提高接口的通用性.这样可以有效地隐藏软件模块内部的实现细节,为外部调用接口的开发者提供更加简洁的接口信息,同时也减少外部调用接口的开发者有意或无意的破坏软件模块的内部数据。
这里对接口提供了扩展,方便开发人员对程序进行进一步改进,同时留出函数接口,有效隐藏内部细节,使代码更具可读性和易维护性。
3.线程安全与可重入函数
线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。
关于可重入函数,有两个观点: (1) 可重入的函数不一定是线程安全的,可能是线程安全的也可能不是线程安全的;可重入的函数在多个线程中并发使用时是线程安全的,但不同的可重入函数(共享全局变量及静态变量)在多个线程中并发使用时会有线程安全问题。(2) 不可重入的函数一定不是线程安全的。
在孟宁老师的Menu项目中,也体会了保证线程安全的思想。
我们打开lab7.1,进入linktable.c中,在结构体的定义中,我们可以看见pthread_mutex_t变量,这个变量即是实现线程安全的PV操作信号量。

接下来我们查看删除表函数,可以看见:

其中第一个红圈画出了的部分,mutex_lock代表着当此现场进入临界区时,会独占临界区一记资源,并将此处上锁,防止其他进程访问。
第二个红圈画出的部分表示解锁,线程会释放出占有资源,并退出临界区,之后其他进程即可进行访问。而mutex就作为互斥变量,对进程访问临界区进行控制。
这个过程可以保证一个线程在进行链表删除操作时,不会被其他线程所干扰,也即同时只能有一个线程来进行删除操作。这样符合软件工程思想的代码段,保证了线程同步和互斥性,可以有效保护共享资源,并进行合理的规划,与此同时可以防止进程死锁的现象出现。
而在lab7.2增加了一些通用接口,使程序更具扩展性与封装性,提高了编写程序的效率。
三.尾声
通过阅读体会孟宁老师的Menu项目代码,我对软件工程中的思想有了更深层次的体悟,也理解了为何软件工程对程序项目有极为重要的意义。软件工程中所体现的模块化、结构化思想,应该应用到我们每一次编写代码的过程中,只有做好每一个小小的细节,才能堆砌起软件项目的“摩天大楼”。同时我们也需要加强代码实践,在实践中才能对有更好的收获,对软件工程有更好的体会。
再次感谢孟宁老师的指导和帮助,让我在软件工程方面有了更深入的了解,以后还需要好好努力,克服自己编码中耦合度高、不规范的等等缺点,继续学习进步。
浙公网安备 33010602011771号