-1

There exists different composition arts/techniques, i will present in the following some of them.

The question then is do you know more techniques additional to my presented ones?

And then the important question is, what kind of different makes it from the client perspective, how should i access from a client a compositionend objectgraph or in an other way asked, which composition-technique is client-friendly in the context of a good object orientented design, which depends on the Law of Demeter?

Which other dependencies could be out there, let me go more into that direction (using the compostion A) and what to go into an other direction (using composition B)

i have choosen my examples with the approach extending a root object, which is initially used by the client in its behaviour:

This question is related to that one: No trivial god-class refactoring

i have an object and a few methods in it

//also called MyObject1
class MyObject{

...

doSomething1(){} doSomething2(){}

}

and now i want to extend this object with more methods, for example a doSomething3 which acts on the state of that object and maybe on some kind of "own" state.

so there are now different ideas how i can achieve this:

  • add this method + its more membervariables, which are needed, to the existing class
  • create a new class MyObject2 and write it down into this class

if i decide for the secound solution, then the question is how to combine MyObject and MyObject2

  • I can integrate MyObject2 into MyObject

    class MyObject {
    

    MyObject2 myObject2 = new MyObject2(this) ...

    doSomething1(){} doSomething2(){}

    }

  • i can let MyObject2 standalone, but when is the question, how the client get access to MyObject2, if he has access to MyObject

  • Third class, that combine the other two

     class ThirdClass {
    

    MyObject myObject = new MyObject() MyObject2 myObject2 = new MyObject2(myObject)

    }

The client have then in option 1) and option 3) the following possibilities:

....myObject.getMyObject2().doSomething3();
....thirdClass.getMyObject2().doSomething3();

Edit (because the solution from Greg Burghardt is a trivial solution, but correct, to my simple examples, but covers not the main-problem):

So let us say we have a MyObject3 built up the same way as MyObject2, depends only on MyObject1 (it's a synonym for MyObject without the 1, to make clear that i dont have type-mistake here), and a MyObject4.... MyObject2-4 don't need to know each other because they extend only the behaviour of MyObject1.

And then i have a MyObject5, which depends directly on MyObject1 and MyObject3

The question is the same, how should i compose that objects, to get access to all functionality of all of these objects from client-side? Which of these objects is the root-object, do i have a "third" object which acts as root-object?

1 Answers1

1

Since refactoring MyObject to use composition, the downstream impact on clients of MyObject is twofold:

  1. There is no impact. The refactoring was doing internal to MyObject. Clients of MyObject can and should continue calling the methods they used to call. This is the important first step, because this reduces how many files need to be changed.

    At this point you would view MyObject as the beginnings of an anti corruption layer.

  2. Begin refactoring clients of MyObject to use MyObject2. This should not be one giant refactoring job. Instead, split it into distinct tasks focused on refactoring one class, or even just refactoring one method in one class.

Doing this two-step refactoring job for clients of MyObject may allow you to eliminate MyObject as a dependency for other classes. Eventually you will have refactored enough of the application that nobody is calling members of MyObject that just pass through to MyObject2. At that point, you can remove those pass-through methods from MyObject. Once MyObject2 is no longer being used from inside MyObject, you can eliminate MyObject2 from inside MyObject.

When you are done with this two-step refactoring process, clients will be using MyObject2 directly instead of the MyObject methods that pass through to MyObject2.