高软作业3:深入理解Callback函数

文章目录

  • 1. 作业要求
  • 2. 回调函数概念
  • 3. Menu程序中回调函数的实现
    • 3.1 模块之间的耦合度
    • 3.2 通用模块的实现
    • 3.3 menu程序中调用通用模块
  • 4. 实际调试结果
    • 4.1 修改VScode的tasks.json
    • 4.2 修正bug
    • 4.3 开始调试

1. 作业要求

参考《代码中的软件工程》第六章可复用软件设计及lab5.2的源代码,完成实验并写一篇实验报告,总结Callback函数的工作机制以及通过参数进行解耦合的方法,深入理解接口设计中的抽象分层。

2. 回调函数概念

在计算机科学中,回调函数是指一段以参数的形式传递给其它代码的可执行代码。

在软件开发中,我们可以把与具体业务无关的代码剥离开来,封装成独立的通用模块(库函数),以便实现代码重用,提高开发效率。
更进一步, 我们可以修改上述通用模块,让它能接收函数作为参数,在通用模块内部,满足一定条件时便可调用传入的函数。相当于用户可以根据需要,向通用模块传递自定义功能的代码段,从而增强通用模块的灵活性和功能。
如下图所示,用户实现主程序、不同回调函数模块——用以实现业务具体功能,它们同处业务层或应用层。然后主程序不是直接调用回调函数X,而是调用通用接口,并把最终需要使用的回调函数X作为参数传给通用函数模块,然后通用函数再***“回过头”***调用相应的函数X,于是将这些函数称作“回调函数”(Callback Function)。
高软作业3:深入理解Callback函数_第1张图片

3. Menu程序中回调函数的实现

3.1 模块之间的耦合度

耦合度是指软件模块之间的依赖程度,为了避免注意力分离,增强代码可读性、可维护性,在软件设计中我们要尽可能降低模块间的耦合度。
根据接口的定义方式,按照耦合度依次递增可将耦合分为:无耦合、数据耦合、标记耦合、控制耦合、公共耦合和内容耦合,下面是常见耦合类型的比较:

耦合方式 含义 举例
公共耦合 当软件模块之间共享数据区或变量名的软件模块之间即是公共耦合 全局变量
数据耦合 在软件模块之间仅通过显式的调用传递基本数据类型 传值
标记耦合 在软件模块之间仅通过显式的调用传递复杂的数据结构(结构化数据) 传递结构体

3.2 通用模块的实现

高软作业3:深入理解Callback函数_第2张图片
SearchLinkTableNode是menu程序中的通用查询模块,用以查询与输入信息相匹配的命令结点,它有以下三个参数

参数 作用
pLinkTable 指定待查询的命令列表,即查询范围
Condition 回调函数,用户自定义的信息匹配方式
args 提供查询信息给回调函数

用户程序定义了通用模块SearchCondition,它需要用户提供“具体的检查方式Condition”、“待检查的目标args”。由于检查方式一般比较复杂多变,此处通过传递一段函数代码(类似函数指针)来实现。而待查询信息不采用全局变量而是使用接口传参方式,因为如果通过全部变量传递目标信息,属于公共耦合方式,耦合度较高,而且会增加通用模块内部信息被暴露的风险。因而为了隐藏信息,本程序改用数据耦合方式,增加了args参数,从而在调用通用函数模块的同时指定了目标数据,降低通用模块与用户程序的耦合度,只有检查到目标args时才通知用户程序。

可见,通过利用callback函数参数,Linktable的查询接口变得更加通用,有效地提高了接口的通用性。

3.3 menu程序中调用通用模块

高软作业3:深入理解Callback函数_第3张图片
高软作业3:深入理解Callback函数_第4张图片
在main函数中,先是初始化命令菜单链表,并把表头存放于head中。然后在死循环中,用cmd接收用户输入的命令名,接着用户程序调用FindCmd函数查询cmd对应的命令数据结点。在FindCmd中,调用通用查询模块SearchLinkTableNode,并指定回调函数SearchCondition作为具体的判定方式,以及待查询的命令名cmd。最后通用模块会根据判定方式返回与cmd匹配的目标数据结点。
如果用户想使用其它判定方式,比如搜索命令菜单中描述信息的部分内容,可以实现新的回调函数,然后作为参数传递给SearchLinkTableNode,而不必改动SearchLinkTableNode 的内部代码,从而保证该模块的通用性。

4. 实际调试结果

4.1 修改VScode的tasks.json

高软作业3:深入理解Callback函数_第5张图片
①因为本程序有多个源程序,所以用 *.c表示所有待编译源文件
②本程序用到多线程,需要连接pthread库

4.2 修正bug

高软作业3:深入理解Callback函数_第6张图片高软作业3:深入理解Callback函数_第7张图片
警告1:main函数缺少返回值类型int
警告2:strcmp函数未显示声明,需要加载头文件

4.3 开始调试

  1. 设置断点 ,输入cmd命令
    高软作业3:深入理解Callback函数_第8张图片
    解决bug后,在main函数中FindCmd函数所在处设置断点,成功编译后进入调试模式。输入命令“quit”,执行到断点,然后单步执行

  2. 进入FindCmd
    高软作业3:深入理解Callback函数_第9张图片

  3. 开始调用通用查询模块SearchLinkTableNode
    高软作业3:深入理解Callback函数_第10张图片高软作业3:深入理解Callback函数_第11张图片
    SearchTableNode的参数Condition已经被替代为具体的检查函数SearchCondition

  4. 第一个数据结点检查
    高软作业3:深入理解Callback函数_第12张图片
    高软作业3:深入理解Callback函数_第13张图片高软作业3:深入理解Callback函数_第14张图片高软作业3:深入理解Callback函数_第15张图片

SearchTableNode获取命令链表第一个数据结点后,进入回调函数Condition检查,由于该结点的cmd=“help”,与输入的命令不符,向SearchTableNode返回FAILURE,PNode迭代为命令链表第二个结点
7. 第二个数据结点检查
高软作业3:深入理解Callback函数_第16张图片

高软作业3:深入理解Callback函数_第17张图片高软作业3:深入理解Callback函数_第18张图片
与第一个结点相似,信息不匹配,继续检查下一个

  1. 第三个数据结点检查
    高软作业3:深入理解Callback函数_第19张图片高软作业3:深入理解Callback函数_第20张图片高软作业3:深入理解Callback函数_第21张图片
    匹配成功,向main函数返回该结点指针

  2. 返回主函数,执行后续操作
    高软作业3:深入理解Callback函数_第22张图片高软作业3:深入理解Callback函数_第23张图片高软作业3:深入理解Callback函数_第24张图片
    高软作业3:深入理解Callback函数_第25张图片
    程序正确输出“quit”命令名和描述,并调用其处理函数,执行退出操作,调试结束。

你可能感兴趣的:(软件工程)