No really; why should I bother with interfaces? (interfaces in c# part 3)

This is a follow up to my 2 video tutorial “Interfaces in C#”. There were some comments left on the YouTube thread suggesting that some folks are understanding how interfaces work, but still don’t see the point in using them. As always, I say that exposure is the best answer. You have to encounter the problems before you could ever hope to understand the proposed solutions to them.

Before we get started, I’d like to comment on one of the user comments which was something along the lines of

“What is the point of using interfaces when you still have to put the code for the interface in the class that implements it?”.

Well, again — implementing interfaces isn’t like inheriting from another class. You don’t do it to gain functionality; you do it declare functionality. I think some of us get caught up on the fact that the syntax is the same for implementing an interface as it is to inherit from another class. Well forget all of that; it’s just syntax.

By implementing one or more interfaces, you’re basically just telling the compiler that your class has the functionality described in the interface. How that functionality is implemented is irrelevant in this context. It’s like me asking you “Hey do you know all the words to *Ice Ice Baby*?” and you say “Why yes I do! It’ll cost you $10!” Then I say cool and call you out on it: SingIceIceBaby(me, you); Whether you actually do or not is another story, but by telling me that you did, you’ve given me an interface to ask you to do so.

 

 

Now, it could be that when I invoke SingIceIceBaby on you, you get half the words wrong, but I don’t care. As the invoker, I just needed a way to ask you to try it. Now if you never heard the song, then you probably wouldn’t tell me that you could sing it, so I wouldn’t ask you to. In otherwords, you have not implemented that interface.

“I ask again, why not just implement the method on the class itself? Why bother with interfaces?”

Well that makes sense in a lot of cases, we’re object oriented programming experts here and we don’t like to have to rewrite identical logic in multiple places, so what if we wanted to be able to call SinglceIceBaby() on any object that knows how? Well I could make some class that knows how to do it, and have other classes could inherit from it, but by doing so, all of those classes are a) using up their ability to inherit from one single class and b) Now everything that inherits from that class become part of the same family of objects. In other words, if Person inherited from the same class that Jukebox inherits from, you are saying that People are from the same family as jukeboxes. That’s uh… that ain’t right and almost guaranteed mess you up in the future! Interfaces give you a way to declare functionality or traits without joining the wrong families. Those functions and methods that look for the interface, don’t care about the details, they just want to interact with members of the interface that it needs.

“I’m gonna need a practical example…”

I thought you’d never ask. And away we go! Let’s start by playing a little game…

What do the following objects have in common?

2015-06-13_14-46-33

Ahhh… the abstraction game! Well let’s start by grouping them by the somewhat obvious traits…

2015-06-13_14-49-32

Ok, so we were able to break these up into 3 groups: phones, payment terminals, and generic input devices. By grouping them like this, we can see that it’s possible to probably base class some of these if we were to represent them in code as objects. In other words, we have 3 groups of objects that are not semantically related across groups. For instance, a rotary phone is in no way semantically related to a cash register. So assuming we needed to tie them together somehow, what’s another common factor?

2015-06-13_14-53-47

Ohhh… they all have different kinds of number pads! Interesting. So these things all have something in common, but are not related. This could pose a potential problem in code. Imagine our code needed a way to interact with anything in the world that had a number pad. Like a person in a video game, or a robot that runs chores for you, or even a 3rd party plugin like a password manager that needs to be able to interface with something in order to punch in your password on your behalf. That’s exactly what these number pads are: Interfaces.

So let’s run through a scenario in code — and I’m going to kinda play devils advocate here while trying to avoid the need for an interface until I can no longer. Imagine all of the objects above are represented in code and we have an object that needs to be able to interact with all of these objects. Without doing much thinking, maybe we would come up with something like this:

This object has a method to deal with inputting information for each individual kind of device. I think it goes without saying that this is absurd. Any time a new type of device is created, a new method would have to be added to this object and any other object that hoped to use it.

Well the first though of most programmers I know would be to try and abstract the devices down to a point where we can be more generic about invoking the input command of the device. Maybe something like this:

Here, we’ve abstracted this down to a generic InputDevice with a single method called DoInput. But keep in mind, that every device is going to need to deal with a key press in a different way! For instance, a rotary phone takes its input much differently than a smart phone or a cash register. Ok so why not make the input method abstract so that each child class can override it to provide its own functionality. That should still allow the child class to be used in place of its parent (polymorphism). Maybe something like this:

 

Simple enough. So that may solve the problem of many devices having a common interface, but remember that the devices aren’t related across groups and may have to play by different rules. For instance, what if the key pad needed each keystroke to be encrypted? Normally what I’d see people do is sub class the InputDevice and implement security in that subclass. Maybe something like this:

 

 

Splendid. But what if another object also needs to be secure. A security access pad, for instance. Oh ok… then just remove the security logic and use it in any class that needs it (composition) like this:

 

Ahhh yes, and the solution is still simple. Each input device can still be used in place of InputDevice but they both have their own security. But what if you’re working with a subsystem, that doesn’t just want an InputDevice but specifically an input device that has implemented security? You still want to be able to use this keypad with anything that can work with keypads, but in this case, you need to be able to use it in an explicitly secure context. Maybe a solution like this:

Ok cool! By subclassing InputDevice and abstracting the Hsm into the secure child, I should now be able to use any children of SecureInputDevice in both a secure context as well as an insecure context. You see a lot of this in older software, the object graph can go on for days; a bajillion different variations of the same object.

Time to play dirty!

But what if the base class contained a trait that contradicted one or more of its subclasses? This would be a total violation of the Liskov Substitution Principle. Let’s change it up a bit — I’m going to change the linear history of the game to illustrate this point:

 

 

Uh oh. Now we have a problem. Despite the SecureInputDevice encrypting each key stroke, it’s still storing the unencrypted keystroke in a public property. How did this happen?! Well SecureInputDevice inherits from InputDevice, so it takes on the traits of InputDevice whether we want it to or not. And sometimes, we have no control over the base class implementation, or if we do, changing its behavior could have unforseen effects on other classes that use or derive from it.

So why did we do it? Well we wanted to inherit the DoInput(char) method so that we could use it across several different types and we were only allowed to inherit from a single class, so the only way to be an InputDevice AND have security features without forcing InputDevice to have security features was to subclass it into SecureInputDevice — forcing us into inheriting behavior from InputDevice which is actually not what we really wanted to do. Make sense? Well how would we get around that? Interfaces…

Consider the following:

 

 

What we’ve done here is, without changing the public interface, we have created two classes that are totally unrelated but share a common method: DoInput. One class is secured, the other isn’t. Both can be used by any method that accepts IKeypadInput, and neither takes on traits that it doesn’t need nor want.

 

 

I’m showing two contexts here. One demands a secure input device, the other doesn’t. By abstracting a common interface, the DoSecureInput method is actually unnecessary. SecureInputDevice is a specific implementation of the device, but in both contexts, we really don’t care; we just want to throw some input at it. Also, by choosing to implement an interface instead of inheriting from a base class, we were able to declare common functionality without creating an unnecessary inheritance of traits between two unrelated objects. It’s worth noting that this is particularly useful in a scenario where you don’t know what the concrete type is going to be, but you know it’s going to be an object that implements IKeypadInput — for instance when you’re getting the object from a factory.

I really hope this helps someone!

Leave a Reply