结对编程收获

Posted eeom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结对编程收获相关的知识,希望对你有一定的参考价值。

结对编程收获

 

这次编程作业一路走来,学到了很多编程中实际很有用的东西,比如总体框架的设计,真的不能自己瞎想,应该到网上去查找相似的代码,先把别人代码的框架大致都看懂了,最好多看几份代码,比较一下几个框架的优点和缺点,然后在写代码之前规划好每个函数的输入输出,只有这样才算有点高年级同学写代码的样子。虽然在作业过程中,甲方的要求一直在改变,但是当你有了一个整体的框架感后,重构起来也能有全局感。

 

总体架构的设计启发

总体结构包括两个类,fomularNode和fomularCore,前者是表达式树的节点,包括必要的成员信息,后者是主要模块,public函数包括Calc Generate setting等主要函数。实现这些类的时候,对C++的public,private相关用法更加熟悉了。其实感觉现在C中的struct也可以这样写了。
其实我现在是学习安全出身的,所以区分private和public的意义我还是很清楚的,但是感觉我们这次作业应该会没有那个黑客闲着回来攻击我们。。。所以个人想法还是尽可能地还是用public,这样使得高层类不会重复调用底层类的组合引发错误。最后再根据实际情况改为private。当然如果真正地去写一些应用的软件的时候,写的时候还是要以安全第一。

    class fomularNode
    {
    public:
        int value;
        bool chFlag;//if true,value is ascii
        fomularNode* lchild;
        fomularNode* rchild;
        fomularNode() :value(0),chFlag(false),lchild(NULL),rchild(NULL){}
        fomularNode(int val, bool flag, fomularNode* lch=NULL, fomularNode* rch=NULL)
        {
            value = val;
            chFlag = flag;
            lchild = lch;
            rchild = rch;
        }
    };

    class fomularCore
    {
    private:
        vector<fomularNode*> fomulars;
        vector<char> ops = {‘+‘,‘-‘,‘*‘,‘/‘,‘^‘,‘(‘,‘)‘};//all ops 需要保持最后两个是括号!
        vector<string> finalRes;//最终结果,和Generate返回值一一对应
        int maxopNum = 5;//每个表达式中运算符个数
        int range = 100;//操作数数的上限
        int precise = 2;//输出精度(最大为6)
        int fomuNum;//表达式个数
        int MaxRange = 100000;//运算中出现的最大数
        bool fractionflag = true;//是否进行分数运算
        double result[MAX_FOMU_NUM];//原始字符串运算结果
        bool okFlag[MAX_FOMU_NUM];//判断原始字符串是否符合要求
    public:
          //省略  
    }    



实现的主要类函数包括:


    COREDLL_API string Calc(string inputFomu)
        {
            int multi;
            int tp;
            string tpFomu;
            long res;
            multi=findMultiple(inputFomu);

            if (fractionflag&&multi != 1&&!withDot(inputFomu))//有浮点‘.‘就认为不是分数运算
            {
                tpFomu.append(to_string(multi));
                tpFomu.append("*(");
                tpFomu.append(inputFomu).push_back(‘)‘);
                res = int(arthimetic(tpFomu));
                tp = gcd(res, multi);
                tpFomu = to_string(int(res/tp));
                if(multi/tp!=1)
                    tpFomu.append("/").append(to_string(multi/tp));
                return tpFomu;
            }
            else
            {
                //这里似乎有概率访问越界
                tpFomu=to_string(arthimetic(inputFomu));
                for (int i = 0; i < 6 - precise; i++)
                    tpFomu.pop_back();
                return tpFomu;
            }
        }

        COREDLL_API vector<string> Generate()
        {

            vector<string> rawFomu;
            vector<fomularNode*> judgedFomu;
            vector<string> finalFomu;


            rawFomu = geneExp(3*fomuNum);//3是可选参数,保证能选出符合要求个数的表达式

            toPostTree(rawFomu);//建树
            toJudgeTree();//判断是否符合要求

            for (size_t i = 0; i < fomulars.size(); i++)
            {
                if (okFlag[i] == true)
                    judgedFomu.push_back(fomulars[i]);//选出合适的树
            }


            finalFomu=fomusToStr(judgedFomu);//树转表达式,去除多余括号

            for (size_t i = 0; i < finalFomu.size(); i++)
            {
                //cout << finalFomu[i] << ‘=‘;
                //cout << Calc(finalFomu[i]) << endl;//测试输出
                finalRes.push_back(Calc(finalFomu[i]));
            }

            return finalFomu;
        }

        COREDLL_API vector<string> getRes()
        {
            return finalRes;
        }

        COREDLL_API bool settingXml(string path)
        {
            //xml方式setting
            string tpop;
            ReadXml(path, fomuNum, maxopNum, range, tpop, fractionflag, precise);
            for (size_t i = 0; i < ops.size(); i++)
            {
                ops.push_back(tpop[i]);
            }
            return true;
        }

        COREDLL_API bool setting(int foN,int maxopN,int MaxR,string op,bool fraction,int preci)
        {
            //非xml方式的setting
            fomuNum = foN;
            maxopNum = maxopN;
            range = MaxR;
            ops.clear();
            for (size_t i = 0; i < op.size(); i++)
            {
                ops.push_back(op[i]);
            }
            fractionflag = fraction;
            precise = preci;
            return true;
        }
 

