我应该从哪个地方提取这个条件方法?

时间:2014-08-25 02:49:48

标签: c++ refactoring

如果我有一个方法属于A类,我想要提取的逻辑大部分都是关于B类的公共方法。我应该将这个逻辑提取到哪里?

  • A的私人方法?

    原因:它是从A的方法中提取的。

  • B的公共方法?

    原因:它描述了B级的状态。

  • 免费功能?

    原因:它不需要访问B的私人会员。

  • 还是总是取决于?

示例:

代码需要重构:

class Cat
{public:
    void eat(const CatFood& cf)
    {
        if(!cf.expired() && cf.flavor() == CatFood::Flavor::Tuna)
           std::cout << "Cat has eaten food." << std::endl;
        else
           std::cout << "Cat is hungry and still meow meow." << std::endl; 
    }
}

版本1:A的私有方法

class Cat
{public:
     void eat(const CatFood& cf)
     {
         if(can_eat(cf))
           std::cout << "Cat has eaten food." << std::endl;
        else
           std::cout << "Cat is hungry and still meow meow." << std::endl; 
     }

 private:
     bool can_eat(const CatFood& cf) const
     { 
         return !cf.expired() && cf.flavor() == CatFood::Flavor::Tuna;
     };
}

版本2:B的公共方法

Cat Cat
{public:
     void eat(const CatFood& cf)
     {
        if(cf.eatable_with_flavor(CatFood::Flavor::Tuna))
           std::cout << "Cat has eaten food." << std::endl;
        else
           std::cout << "Cat is hungry and still meow meow." << std::endl; 
     }
}

class Catfood
{
 public:
     bool eatable_with_flavor(CatFood::Flavor specific_flavor) const
     { 
         return !expired() && flavor() == specific_flavor;
     };

     bool expired(){...}
}

版本3:免费功能

Cat Cat
{public:
     void eat(const CatFood& cf)
     {
        if(eatable_with_flavor(cf, CatFood::Flavor::Tuna))
           std::cout << "Cat has eaten food." << std::endl;
        else
           std::cout << "Cat is hungry and still meow meow." << std::endl; 
     }
}

bool eatable_with_flavor(const CatFood& cf, CatFood::Flavor specific_flavor)
{ 
    return !cf.expired() && cf.flavor() == specific_flavor;
};

我总是使用版本1,因为它发生在A类中,只是简单地提取原始版本旁边的代码。而且我认为我提取的逻辑只描述了B类的状态,最好放入B类。之后,我观察到新方法中的代码只调用B的公共方法,最好把它放到免费中。功能。我被告知使函数成为成员函数的唯一原因是你需要访问类的私有成员,或者你应该使它成为一个自由函数。

这三个版本的外观有其原因。任何人都可以给我一个建议或指出我错在哪里。

btw:我应该为这种条件方法编写一个测试吗?因为它看起来很琐碎。但我知道尽可能多地测试功能是个好习惯。

1 个答案:

答案 0 :(得分:0)

这是一个很好的例子:Composition or inheritance?

由于isEatable目前仅依赖于CatFood,因此将其置于CatFood中是最自然的决定。然而,当你开始问:我下一步会去哪里时,往往会出现真正有趣的问题(以及答案)?如果您想添加DogDogFood,可能会继承与CatCatFood相同的基类,该怎么办?如果那么isEatable可能会突然依赖于想要吃它的Animal(根据我自己的经验,年龄,在这个决定中扮演重要角色)会怎样?在考虑了这些问题后,您可以选择观察到最少耦合和可能还有其他好处的问题,或者......

您可以直接了解这一问题,并专注于在代码投入生产之前必须面对的所有其他问题。 :)