代码中的软件工程

参考文献:相关课件

一、配置环境(以win10为例)

1. 安装C/C++编译器和调试器

  • Step1:下载并安装MinGW(建议安装在默认的安装路径)
  • Step2:配置环境变量(将MinGW的安装路径添加到Windows的path变量中)

然后打开cmd查看是否安装成功:

 上图显示安装成功。

2. 安装vscode并进行相关配置

  • Step2:编写一个hello world程序看看是否运行成功

 运行成功!

下边附上 launch.json文件和 tasks.json文件:

launch.json文件:

 1 {
 2     "version": "0.2.0",
 3     "configurations": [
 4         {
 5             "name": "编译并运行",
 6             "type": "cppvsdbg",
 7             "request": "launch",
 8             "program": "C:\\Windows\\System32\\cmd.exe",    //使用cmd.exe显示运行结果;
 9             "args": [
10                 "/C",
11                 "${workspaceFolder}\\bin\\${fileBasenameNoExtension}.exe",  //填写.exe文件的存放路径,workspaceFolder为当前工作区路径;
12                 "&",
13                 "echo.",    //换行;
14                 "&",
15                 "pause"     //防止窗口闪退;
16             ],
17             "stopAtEntry": false,
18             "cwd": "${workspaceFolder}",
19             "environment": [],
20             "externalConsole": true,
21             "preLaunchTask": "C/C++: g++.exe build active file"
22         },
23         {
24             "name": "使用GDB分步调试",
25             "type": "cppdbg",
26             "request": "launch",
27             "program": "${workspaceFolder}\\bin\\${fileBasenameNoExtension}.exe",   //.exe文件的路径名;
28             "args": [],
29             "stopAtEntry": false,
30             "cwd": "${workspaceFolder}",
31             "environment": [],
32             "externalConsole": false,
33             "MIMode": "gdb",
34             "miDebuggerPath": "C:\\MinGW\\bin\\gdb.exe",    //此处应填写本主机的gdb.exe路径名;
35             "setupCommands": [
36                 {
37                     "description": "为 gdb 启用整齐打印",
38                     "text": "-enable-pretty-printing",
39                     "ignoreFailures": true
40                 }
41             ],
42             "preLaunchTask": "C/C++: g++.exe build active file"
43         }
44     ]
45 }

tasks.json文件:

 1 {
 2     "tasks": [
 3         {
 4             "type": "shell",
 5             "label": "C/C++: g++.exe build active file",
 6             "command": "C:\\MinGW\\bin\\g++.exe",    //此处应当填写本主机的g++.exe文件路径;
 7             "args": [
 8                 "-g",
 9                 "${file}",
10                 "-o",
11                 "${workspaceFolder}\\bin\\${fileBasenameNoExtension}.exe"  //.exe文件的存放路径;
12             ],
13             "options": {
14                 "cwd": "${workspaceFolder}"
15             },
16             "problemMatcher": [
17                 "$gcc"
18             ],
19             "group": {
20                 "kind": "build",
21                 "isDefault": true
22             }
23         }
24     ],
25     "version": "2.0.0"
26 }

 2、代码的成长

根据老师的lab1到lab7.2版本的项目文件,可以发现一个项目从"Hello world"到一个完整的菜单功能小程序的成长历程。

lab1版本:

 lab3.3版本:

 lab7.2版本:

3. 模块化设计

模块化设计,简单地说就是程序的编写不是开始就逐条录入计算机语句和指令,而是首先用主程序、子程序、子过程等框架把软件的主要结构和流程描述出来,并定义和调试好各个框架之间的输入、输出链接关系。

模块化的目的是为了降低程序复杂度,使程序设计、调试和维护等操作简单化。改变某个子功能只需相应改变相应模块即可。

在软件工程中的模块化设计便是将一个将为庞大复杂的程序,拆分成多个部分,彼此之间相关性不大,但各部分本身内容很集中,即实现高内聚低耦合。耦合度是指软件模块之间的依赖程度,一般可以分为紧密耦合(Tightly Coupled)、松散耦合(Loosely Coupled)和无耦合(Uncoupled)。 一般在软件设计中我们追求松散耦合。

在lab1~lab3.2中,项目都没有设置头文件,由于前期的版本代码量较少,因此源代码只放置于一个文件无伤大雅,但是随着版本数的逐渐升高,代码量开始越来越大,因此再将全部代码都放置于一个文件中就显得过于杂乱。

