以 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.clinktable.c 这两个文件。然后打开 test*.c (任意一个),按下 F5 即可开始 Debug(或者按 Ctrl + F5 直接运行)。

二、模块间的解耦合

在开发时,为了使代码更加清晰,以及使模块能够很好的重复使用,需要降低模块间的耦合度,将与模块本身无关的代码抽出。模块之间通过约定接口的方式来互相调用。例如在此项目中,链表的实现独立于主程序,使其能够通用。

可以看到,程序目录大体分成 linktablemenutest 三个模块,分别是链表、menu 功能以及测试文件。test 当中还包含了为了测试不同功能而设计的 test_forktest_reply 等。

查看 linktable.h,这是其提供给外部的接口。

linktable 的接口定义中,除了常规的增加、删除等方法之外,还有一个以函数指针作为参数的 callback 方式的接口,这使得我们可以进一步解耦,search 方法不需要知道调用时具体传入了什么 Condition 进去,只要其参数列表相符,就能正常调用。

继续查看 linktable.c,可以发现一个更为具体的 LinkTable 声明:

这是 LinkTable 的定义。为了隐藏其中一些数据,以便调用者不能轻易地修改而导致意外错误,这里把这个定义放在了 .c 文件中,而 .h 中只保留其声明。这进一步增加了程序的安全性,也减少了暴露的接口数。

接下来查看 menu.c,其中包含了另一个 DataNode

除了 LinkTableNode 中的 pNext 域之外,DataNode 还包含了一些功能相关域 cmddesc 等,可以由 LinkTableNode 强制转换:

如果使用面向对象语言,这里还可以使用继承来实现,避免强制类型转换可能带来的问题。

线程安全

如前文图所示,LinkTable 结构中包含了信号量 mutex

在代码实现当中,为了确保某些过程不被其他进程打断而导致数据出错,使用信号量锁来使这些过程原子化,实现临界资源的互斥访问,保证线程安全。

总结

在软件开发过程中,除了关注具体的实现细节之外,我们更应关注其设计模式以及结构,使我们的程序能够尽可能容易地接受变化,以及更容易地被重复使用,避免大量的复制代码。同时,对于多线程的场景,应关注其数据一致性,更进一步的,针对非单机程序,比如我们的程序部署在多台服务器上,形成一个分布式架构,我们需要更为深入的思考,针对高并发的访问,应怎样在保持一致性的前提下尽可能的提高性能。

posted @ 2020-11-03 17:44  Clesora  阅读(312)  评论(0)    收藏  举报