Moving privacy around. PART 3 : the dependency injection way
July 7th, 2009As we move on, we are going to reach more defined patterns. Big classicals patterns are very well defined and studied. Instead of previous solutions which are more like tricks, language idioms.
Protecting by using interface is a factory technique, used to build a dependency injection. This one is very important, as it’s really the one that allow growing an application as a library of classes, rebinding things as needed, and changing the behaviour of the whole program by changing things at the highest level of the application.
class ABC : A,B,C {
} abc;
class Application {
private:
ABC abc;
public:
A *getA() { return abc; }
B *getB() { return abc; }
D *getD() { return new D(abc); }
}
A,B,C are several interfaces on a object. Anything inside Application has access to the full ABC class, that mean it can access anything from the A, B or C interface. Anything outside has access to A, or B without even knowing that they are the same object.
From the inside of Application you can choose to give others objects direct reference to ‘abc’. Thats the case of D, it is given a direct reference on abc, thus he has no restriction on interface usage and can use the interface C even if it’s not available from the outside of the application.
Actually, this is the way dependency injection container work. I figured this one out reading : Dependency Injection in Ruby - { |one, step, back| }. If it worked for me it should work for some of you too.
Take a bit of time on this technique, and try to figure out how some of your code could be rewrapped into this form, if it isn’t already. It has been an great ahah moment for me.
Final word
Encapsulation does not have to be an all or nothing thing. Not everything need to be public to the whole application. You control privacy by putting data private inside an object, then by choosing who you give credential to theses datas.
I find oo design relatively easy since I understood this. It’s very mechanical : introduce interface or object, splice, and on and on. It’s very suitable for incremental design because you can regroup then dispatch functionnalities between objects. Packages are clusters of sub-objects recursively down to the smallest parts of the applications.
You design packages built of clusters of sub-objects, recursively.
