zoukankan      html  css  js  c++  java
  • 结对编程收获

     
     

    结对编程收获

    沈三景 软件工程 结对编程


     

    前言

    本次结对编程,过程异常坎坷,遇到了很多以前没有遇到过的问题,比如:如何写API文档才能让UI组更加容易读懂,如何定义接口,如何封装代码等等。但是结果还算不错,学会了一些在正常上课过程中没法学到的东西。


     

    结对编程

    在结对编程中,比起个人作业多出了两个人交流以及分工的部分,两人分别承担驾驶员和领航员的角色的模式,“驾驶员”负责具体的编码工作,“领航员”则负责检查,及时纠正代码中的问题。结对编程的形式使得代码处于不断地审查过程,每一段代码都由一个人编写,另一个人检查,最大程度上减少了出现bug的可能。在本次结对编程作业中,为了更好的体验驾驶员和领航员的角色,我和队友商量了一下后决定由队友写generate(),我写calc()。在写generate()时,队友担任驾驶员,我担任领航员,负责审查;在写calc()时,则相反。


     

    calc()函数的一些想法

    刚开始我打算先通过二叉树将中缀表达式转化为后缀表达式,然后用堆栈处理后缀表达式,由于题目要求所有的计算步骤中都不允许出现负数,所以可以通过二叉树的左右子树交换的方式来规避负数的出现(即出现负数就交换)。但是后来看了顾老师的课件(当时在复习二叉树)发现可以将中缀表达式直接通过堆栈的方式来计算(这里要求构造两个栈,一个存操作数,另一个存运算符)当时就感觉我应该好好复习数据结构了。言归正传,下面附上calc()的全部代码(篇幅限制没有给出里面函数的代码):

    int calc(vector<string> &vs, vector<string> &vscal)
    {
        string str;
        vector<string> vstr;
        stack<string> OPND;
        stack<string> OPTR;
        for (int q = 0; q < vs.size(); q++)
        {
            str = vs[q];
            splitstr(vstr, str);
            OPTR.push("#");
            int i = 1;
            int k = 0;
            int sumsub = 0;
            int foundsub = 0;
            string op;
            string a, b, c;
            double doublea, doubleb, doublec;
            map<int, int> order1, order2;
            for (int j = 0; j < vstr.size(); j++)
            {
                order1[j] = j;
                order2[j] = j;
            }
            while (1)
            {
                if (!isoptr(vstr[i]))
                {
                    OPND.push(vstr[i]);
                    i++;
                    continue;
                }
                else
                {
                    while (1)
                    {
                        op = OPTR.top();
                        switch (cmp(op, vstr[i]))
                        {
                        case 0:
                            b = OPND.top();
                            OPND.pop();
                            a = OPND.top();
                            OPND.pop();
                            OPTR.pop();
                            stringtodouble(b, doubleb);
                            stringtodouble(a, doublea);
                            if (op == "+")
                            {
                                doublec = doublea + doubleb;
                                doubletostring(c, doublec);
                                OPND.push(c);
                            }
                            if (op == "-")
                            {
                                sumsub++;
                                doublec = doublea - doubleb;
                                if (doublec < 0)
                                {
                                    doublec = doubleb - doublea;
                                    for (k = 0; k < vstr.size(); k++)
                                    {
                                        if (vstr[k] == "-")
                                        {
                                            foundsub++;
                                        }
                                        if (foundsub == sumsub)
                                        {
                                            break;
                                        }
                                    }
                                    int k1 = k, k2 = k;
                                    k1--;
                                    k2++;
                                    while (vstr[k1] != "+" && vstr[k1] != "-" && vstr[k1] != "#")
                                    {
                                        k1--;
                                    }
                                    while (vstr[k2] != "+" && vstr[k2] != "-" && vstr[k2] != "#")
                                    {
                                        k2++;
                                    }
                                    int s;
                                    for (s = 1; s < k2 - k; s++)
                                    {
                                        order2[k1 + s] = order1[k + s];
                                    }
                                    order2[k1 + s] = k;
                                    int t = k1 + s;
                                    for (s = 1; s < k - k1; s++)
                                    {
                                        order2[t + s] = order1[k1 + s];
                                    }
                                    doubletostring(c, doublec);
                                    OPND.push(c);
                                }
                                else
                                {
                                    doubletostring(c, doublec);
                                    OPND.push(c);
                                }
                            }
                            if (op == "*")
                            {
                                doublec = doublea * doubleb;
                                doubletostring(c, doublec);
                                OPND.push(c);
                            }
                            if (op == "/")
                            {
                                doublec = doublea / doubleb;
                                doubletostring(c, doublec);
                                OPND.push(c);
                            }
                            break;
                        case 1:
                            OPTR.push(vstr[i]);
                            break;
                        case 2:
                            OPTR.pop();
                            break;
                        default:
                            break;
                        }
                        if (cmp(op, vstr[i]) != 0)
                        {
                            break;
                        }
                    }
                }
    
                if (vstr[i] == "#" && OPTR.top() == "#")
                {
                    break;
                }
                i++;
            }
            string ans;
            ans = OPND.top();
            string anscal = "";
            for (int i = 1; i < vstr.size() - 1; i++)
            {
                //          cout << vstr[order2[i]];
                anscal += vstr[order2[i]];
            }
            anscal += "=";
            //      cout << "=";
            anscal += ans;
            //      cout << ans;
            vscal.push_back(anscal);
            vstr.clear();
            while (!OPND.empty())
            {
                OPND.pop();
            }
            while (!OPTR.empty())
            {
                OPTR.pop();
            }
        }
        return 0;
    }
    

    算法的思想如下:
    堆.png-69.8kB
    从上面的代码可以看出,我已经养成了一定的代码规范,如:

    • {}各占一行
    • 缩进,一般以4个空格
    • 行宽,不多于100个字符
    • 命名有一定的实际意思,诸如判断运算符的函数命名为isoptr()

    这也算是学这门课的一个收获吧。


     

    关于封装的一些想法

    查了Google,数据封装是一种把数据和操作数据的函数捆绑在一起的机制,是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。对于本次实验来说我们要写很多函数,这有利于代码维护。但是我们只需提供一个接口,UI组不需要关心我们内部的具体结构,不需要实际细节,就能够使用我们的core。我们刚开始打算用dll封装,但是查了一些资料,以及在按照常规套路进行一番操作之后,发现并不能封装成DLL,编译器报错说是找不到文件(文件明明都在啊……),忙了一段时间之后还是不能解决,请教了以及封装好的组,还是解决不了。于是弃疗直接用头文件加上命名空间来与UI组对接,在对接过程中也出现了许多问题,比如:IDE不能识别加进去的头文件,解决办法:在IDE里添加新的空文件,然后将代码复制过去。(至今没有明白这是为啥)


     

    关于接口的一些想法

    有部分UI组使用内存操作的,另外的一些组是通过文件的方式操作,所以我们定义了两套接口,具体情况如下:

    • 通过文件操作:
      参数说明:
      numofques:算式总数
      numofopera:最多产生的运算符个数
      range:操作数范围
      accuracy:精度,取值范围为0~4,表示小数点后0~4位,超出范围取0或4
      zerodiv:是否支持整除,true表示支持整除,此时精度无效

      函数说明:
      GenerateNobrackets:产生不带括号的算式,结果需要另外计算
      Generatebrackets:产生带括号的算式,结果可以直接在产生时计算

      函数原型:
      void GenerateNobrackets(int numofques, int numofopera, int range, int accuracy, bool zerodiv);
      void Generatebrackets(int numofques, int numofopera, int range, int accuracy, bool zerodiv);

      调用函数后产生的算式存在result.txt,算式结果存在key.txt

    • 通过内存操作
      参数说明:
      numofques:算式总数
      numofopera:最多产生的运算符个数
      range:操作数范围
      accuracy:精度,取值范围为0~4,表示小数点后0~4位,超出范围取0或4
      zerodiv:是否支持整除,true表示支持整除,此时精度无效

      函数说明:
      GenerateNobrackets:产生不带括号的算式,结果需要另外计算
      Generatebrackets:产生带括号的算式,结果可以直接在产生时计算

      函数原型:
      void GenerateNobrackets(vector &vs, vector &vscal,int numofques, int numofopera, int range, int accuracy, bool zerodiv);
      void Generatebrackets(vector &vs, vector &vscal,int numofques, int numofopera, int range, int accuracy, bool zerodiv);

      调用函数后产生的算式存在vs里面,算式结果存在vscal里面


     

    关于Debug的一些想法

    Debug是一个老大难的问题,我本人也是十分畏惧Debug,对于一些编译不通过的bug还好说,但是对于一些运行中出现的error就十分的头疼,比如越界,非法访问内存地址。所幸这次是结对编程,队友很carry,有时候很低级的错误自己打死发现不了,但是队友能够一眼看出,这大大的提高Debug的效率,做到了优势互补。


     

    关于对接

    刚开始对接很不顺利,因为第一组是用文件进行操作的,而我们是用vector方式传递数据,这就很头疼,最后我觉得其它UI组也可能用文件进行操作,于是就添加了file版本,最终在我给出file版本后,那一组仅仅用了不到20分钟就对接完成(目前最快的一组不到十分钟就完成了,haha)。


     

    关于本次结对编程的想法与收获

    1. 最大的收获就是一个良好的接口应该在一开始就和 UI组商量好, 例如给UI需要哪些数据,是用什么形式封装,这样封装会产生哪些问题,这些问题该怎么解决诸如此类。一个好的接口可以简化使用,更好的体现功能,也可以将内部的实现隐藏起来,保护程序不被修改,事半功倍。
    2. 结对编程能够很大的提高效率,特别是队友比较可靠的时候。
    3. 要多与UI组沟通,这个沟通不仅仅是刚开始时的沟通,而是在编程时,尽可能的多交流,这样才能及时发现对接上的一些问题,真正做到敏捷原则。
  • 相关阅读:
    jdk1.7下载
    Java导入导出Excel工具类ExcelUtil
    对接支付宝沙箱测试代码参数设置
    对接支付宝遇到的坑sign check fail: check Sign and Data Fail
    eclipse 如何配置activity(无网络状态下)
    Redis的总结
    java实现给pdf文件加水印!
    java中位移算法!
    spring整合springmvc案例
    读书笔记
  • 原文地址:https://www.cnblogs.com/sanjing/p/8894177.html
Copyright © 2011-2022 走看看