面向对象的多态(一)

昨天尝试向Nikey解释多态的用途,以失败告终。究其原因,一是没找到一个好的例子,二是Nikey实在没啥耐心听大段的长篇大论。现在尝试以博客的形式解释。

Nikey从事软件测试工作,脚本语言的初学者,写过一些小型自动化脚本,习惯于面向过程的思维(以函数来封装变化),还不太习惯于写伪代码,凡事要搞清楚细节,至少知道应该怎么实现。于是考虑,描述问题用的场景应该实用,贴近她的工作(而不是写什么bank,account之类的书本案例),伪代码不能太伪,至少她要知道怎么实现。

好,我们开始。Nikey最近的任务是网站测试,一个最简单的test case,打开一个网站,然后点击后退。这是一个国外的网站,所以要求同时兼容IE和Firefox。

首先,我们把测试脚本写出来。脚本很简单,描述每一个测试步骤。

void SimpleTestCase()
{
     Navigate();

     ValidateNavigate(); 

     Back();

     ValidateBack(); 

}

接下去要考虑的事情,就是看怎么实现具体的方法了。很幸运地,VS开始支持录制脚本了(类似QTP),所以我们不需要太担心如何调用浏览器的navigate和back操作,录制就好。针对navigate这个动作,我们针对IE和Firefox分别录了两次。

void NavigateInIE()
{
    //在IE打开网站
}

void NavidgateInFF()
{
    //在Firefox打开网站


但是在试图把这两个函数统一起来的时候碰到了点问题,VS能抓到IE的对象,所以NavigateInIE里面是对象调用。但VS抓不到FF的对象,所以NavigateInFF是以模拟鼠标点击的方式实现的。(以上纯属虚构,主要想表达的是,NavigateInIE和NavigateInFF这两个方法区别很大,没有任何共同点可以抽取,或者说抽取公有函数的价值不高。)同样的BackInIE()和BackInFF()也会碰到类似的问题。

那么我们的test script会变成什么样呢?

void SimpleTestCase(string browser)
{
    switch (browser)
    {
        case "IE":
            NavigateInIE();
        case "FF":
            NavigateInFF();
    }    
    ValidateNavigate(); 
    switch (browser)
    {
        case "IE":
            BackInIE();
        case "FF":
            BackInIE();
    }
    ValidateBack(); 
}

test script的可读性瞬间变差了N个级别,test script里面我们应该只关心测试需要做的事情(打开网站),而不要关心事情怎么做(怎么能让IE打开一个网站)。我们试着把事情怎么做这些细节封装起来。

void SimpleTestCase(string browser)
{
    Navigate(browser);    
    ValidateNavigate(); 
    Back(browser);
    ValidateBack(); 
}

void Navigate(string browser)
{
    switch (browser)
    {
        case "IE":
            NavigateInIE();
        case "FF":
            NavigateInFF();
    }    
}

void Back(string browser)
{
    switch (browser)
    {
        case "IE":
            BackInIE();
        case "FF":
            BackInFF();
    }
}

我们可爱的test script又回来了,很好维护,测试要调用的时候也很方便。在两个浏览器里面测试,只要调用下面两句代码即可。

SimpleTestCase("IE");
SimpleTestCase("FF");

整个世界干净了,但是似乎发现了那么点坏味道。我们说,代码尽量不要copy & paste,这会影响代码维护。但是回顾Navigate和Back这两个方法,会发现它们的共同点非常多,这样的代码有问题吗?

如果不发生变化,代码其实无所谓可维护性,反正是给机器看的。但据说不会变化的只有变化本身,于是...

市场部经理提出,现在Chrome的占有率比Firefox高了,我们应该把它列入到测试范围。看看我们需要做什么:

1、增加(录制)NavigateInChrome方法

2、增加(录制)BackInChrome方法

3、修改Navigate方法,为Chrome增加一条选择支

4、修改Back方法,为Chrome增加一条选择支

5、增加test script的调用,SimpleTestCase("Chrome")

其中3和4,它们的修改会非常相似,都是需要增加类似下面的代码。

case "Chrome":
     DosomethingInChrome(); 

想像一下,如果我们在测试过程中,用到的浏览器功能不只是navigate和back,还有其他的100个浏览器功能,那增加对Chrome支持的时候,我们不是要把上面的代码复制102次??有什么办法能解决这个问题呢?

原文地址:https://www.cnblogs.com/woodylic/p/2558707.html