Moving privacy around. PART 3 : the dependency injection way

July 7th, 2009

As 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.

Moving privacy around. PART 2 : moving methods to another object

July 7th, 2009

Next we can move to more regular techniques that shouldn’t make you cry, get mad and kill your bunny.

Move private methods to a separate object and agregate that object :

class View{
    public:
    void Redraw();
    private:
    void DrawTriangle();
    void DrawCircle();
}

become :

class Drawer{
    public:
    void DrawTriangle(any_private_view_data*);
    void DrawCircle(any_private_view_data*);
}

class View{
    public:
    void Redraw();
    private:
    Drawer m_drawer;
}

Look how DrawTriangle and DrawCircle are public now on the new object Drawer. Of course Drawer need some privates datas of View but the good news is : View is calling us and it can give us any data we need.

Any data that thoses methods need are given in parameters. Theses parameters are private but they belong to View and View is calling us. View has access to all the privates fields. View can delegate its rights to Drawer object. Wait ! We can delegate our rights to others objects by giving pointers around ;) . Its a access delegation pattern.

Like _why would say, its so beautiful that it makes you cry !

Ability to delegate access helps a lot in building flexible design.

Here we are :
Solution 1 says everything is out.
Solution 2 defines the connections that help building a flexible design.
Solution 3 is about using abstract interfaces

Moving privacy around. PART 1 : put everything in public

July 5th, 2009

I present here techniques that control the encapsulation, they aren’t grand secret, but it has taken me a while to figure them out. In fact they are known patterns, but have been little observed in how they control and delegate ownership.

Ways to control encapsulation :

control by removing privacy

Move all methods to public.

As I said, this will feel wrong (heretic ? ) to many, given that all oo seem to be about keeping a minimum of things public.

I do like programming with minimal constraints, so it is suitable to my style. I can still read code written that way years after without turning mad as if I saw the big cthulhu so it is probably sort of safe.

There are rules that you have to follow to avoid falling on the dark side :

  • methods should be meaningful as a part of the public api
  • methods should not have side effects
  • object should not be part of a releasable API that would be used in code that couln’t be rebuilt

In other words doing this is only suitable for methods that present all quality to be public. It is generally acceptable for internal design, build incrementally.

Special note : If you are building a API putting a lot of things in public is BAD, BAD, BAD. API design has special rules, you have to anticipate change and this technique is very bad at anticipating changes.

But the good news is that its dead simple :

class {
    public:
    void Redraw();
    private:
    void DrawTriangle();
    void DrawCircle();
}

become :

class {
    public:
    void Redraw();
    void DrawTriangle();
    void DrawCircle();
}

Here are some thoughts to meditate about putting everything in public :
/*
Emacs have well defined actions extensions point but no way to control privacy in package. Any function can be overwritten, public and private are maintained through usage. If you extend from any point, it may not work with others extensions… It doesn’t seem to work too bad.
*/
/*
Javascript has no way to control public, private access. You can do OO through closure or prototype, but the only way that scale is prototype based and then there is no practical way to have privates. And you know what ? it doesn’t really matter.
*/

FScript - Writing plugins for FARR with javascript

April 6th, 2009

Find and Run Robot plugins are written in a native language like C++. Thus to build plugins you need a compiler and know the desuate art of native code programming.

FScript is a bridge plugin for FARR that allow to create FARR plugins in javascript.

You can get the last version of the dll at : http://e.craft.free.fr/farr/FScript/

Take the version with the highest version number.

An help file that detail most of the functions is available at http://e.craft.free.fr/farr/FScript/help.html

There is many plugins written that you can find on the DC forums, in the plugin list, or on the CZB page : http://czb.dcmembers.com/

Discuss it on dc forum : FScript Javascript SDK

Go write the code. Don’t delocalize.

March 31st, 2009

So you’ve got a log library, or a string one, various patterns and you think for the sake of reuse that it should fit in that new project. But hell no ! Reusable libraries, or generic, whatever you call them bring overweight with them. Overweight come in various form : memory usage, design complexity, inefficiencies of many forms…

If I’m in need of a bezier function, a simple parser, … I just code it. Of course there is vectorial libraries, and things like boost spirit. But I’m speaking of one single type of bezier function. Do I really need a complete vectorial library ?

If you need something that can be achieved with some hundreds lines of code, go write them. Don’t delocalize ! Libraries solve interesting problems usually. You don’t want to give all the fun to someone else ? Keep the fun for yourself. If its hard, try. Writing crappy binding code won’t make you a programmer. Write difficult code will. There is not that much good problems. Don’t give up.

