Question

I have a domain model, persisted in a database, which represents a graph. A graph consists of nodes (e.g. NodeTypeA, NodeTypeB) which are connected via branches. The two generic elements (nodes and branches will have properties). A graph will be sent to a computation engine. To perform computations the engine has to be initialised like so (simplified pseudo code):

Engine Engine = new Engine() ;
Object ID1 = Engine.AddNodeTypeA(TypeA.Property1, TypeA.Property2, …, TypeA.Propertyn);
Object ID2 = Engine.AddNodeTypeB(TypeB.Property1, TypeB.Property2, …, TypeB.Propertyn);
Engine.AddBranch(ID1,ID2);

Finally the computation is performed like this:

Engine.DoSomeComputation();

I am just wondering, if there are any relevant design patterns out there, which help to achieve the above using good design principles. I hope this makes sense. Any feedback would be very much appreciated.

Was it helpful?

Solution

Engine looks like it's breaking the Open/Closed principal and probably the Single Responsibility principal too. If Engine's purpose is to do some computation then it probably shouldn't know how to create ID1 or ID2 from different node types which would be an SRP violation. The names AddNodeTypeA and AddNodeTypeB lead me to think that there could be a C, D, etc. This means that any new NodeType would require the Engine class to change which is where OCP appears to be broken.

The Adapter pattern would resolve both of those concerns

class Engine
{
    public void AddBranch(Branch branch1, Branch branch2)
    {
        //do something
    }

    public void DoSomeComputation();
    {
        //do something
    }
}

interface BranchAdapter
{
    Branch GetBranch();
}

class NodeTypeABranchAdapter : BranchAdapter
{
    private readonly TypeA _typeA;
    public NodeTypeABranchCreator(TypeA typeA)
    {
        _typeA = typeA;
    }

    public Branch GetBranch()
    {
        //do processing to take _typeA and transform it into Branch
    }
}

class NodeTypeBBranchAdapter : BranchAdapter
{
    private readonly TypeB _typeB;
    public NodeTypeABranchCreator(TypeB typeB)
    {
        _typeB = typeB;
    }

    public Branch GetBranch()
    {
        //do processing to take _typeB and transform it into Branch
    }
}

The calling code could then work like so

var engine = new Engine();
Branch id1 = new NodeTypeABranchAdapter(TypeA).GetBranch();
Branch id2 = new NodeTypeBBranchAdapter(TypeB).GetBranch();
engine.AddBranch(id1, id2);
engine.DoSomeComputation();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top