The S.O.L.I.D way: When it’s a Class and when it’s NOT???

April 17, 2014

no comments

Actually at first it’s seems a very dumb question, because for sure we know when we declaring a new class. But I found that it’s not so true!!!

Let’s take the next scenario. You are creating a new website for “Games how to???” For example:

  • Soccer​
    • 2 teams, 11 players on each team
    • 1.5 hours with one breaks
    • Cannot touch with the hand
    • Ball cannot get out from the field borders
    • Need soccer field
  • Basketball
    • 2 teams, 5 players on each team
    • 1 hour game, with 4 breaks
    • Cannot walk with the without dribble
    • Ball cannot get out from the field borders
    • Need basketball field
  • Cheese
    • 2 players
    • Each move can/or not be limited with response time
    • The game can last for ever
    • Need cheese board
  • Blackjack
    • Not mention limitation on number of players
    • Need to have 21 (or must close to it)
    • Need number of decks
  • Solitaire
    • Single player
    • ‘Clean’ the Decks to win
    • No game time limitation

So, are they all different Classes diverted from some Supper Abstract Class “Game”? Or what?

For sure we should reference to the basic S.O.L.I.D principles (see wiki SOLID (object-oriented design))

Initial Stands for
(acronym)
Concept
 S  SRP Single responsibility principleclass should have only a single responsibility (i.e. only one potential change in the software’s specification should be able to affect the specification of the class)
 O  OCP Open/closed principle“Software entities … should be open for extension, but closed for modification.”
 L  LSP Liskov substitution principle“Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.” See also design by contract.
 I  ISP Interface segregation principle“Many client-specific interfaces are better than one general-purpose interface.”
 D  DIP Dependency inversion principleOne should “Depend upon Abstractions. Do not depend upon concretions.”
Dependency injection is one method of following this principle.
(The table taken from wiki)

If we consider the first S.O.L.I.D principle we can assume that each game is a Class that handle his own responsibility and it’s because that each game have his own roles, accessories, game time and what else.

But actually is it?

Class is distinguish from other Classes by his fields and his responsibility. Fields are by Game structure and Responsibility is actuality (in this case) as set of Rules, vector/ array / list of Roles, another Field that holds the Rules!

So, let’s say that Game Class looks like:

As you can see this is a BAD Class description, because:

  • Game that have no teams will not use the ‘numberOfteams’ field.
  • Solitaire & Blackjack will not use the ‘fieldInfo’ field.
  • And so on…

Yes, we can use it with no population of the un-needed fields and not validate them with the rules.

BUT IT’S THE WORNG WAY TO DO IT!!!

How to categorize? How to Class?

If you listen to the business it will work well until the time you understand that the business didn’t understand the customer and all change and now all your class diagram.

We must understand the business but also ask the right questions!

Quick & Dirty

First let’s take a look on a basic final Game Classes that might be good for us.

The good thing is that all is there and we are not missing anything, the bad is that we duplicate a lot and on an extension or fix we’ll need to open must of the Classes ones again.

Capsulation step by step

When we can look at a game there are some basic fields that exist on every games, no matter if it’s a team game, a ball game, a card game, timed game or whatever game.

We are taking about,

game name and game rules
. Each game must have a name to understand on witch game are we talking about and his rules about how to play it. From this we have found our abstract base class


Game
.

Now I spitted the games to two divisions


PlayersGame
TeamsGame.

As you can see the Class that will implement the IPlayer interface will be responsible on the Player entity and the Class that will implement the ITeam interface will be responsible on the Team contains one or more Players. We must capsulate and set responsibility on each Class.

So now; we have:

  1. Cheese Game
    1. 2 Players ç PlayersGame
    2. Game Box
    3. Game Rules çInherit IRule on Game Class
  2. Poker Game
    1. Several Players ç PlayersGame
    2. Cards deck
    3. Game Rules çInherit IRule on Game Class
  3. Soccer / Basketball Game
    1. 2 Teams ç TeamsGame
      1. 5 or 11 Players (each player different rules)
    2. Field
    3. Game duration
    4. Game Rules çInherit IRule on Game Class
  4. Solitaire Game
    1. Single ç PlayersGame
    2. 5 Cards Deck
    3. Game Rules çInherit IRule on Game Class
  5. Puzzle Game
    1. Several Players or ç PlayersGame
    2. Game Box
    3. Game Rules çInherit IRule on Game Class

Like you can see above, the final Classes will be:

  • BoxGame – have a parameter for the game box (i.e. Cheese, Puzzle or other)
  • CardsGame – have a parameter for the game cards kit (i.e. Solitaire, Poker, Blackjack or other)
  • BallGame – have parameter for the “game field” (should be interface) and parameter for the game ball.

So, Cheese & Puzzle are instances of BoxGame, and Solitaire & Poker are instances of CardsGame and Soccer & Basketball are instances of BallGame.

For the actual game we must inherit from IRule interface and create concrete Interfaces & Classes for it, like;

1: public bool validate(IGame game){
2:
3:     /// Check that ball didn't pass the Field borders
4:     return true;
5: }

Hope that you find this article enlightening. Remember that at the end we want to encapsulate and use O.O.P / O.O.D but too much derived Classes are disadvantage. Remember to use the S.O.L.I.D rules correctly and “feel” the project.



Amour Shmuel

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*