aspose file tools*
The moose likes Java in General and the fly likes 'Reaching through' multiple classes (law of demeter) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark " Watch " New topic
Author

'Reaching through' multiple classes (law of demeter)

Stephen Bell
Ranch Hand

Joined: May 11, 2013
Posts: 38
Hi all!

I'm writing a game using OpenGL on Android but this question is not Android specific so have posted it here.

Basically I have 3 classes (A 'main' rendering class, where I basically call everything and where my main loop is based), a 'Resource' class which is a custom class where I load all my resrouces and create all of my objects, and another custom class 'Quad' which contains all of my code to create my OpenGL textured quad objects (used for my sprites).

So, this is a simplified version of my setup.

My Resource Class



My Quad Class



And finally, my main GLRenderer class:




This is working perfectly and I'm really happy because, previously, I had all of my objects in my 'MyGLRenderer class' and it was just unmanageable. (This example shows only 1 object, but I'm working with tons of objects so my main class held all of the corresponding object declarations, object creation code etc... and it was huge.).

I split the resources into their own class to make things more manageable and they really are, however. I don't understand if this breaks the 'law of demeter' - and if it does, why is this a problem?

I've read so much on this 'law' but I can't understand why breaking it is a bad thing (when I say I don't understand, I mean that I don't understand the explanations I've read). I do know that breaking this law won't affect performance or 'break' the code though (ie cause it to not run).

So, does my code break this law when I'm drawing my sprite, if so could someone please explain in relation to my code why and offer an alternative way for me to access my objects, or if I'm happy with it, should I just leave it?

Thanks!


Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Yes, your code does break that rule.

What makes that rule important is that it enforces encapsulation. The problem with breaking the rule is that, now, your main class needs to know specifics about the resources class and can break if the resources class changes internally (such as changing the name of the variable or how it is stored). Such changes happen a lot, and when you do the pass-through calling these changes make you have to modify the calling code. And this makes maintenance harder. It also doesn't save you much, because you also need to know about the sprite in order to do the drawing, so all you get is an extra dependancy which is a bad thing.

If the main class needs to know about sprite, then the sprite should be a member of the Main class, so as to keep the dependencies to a minimum. and keep the maintenance cost down. On the other hand, having a class manage your resources is a good idea. But if you do that, you should do it completely, giving the resource class complete responsibility for the resources, and not giving away its internals. That Could mean providing a public void drawResources() method So the main class does not need to know about the resource class' variables.


Steve
Stephen Bell
Ranch Hand

Joined: May 11, 2013
Posts: 38
Hi Steve,

Thanks for you reply.

I assume you mean it could cause problems if I (as the developer) make changes to the code?

Could you please show with pseudo code (based on my code) how this could cause an issue? I would appreciate it as I've read the same thing, but I still don't really understand, I'll probably understand better with the help of an example - thanks!

Also, regarding your solution of a 'drawResources()' method, I don't really understand, could you please show me in pseudo code? (bearing in mind, my resources class shouldn't do any actual drawing, I designed it specifically to hold my object creation and graphics loading). I really want to try to keeps everything 'modular' as it makes things a lot easier when it comes to readability.

Thanks again, really appreciate your help :-)

---------------------------------------------------------

Been reading up a bit more and I think I get what you mean, create a proxy method in my Resources class that passes my sprites onto my Quad class to draw? Thanks
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Stephen Bell wrote:Hi Steve,

Thanks for you reply.

I assume you mean it could cause problems if I (as the developer) make changes to the code?

Could you please show with pseudo code (based on my code) how this could cause an issue?


No pseudocode needed. You have the line of code like res.mySprite.whatever(). What will happen when you change the name of the variable mySprite to playerSprite? The resource class will compile fine, but the main class is broken. Now you have track down every place you use that variable and fix it. Nos let's say you want the game skinnable, so instead of a single variable for the playerSprite you have a map keyed to the skin the game is being played with. Now not only does the main class' call through break, it needs to know more info, like the current key to the map. Things will get even harder to fix when you start to do slme resource-saving tricks like memory caching.

The other problem you will see is the enforced sequencing of calls. You have a method called loadResources() which presumably must be called before using a resource like mySprite. How do you enforce that? Right now in the main class you probably call the method at the proper time, but how about in a month when you come back to refactor the main class or add threads or something? Since the variable reference is accessed directly it will be easy to miss that load step or let it get called out of order. Those types of problems can be tough to track down too, since they could be sporadic. But if the resource class takes full responsibility of managing the resources, and only allows indirect access to the resources it holds through methods, the resource class can ensure the loading is done before anyone can use the resources. The closest you can do when you allow other classes to directly access the field is to document it and hope people read, remember, and act on the documentation.
Stephen Bell
Ranch Hand

Joined: May 11, 2013
Posts: 38
I understand - thanks for this, appreciate it!
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: 'Reaching through' multiple classes (law of demeter)