Don't Check Types
Resist every opportunity to verify the instance of an object.
Metaphor
Imagine, you're entering a bar and a security guard stops you from doing so.
They look at your face and scrutinize you up and down before refusing your entry for whatever reason popped in their head.
Isn't that rude ?
Is that acceptable ?
A somewhat better behavior would have been for the security guard to ask you for your ID, but that's still rude and uncomfortable. I don't like random people gazing at my ID.
Citizens in a well behaved society discuss and make an opinion through that discussion. They don't judge a book by its cover and they certainly don't ask to see the cover in the first place.
Poor-lymorphism
The biggest problem about checking the type of an object is how it breaks the very idea and ideal of object ignorance.
As an object, I want to communicate to other objects through their public interface.
I don't care about who they are and how they do it. That's their problem and I don't want to have nothing to do with it. No, thanks !
I just want to know they can understand my message and perform their part of the job.
That's what polymorphism is about : being able to communicate to a wealth of object with complete ignorance of who they are.
Aren't we constantly told to reduce coupling ?
Message passing, polymorphism and event-driven systems are all about the lowest coupling ever ! You really can't reduce it more without completely destroying it and separating the two systems !
That's a central concept of extensible systems and the heart of the Open-Closed Principle.
However, by checking the type of an object, you're ruining everything.
All our efforts, reduced to ashes.
Suddenly, our code becomes aware of concrete instances of classes. It looses its ability to treat classes with ignorance because its hanger got knowledge
And everything you know can (and will) be held against you sooner or later.
Breaking the dependency
Let's take the example of multiple type of users : BannedUser, RegularUser and AdminUser. We'll assume a workflow where a user is trying to perform some sensible operation on data they own.
That's terrible design, because it somehow uses polymorphism (every class is a subclass of a common User class, or some User interface) but break-up at the first occasion. They'd make a terrible date.
Now what if we had this sort of code instead.
That code is much better. At least, it doesn't rely on type checking !
However, it's still bad code. Because every method is a reflection of its subtypes, which means not only subtypes know about their supertype, but the supertype also knows about its subtypes.
That's terrible. Adding a new type to the hierarchy will force us to add yet another method in the parent class. The parent class knows to much.
Now what if we had this sort of code instead.
Not only are we decoupled from the classes, but by thinking in term of "capabilities", we're exhibiting composition !
See how the semantic changes and how the return values are different ? These falses are a negative signal indicating a lack of possibility, which fits perfectly for a BannedUser. In the opposite, these trues are a positive signal.
You can rename isAllMighty by anything you like, as long as it reflects the capability of doing things that bypass regular checks. Actually, I believe you should.
Last updated