这种设计是否过度工程化?

时间:2011-03-23 10:36:57

标签: c++ polymorphism

您是否会考虑使用接口和多态来扩展此设计以进行过度设计?

赞成

  • 可扩展
  • 封装
  • 自动神奇

缺点

  • 更多代码
  • 使用起来有点笨重(你必须使用不同的类型名称才能获得不同的行为)
  • 由于虚函数调用,
  • May 的使用效率较低。

我的直觉是,对于这种特殊情况,单个if语句和布尔标志是优越的选择,但不是每个人都同意我。

的想法是什么?


原始

// Connects to a local pipe, and naturally
// owns that connection
struct CommandWriter
{
   CommandWriter() {
       fd = open("/path/to/fifo", O_WRONLY);
       if (fd == -1)
           throw std::runtime_error("Could not establish connection to FIFO");
   };

   ~CommandWriter() {
       close(fd);
   };

   // (Has useful member functions here)

   private:
      CommandWriter(CommandWriter const&); // Not relevant to question

      int fd;
};

使用布尔标志扩展

// Adds a constructor where an FD can be specified
// from the call site, and no ownership is taken
struct CommandWriter
{
   CommandWriter() : owns_fd(true) {
       fd = open("/path/to/fifo", O_WRONLY);
       if (fd == -1)
           throw std::runtime_error("Could not establish connection to FIFO");
   };

   CommandWriter(int fd) : fd(fd), owns_fd(false) {};

   ~CommandWriter() {
       if (owns_fd)
          close(fd);
   };

   // (Has useful member functions here)

   private:
      CommandWriter(CommandWriter const&); // Not relevant to question

      int  fd;
      bool owns_fd;
};

使用多态扩展

// Sorry for the poor type names!
struct ICommandWriter
{
   virtual ICommandWriter() {}

   // (Has useful member functions here)

   private:
      ICommandWriter(ICommandWriter const&); // Not relevant to question
};

struct CommandWriter_Connects : ICommandWriter
{
   CommandWriter_Connects() {
       fd = open("/path/to/fifo", O_WRONLY);
       if (fd == -1)
           throw std::runtime_error("Could not establish connection to FIFO");
   };

   ~CommandWriter_Connects() {
       close(fd);
   };

   // (Has useful member functions here)

   private:
      int fd;
};

struct CommandWriter_Uses : ICommandWriter
{
   CommandWriter_Uses(int fd) : fd(fd) {};

   ~CommandWriter_Uses() {};

   // (Has useful member functions here)

   private:
      int fd;
};

6 个答案:

答案 0 :(得分:9)

这取决于你将使用它。如果你有一个大项目,并且会多次使用该类的变体,那么确保它具有灵活性是有意义的。

经验法则:

  1. 使用一次 - 只需保持简单。
  2. 使用它两次 - 保持简单并根据需要进行复制和更改
  3. 三个或更多 - 概括它并使其适用于所有情况。
  4. 当然有很多例外,但这是一个起点。

答案 1 :(得分:7)

为什么不只是duplicate文件描述符?这样,当对象被销毁时,您可以关闭它()并让操作系统处理剩下的事情:

CommandWriter::CommandWriter (int _fd) : fd (dup (_fd)) {};

为此添加一个布尔标志就是发明了一个轮子。使用多态性正在构建一架frigging直升机。

答案 2 :(得分:1)

我同意你的意见,布尔解决方案在这里是合适的,如果你不希望将来添加更多功能。

另一种解决方案是使用Strategy Pattern。这类似于Boost智能指针的自定义删除器。

答案 3 :(得分:1)

我认为过度工程。第二个代码片段更加简洁,使用起来非常简单。使用标志来表示对象的所有权并不是完全惯用的,但可以经常看到它,所以我认为大多数人会很快理解这个意图。

保持简单和愚蠢。

(如果确定将来需要添加更多代码路径,我更喜欢多态解决方案。)

答案 4 :(得分:1)

我更喜欢界面。原因是,界面的用户清楚可以有各种实现。也许在一个月内你需要实现一个CommandWriter来写一个db而不是一个文件(确定你甚至可以子类化布尔版本,但对于用户来说这并不是一个明显的接口)。

同样对于单元测试,我会说接口是更干净的方法,因为你可以为要测试的类和使用ICommandWriter的类实现存根。

但如上所述,如果您打算只使用一次,只需使用带有布尔标志的版本。

答案 5 :(得分:1)

在多态性代码中:

// (Has useful member functions here)

是吗?如果在所有三个地方(基类和两个派生类)中有很多成员函数,那么拥有和非拥有的编写者实际上是完全不同的野兽。最好将它们分成不同的类,而不是根据设置的构造函数根据设置的布尔标志来设置一个行为非常不同的类。

我怀疑所有有用的成员函数都在基类中,并且所有派生类都是更改构造和销毁。在那种情况下,我想要一个持有fd的smart_fd类并且知道如何处理它(你需要两种情况 - 调用close或什么都不做。shared_ptr允许任意破坏函数,但是你可能在这里不需要它。)

然后在CommandWriter中使用其中一个,并根据调用CommandWriter的构造函数对其进行不同的初始化。

经验法则:管理资源的类应该不做任何其他事情。