The connundrum of encapsulation
January 29, 2007, 11:33:13 pm

Over the years it has become apparent to me that the better you encapsulate, the less heart ache you'll have if you want to change all your APIs around. At the same time, it has also become clear that the better you encapsulate, the more APIs you are creating.

To explain this a little better, let's take an example:

aNode styles background color red

In this example, we start from aNode and we ask for styles for aNode, then we ask for the background of the styles, then we ask for the colour of the background and finally we ask for the red component of the colour. This is a classic example of a multipart send. This is an example that a pure encapsulator would point to say and say "This is brittle".

Yet at the same time, we know the code is readable and obvious as to what it's doing. It's clear what objects we're talking to, who's responsibility is what and things -are- well encapsulated.

If we were going to be encapsulation gods, we would make the following methods:

Node>>styleBackgroundColorRed

^self styles backgroundColorRed

Styles>>backgroundColorRed

^self background colorRed

Background>>colorRed

^self color red

It's quite clear that this cures encapsulation, sure, and if you want to get your backgroundColorRed from some other source, it's easy for a subclass to override the behaviour. However, now we have a mess.. in several respects. We've added three more methods to our code base that we have to maintain - and worse, we've added three new bits of API (whether you stick them in private categories or not!).

So there's clearly a trade off. When does encapsulation apply? .. when something isn't API? - certainly.. but where do you draw the line?

By on January 30, 2007, 1:17:07 am

I advocate complete encapsulation. Complete. It's pretty easy to do. You make one top level object, and all messages are sent to it. All messages. Bury every possible send to any of your system with methodNamesThatAreMereCamelCaseConcatonations of the various paths. I call this object "Main." All your method are ours.

(I'm being sarcastic here, I'm in support of the jst of your post)

By Terry on January 30, 2007, 8:39:07 am

Comment by Terry

Like yourself, I much prefer to use encapsulation but it is a problem when dealing with generic objects, like a tree node. If the intermediate objects are not generic then I create the intermediate forwarding methods. For generic objects I like to create a utility getter method in the sender. While this is not encapsulation, it restricts the proliferation of these cascading message sends to a minimal set of well defined locations and makes it easier to modify when the object structure changes.