从bug收获的

变量的取名真的很重要!!检查发现是判断二叉树是否相同的子函数的变量名写错了,左子树 lch 和右子树 rch 使用错误,再次阅读时也难以发现,说明一个好的变量名的重要性。

 

界面模块,测试模块和核心模块的松耦合

本次课程UI组和Core组的划分,让我对MVC原则理解更深刻了。具体来说,Core组主要负责程序核心(Model),UI 组的工作主要是用户交互(Controller)和数据显示(View)。当然,Core和UI组的功能划分也没有这么详细,具体情况具体分析,主要还是看编程者的思路。 具体对接的时候,有的UI组做的东西多,其实把core的一部分也做进来了,所以对接的时候还是很麻烦的。

 

感觉xml真心好用

这次xml读写部分是我写的,感觉xml读写方式真心好用,虽然最后貌似没有UI组用xml,大家都是通过函数接口直接通信的。但是涉及到不同的语言的交互,xml就能发挥它的威力了,比如我用C#写一个UI,用matlab写一个core,这个时候用xml就很方便了。而且相较于txt,xml应该不会受到编码方式以及其他各种格式的影响。

 

我认为个人作业和结对编程的区别

这次作业最大的收获就是明白了结对编程的意义,有一个好的队友真地很重要。在和队友结对编程的过程中,能看到对方的优点,同时看到自己的缺点,队伍里两个人由此都能得到巨大的进步。从开发层次来说,编写的代码同时经过2个人的眼睛,设计质量和代码质量都有了很大的提高,同时代码也更加规范了,因为谁也用不惯对方的代码风格,最后更多地偏向于书上提供的规范。同时,在这次结对编程中,认为马同学解决问题的能力很强,在难以描述的bug面前,总能在很短时间内解决问题,给我们的结对编程工作带来更大的信心以及更高的满足感。同时我们不断地编程过程,就是不断的复审过程,因为我们的一举一动都在对方的视线之内,在这种督促的压力下,我们的工作显得更加认真,并且我们要提高自己能力不让对方小看。结对编程使这次作业开发流程显得更加规范。

 

走上工作岗位之后,是否会采用结对编程?

走上工作岗位之后,很大概率不会采用结对编程。当然,培训新人的时候可能会考虑。因为结对编程特别适合于知识的分享和传递,特别适合于帮助开发者快速熟悉自己所不熟悉的领域。更多情况下是两个人水平相似,因此结对编程有浪费时间的嫌疑。另外结对编程的双方如果性格不合(这点概率是很大的),可能陷入很多的争吵,而导致进度停滞不前。而且结对要求结对的双方都要保证有充沛的精力,因为很容易疲劳。最后,结对编程不能完全替代代码评审,虽然结对编程对代码的审核程度比代码评审更加细致,但两个结对的人有一定的思维趋同性,从而忽略同样的问题。

 

结对编程,教会我什么

这两次作业给以后开发流程有很多可以借鉴的地方,其中个人感觉最重要的一点是要跑在时间前面,因为我(陈灿)第一次个人作业是在截至时间前一分钟提交的。把事情留在最后,的确能提高时间的效率,但是这是在拿自己project的质量冒险,因为在软件开发的过程中,可能会有各种各样的bug跳出来,而且在太大压力下编写的程序很大概率会有一些潜在的bug。在接下工程的那天开始,就得有一个详细的计划,规定XX天之前必须完成什么阶段。而且还要有足够的时间余量,来应对突发情况,这才是一个合格的程序员应该具备的素养。

以上是关于结对编程收获的主要内容,如果未能解决你的问题,请参考以下文章

结对编程收获

结对编程总结,收获和教训:by张惠雨&梁佳佳

结对编程收获

结对编程收获

结对编程收获

结对编程收获-Core10组-PB16110698