Friends in an unfriendly world

This post is about a pattern to simulate friend classes in languages that do not support them, like Java and C++.

Basic layered architecture, domain-driven design idioms like factories and repositories, and even some of the Gang of Four‘s patterns, like the Memento Pattern, are well-suited for C++’s friend class language feature:

class X
{
private:
int a, b;
friend class F;
public:
X() : a(1), b(2) { }
};

class F
{
public:
void print(X& x)
{
cout << "a is " << x.a << endl;
cout << "b is " << x.b << endl;
}
};

I have many times lamented the fact that Java and C# don’t have friend classes, but instead have package access and internal access, respectively.

This accomplishes basically the same thing, except the solution doesn’t scale. I don’t want a package or assembly for every entity, that entity’s repository, that entity’s factory, and that entity’s UI builder.

Flailings such as the Method Regulator Pattern, The Coder’s Whiteboard, and The Getter Setter Debate were inspired by this unfortunate situation.

None of those work-arounds, including just trusting your fellow programmers to leave your getters alone or having a domain entity with methods like displayOn(Screen) and storeIn(Repository), satisfied me. Friend classes are the right tool for the job.

Then one day not too long ago, I was pointed to the Fluent Builder Pattern on the DDD Yahoo! discussion group:

A method of alleviating the pain of the many parameters to the
constructor is to introduce a fluent builder.

The builder explicitly has the responsibility of building up the
parameters for the Pen so SoC etc are maintained while keeping things
in an ok form.

This pattern is implemented with a private inner class. Access to this class is exclusively through its containing class. This got me thinking: couldn’t I go down this same route?

The Friend Class Pattern

After a short misguided attempt at having repositories and factories inherit from a private inner class, I settled on an approach.

First, you have your domain object. Its public interface should consist only of domain-meaningful business methods.

public class Pen
{
    private int length;
    private String color;
    
    private Pen()
    {
        // Pens are built by a factory
    }
    
    public void dispenseInkOnto(Surface s)
    {
        // domain-meaningful stuff
    }
}

Here is the general UML:

Now, just like friend classes in C++ “declare” their friends in the class, so will we in the Pen class. First, though, we define the inner class, called Accessor:

public class Pen
{
	...
    private static class Accessor
    {
        private Pen p;
        
        public Accessor(Pen p)
        {
            this.p = p;
        }
        
        public int getLength()
        {
            return this.p.length;
        }
        
        public String getColor()
        {
            return this.p.color;
        }
        
        public void setLength(int L)
        {
            this.p.length = L;
        }
        
        public void setColor(String S)
        {
            this.p.color = S;
        }
        
        public Pen getPen()
        {
            return this.p;
        }
        
        public void injectPen(Pen p)
        {
            this.p = p;
        }
    }
}

General UML:

This keeps meaningless getters and setters out of the expressive domain object. They are not part of its public interface. Now the problem is: how do we let certain external classes, who can’t even see this private inner class, have access to this class?

The answer: interfaces.

public interface PenAccessor
{
    public int getLength();    
    public String getColor();
    
    public void setLength(int L);    
    public void setColor(String S);
    
    public Pen getPen();
    
    public void injectPen(Pen p);
}

public class Pen
{
	...
    private static class Accessor implements PenAccessor
    {
        ...
    }

The picture:

Since the interface is public, but the implementation is private, whomever can get their hands on a PenAccessor doesn’t necessarily get to use it; the only class who can provide the sole implementation of PenAccessor is Pen.

Therefore, friends of Pen, like PenRepository and PenFactory, each have a member of type PenAccessor, and its implementation is injected by Pen. Pen “declares” that PenRepository and PenFactory are its friends by instantiating them and passing them each an instantiation of Accessor:

public class Pen
{
    private int length;
    private String color;
    
    private Pen()
    {
        
    }
    
    public void dispenseInkOnto(Surface s)
    {
        // domain-meaningful stuff
    }
    
    // friends
    
