Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

My game reads a number of JSON files, deserializes them, and hands the resulting objects off to the classes that need them. These deserialized objects, which can be thought of as the domain model, are normally very simple:

public class Settings
{
    public bool FullScreen = false;
    public int WindowWidth = 800;
    public int WindowHeight = 600;
}

But one of these objects is not so simple:

public class Sprite
{
    [JsonProperty]
    private readonly string assetName;

    [JsonProperty]
    private Vector2 position;

    // other properties...

    public Sprite( string assetName, Vector2 position )
    {
        this.assetName = assetName;
        this.position = position;
    }

    public void Move( Vector2 direction )
    {
        // do move
    }

    // other methods...
}

The properties of the Sprite class are private because I want to have good encapsulation. This means it has a constructor that accepts many arguments and several other methods for setting its properties. Also, each property needs an attribute so it can be read by the JSON parser. It looks like a POCO, but I read that POCOs should be persistance ignorant. I could create a simpler domain model that acts more like a DTO to satisfy this:

public class Sprite
{
    public string AssetName = "default.png";
    public Vector2 Position = Vector2.Zero;
}

Now my Sprite class is nice and ignorant. I can write another class to handle business logic type of stuff:

public class SpriteWhatever
{
    private Sprite sprite;

    public SpriteWhatever( Sprite sprite )
    {
        this.sprite = sprite;
    }

    public void Move( Vector2 direction )
    {
        // do move
    }

    // other methods...
}

But then I'm worried that my domain model is anemic. In order to avoid that, I could just make all the properties of the Sprite class public, and keep all the business logic in it, but then I have no encapsulation.

What should I do?

share|improve this question
4  
Rules should be learned so that they can be followed most of the time, and broken when it makes sense to do so. –  Robert Harvey Feb 15 at 3:56
    
I agree, but can you give me anything more specific? You basically just gave me another rule. –  Koveras Feb 15 at 17:03
    
Does it make sense to make it anemic, despite the fact that Fowler doesn't like it? –  Robert Harvey Feb 15 at 17:23
    
I'm starting to wonder if the domain model fits into my application at all. Terms like "business rules," "business logic," "business objects" all suggest... businesses. –  Koveras Feb 15 at 19:32
    
"Business logic" just means the "business-end" of your application. That is, the part that actually does any real work. UI, database, JSON... Those are all just ceremony so that you can apply logic to your data. Though I'll grant you that "business logic" is not normally a term I would ascribe to game logic, and your example does look like a game. Gamers don't typically do all this "business domain" stuff, although some of it is applicable. –  Robert Harvey Feb 15 at 19:34
add comment

2 Answers

I think your approach is on the right direction. One important thing: your domain model is not the Sprite class but the SpriteWhatever class! A real domain model is the place where your business rules and behaviors are located. In your example, this is the SpriteXXX class. The Sprite class is only a data structure for carrying data. Of course this class is anemic, because data structures are anemic by definition.

share|improve this answer
    
Wow, that explains a lot. I had it completely backwards! So should I keep my Sprite class the way it was, with JsonProperty attributes, private properties and public methods? Would it make more sense to make the properties public because it is basically an entity? Wouldn't that cause encapsulation problems? Do I need to change anything? –  Koveras Feb 15 at 17:07
add comment

This is an answer to the question you posted in the comment on @AlfredoCasado's answer. It's only about the encapsulation aspect of your question.

[tl;dr]: The important thing about encapsulation is getting the functionality in methods/properties, not restricting access to the data.


The Wikipedia Article about encapsulation mentions these two definitions:

  • A language mechanism for restricting access to some of the object's components.
  • A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.

Many believe the first one (data hiding and access control) is the most important, and the article alludes to this. Note Robert Harvey's comment about rules: this is one you can be less guilty about breaking. Data Hiding is about 15-20% of the benefit. Using a property to wrap a member, by the way, is not even data hiding (unless it's a value type you're making read-only, or, returning a clone of a reference type or an immutable type; but often those are OOAD hints that you should be returning a value from a method).

Most of the benefit of Encapsulation comes from the 2nd item: bundling data. I would also add, organizing functionality in methods of an object (which also hides implementation, but that's not the point). This is 80-85% of the benefit of encapsulation.

Thus instead of an object's consumer having to worry about the details, you can do (and see) in a few lines of code, using terms from your ubiquitous language, that you've carried over into your method names, exactly what you want.

Then no matter how smart you are, your brain uses less horsepower, and you can do more. That's the 'magic' of OO right there. Data hiding isn't.

Another note about data hiding: It's just a hint to the programmers of the objects you made (50-80% of the time this is you). Devs can (and I see it all the time) check out your class and make private stuff public. Even if you're writing libraries for sale (and who does that?) they can use reflection to hack it. We've done it at my shop and saved tons of money! Who cares if the next version breaks because the implementation was private? We have control over which version we use!!

Bottom line you have to know or notice either way. If you don't know why it's private you won't take the hint. If you do, it won't matter. Yes, data hiding pushes devs in the right direction, and encourages good modelling practices. Here's the Elephant in the room: Encourage all you want. A person who doesn't know OOAD won't learn from encouragement. Better to spend the time teaching them.

Wow, that was long.

edit (See comment by @DavidKennedy85) I completely agree ... however, organizing the implementation into methods of an object (which I bet you do) provides that functionality as well - an accomplishes the lion's share of the benefits of encapsulation. I am not implying the first aspect is worthless - this is just what is taught so much (bulk of article reflects that). The quote you mention brings up an important point - limiting the size of the interface surface to a cleverly-succinct small subset. (limit interdependencies). Another way to improve objects is to limit that state the object retains - meaning there will be fewer fields to make private. I am sure we agree on this things - I am just pointing out the obvious that for a dev to design her objects right, she has to start by first knowing how, then doing the design, and the private fields and methods will automatically become obvious without her having had to think about their accessibility; however focusing first on the fact that some things should have limited access isn't nearly as useful as the mountain of other 'artwork' that is involved in a proper design, and if proper design is done, what's public and private in the end won't be the thing that matters.

A crappy design can expose itself in lots of publics - but that could be a good design. You can also have a crappy design with very few publics.

Now I'm just ranting - but I have a right to with every other programmer that came out of uni being told that it would be as easy as data hiding and a couple other concepts that sound good but are too basic to be helpful (like 'is-a/has-a'). It's not, it's much harder, and I was not taught the important things!

share|improve this answer
    
While the Wikipedia article mentions both uses for encapsulation, the rest of the article is entirely about the first. I've always found the primary benefit from encapsulation in this paragraph: Hiding the internals of the object protects its integrity by preventing users from setting the internal data of the component into an invalid or inconsistent state. A benefit of encapsulation is that it can reduce system complexity, and thus increases robustness, by allowing the developer to limit the inter-dependencies between software components. How do you reconcile this to your answer? –  Koveras Feb 15 at 18:16
    
@davidkennedy85: which part? Private to avoid invalid state? If they want to create an invalid state, they probably can. Reducing system complexity is generally beneficial, but not a goal in and of itself. –  jmoreno Feb 16 at 6:51
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.