Object-Oriented Design – Is Separating Classes into Data and Method Only Classes a Good Pattern?

dtoobject-orientedstatic methods

For example, a class usually have class members and methods, eg:

public class Cat{
    private String name;
    private int weight;
    private Image image;

    public void printInfo(){
        System.out.println("Name:"+this.name+",weight:"+this.weight);
    }

    public void draw(){
        //some draw code which uses this.image
    }
}

But after reading about Single responsibility principle and Open closed principle, I prefer separate a class into DTO and helper class with static methods only, eg:

public class CatData{
    public String name;
    public int weight;
    public Image image;
}

public class CatMethods{
    public static void printInfo(Cat cat){
        System.out.println("Name:"+cat.name+",weight:"+cat.weight);
    }

    public static void draw(Cat cat){
        //some draw code which uses cat.image
    }
}

I think it fits Single responsibility principle because now the responsibility of CatData is to keep data only, doesn't care about the methods (also for CatMethods). And it also fits the open closed principle because adding new methods doesn't need to change the CatData class.

My question is, is it a good or an anti-pattern?

Best Answer

You have shown two extremes ("everything private and all (maybe unrelated) methods in one object" vs. "everything public and no method inside the object"). IMHO good OO modeling is none of them, the sweet spot is somewhere in the middle.

One litmus test of what methods or logic belongs into a class, and what belongs outside, is to look at the dependencies the methods will introduce. Methods which don't introduce additional dependencies are fine, as long as they fit well to the abstraction of the given object. Methods which do require additional, external dependencies (like a drawing library or an I/O library) are seldom a good fit. Even if you would make the dependencies vanish by using dependency injection, I still would think twice if placing such methods inside the domain class is really necessary.

So neither you should make every member public, nor do you need to implement methods for every operation on an object inside the class. Here is an alternative suggestion:

public class Cat{
    private String name;
    private int weight;
    private Image image;

    public String toString(){
        return "Name:"+this.name+",weight:"+this.weight;
    }
    public Image getImage(){
        return image;
    }
}

Now the Cat object provides enough logic to let surrounding code easily implement printInfo and draw, without exposing all attributes in public. The right place for these two methods is most probably not a god class CatMethods (since printInfo and draw are most probably different concerns, so I think it is very unlikely they belong into the same class).

I can imagine a CatDrawingController which implements draw (and maybe uses dependency injection for getting a Canvas object). I can also imagine another class which implements some console output and uses toString (so printInfo may become obsolete in this context). But for making sensible decisions on this, one need to know the context and how the Cat class will actually be used.

That is actually the way how I interpreted Fowler's Anemic Domain Model critics - for generally reusable logic (without external dependencies) the domain classes themselves are a good place, so they should be used for that. But that does not mean to implement any logic there, quite the opposite.

Note also the example above leaves still room for making a decision about (im)mutability. If the Cat class will not expose any setters, and Image is immutable itself, this design will allow to make Cat immutable (which the DTO approach won't). But if you think immutability is not required or not helpful for your case, you can also go into that direction.

Related Topic