    public static PenFactory factory()
    {
        return new PenFactory(new Accessor(new Pen()));
    }
    
    public static PenRepository repository()
    {
        return new PenRepository(new Accessor(new Pen()));
    }

    private static class Accessor implements PenAccessor
    {
        ...
    }
}

The direct instantiation can, of course, be replaced by a factory method, or a full fledged factory. The complete picture now:

I’d be a professor if I didn’t explain those two mysterious methods, injectPen() and getPen(), in PenAccessor. This is best shown via example:

public class PenFactory
{
    private PenAccessor accessor;
    
    public PenFactory(PenAccessor accessor)
    {
        this.accessor = accessor;
    }
    
    // I'd opt for a fluent interface, but
    // it's just an example
    public Pen createPen(String color, int length)
    {
        this.accessor.setColor(color);
        this.accessor.setLength(length);
        
        return this.accessor.getPen();
    }
}

public class PenRepository
{
    private PenAccessor accessor;
    
    public PenRepository(PenAccessor accessor)
    {
        this.accessor = accessor;
    }
    
    public void store(Pen p)
    {
        this.accessor.injectPen(p);
        
        String query = "..." + this.accessor.getColor() + 
        			   "..." + this.accessor.getLength();
    }
}

As you can see, getPen() is for friends who need to get the Pen object they are accessing, like a factory. injectPen() is for friends who are passed a Pen and need to access it, like a repository.

Think of PenAccessor as a “slot” into which the private implementation is plugged. The only way that slot is filled is by Pen.

Finally, here is a main method to glue it together…note the comments that demonstrate that Pen’s getters and setters are not exposed, and outside classes can’t somehow get a hold of the private accessor class either.

public class Main
{
    public static PenFactory getPenFactory()
    {
        return Pen.factory();
    }
    
    public static PenRepository getPenRepository()
    {
        PenRepository repoToReturn = Pen.repository();        
        return repoToReturn;
    }    

    public static void main(String[] args)
    {
        Pen blackPen = getPenFactory().createPen("Black", 9);
        //Pen bluePen = new Pen(); //won't compile
        // blackPen.getLength(); //won't compile
        //PenAccessor accessor = new Pen.Accessor(blackPen); //won't compile
        // accessor.setColor("brown"); //won't compile
        
        getPenRepository().store(blackPen);
    }
}

Variations

This is a fairly simple example, where one “lonely” class has several friends.

Variation #1

What if a “lonely” class is a friend to more than one class?

In the example, suppose the PenRepository needs to take in a Pen and a User, and needs to access the internals of both. Since the lonely classes have to instantiate their friends, and because you can’t have two classes instantiating the same instance at once, you have to choose one that will instantiate the friend and its accessor, and the other takes in the friend and injects only.

Time for code:

public class PenRepository
{
    private PenAccessor accessor;
    private UserAccessor userAccessor;
    
    public PenRepository(PenAccessor accessor)
    {
        this.accessor = accessor;
    }
    
    public void store(Pen p, User u)
    {
        this.accessor.injectPen(p);
        this.userAccessor.injectUser(u);
        
        String query = "..." + this.accessor.getColor() + 
        			   "..." + this.accessor.getLength() +
        			   "..." + this.userAccessor.getFirstName() +
        			   "..." + this.userAccessor.getLastName();
    }
    
    public void injectUserAccessorInstance(UserAccessor accessor)
    {
        this.userAccessor = accessor;
    }
}

public class Main
{
    ...    
    public static PenRepository getPenRepository()
    {
        PenRepository repoToReturn = Pen.repository();
        
        User.injectUserInstanceIntoPenRepository(repoToReturn);
        
        return repoToReturn;
    }
    ...
}

public class User
{
    private String firstName;
    private String lastName;
    
    public User(String first, String last)
    {
        this.firstName = first;
        this.lastName = last;
    }
    
    public User()
    {
        
    }
    
    public static void injectUserInstanceIntoPenRepository(PenRepository repo)
    {
        repo.injectUserAccessorInstance(new Accessor(new User()));
    }
    
