1

I'm currently working on a game. At the moment, I have one class (the game's environment) responsible for holding collections of game objects (enemies, weapons, etc.) and doing collision-checks, calling the objects' creation routines, etc. As I've progressed with the project, I've started to wonder if I should have a more layered approach - is it better to have, say, a WeaponsManager, an EnemiesManager, and an Environment holding everything together, or to have my Environment class manipulating each object as I'm doing right now?

It might be worth mentioning that the game objects are already fairly heavily layered:

BaseClass
-----EnemyClass
----------Enemy1Subclass
----------Enemy2Subclass
-----WeaponClass
----------Weapon1Subclass
----------Weapon2Subclass

BaseClass has basic object properties defined, such as position. EnemyClass and WeaponClass are fairly generic classes that define more class-specific methods and properties, such as speed for EnemyClass or damage for WeaponClass. They mostly exist so I can have fairly generic collections instead of a separate collection for each individual enemy/weapon type. Enemy1Subclass/Enemy2Subclass and Weapon1Subclass/Weapon2Subclass are the actual enemy/weapon classes, which are actually created and used.

My Environment class stores collections of EnemyClass/WeaponClass and does the necessary manipulation by calling the game objects' methods.

Environment (manipulates EnemyClass and WeaponClass objects by iterating over their respective arrays and calling their respective methods; doesn't do any subclass-specific stuff)
-----EnemyClass array
----------Enemy1Subclass entry
----------Enemy2Subclass entry
----------Enemy1Subclass entry
-----WeaponClass array
----------Weapon1Subclass entry
----------Weapon2Subclass entry
----------Weapon2Subclass entry

But now I'm wondering if yet another layer of separation would be a good idea, with Environment holding EnemyManager/WeaponManager classes and the respective managers holding and manipulating their collections:

Environment (calls generic instantiation, destruction, moving, etc. methods in EnemyManager and WeaponManager; doesn't ever directly interact with an EnemyClass or WeaponClass object)
-----EnemyManager (gets instructions from Environment and manipulates EnemyClass objects to carry out those instructions)
----------EnemyClass array
---------------Enemy1Subclass entry
---------------Enemy2Subclass entry
---------------Enemy1Subclass entry
-----WeaponManager (gets instructions from Environment and manipulates WeaponClass objects to carry out those instructions)
----------WeaponClass array
---------------Weapon1Subclass entry
---------------Weapon2Subclass entry
---------------Weapon2Subclass entry

Thoughts? Suggestions? I've not been able to find anything about this kind of "more classes or harder-working classes" convention, so any answer is fair game, right up to and including "your model is trash, start over." Although hopefully it won't come to that. ;)

cf-
  • 8,598
  • 9
  • 36
  • 58
  • 1
    May be suited best at http://programmers.stackexchange.com/ or http://codereview.stackexchange.com/ – rajesh Apr 10 '13 at 05:34
  • flagging as I think this is a debatable question. There is no good answer to this IMO. But you should consider reading design patterns books so that you can get an idea as to what suits better for your domain or problem. – Narendra Pathai Apr 10 '13 at 05:47

3 Answers3

3

Generally speaking (very generally), a major advantage of object-oriented languages is Encapsulation - the idea that it is better to group related functions/methods and data together (with appropriate permissions). Applied here, that means that it is nicer to separate code as far as "it makes sense". In your example, "harder working classes" implies classes that are larger, more difficult to understand as a whole, and dealing with large amounts of data. Two nice guidelines that cover either side of the continuum:

  • If you need a flowchart to keep track of everything that happens inside one class, you should probably make another class
  • If you notice Class A only contains Class B which only contains Method C, perhaps this can all be within one function

    In summary, just do your best to ensure that your code is divided up in reasonable, NOT superfluous sections.

WannabeCoder
  • 498
  • 1
  • 5
  • 20
  • There are 554 lines in my Environment class; a significant chunk of that is object manipulation which could be easily split out into another class or two. Your flowchart comment decided things for me (I hadn't fully realized exactly how complex my Environment had gotten!) – cf- Apr 10 '13 at 06:06
0

Remember, in (almost) all programming, clarity is key.

In this case, do what makes the most intuitive sense. What I've found is that it's generally worth the pain to split programs and functions into multiple classes, because it improves maintainability, and makes code generally more explicit.

However, there is a fine line between syntactic sugar and syntactic saccharin. In other words, keep your organization as neat as possible, but don't overdo it. Do what makes your code the clearest.

In this case, this seems like a good use for interfaces. Try to avoid instanceof when you can create a new instance of an interface or abstract class.

  • I'm actually thinking an abstract class might be better than an interface for the BaseClass, since some behavior is the same across all classes (i.e. positioning constraints and positioning) and some is class-specific. It's my understanding that an Interface can't implement these cross-class methods while an abstract class can, and both can be inherited for the class-specific behavior. I've been able to get away with just two instanceof operators, using a bunch of overloaded methods and moving some logic from Enemy1Subclass/Enemy2Subclass into EnemyClass to make stuff more generic instead. – cf- Apr 10 '13 at 05:45
  • @user2245528 That it probably would be. I can't really say for certain without being more familiar with your project's design and layout, but it sounds like you're on the right track. –  Apr 10 '13 at 05:46
0

Although it's good to think a bit about architecture before you start hacking - think of programming as an iterative process. So start with the simplest possible thing and then keep refactoring constantly. That way you don't overengeneer and keep your code maintainable. So concerning your post title, start with one class doing the work and if you come to a point where it makes sense to extract certain things, then do it - today's IDEs will make it very easy for you.

Alexander Rühl
  • 6,769
  • 9
  • 53
  • 96