• Coding道场:第一次


    10/23日,我在部门内部进行了一次内部学习,使用目前流行的Coding Dojo(道场)方式,进行了TDD开发的演练。演练的题目如下:
     
     
    有关Coding道场的介绍,请自行百度一下,我就不再多做介绍了。
     
    从效果来看,基本达到了传达TDD是什么样的开发方式的目的。尤其是大家从最初满脑子如何实现这个程序,怎样去设计算法,逐渐转变为了先想如何测试,从最简单的实现开始,最终演化成最终的设计。当然,目前为止,参加人员也只是理解了TDD是一个什么样的开发方式而已,还谈不到真正使用TDD进行开发。这需要一个更加长期的自我训练和使用的过程。使用TDD,最主要的是一种思维方式的变化。
    首先:要坚信所有的程序皆可测,如果不能测试,不是产品的特性导致,而是自己的能力不足导致,设计上有问题。因此必须从设计上加以改变,使得程序可测。如一般认为曲线的显示是否正常,是无法使用自动测试的。换个角度:如果显示只是一个数据-坐标的转换的话,测试的重点就变成了数据是否正确,而这一点是完全可测的。
    其次:虽然需要全局的考虑,但是要从简单入手,演进式设计。
    这一点,在本次道场演练中体现的就很明显,此次道场开始,很多人的想法就是,建立某种算法,将需要的字符显示出来。于是第一个函数就是:void DisplaySegmentDigital(String input),然后再写那些子函数。如何测试这个函数?这是一个输出到屏幕显示的函数,它只能用眼来判断,显然不适合自动测试或者单元测试。所以,TDD不是一个先实现框架,再实现具体功能的做法。输出到屏幕,只是最后的一个过程,也是一个简单的过程,因此可以不必作为重点。重点在于显示的数据是什么?所以,函数就变为了:String DisplaySegmentDigital(String input)。这个时候,这个函数不再是向屏幕输出,而是输出一个字符串,再由另外一个字符串显示函数完成向屏幕的输出。而原来这个函数就变得可测了。于是,第一个测试函数被写出来了:
    String strText = "910"; String strTextResult = "._.|_|..|.....|..|._.|.||_|";  
    String strOutput = digitalSegment.DisplaySegmentDigital(strText);   
    assertEquals(strOutput , strTextResult);
    第一个测试顺利通过,因为实现非常简单:
    public String DisplaySegmentDigital(String strText) {
        return "._.|_|..|.....|..|._.|.||_|";
    }
    接下来的困难是:下一个测试什么?测试“3456”的输出?OK,我们先试试看,于是我们想写第二个测试:

    String strText = "3456"; String strTextResult = "????????";

    问题接着出来了:这串问号该填什么?这样测试真的有意义么?几乎所有的人都直觉得发现这里有问题。简短的讨论后,结论是应该测试每个数字的显示,而非一个字符串。于是,测试变为:

    String strText = "9"; String strTextResult = "._.|_|..|";  

    String strOutput = digitalSegment.DisplaySegmentDigital(strText);  

    assertEquals(strOutput , strTextResult);

    实现变为:

    public String DisplaySegmentDigital(String strText) {

     if(strText == "9")

      return "._.|_|..|";

     else

      return null;

    }

    实现后,接着测试:

    strText = "1"; strTextResult = ".....|..|";  

    strOutput = digitalSegment.DisplaySegmentDigital(strText);  

    assertEquals(strOutput , strTextResult);

    实现也变为:

    public String DisplaySegmentDigital(String strText) {

     String[] strResult=new String[10];

     strResult[0]="._.|.||_|";

     strResult[1]=".....|..|";

     strResult[9]="._.|_|..|";

     return strResult[Integer.parseInt(strText)];

    }

    至此,很显然我们的算法也就自然而然的诞生了。可能与很多人自己开始的算法设计不太一样,但也不应该差到哪里:)。这就是TDD演进式设计。

    但有个问题,._.|_|..|是什么东东?我怎么知道最终输出是正确的。因此,我们稍微改变了一下写法:

    String strText = "9";   String strTextResult = "._." +
                                                                     "|_|" +
                                                                      "..|";     

    String strOutput = digitalSegment.DisplaySegmentDigital(strText);

    assertEquals(strOutput , strTextResult);

    strText = "1";   

    strTextResult = "..." +

                            "..|" +

                            "..|";     

    strOutput = digitalSegment.DisplaySegmentDigital(strText);      

    assertEquals(strOutput , strTextResult);

    实现变为:

    public String DisplaySegmentDigital(String strText) {

     String[] strResult=new String[10];

     strResult[0]="._." +

                         "|.|" +

                         "|_|";

     strResult[1]="..." +

                         "..|" +

                         "..|";

     strResult[9]="._." +

                        "|_|" +

                         "..|"; 

     return strResult[Integer.parseInt(strText)];

    }

    现在直观多了。

    为什么一定要变得直观,其目的不单纯是为了程序的易读性,更重要的是:测试不应该抄实现的代码,实现也不要抄测试的代码,否则后果很严重。写测试代码时,必须是含着测试的心态,含着使用者的心态去写测试代码,而非一门心思去想实现。如果这样,TDD就失败了。这也是为什么TDD要求先写测试代码,再写实现代码的原因。因为我们一旦先想到了实现,那么接下来的测试,必然会跟着实现的逻辑走,从而违背“测试独立性”的原则。实现发生错误,测试也无法发现。

    接下来需要整理一下代码,显然DisplaySegmentDigital这个函数名不是那么准确,后来议论了一番,得出的名字是:GetDigitalDisplayContent。结束后,我想GetDigitalFont可能更好。

    好了,有关第一次道场就写到这里,留一个小小的问题:到目前为止我们还没有设计显示的算法。为了便于输出,目前的设计如何改进?

  • 相关阅读:
    LVM磁盘逻辑卷扩容
    confluence 搭建总结
    GTX1050ti安装tensorflow2.0(gpu)
    sublime text 配置 markdown和预览
    Python 程序打包成 exe 可执行文件
    devc++ 配置openCV
    Ubuntu安装sublime text3
    sublime text 配置Miniconda编译环境
    sublime text 配置devc++ 编译环境
    2013-03-27 problem2 A Famous ICPC Team
  • 原文地址:https://www.cnblogs.com/Wangyong-Wen/p/4047842.html
Copyright © 2020-2023  润新知