其他分享
首页 > 其他分享> > 代码中的软件工程

代码中的软件工程

作者:互联网

一.编译调试环境配置及代码规范

本次实验在Ubuntu20.04系统下,VS code + GCC工具集编译环境下完成。

1.安装VS code:下载VS code安装包后,在文件路径下执行:

sudo dpkg -i filename.deb

安装GCC:在终端执行:

sudo apt-get install gcc

image-20201109163806568

使用 gcc -v 命令可以看到GCC已经安装完成。

以lab1为例,使用GCC编译hello.c文件,执行,可以看到输出hello。

image-20201109164630699

编译环境配置完成。

2.代码风格规范

​ •缩进:4个空格;

​ •行宽:< 100个字符;

​ •代码行内要适当多留空格,如“=”、“+=” “>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后应当加空格。对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格,如for (i=0; i<10; i++)和if ((a<=b) && (c<=d));

​ •在一个函数体内,逻揖上密切相关的语句之间不加空行,逻辑上不相关的代码块之间要适当留有空行以示区隔;

​ •在复杂的表达式中要用括号来清楚的表示逻辑优先级;

​ •花括号:所有 ‘{’ 和 ‘}’ 应独占一行且成对对齐;

​ •不要把多条语句和多个变量的定义放在同一行;

​ •命名:合适的命名会大大增加代码的可读性;

​ •类名、函数名、变量名等的命名一定要与程序里的含义保持一致,以便于阅读理解;

​ •类型的成员变量通常用m_或者_来做前缀以示区别;

​ •一般变量名、对象名等使用LowerCamel风格,即第一个单词首字母小写,之后的单词都首字母大写,第一个单词一般都表示变量类型,比如int型变量iCounter;

​ •类型、类、函数名等一般都用Pascal风格,即所有单词首字母大写;

​ •类型、类、变量一般用名词或者组合名词,如Member

​ •函数名一般使用动词或者动宾短语,如get/set,RenderPage;

二.模块化软件设计

模块化是在软件系统设计时保持系统内各部分相对独立,以便每一个部分可以被独立地进行设计和开发。模块化软件设计的方法如果应用的比较好,最终每一个软件模块都将只有一个单一的功能目标,并相对独立于其他软件模块,使得每一个软件模块都容易理解容易开发。因此,软件设计中的模块化程度便成为了软件设计有多好的一个重要指标,一般我们使用耦合度和内聚度来衡量软件模块化的程度。

耦合度是指软件模块之间的依赖程度,一般可以分为紧密耦合、松散耦合和无耦合。一般在软件设计中我们追求松散耦合。

image-20201109170317920

内聚度是指一个软件模块内部各种元素之间互相依赖的紧密程度。理想的内聚是功能内聚,也就是一个软件模块只做一件事,只完成一个主要功能点或者一个软件特性。

进行了模块化设计之后我们往往将设计的模块与实现的源代码文件有个映射对应关系,因此我们需要将数据结构和它的操作独立放到单独的源代码文件中,这时就需要设计合适的接口,以便于模块之间互相调用。

在menu项目中,分为了linktable,menu,test三个模块。其中,linktable.h文件里声明了数据结构及对其的操作函数,其具体实现在linktable.c中完成。

对数据结构的定义:

typedef struct LinkTableNode
{
    struct LinkTableNode * pNext;
}tLinkTableNode;

对数据结构的操作:

/*
 * Create a LinkTable
 */
tLinkTable * CreateLinkTable();
/*
 * Delete a LinkTable
 */
int DeleteLinkTable(tLinkTable *pLinkTable);
/*
 * Add a LinkTableNode to LinkTable
 */
int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
/*
 * Delete a LinkTableNode from LinkTable
 */
int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
/*
 * Search a LinkTableNode from LinkTable
 * int Conditon(tLinkTableNode * pNode,void * args);
 */
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args);
/*
 * get LinkTableHead
 */
tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);
/*
 * get next LinkTableNode
 */
tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);

具体实现:

/*
 * LinkTable Type
 */
struct LinkTable
{
    tLinkTableNode *pHead;
    tLinkTableNode *pTail;
    int			SumOfNode;
    pthread_mutex_t mutex;

};
/*
 * Create a LinkTable
 */
tLinkTable * CreateLinkTable()
{
    tLinkTable * pLinkTable = (tLinkTable *)malloc(sizeof(tLinkTable));
    if(pLinkTable == NULL)
    {
        return NULL;
    }
    pLinkTable->pHead = NULL;
    pLinkTable->pTail = NULL;
    pLinkTable->SumOfNode = 0;
    pthread_mutex_init(&(pLinkTable->mutex), NULL);
    return pLinkTable;
}

/*
 * Delete a LinkTable
 */
int DeleteLinkTable(tLinkTable *pLinkTable)
{
    if(pLinkTable == NULL)
    {
        return FAILURE;
    }
    while(pLinkTable->pHead != NULL)
    {
        tLinkTableNode * p = pLinkTable->pHead;
        pthread_mutex_lock(&(pLinkTable->mutex));
        pLinkTable->pHead = pLinkTable->pHead->pNext;
        pLinkTable->SumOfNode -= 1 ;
        pthread_mutex_unlock(&(pLinkTable->mutex));
        free(p);
    }
    pLinkTable->pHead = NULL;
    pLinkTable->pTail = NULL;
    pLinkTable->SumOfNode = 0;
    pthread_mutex_destroy(&(pLinkTable->mutex));
    free(pLinkTable);
    return SUCCESS;		
}

在menu.c中导入linktable.h即可实现导入数据结构及其操作。

#include "menu.h"

三.可重用接口设计

接口就是互相联系的双方共同遵守的一种协议规范,在我们软件系统内部一般的接口方式是通过定义一组API函数来约定软件模块之间的沟通方式。换句话说,接口具体定义了软件模块对系统的其他部分提供了怎样的服务,以及系统的其他部分如何访问所提供的服务。在面向过程的编程中,接口一般定义了数据结构及操作这些数据结构的函数;而在面向对象的编程中,接口是对象对外开放的一组属性和方法的集合。函数或方法具体包括名称、参数和返回值等。

接口规格包含五个基本要素:

​ •接口的目的;

​ •接口使用前所需要满足的条件,一般称为前置条件或假定条件;

​ •使用接口的双方遵守的协议规范;

​ •接口使用之后的效果,一般称为后置条件;

​ •接口所隐含的质量属性。

下面的函数接口代码是取出链表头节点的函数声明,以此来分析函数接口的基本要素。

tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);

1.接口目的是取出链表的头节点,函数名GetLinkTableHead即表明接口目的;

2.接口前置条件是存在链表pLinkTable,即链表pLinkTable != NULL;

3.双方遵守的协议规范是通过数据结构tLinkTableNode和tLinkTable定义的;

4.接口后置条件是找到了链表的头节点,并返回tLinkTableNode类型的指针;

Callin和Callback接口:

下面的代码是搜索链表中的节点的函数声明

tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args)
{
}

作为参数的Conditon函数就是Callback接口

标签:代码,接口,软件工程,mutex,pLinkTable,tLinkTable,NULL,tLinkTableNode
来源: https://www.cnblogs.com/hasi/p/13950471.html