结对编程收获

      前前后后耗时两周的结对编程作业,我经历了很多,收获了很多,真是感觉自己从一个什么都不懂的菜狗到一个伟大的程序员又进了一步啊!由于收获非常之多,下面我将一一列出。

  • c++学习

由于本人之前实在太菜,所以首先恶补了C++知识,具体如下:

  1. 类和对象

C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。

类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。

定义一个类,本质上是定义一个数据类型的蓝图。这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。例如,我们使用关键字 class 定义 Box 数据类型,如下所示:

class Box
{
   public:
      double length;   // 盒子的长度
      double breadth;  // 盒子的宽度
      double height;   // 盒子的高度
};

关键字 public 确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访的。另外还有private 或 protected。他们的区别好像在继承中有所体现。

2.继承

面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行时间的效果。当创建一个类时,我们不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。继承代表了 is a 关系。

一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:

class derived-class: access-specifier base-class

其中,访问修饰符 access-specifier 是 public、protectedprivate 其中的一个,base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier,则默认为 private。

当一个类派生自基类,该基类可以被继承为 public、protected private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。我们几乎不使用 protected private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:

    • 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有保护成员来访问。
    • 保护继承(protected): 当一个类派生自保护基类时,基类的公有保护成员将成为派生类的保护成员。
    • 私有继承(private):当一个类派生自私有基类时,基类的公有保护成员将成为派生类的私有成员。

多继承即一个子类可以有多个父类,它继承了多个父类的特性。

好,有了上面这些东西,虽然也不是很懂,但是用于现学现卖的快开发是够用了。下面我们来具体看看Qt。

  • QT概观

首先我并不知道qt是什么东西,于是我上网查了下:

Qt是桌面,嵌入式和移动的跨平台应用开发框架。支持的平台包括Linux,OS X,Windows,VxWorks,QNX,Android,iOS,BlackBerry,Sailfish OS等。

Qt本身不是一种编程语言。它是一个用C ++编写的框架。但它不仅仅只是一个GUI工具包,它提供了在网络,数据库,OpenGL,Web技术,传感器,通信协议(蓝牙,串行端口,NFC),XML和JSON处理,打印,PDF生成等领域的跨平台开发的模块。

Qt拥有自己的集成开发环境(IDE),名为Qt Creator。它运行在Linux,OS X和Windows上,提供智能代码完成,语法高亮,集成帮助系统,调试器和分析器集成以及所有主要版本控制系统(例如git,Bazaar)的集成。

看完这些后我对qt还是一头雾水,但是这并不妨碍我现学现卖。

首先,我们来看看界面:

                东西很多,组件更多。看到了这些东西后,我终于能大概看懂例程了

               

                这就是主程序。当然了,我是基本看不懂的。但是这并不妨碍我编程,因为我发现了居然可以拖部件编辑UI。

               首先我们来创建工程

 

 

好了,通过以上步骤,我们就成功建立了一个窗口工程。当时觉得很开心,但其实这玩意儿其实已经给以后的爆炸埋下了伏笔。没有资料参考,没人给出解释,我们两个人就这样肝了一天一夜。最后只知道可能是编译器不支持,然后对接也变得异常麻烦。

回到正题,工程建好后,也知道拖拽,但是还是不会写程序。为啥呢?不知道程序怎么运行的。不知道各个槽函数运行完了会回到哪里,也不知道各个按钮,layout。。。到底怎么设置,有哪些参数,窗口cpp里到底该写啥。最后我们一顿乱写,渐渐找出的办法。

反正都要用的变量就写全局,槽函数就当中断,main里啥都不用管。

嗯,然后就一通乱写,就把程序写完了。

  • 结对编程

                写的过程中,我俩轮流主刀,另一人就在旁边看着。经常会有想抢过键盘的冲动。我们发现,关于实现的细节,两人讨论过多反而会拖慢进度。一段时间后,迫于时间课业压力,我俩分模块编程,速度大为提高。

1.结对编程并不适用于简单的写代码的工作,结对编程更适用于解决一些方向性的问题

2.结对编程中,双方的互动目的在于开启思路,避免单独编程时思维容易阻塞的情况。

3.对于自己不完全理解的任务,以及耦合度较高的任务,结对编程可以大大缩短调试及测试的时间。

4.结对编程可以让别人迅速地审查自己写的代码,避免了很多的陷阱和缺陷。

5.结对编程可以让同组的人分享关于系统细节的知识,并且互相学习编程技巧。

 

  但是结对编程也有一些缺点。虽然它一定程度地缩短了开发时间,而且对代码质量产生了正的边际效益,但是它同时增加了开发人员的工作时间,也就是说与单独编程相比花费增加了。所以我觉得在开发过程中,应该先尽量将任务分解成独立的模块,各干各活,在模块之间发生耦合的时候再进行结对编程,这样可以让效率最大化。

