October 23, 2007

...Learn TDD with Codemanship

How Dependency Inversion Works

One of the underpinning principles of good object oriented design - apart from the It's Good If Jason Says It Is principle, of course - is dependency inversion.

Basically this means that where we see classes that depend on multiple concrete classes that do similar things, we should abstract those similar things into a common base class and have our client depend on that instead.

Smart-arsed developers who come to my training courses - and there's always at least one in the room (usually me, admittedly) - will sometimes point out that dependency inversion does not reduce the overall number of dependencies in the code. In fact, it increases them by one - since we've added a new abstraction, making our multiple concrete classes dependent on that (by inheritence) and then adding a new dependency between the client and this abstraction.

In general, more dependencies might be considered a bad thing. But the effect is more subtle than that. We do indeed have one more dependency than we started with. But we also now have considerably more dependencies upon abstractions than before.

If the code in this new abstraction is indeed common to the multiple concrete classes that we refactored it out of, then we can safely conclude that it is less likely to change than they are. In which case our client and all our concrete subclasses now depend on something that is less likely to change than before.

Simulations I've done strongly suggest that as the proportion of dependencies on suppliers that are less likely to change than their clients increases, the probable extent of change propagation decreases significantly. So the effect of dependency inversion is to help limit change propagation by increasing dependencies on types that are less likely to change.

It also helps us to remove duplicate code (e.g., calls to lion.feed(), tiger.feed() and leopard.feed() in Zookeeper) from the client, and maybe factor out any duplicate logic from the concrete subclasses into their shared base class, which reduces complexity - also considered to be a good thing.

And that's how dependency inversion works. It is, I tell you!
Posted 13 years, 10 months ago on October 23, 2007