例如,lab3.1:

 1 /**************************************************************************************************/
 2 /* Copyright (C) mc2lab.com, SSE@USTC, 2014-2015                                                  */
 3 /*                                                                                                */
 4 /*  FILE NAME             :  menu.c                                                               */
 5 /*  PRINCIPAL AUTHOR      :  Mengning                                                             */
 6 /*  SUBSYSTEM NAME        :  menu                                                                 */
 7 /*  MODULE NAME           :  menu                                                                 */
 8 /*  LANGUAGE              :  C                                                                    */
 9 /*  TARGET ENVIRONMENT    :  ANY                                                                  */
10 /*  DATE OF FIRST RELEASE :  2014/08/31                                                           */
11 /*  DESCRIPTION           :  This is a menu program                                               */
12 /**************************************************************************************************/
13 
14 /*
15  * Revision log:
16  *
17  * Created by Mengning, 2014/08/31
18  *
19  */
20 
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 
25 int Help();
26 int Quit();
27 
28 #define CMD_MAX_LEN 128
29 #define DESC_LEN    1024
30 #define CMD_NUM     10
31 
32 typedef struct DataNode
33 {
34     char*   cmd;
35     char*   desc;
36     int     (*handler)();
37     struct  DataNode *next;
38 } tDataNode;
39 
40 static tDataNode head[] = 
41 {
42     {"help", "this is help cmd!", Help,&head[1]},
43     {"version", "menu program v1.0", NULL, &head[2]},
44     {"quit", "Quit from menu", Quit, NULL}
45 };
46 
47 int main()
48 {
49     /* cmd line begins */
50     while(1)
51     {
52         char cmd[CMD_MAX_LEN];
53         printf("Input a cmd number > ");
54         scanf("%s", cmd);
55         tDataNode *p = head;
56         while(p != NULL)
57         {
58             if(strcmp(p->cmd, cmd) == 0)
59             {
60                 printf("%s - %s\n", p->cmd, p->desc);
61                 if(p->handler != NULL)
62                 {
63                     p->handler();
64                 }
65                 break;
66             }
67             p = p->next;
68         }
69         if(p == NULL) 
70         {
71             printf("This is a wrong cmd!\n ");
72         }
73     }
74 }
75 
76 int Help()
77 {
78     printf("Menu List:\n");
79     tDataNode *p = head;
80     while(p != NULL)
81     {
82         printf("%s - %s\n", p->cmd, p->desc);
83         p = p->next;
84     }
85     return 0; 
86 }
87 
88 int Quit()
89 {
90     exit(0);
91 }

lab3.2也是如此

  1 /**************************************************************************************************/
  2 /* Copyright (C) mc2lab.com, SSE@USTC, 2014-2015                                                  */
  3 /*                                                                                                */
  4 /*  FILE NAME             :  menu.c                                                               */
  5 /*  PRINCIPAL AUTHOR      :  Mengning                                                             */
  6 /*  SUBSYSTEM NAME        :  menu                                                                 */
  7 /*  MODULE NAME           :  menu                                                                 */
  8 /*  LANGUAGE              :  C                                                                    */
  9 /*  TARGET ENVIRONMENT    :  ANY                                                                  */
 10 /*  DATE OF FIRST RELEASE :  2014/08/31                                                           */
 11 /*  DESCRIPTION           :  This is a menu program                                               */
 12 /**************************************************************************************************/
 13 
 14 /*
 15  * Revision log:
 16  *
 17  * Created by Mengning, 2014/08/31
 18  *
 19  */
 20 
 21 
 22 #include <stdio.h>
 23 #include <stdlib.h>
 24 
 25 int Help();
 26 
 27 #define CMD_MAX_LEN 128
 28 #define DESC_LEN    1024
 29 #define CMD_NUM     10
 30 
 31 /* data struct and its operations */
 32 
 33 typedef struct DataNode
 34 {
 35     char*   cmd;
 36     char*   desc;
 37     int     (*handler)();
 38     struct  DataNode *next;
 39 } tDataNode;
 40 
 41 tDataNode* FindCmd(tDataNode * head, char * cmd)
 42 {
 43     if(head == NULL || cmd == NULL)
 44     {
 45         return NULL;        
 46     }
 47     tDataNode *p = head;
 48     while(p != NULL)
 49     {
 50         if(!strcmp(p->cmd, cmd))
 51         {
 52             return p;
 53         }
 54         p = p->next;
 55     }
 56     return NULL;
 57 }
 58 
 59 int ShowAllCmd(tDataNode * head)
 60 {
 61     printf("Menu List:\n");
 62     tDataNode *p = head;
 63     while(p != NULL)
 64     {
 65         printf("%s - %s\n", p->cmd, p->desc);
 66         p = p->next;
 67     }
 68     return 0; 
 69 }
 70 
 71 /* menu program */
 72 
 73 static tDataNode head[] = 
 74 {
 75     {"help", "this is help cmd!", Help,&head[1]},
 76     {"version", "menu program v1.0", NULL, NULL}
 77 };
 78 
 79 int main()
 80 {
 81     /* cmd line begins */
 82     while(1)
 83     {
 84         char cmd[CMD_MAX_LEN];
 85         printf("Input a cmd number > ");
 86         scanf("%s", cmd);
 87         tDataNode *p = FindCmd(head, cmd);
 88         if( p == NULL)
 89         {
 90             printf("This is a wrong cmd!\n ");
 91             continue;
 92         }
 93         printf("%s - %s\n", p->cmd, p->desc); 
 94         if(p->handler != NULL) 
 95         { 
 96             p->handler();
 97         }
 98    
 99     }
100 }
101 
102 int Help()
103 {
104     ShowAllCmd(head);
105     return 0; 
106 }