到此为止,本来以为就能这样结束软工作业。但是,噩梦才刚刚开始

  • 对接

                本来以为直接用.h就好,但是老师要求要用dll。这确实有好处。于是我们又开始上网查资料对接,在这过程中又学到了好多好多东西。下面详细给出:

                总共有三种方法:

    1. 使用Win32 API
      在显式链接下,应用程序必须进行函数 调用以在运行时显式加载 DLL。为显式链接到 DLL,应用程序必须:
      调用 LoadLibrary(或相似的函 数)以加载 DLL 和获取模块句柄。
       调用 GetProcAddress,以获 取指向应用程序要调用的每个导出函数的函数指针。由于应用程序是通过指针调用 DLL 的函数,编译器不生成外部引 用,故无需与导入库链接。
      使用完 DLL 后调用 FreeLibrary。但是我们用的Qt,所以当然不用他啦。
    2. #include <QApplication>  
      #include <QDebug>  
      extern "C"    //由于是C版的dll文件,在C++中引入其头文件要加extern "C" {},注意  
      {  
              #include "dll.h"  
      } 
       int main(int argv ,char **argv)  
      {  
             QApplication app(argv,argv);  
             HelloWordl();          //调用Win32 API 弹出helloworld对话框  
             qDebug()<<add(5,6);    // dll 中我自己写的一个加法函数  
             return 0;  //完成使命后,直接退出,不让它进入事件循环  
      }  

隐式调用

    这个时候我们需要三个文件,头文件(.h)、导入库文件(.lib)、动态链接库(.dll),具体步骤如下:

1、首先我们把 .h 与 .lib/.a 文件复制到程序当前目录下,然后再把dll文件复制到程序的输出目录,

2、下面我们在pro文件中,添加 .lib 文件的位置: LIBS+= -L D:/hitempt/api/ -l myDLL

         -L 参数指定 .lib/.a 文件的位置

         -l  参数指定导入库文件名(不要加扩展名) 

         另外,导入库文件的路径中,反斜杠用的是向右倾斜的 

3、在程序中include头文件(我试验用的dll是用C写的,因此要用 extern "C" { #include "dll.h" } )

 上面是隐式调用的实例代码。

隐式调用相当简洁,但是我们尝试了一天,用尽各种办法之后,就是有问题。最终我们得知,我们的编译器不支持。我们以不知道这是什么鬼畜原因,然后就只能尝试最麻烦的显示调用

3.显示调用

#include <QApplication>  
#include <QLibrary>  
#include <QDebug>  
#include <QMessageBox>  
#include "dll.h"             //引入头文件  
typedef int (*Fun)(int,int); //定义函数指针,以备调用  
int main(int argc,char **argv)  
{  
    QApplication app(argc,argv);  
    QLibrary mylib("myDLL.dll");   //声明所用到的dll文件  
    int result;  
    if (mylib.load())              //判断是否正确加载  
    {  
        QMessageBox::information(NULL,"OK","DLL load is OK!");  
        Fun open=(Fun)mylib.resolve("add");    //援引 add() 函数  
        if (open)                  //是否成功连接上 add() 函数  
        {  
            QMessageBox::information(NULL,"OK","Link to Function is OK!");  
            result=open(5,6);      //这里函数指针调用dll中的 add() 函数  
            qDebug()<<result;  
        }  
        else  
            QMessageBox::information(NULL,"NO","Linke to Function is not OK!!!!");  
    }  
    else  
        QMessageBox::information(NULL,"NO","DLL is not loaded!");  
        return 0;  //加载失败则退出28}  

如上,每个函数都要改,可以说是相当麻烦了。而且每个组的函数名还不一样,所以对接是一项非常单调有无聊的工作。

这并不算完。

由于采用了显式调用,函数名是必须要知道的。但是我也不知到为什么反正core组的函数名就是不是简简单单看到的那样,而是还要加上各种乱七八糟的东西。没有经验的我们又卡了老半天。最后用了个什么depend看了函数名,最后才终于可以用了。

然后就是对接操作。前两组设置和调用方式差不多,都是结构体设置+数组存储,对接起来稍快。后来有的组参数稍多,设置方式不同,存取模式也不一样,有的又是文件读取,修改复杂度很大。不同编译器又时不时的叫错,相当繁琐。值得高兴的是,大部分组的鲁棒性都很好,极少出现崩溃的情况。

对接收获:

  1. 接口应该一开始就商量好,否则每一组都会改,相当麻烦。
  2. 没事别一开始就搞后果教育,我并不是非要栽跟头才能听进去。

小结:

说了这么多,以上都是次要的。这次结对作业最最重要的收获当然是磨练了我的意志品质,培养了我细致耐心的性格,自我情绪管理以及欠多少作业都不慌的淡定。

 

原文地址:https://www.cnblogs.com/ustcccj/p/8884606.html