Tuesday, May 31, 2011

Virtual properties - they're just dumb

Have you ever seen code of the form:

// Make it virtual so that implementers can provide their own version for them to use
public virtual IManager Manager { get; set; }

?

Code like this just angers me. For one, why didn't they pass it into the constructor? This is much clearer. For two, why does a *base* class need to define what classes the derived classes need to use in order to accomplish their tasks? This is ludicrous. That particular property isn't even used in the base class anywhere - and that's the main problem with it.

When you put something like this on your base classes, it's implying to the deriver that there's some reason that the base class needs it, so the deriver should provide their own implementation that doesn't break the invariants that the IManager interface is bound to. However, since it's not actually used in the base class (notice the comment? It very clearly states that the implementers will be required to use the class, not the base class), the base class shouldn't even have a reference to the IManager type.

The codebase that I was looking at was a real joke, and the original implementers had no idea what OOP means. Without any real depth of knowledge, OOP can quickly turn into POOP.

Thursday, May 26, 2011

Implementation hiding - it's important

I've decided to do away with the annoying naming scheme.

For this post, I'd like to talk about something that's very near and dear to me - implementation hiding. This is the concept in object-oriented design that allows a class' implementation to change without affecting the public interface of that class. It also allows things like schemas to change without requiring massive changes all throughout an application - if you hide the information and implementations of things, then no one can rely on those data and end up getting screwed when the schema has to change. This is important.

It's so important that the majority of the object-oriented design principles are focused purely on it. Most design patterns also encapsulate some form or another of implementation hiding in such a way that it makes it easier to change the code if needed, as well as at the level that's needed. Being able to change code efficiently and quickly - it's important.

An area that I really like to use implementation hiding is around legacy code. Let's say you have a COM library that you call into in order to generate some bitmaps of graphs for a scientific application. But let's also say you want to be able to make your class testable - to test it, you really don't want to pull in the COM library, initialize it, and so on; that's not just a lot of work, that's dangerous in a unit-testing scenario. So, instead of having just a class that calls directly into the COM library, have an interface that that class can implement that represents all of your code. In this way, a unit-test can create a mock of the interface and you can focus on test-driving it much more easily. Later on, when you're doing integration testing, you can test the class that calls the COM library directly, but this should always be done very carefully, and perhaps only on a CI server, in order to save developer time and effort (integration testing can take quite a long time; hence, I prefer to run it on a server instead). This is important.


Another way in which implementation hiding can be effective is on a codebase that uses a lot of static functions and such. It is often the case that as a developer, you'll get put onto a project that someone from a long time ago started coding and were only vaguely aware, if at all, of the principles we have these days, and because of that, they make it a very ugly solution. Your job is to clean it up where you can, and introduce new features. In order to integrate new features, though, a lot of stuff may have to change, and hiding these changes beneath an interface is an incredibly important way of cleaning up the codebase and making it safer for other developers to delve into.

Consider for example a codebase in which static classes and functions are the primary way the original developer worked. I think we've pretty much all seen this. None of it is testable at all, though. Sure, you can make calls to static classes in your unit tests, but that is possibly worse than not unit testing at all, because if the static class has to change, it now breaks both in the consuming system code and in the tests. Better would be to put an interface around it to wrap calls to the static classes, and replacing the calls to these in the consuming system code with calls to the interface. It sounds unimportant, but believe me, slowly removing static classes from your codebase over time is going to help you in the long-run, and not just with unit testing. It's very important.

Insulate change. Hide implementations. Winning.