polymorphism, not just for interviews

If you have never watched/read anything by/about Richard Feynman you need to stop reading this post right now! There is a marathon to be done. He was a brilliant man with an amazing ability to de-construct complicated concepts into laymen-friendly terms. In this video, he talks about the difference between knowing something and knowing the name of something. But he also points out the importance of having a common language.

5:14 - what he forgot to tell me was that the knowing the names are things is useful if you want to talk to somebody else.

So it isn't surprising that a lot of people, including yours truly, do the following google search before going on job interviews. Ideally, this is simply a lexical refresher for the abstractions and concepts you already use in your everyday work. On the other hand, this could be real cramming.

In education, cramming ("mugging or swotting, from swot, akin to 'sweat', meaning 'to study with determination'") is the practice of working intensively to absorb large volumes of informational material in short amounts of time.

In which case the person doing the search is trying to pull the wool over your eyes and make themselves appear more equitable then they are. The reason for the interview. This is why you should never ask those "interview questions" at your interviews. (But this isn't an interview / interviewee / interviewer bashing post.)

While the post is inspired by a real work interaction, the code in the examples are all faked, and no names will be used. The villain of our clean code story will be Microsoft Bob a diligent employee but sometimes misunderstood.

BOB

Interview

Since 'C++' we have all gone OO happy with our general language choices. As a result polymorphism comes up in pretty much any interview for software engineering. And it better. This is something you really need to know as a software developer. One of those, makes your life easier bits of knowledge.

But at an interview, generally the person is asked what it is? MS Bob is ready with a good replay.

In object-oriented programming, polymorphism refers to a programming language's ability to process objects differently depending on their data type or class. More specifically, it is the ability to redefine methods for derived classes. - Google Define.

MS Bob even went into detailed examples of how it has been used in the past on project he has worked on.

Creating custom data access layer to work with different DBMS.

And so MS Bob gets hired. But do we really know if MS Bob understands polymorphism. For example, here Bob only worked on the project, another engineer may have created the structure which Bob was diligent enough to follow.

Work

Well the day to shine comes eventually to every developer where they create their own project from scratch. To the developer this is the moment of truth. MS Bob's moment came in the form of a calculator application. And our imaginary MS Bob wrote: full LinqPad example

void Main()  
{
  var m = new Math();
  m.process("add", 1, 2).Dump();
}

public class Math {

  public int process(string type, int n1, int n2) {
    int result;
    switch (type) {
      case "add":
      result = n1 + n2;
      break;

      ...

      case "div" :
      result = n1 / n2;
      break;

      default :
      result = 0;
      break;
    }
    return result;
  }
}

Needless to say, this solution lacks a level of elegance OO allows us. As result this solution
- hard to expand on. Adding a new operation for example will require a full round of testing for all the other features.
- doesn't embody the concept of separation of concerns - hard to unit test because each test ends up testing multiple concerns. - not to mention the needless increase in cyclomatic complexity.

MS Bob's switch case had to go.

Polymorphic Solution

The process function in the math class is doing multiple things. It is figuring out what the operation is, and then it is preforming it. full LinqPad example

void Main()  
{
  (new Add()).process(1, 2).Dump();
  (new Sub()).process(1, 2).Dump();
}

public interface Math  
{
  int process(int n1, int n2);
}

public class Add : Math  
{
  public int process(int n1, int n2)
  {
    return n1 + n2;
  }
}

...

public class Div : Math  
{
  public int process(int n1, int n2)
  {
    return n1 / n2;
  }
}

Ok, so lets see how this code holds up to the scrutiny we placed on Bobs code.

  • hard to expand on Not at all, i can create a new project import this assembly and create any number of math operations that take two integers and result in an integer. Endless possibilities for growth.
  • doesn't embody the concept of separation of concerns Each operation is implemented in it's own class. Addition knows nothing about subtraction and vice versa. Also there is no conditional logic required.
  • hard to unit test Not at all. Since each class is only responsible for one thing, each class only really needs to be tested against it's primary function. The are no conditional branches so failed tests are easy to trouble shoot.
  • needless increase in cyclomatic complexity As pointed out above, there are no branching conditionals in this code.

Conclusion

So MS Bob is made up, but switch statements are littered through out much of the code I end up reading. It is a lazy solution in a scenario where clean code polymorphic solution is just as easy to create. But this is the difference between knowing the name of something and knowing something as Richard Feynman so cleverly explained in the video.

While I am not saying that you should never use a switch, the polymorphic solution fits much better into the modern day tool kit. Dependency injection containers for example are a great tool for application composition. And this type of polymorphic programing fits like a glove with convention/interface based dependency resolution.

Also, MS Bob will make future appearances, and while todays instance of MS Bob relates to a specific interaction I had at work, I too was once MS Bob on this subject. The concepts aren't hard to get, but even with out practice knowing the name isn't enough.