How can I remove/refactor a «friend» dependency declaration properly?

Let’s setup some constraints for refactoring first:

  1. The ClassAAccessor’s publicly visible interface should change in no way
  2. The ClassA internal operations should not be visible/accessible from the public
  3. The overall performance and footprint of the original design should not be hurt

Step 1: Introduce an abstract interface

For a first shot, I factored out the «friend» stereotype, and replaced it with a class (interface)
InternalInterface and the appropriate relations.

1st shot refactoring

What made up the «friend» dependency, was split up into a simple dependency relation (blue) and
a «call» dependency (green) against the new InternalInterface element.


Step 2: Move the operations, that make up the «call» dependency to the interface

The next step is to mature the «call» dependency. To do this, I change the diagram as follows:

Matured design

  • The «call» dependency turned into a directed association from
    ClassAAccessor to the InternalInterface (I.e. ClassAAccessor contains
    a private variable internalInterfaceRef).
  • The operations in question were moved from ClassA to InternalInterface.
  • InternalInterface is extended with a protected constructor, that it’s useful in inheritance
    only.
  • ClassA‘s «generalization» association to InternalInterface is marked as protected,
    so it’s made publicly invisible.

Step 3: Glue everything together in the implementation

In the final step, we need to model a way how ClassAAccessor can get a reference to InternalInterface. Since the generalization isn’t visible publicly, ClassAAcessor can’t initialize it from the ClassA reference passed in the constructor anymore. But ClassA can access InternalInterface, and pass a reference using an extra method setInternalInterfaceRef() introduced in ClassAAcessor:

Glue everything together


Here’s the C++ implementation:

class ClassAAccessor {
public:
    ClassAAccessor(ClassA& classA);
    void setInternalInterfaceRef(InternalInterface & newValue) {
        internalInterfaceRef = &newValue;
    }
private:  
    InternalInterface* internalInterfaceRef;
};

This one is actually called, when the also newly introduced method ClassA::attachAccessor()
method is called:

class ClassA : protected InternalInterface {
public:
    // ...
    attachAccessor(ClassAAccessor & accessor);
    // ...
};

ClassA::attachAccessor(ClassAAccessor & accessor) {
    accessor.setInternalInterfaceRef(*this); // The internal interface can be handed
                                             // out here only, since it's inherited 
                                             // in the protected scope.
}

Thus the constructor of ClassAAccessor can be rewritten in the following way:

ClassAAccessor::ClassAAccessor(ClassA& classA)
: internalInterfaceRef(0) {
    classA.attachAccessor(*this);
}

Finally you can decouple the implementations even more, by introducing another InternalClientInterface like this:

enter image description here


It’s at least necessary to mention that this approach has some disadvantages vs using friend declarations:

  1. It’s complicating the code more
  2. friend doesn’t need to introduce abstract interfaces (that may affect the footprint, so constraint 3. isn’t fully fulfilled)
  3. The protected generalization relationsip isn’t well supported by the UML representation (I had to use that constraint)

Leave a Comment

tech