Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this design over-engineering?

Would you consider using an interface and polymorphism to extend this design to be over-engineering?

Pros

  • Extensible
  • Encapsulated
  • Auto-magical

Cons

  • Lots more code
  • A little bulky to use (you have to use a different type name to get the different behaviour)
  • May be less efficient to use due to virtual function calls.

My instinct is that, for this particular case, a single if statement and a boolean flag is the superior option, but not everybody has agreed with me.

What do you think?


Original

// 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;
};

Extended with a boolean flag

// 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;
};

Extended with polymorphism

// 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;
};
like image 275
Lightness Races in Orbit Avatar asked Mar 23 '11 10:03

Lightness Races in Orbit


People also ask

What do you call over engineering?

Overengineering (or over-engineering), is the act of designing a product or providing a solution to a problem in an elaborate or complicated manner, where a simpler solution can be demonstrated to exist with the same efficiency and effectiveness as that of the original design.

What does it mean when something is over engineered?

Definition of overengineer transitive + intransitive. : to engineer (something, such as a product) to have more functions, capabilities, etc. than are necessary or desirable The pressure to overreact to feedback … will lead many companies to overengineer their products, until common sense kicks back in.—

Are some products over engineered?

Other examples of overengineering are less positive. In the US, a start-up called Juicero developed a juicing press to squeeze out their pre-prepared juice pouches. The press cost over $400 and faced huge criticism when consumers discovered that the juice could be squeezed out just as effectively by hand.

What is over engineering in software?

According to Wikipedia, overengineering is "the act of designing a product to be more robust or have more features than often necessary for its intended use, or for a process to be unnecessarily complex or inefficient" To be honest, this is not very helpful - especially for software developers.


1 Answers

It depends on what you will use it for. If you have a big project and will use variants of the class many times then certainly it makes sense to make it flexible.

A rule of thumb:

  1. Use it once - just keep it simple.
  2. Use it twice - Keep it simple and make a copy and change as needed
  3. Three or more - Generalise it and make it work for all cases.

Of course there are many exceptions, but that is a starting point.

like image 157
Michael J Avatar answered Nov 04 '22 22:11

Michael J