    private static class Accessor implements UserAccessor
    {
        ... same idea as Pen's Accessor ...
    }
}

Note that User has a public constructor for the purpose of this example.

You’ll notice that this situation lends itself to a repository factory to encapsulate the construction of the repository.

Variation #2

What if you only want to force construction of an object through another, but don’t care about who calls accessors? Let’s say you have a PenTransferObject, so you can display on the UI, and a PenTransferObjectFactory that takes Pens and spits out PenTransferObjects.

You want everyone to use the factory to get transfer objects, but don’t care if they use getters and setters, because, after all, it is a DTO.

First, the DTO:

public class PenTransferObject
{
    private String penString;
    
    private PenTransferObject()
    {
        
    }
    
    public static void injectTOInstanceIntoFactory(PenTransferObjectFactory factory)
    {
        factory.injectPenTOInstance(new PenTransferObject());
    }
    
    public void setPenString(String color, int length)
    {
        this.penString = "This is a " + color + " pen " + length + " inches long."; 
    }
    
    public void displayOn(Screen1 screenParams)
    {
        screenParams.statusBarText = this.penString;
    }    
}

Nothing special, just a private constructor. Just note that it injects an instance of itself into the factory — just an instance, not wrapped around an accessor, because it doesn’t have one.

Now the factory:

public class PenTransferObjectFactory
{
    private PenAccessor accessor;
    private PenTransferObject penTO;
    
    // I am a friend of Pen...
    
    public PenTransferObjectFactory(PenAccessor accessor)
    {
        this.accessor = accessor;
    }
    
    // ...and a friend of PenTransferObject
    
    public void injectPenTOInstance(PenTransferObject penTO)
    {
        this.penTO = penTO;
    }
    
    public PenTransferObject createTO(Pen p)
    {
        this.accessor.injectPen(p);
        
        penTO.setPenString(this.accessor.getColor(), this.accessor.getLength());
        
        return penTO;
    }
}

This factory is a full-fledged friend of Pen, but only a…we’ll call it “constructor friend” of PenTransferObject.

Now usage:

public class Main
{
    ...
    public static PenTransferObjectFactory getPenTOFactory()
    {
        // ask Pen, friend of PenTransferObjectFactory,
        // for an instance of PenTransferObjectFactory
        PenTransferObjectFactory TOFactory = Pen.TOFactory();
        
        // tell PenTransferObject, also a friend of PenTransferObjectFactory,
        // to give our instance of PenTransferObjectFactory an instance of PenTransferObject
        PenTransferObject.injectTOInstanceIntoFactory(TOFactory);
        
        // now the PenTransferObjectFactory is fully configured with access
        // to all its friends
        
        return TOFactory;
    }

    public static void main(String[] args)
    {
        Pen blackPen = ...
        
        PenTransferObject to = getPenTOFactory().createTO(blackPen);        
        Screen1 params = new Screen1();        
        to.displayOn(params);
    }
}

Works.

Variation #3

Finally, what if class A declares class B is its friend, which declares class C is its friend?

This gets sticky, but you can still use the Friend Class Pattern shown here. I won’t show the code. However, essentially what you end up doing is that class B, when instantiating class C and giving it an instance of its private accessor, must ask class A for an instance of itself.

Why? Because class A says class B is a friend, and by definition of the Friend Class Pattern, anyone who wants a fully functioning class B instance, including class B itself, must go through class A.

Just remember: if you have a design like this, re-think it. I ran into the problem during my re-implementation of The Project, and it turned out to be a funky design. I had two domain objects as friends.

Generally, I think the only friendships that should exist are in the context of patterns or between domain objects and classes that interact with other layers.

Though some might think that friend classes violate object-oriented principles, I’ve found that going 100% with any OO idiom will crash you into the fenders of other idioms. Correctly used, I think the Friend Class Pattern can alleviate some of the ugliness of your code and help you find the right balance.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: