Question

I've been studying some Object Oriented Analysis and Design lately, and I feel that I got a pretty good overall feel for it.

But this little scenario keeps bugging me.

Let's say I'm designing a simple board game. I have class Game which holds info about the board and the players. Players are created from the class Player. All players have a bank account created from the class BankAccount.

My Game handles the logic about what should happen following a move. Most of the time this involves withdrawing or depositing some amount from a players bank account.

My BankAccount has the methods for withdrawing, depositing and returning the balance. But my Game doesn't know about a players bank account. Only about the player. Do I give my Player class a method getAccount, so i can call playerObject.getAccount().withdraw()? Or how do I go about assigning the responsibility for this behaviour? Should my Player class implement a method withdraw() that just calls account.withdraw() on it's associated account object?

Was it helpful?

Solution

A Bank ought to have control of the BankAccounts, not the player objects.

In other words a Bank should be a collection of BankAccounts plus some additional methods for managing those accounts.

This is so you can do things like:

bank.WithDrawMoney(player, amount);

or

bank.TransferMoney(playerFrom, playerTo, amount);

In this case the bank would "look up" the account that that player has and remove the appropriate funds from it.

Imagine if it was a real bank account. A person doesn't carry that account with them, only a reference to it. A Bank is responsible for transfer of funds (deposits, withdrawals..).

So, at a top level, you are going to have a Game which contains objects such as Players, Bank, and Board. It may have top methods such RollDice(). The Board may have a method such as Move(player, distance);

OTHER TIPS

playerObject.getAccount().withdraw() violates the "Law" of Demeter.

Expose the methods on Player, etc. that make sense for a player. Investigate Inversion of Control for dealing with dependencies.

I think you want to ask yourself this question: is account that the player holding a public property of the player? If yes, maybe getAccount() is not a bad option.

In the end it all comes down to balance. If your account class has 20 methods/properties (let's ignore arguments on whether or not 20 is a high number), then clearly from coding perspective having one function player.getAccount() would duplicate a lot less code than having 20 functions in the player that simply forward the calls into the account.

On the other hand, you need to remember that getAccount() now couples your game class implementation to the fact that each player must have an a account. You can't have players that don't have bank accounts.

In a better OO strategy you want each class to serve as some kind of abstraction, so that it provides a simplified view to its clients while hiding complexity/details behind private variables. You are not doing that if you have getAccount() but you are also not doing that if you simply expose every single account function in the player class.

So instead, you could have player class simply have a function getCash(). From outside (i.e. game class perspective) it doesn't matter how the player gets the cash. Internally, the player can go to the bank account and perform a withdraw. But by keeping two things decoupled, later on you could have a different player class that might get the cash in some other way (i.e. reach into his own wallet). The key is only to expose to the outside the behavior of the player himself and hide how that behavior is implemented (i.e. don't advertise that money is retrieved from bank account).

For what it's worth, I usually find it productive to try and start out thinking in the problem domain, away from code as others have touched on.

I'll assume its a Monopoly-like boardgame. How would payment pan out in real life? What process is one actually trying to model?

I realise you've stated you have a bank account class, but if the process is Joe Bloggs actually paying, in cash (from his stash in the toilet cistern), Fred, without anything to do with the bank, then he's not going to need a bank account. If Fred then chooses to bank it at some point —rather than keep stuffing it under the mattress (or gameboard)— then at that point he will need a bank and an account.

Assuming player can get/has a handle on the other players, the first process would see (in Player) something like:

void payPlayer( player, amount )
{
  spendCash( amount ); // reduces stash by "amount"
  player.recieveCash( amount );

}

The size of the stash of cash might just be an attribute of the player class.

The second activity is a totally different thing. Fred now has to first tell his bank that he wants to deposit $100 and then his bank, either by hole-in-the wall or teller, will (hopefully) credit his account. So Fred really does need a bank and probably an account now. But why does he need the account? What purpose does it serve within the game? Is it definitely a necessary component of the program or is it just there because banks are where money goes in real life?

Then there is the case where a player really does want to transfer bank funds in his or her account to another player's account as payment. In this scenario both players need a bank and account, but only the bank can actually transfer funds, so they just need to know about the bank for that. One would only do this, of course, if the bank had some other, significant, role in the game.

So the answer to how to implement the transfer of money in the game depends entirely on the game mechanics. If you really need a bank account-like class then it's a pretty safe bet you should have a bank. But you have to ask yourself why do you really need bank account objects flying around in the first place? And if a player's bank account is directly associated with them, is it really a bank account any more, or just Joe dipping his hand into the toilet cistern?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top