For the productivity aspect argument of code reuse, in fact :
Not reusing code is a good thing for your project. Included code is easier to manage, best fit your project, has a simpler api for your project needs. It may have bugs, but if you know your job it will be bugs that you can fix.

Great piece of code don’t use libraries : the V8 engine
Many computer programs are built using previous versions, or related code, but V8 was started from scratch a blank slate.
Why is Git so Fast? Maybe Git is fast because it doesn’t use much external code.
People make fun of those with NIH Syndrome, but my observation is that folks who suffer from this disorder tend to create faster software, even if they also tend to ship everything late.

Common sense, common sense… the shipping late is to consider though ;)

main() is the config file - consequences of the dependency injection pattern

February 4th, 2008

The very purpose of main() is to configure the library of classes into a software. It should document communication between parts of the design. main() can be the abstract of the design. This design occur when building software using DI.

The worm hole globals - communication issues in design.

DI reverse application design. Without DI, when I needed an object to use another, I included some headers at top of my file, then create that object from where I was. Everything is concrete, nothing can change, there is a dependency between ‘’game'’ and ‘’bob'’.
Bob game

#include "bob.h"
struct Game {
    Game() {
    Bob bob;
   }
}

The issue of software design is communication :
Applications build dialogs, that build buttons, that do something in some unconnected part of an application. Buttons usually use some kind of mvc pattern, with an ugly controller, that end up beeing some kind of ugly mess.
Communication problem

#include "bob.h"
struct ButtonController {
    onclick() {
        // how can i talk to bob ?
    }
}

Communication issue lead to creating worm holes in the design, in the form of globals (Pray that the universe is better at maintaining worm holes than we are… ). Globals came from this kind of internal discussion : Globals sucks but Button really want to talk to Bob; there is only one Bob now so it can as well be global. It can even scale to a list of Bob, in case there were more than one Bob and you can felicitate anticipating changes so well. Great.
Like all software, it doesn’t matter if it is clean or ugly, it will work anyway. Good night.
The global Bob

#include "bob.h"
struct ButtonController {
    onClick() {
        theBob.heyBob(); // the Bob has gone global
    }
}

There is nothing wrong with logging beeing global since it is purposely available from everywhere. Logging, can be global, debugging tools as well.
Anything that does not need this ubiquitus requirement probably shouldn’t be globals.

main() is the config file.

Building software the DI way lead to something like this :

#include "level"
#include "monster"
#include "bob"

main() {
    struct Game {
        Level *getLevel() {
            return new Level("squarespounge01.lvl", getBobTheSquareSpounge());
        }
        Bob *getBobTheSquareSpounge() {
            return new Bob();
        }
    } game;

    game.getLevel()->play();
}

Game will tend to implements multiples abstracted interfaces, that are needed by the object created by the Game.

struct IMonsterProvider {
    virtual IMonster *createMonster()=0;
};
struct Game : IMonsterProvider {
    Level *getLevel() {
        return new Level("squarespounge01.lvl",
                                static_cast<IMonsterProvider*>(this), 
                                getBobTheSquareSpounge());
    }
    Bob *getBobTheSquareSpounge() {
        return new Bob();
    }
    Monster *createMonster() {
        return new Monster();
    }
} game;

Level can now create Monsters, the kind of monster to create is controlled by the game. Worm holes globals disappeared. main() document all communication between components. Communication between different part of the applications become apparent in only one class.

Eternal Code

November 10th, 2006

I often hear that code has to be rewritten from time to time. The reason invoked is that code progressively become impossible to understand and incapable of accepting modifications. Multiples successives hacks ?

Legacy Code perfecttly describe that code without test become instantly old. The inverse is true, tested code does not age, it stay maleable. After 3 years of TDD oriented code, I feel that my code is clearer and more maintainable today, than the day it was written.

Test first, test after

October 31st, 2006

TDD feel weird as a beginner. However…

  • If I write tests after, I describe what the code does
  • If I write tests first, I describe what I want the code to do

Which one is reversed now ?

Intro

October 28th, 2006

Is it sadism for someone who can’t explain to write for everyone ? I can see Olive’ laughing out loud looking at the incomprehensible emanation of thoughts I already formulated. That’s an enthousiasm thing. If I love something, I have to explain it right now… but to explain something clearly, you must let it stand a bit, let the ideas group together as words. As the teacher of a fellow said, chaos lead nowhere but to a sticking mess.