Okay, I keep digging into the Delphi Spring Framework and I keep finding cool stuff you can do, so I can hardly wait to write all these articles. Seriously, this is a mind-expanding experience.
First, though, I need to talk about some general topics. There are a few things that need to be accepted and understood before Dependency Injection can really sink in. (And again, I want to point out that I’m deeply indebted to Misko Hevery of Google for a lot of this material.)
The Law of Demeter (LoD)
First topic -- the Law of Demeter. What exactly is the Law of Demeter? The strict definition goes like this:
A method of an object may only call methods of:
- The object itself.
- An argument of the method.
- Any object created within the method.
- Any direct properties/fields of the object.
That’s a bit formal, so here’s a “real world” example:
Let’s say you go into a store. You buy a bunch of stuff, and the total is $25. When you go to pay, what do you do? If you are believer in the Law of Demeter, then you pull out your wallet and give the $25 to the clerk – just the money, nothing more.
But no, you are a scofflaw and fear not the deep coupling of your wallet to other people and thus you think the Law of Demeter is for weaker men, so you pull out your wallet and hand the whole thing over to the clerk and let her decide what to do for the payment.
Sure, you intended to pay with cash, but instead the clerk takes your wallet, uses a credit card to pay for the stuff, drops your library card on the floor, runs your BuyMore loyalty card through a degaussing machine, and draws a moustache on the picture of your wife. You paid for the stuff, but wow, what a mess!
That’s why you should follow the Law of Demeter in a nutshell. It’s basic premise is that you should only hand over (and on the other side, only ask for) exactly what you need to hand over (or ask for). Things should be linked together with as thin a string as possible. The Venn diagram illustrating the connections between classes should have as small an overlap as can be managed. In this example, you might not even want the clerk to know you have a wallet, right?
Or in another example, you wouldn’t give the paperboy your wallet or let him search around your house for spare change.
A Coding Example
So for instance, in code, you may have a Transaction class that needs a form of payment to be completed. And hey, look! The Customer class has different Forms of Payment, so you pass a Customer to the Transaction. Sure, at first all is well, because you are very careful and all you do is grab the Form of Payment from the customer and use it. What could possibly go wrong?
But a few months pass, and that (cough, cough) “less experienced” developer comes along and says “Hey look! Here’s a Customer object! I think I’ll change his address here instead of over there!” and all heck breaks loose. Pretty soon, you are fixing a bug in the Transaction class and Customer data changes. You fix a Customer bug and access violations start flying when you try to commit transactions to the database. The next thing you know, changing a Customer address is sending major cash bonuses to your office cleaning service, and before you know it, there is no end to the havoc reeked by that little Customer object innocently sitting in the Transaction class.
The right thing to do, of course, is to simply pass the Form of Payment itself, or better yet, forget the Form of Payment and pass in just the money itself in some form. The idea is that your classes should ask for a little as possible, and refuse to accept more than they need. If you have code like this --
-- that is, code that seems to drill down deep into a class hierarchy -- then you probably deserve a ticket from the cops for breaking the Law of Demeter. You’ve gone searching down a rabbit hole for something that you should have just asked for to start with.
The classic quote is “Only talk to your friends, and never talk to strangers”. “Mind your own business” comes to mind as well.
Or let’s put it in even starker terms: Pretend that every class you write is a pristine clean room with no germs, dirt, or any other yucky stuff in it – and that you plan on keeping it that way. Are you going to let some delivery guy who just tramped through a horse barn while sneezing because of the ebola virus just walk into your room and hand you a package? Heck no! You are going to make him shower, scrub, de-sanitize, purify, and otherwise delouse himself before entering. Heck, you should probably make this guy put on some sort of bio-hazard suit on before you let him in. Or even better still, don’t let him in at all, and only let him pass in whatever he’s trying to give you via some secure slot in the door.
That’s how you should be treating any outsider class that want’s to sneak in to the current class.
Law of Demeter in Delphi
Delphi and the Law of Demeter can be good friends. Here are some pointers to help out in your Delphi code:
- Limit the number of units in your uses clauses. If you have a long list of items in your uses clause, it is a strong indication that things are tightly linked together.
- Limit the scope of your uses clauses. If you can put an item in the uses clause of the implementation, do so.
- Use strict private and strict protected. This will limit you from the temptation to make classes “friends” of each other in the same unit.
- As noted above, anytime you have a chain of “dotted” properties in a single line, you should examine this for violations of LoD.
- Anytime you are creating a lot of temporary object, this might indicate un-necessary dependencies.
- Check your constructors – if they are creating a lot of things or taking a lot of other classes as parameters, then the same thing applies: the possibility of too much coupling.
Note that these aren’t iron-clad rules, but rather suggestions of examination and consideration. It need not become “a Dot Counting Exercise.” The idea is to reduce coupling and thus limit the damage any one modification can have on the system as a whole.
Following the Law of Demeter is a key to creating clean, easier to maintain code. Once you get that down, you’ll also find that you are writing code that is easy to test. Next time, we’ll take a look at why it’s important to write testable code.