真正的模块化设计思想从lab3.3开始。lab3.3将项目的不同功能分别放在不同的文件里,如菜单项目的功能部件放在linklist.c文件里,项目的主函数放置在menu.c文件里,对数据结构等的声明放在了头文件linklist.h里。使得整个项目的不同模块得以变得清晰。

lab3.3版本体现了KISS原则,即:一行代码只做一件事,一个块函数只做一件事,一个函数只做一件事,一个软件模块只做一件事。

lab3.3源码如下:

linklist.h文件:

 1 /**************************************************************************************************/
 2 /* Copyright (C) mc2lab.com, SSE@USTC, 2014-2015                                                  */
 3 /*                                                                                                */
 4 /*  FILE NAME             :  linklist.h                                                           */
 5 /*  PRINCIPAL AUTHOR      :  Mengning                                                             */
 6 /*  SUBSYSTEM NAME        :  menu                                                                 */
 7 /*  MODULE NAME           :  linklist                                                             */
 8 /*  LANGUAGE              :  C                                                                    */
 9 /*  TARGET ENVIRONMENT    :  ANY                                                                  */
10 /*  DATE OF FIRST RELEASE :  2014/09/10                                                           */
11 /*  DESCRIPTION           :  linklist for menu program                                            */
12 /**************************************************************************************************/
13 
14 /*
15  * Revision log:
16  *
17  * Created by Mengning, 2014/09/10
18  *
19  */
20 
21 
22 /* data struct and its operations */
23 
24 typedef struct DataNode
25 {
26     char*   cmd;
27     char*   desc;
28     int     (*handler)();
29     struct  DataNode *next;
30 } tDataNode;
31 
32 /* find a cmd in the linklist and return the datanode pointer */
33 tDataNode* FindCmd(tDataNode * head, char * cmd);
34 /* show all cmd in listlist */
35 int ShowAllCmd(tDataNode * head);

linklist.c文件:

 1 /**************************************************************************************************/
 2 /* Copyright (C) mc2lab.com, SSE@USTC, 2014-2015                                                  */
 3 /*                                                                                                */
 4 /*  FILE NAME             :  linklist.c                                                           */
 5 /*  PRINCIPAL AUTHOR      :  Mengning                                                             */
 6 /*  SUBSYSTEM NAME        :  menu                                                                 */
 7 /*  MODULE NAME           :  linklist                                                             */
 8 /*  LANGUAGE              :  C                                                                    */
 9 /*  TARGET ENVIRONMENT    :  ANY                                                                  */
