以 menu 程序为例的代码分析
参考资料:https://gitee.com/mengning997/se/blob/master/README.md#代码中的软件工程
源代码:https://github.com/mengning/menu
一、环境搭建与运行
这里使用 Windows 下的 WSL (Windows Subsystem for Linux) 中的 gcc 作为编译器,搭配 VSCode 使用。此处略过安装 VSCode 和安装 WSL 的过程。
1. 在 WSL 中安装编译工具
在 WSL 终端执行:
sudo apt install gcc make build-essentials
2. 安装 VSCode 插件
在 VSCode 中安装 WSL 插件和 C/C++ 插件。
3. 在 WSL 中启动 VSCode
在 WSL 终端定位到 menu 目录,然后执行 code .:
cd /[my_directory]/menu
code .
会看到提示正在安装 VSCode Server for WSL,稍后自动打开 VSCode。再次进入插件,选择 C/C++ 插件,选择 Install for WSL,来将该插件安装到 WSL 中。
4. 配置编译任务
在 VSCode 中选择 Terminal -> Configure Default Build Task,编辑弹出的 json 文件。
如图,在 args 参数中添加依赖的 menu.c 和 linktable.c 这两个文件。然后打开 test*.c (任意一个),按下 F5 即可开始 Debug(或者按 Ctrl + F5 直接运行)。
二、模块间的解耦合
在开发时,为了使代码更加清晰,以及使模块能够很好的重复使用,需要降低模块间的耦合度,将与模块本身无关的代码抽出。模块之间通过约定接口的方式来互相调用。例如在此项目中,链表的实现独立于主程序,使其能够通用。
可以看到,程序目录大体分成 linktable、menu 和 test 三个模块,分别是链表、menu 功能以及测试文件。test 当中还包含了为了测试不同功能而设计的 test_fork、test_reply 等。
查看 linktable.h,这是其提供给外部的接口。
在 linktable 的接口定义中,除了常规的增加、删除等方法之外,还有一个以函数指针作为参数的 callback 方式的接口,这使得我们可以进一步解耦,search 方法不需要知道调用时具体传入了什么 Condition 进去,只要其参数列表相符,就能正常调用。
继续查看 linktable.c,可以发现一个更为具体的 LinkTable 声明:
这是 LinkTable 的定义。为了隐藏其中一些数据,以便调用者不能轻易地修改而导致意外错误,这里把这个定义放在了 .c 文件中,而 .h 中只保留其声明。这进一步增加了程序的安全性,也减少了暴露的接口数。
接下来查看 menu.c,其中包含了另一个 DataNode:
除了 LinkTableNode 中的 pNext 域之外,DataNode 还包含了一些功能相关域 cmd、desc 等,可以由 LinkTableNode 强制转换:
如果使用面向对象语言,这里还可以使用继承来实现,避免强制类型转换可能带来的问题。
线程安全
如前文图所示,LinkTable 结构中包含了信号量 mutex。
在代码实现当中,为了确保某些过程不被其他进程打断而导致数据出错,使用信号量锁来使这些过程原子化,实现临界资源的互斥访问,保证线程安全。
总结
在软件开发过程中,除了关注具体的实现细节之外,我们更应关注其设计模式以及结构,使我们的程序能够尽可能容易地接受变化,以及更容易地被重复使用,避免大量的复制代码。同时,对于多线程的场景,应关注其数据一致性,更进一步的,针对非单机程序,比如我们的程序部署在多台服务器上,形成一个分布式架构,我们需要更为深入的思考,针对高并发的访问,应怎样在保持一致性的前提下尽可能的提高性能。

浙公网安备 33010602011771号