10 /*  DATE OF FIRST RELEASE :  2014/09/10                                                           */
11 /*  DESCRIPTION           :  linklist for menu program                                            */
12 /**************************************************************************************************/
13 
14 /*
15  * Revision log:
16  *
17  * Created by Mengning, 2014/09/10
18  *
19  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include "linklist.h"
24 
25 
26 tDataNode* FindCmd(tDataNode * head, char * cmd)
27 {
28     if(head == NULL || cmd == NULL)
29     {
30         return NULL;        
31     }
32     tDataNode *p = head;
33     while(p != NULL)
34     {
35         if(!strcmp(p->cmd, cmd))
36         {
37             return p;
38         }
39         p = p->next;
40     }
41     return NULL;
42 }
43 
44 int ShowAllCmd(tDataNode * head)
45 {
46     printf("Menu List:\n");
47     tDataNode *p = head;
48     while(p != NULL)
49     {
50         printf("%s - %s\n", p->cmd, p->desc);
51         p = p->next;
52     }
53     return 0; 
54 }

menu.c文件如下:

 1 /**************************************************************************************************/
 2 /* Copyright (C) mc2lab.com, SSE@USTC, 2014-2015                                                  */
 3 /*                                                                                                */
 4 /*  FILE NAME             :  menu.c                                                               */
 5 /*  PRINCIPAL AUTHOR      :  Mengning                                                             */
 6 /*  SUBSYSTEM NAME        :  menu                                                                 */
 7 /*  MODULE NAME           :  menu                                                                 */
 8 /*  LANGUAGE              :  C                                                                    */
 9 /*  TARGET ENVIRONMENT    :  ANY                                                                  */
10 /*  DATE OF FIRST RELEASE :  2014/08/31                                                           */
11 /*  DESCRIPTION           :  This is a menu program                                               */
12 /**************************************************************************************************/
13 
14 /*
15  * Revision log:
16  *
17  * Created by Mengning, 2014/08/31
18  *
19  */
20 
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include "linklist.h"
25 
26 int Help();
27 
28 #define CMD_MAX_LEN 128
29 #define DESC_LEN    1024
30 #define CMD_NUM     10
31 
32 /* menu program */
33 
34 static tDataNode head[] = 
35 {
36     {"help", "this is help cmd!", Help,&head[1]},
37     {"version", "menu program v1.0", NULL, NULL}
38 };
39 
40 main()
41 {
42    /* cmd line begins */
43     while(1)
44     {
45         char cmd[CMD_MAX_LEN];
46         printf("Input a cmd number > ");
47         scanf("%s", cmd);
48         tDataNode *p = FindCmd(head, cmd);
49         if( p == NULL)
50         {
51             printf("This is a wrong cmd!\n ");
52             continue;
53         }
54         printf("%s - %s\n", p->cmd, p->desc); 
55         if(p->handler != NULL) 
56         { 
57             p->handler();
58         }
59    
60     }
61 }
62 
63 int Help()
64 {
65     ShowAllCmd(head);
66     return 0; 
67 }

4. 可重用接口

接口是指对协定进行定义的引用类型。其他类型实现接口,以保证它们支持某些操作。接口指定必须由类提供的成员或实现它的其他接口。与类相似,接口可以包含方法、属性、索引器和事件作为成员。

接口使得模块与模块之间得以相互合作,且又能降低彼此的耦合性。

例如lab5.2就使用了许多接口:

 1 typedef struct LinkTableNode
 2 {
 3     struct LinkTableNode * pNext;
 4 }tLinkTableNode;
 5 
 6 typedef struct LinkTable tLinkTable;
 7 
 8 tLinkTable * CreateLinkTable();
 9 
10 int DeleteLinkTable(tLinkTable *pLinkTable);
11 
12 int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
13 
14 int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
15 
16 tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args);
17 
18 tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);
19 
20 tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);

5. 总结

对于今后的软件开发,我们要做到以下几点:

  • 对于每个文件内部,我们应当保持一个良好的编码习惯:使用空格键将各个编码元素隔开;类名、变量名和函数名的命名遵守统一的命名规范;学会使用注释来帮助读者阅读源码等,从而使代码看上去尽可能简洁明了;
  • 项目中的各个功能部件独立划分,遵从KISS原则,这样既有利于增加代码的可读性,也利于日常的维护和bug的修复;
  • 各模块之间使用接口进行连接,并尽可能降低各模块之间的耦合程度,提升模块内部的内聚程度;
  • 熟练掌握操作系统的基本知识,确保代码运行的线程安全。

 

posted @ 2020-11-05 18:13  icandoitbetter  阅读(190)  评论(0)    收藏  举报