Use Case Realizations for the Monopoly Iteration - UML

First, an education point: Please don't dismiss this case study because it isn't a business application. The logic, especially in later iterations, becomes quite complex, with rich 00 design problems to solve. The core object design principles that it illustrates - applying Information Expert, evaluating the coupling and cohesion of alternatives - are relevant to object design in all domains.

Figure 18.20 Creation of the initial domain object and subsequent objects.

We are designing a simplified version of Monopoly in iteration - 1 for a scenario of the use case Play Monopoly Game. It has two system operations: initialize (or startUp) and playGame. Following our guideline, we will ignore initialization design until the last step and focus first on the main system operations - only playGamein this case.

Also, to support the goal of low representational gap (LRG), we look again at Figure, which shows the Domain Model. We turn to it for inspiration as we design the domain layer of the Design Model.

How to Design playGame?

The playGamesystem operation occurs when the human game observer performs some UI gesture (such as clicking a "play game" button) to request the game to play as a simulation while the observer watches the output.

We didn't write a detailed use case or an operation contract for this case study. as most people know the rules; our focus is the design issues, not the requirements.

Figure 18.21 Iteration - 1 Domain Model for Monopoly.

Choosing the Controller Class

Our first design choice involves selecting the controller for the system operation message playGamethat comes from the UI layer into the domain layer. By the Controller pattern, here are some choices:

Represents the overall "system," "rootMonopolyGame - a kind of root object," a specialized device, or a major subsystem.

Represents a receiver or handler of all system events of a use case scenario.

object: We think of most of the other domain objects as "contained within" the MonopolyGame. Abbreviated MGamein most of the UML sketches.

MonopolyGameSystem - a name suggesting the overall system

PlayMonopolyGameHandler - constructed from the pattern <use - case - name> "Handler"

PlayMonopoly GameSession

Choosing a root - object facade controller like MonopolyGame (MGamein Figure) is satisfactory if there are only a few system operations (there are only two in this use case) and if the facade controller is not taking on too many responsibilities (in other words, if it is not becoming incohesive).

Figure 18.22 Applying Controller to the playGamesystem operation.

The Game - Loop Algorithm

Before discussing 00 design choices, we prepare by considering the basic algorithm of the simulation. First, some terminology:

  1. turn - a player rolling the dice and moving the piece
  2. round - all the players taking one turn

Now the game loop:

for N rounds

for each Player p p takesa turn

Recall that the iteration - 1 version does not have a winner, so the simulation simply runs for N rounds.

Who is Responsible for Controlling the Game Loop?

Reviewing the algorithm: The first responsibility is game loop control - looping for N rounds and having a turn played for each player. This is a doing responsibility and is not a creation or controller problem, so naturally, Expert should be considered. Applying Expert means asking, "What information is needed for the responsibility?" Here's the analysis:

Table

Therefore, by Expert, MonopolyGameis a justifiable choice to control the game loop and coordinate the playing of each round. Figure illustrates in UML. Notice the use of a private (internal) playRoundhelper method; it accomplishes at least two goals:

  1. It factors the play - smgle - round logic into a helper method; it is good to organize cohesive chunks of behavior into small separate methods.
  2. Good 00 method design encourages small methods with a single purpose. This supports High Cohesion at the method level.
  3. The name playRoundis inspired by domain vocabulary - that's desirable, it improves comprehension.

Figure 18.23 Game loop.

Who Takes a Turn?

Taking a turn involves rolling the dice and moving a piece to the square indicated by the total of the dice face values.

What object should be responsible for taking the turn of a player? This is a doing responsibility. Again, Expert applies.

Now, a naive reaction might be to say "a Player object should take the turn" because in the real world a human player takes a turn. However - and this is a key point - 00 designs are not one - to - one simulations of how a real domain works, especially with respect to how people behave. If you applied the (wrong) guideline "put responsibilities in software objects as they are assigned to people" then, for example in the POS domain, a Cashier software object would do almost everything! A violation of High Cohesion and Low Coupling. Big fat objects.

Rather, object designs distribute responsibilities among many objects by the principle of Information Expert (among many others).

Therefore, we should not choose a Player object just because a human player takes a turn.

Yet, as we shall see, Player turns out to be a good choice for taking a turn. But the justification will be by Expert, not inspiration from how humans behave. Applying Expert means asking, "What information is needed for the responsibility?" Here's the analysis:

Table

Now, this is an interesting problem! There are three partial information experts for the "take a turn" responsibility: Player, MonopolyGame, and Board.

What's interesting about this problem is how to resolve it - the evaluations and trade - offs an 00 developer may consider. Here's the first guideline to solve the problem:

Guideline: When there are multiple partial information experts to choose from. place the responsibility in the dominant information expert - the object with the majority of the information. This tends to best support Low Coupling.

Unfortunately, in this case, are all rather equal, each with about one - third of the information - no dominant expert.

So, here's another guideline to try:

Guideline: When there are alternative design choices, consider the coupling and cohesion impact of each, and choose the best.

OK, that can be applied. MonopolyGameis already doing some work, so giving it more work impacts its cohesion, especially when contrasted with a Player and Board object, which are not doing anything yet. But we still have a two - way tie with these objects.

So, here's another guideline:

Guideline: When there is no clear winner from the alternatives other guidelines, consider probable future evolution of the software objects and the impact in terms of Information Expert, cohesion, and coupling.

For example, in iteration - 1, taking a turn doesn't involve much information. However, consider the complete set of game rules in a later iteration. Then, taking a turn can involve buying a property that the player lands on, if the player has enough money or if its color fits in with the player's "color strategy." What object would be expected to know a player's cash total? Answer: a Player (by LRG). What object would be expected to know a player's color strategy? Answer: a Player (by LRG, as it involves a player's current holdings of properties).

Thus, in the end, by these guidelines Player turns out to be a good candidate, justified by Expert when we consider the full game rules.

Based on the above, Figure illustrates the emerging dynamic design and static design.

Applying UML: Notice the approach to indicating that the takeTurnmessage is sent to each player in a collection named players.

Taking a Turn

Taking a turn means:

  1. calculating a random number total between 2 and 12 (the range of two dice)
  2. calculating the new square location
  3. moving the player's piece from an old location to a new square location

First, the random number problem: By LRG, we'll create a Die object with a faceValueattribute. Calculating a new random faceValueinvolves changing information in the Die, so by Expert Die should be able to "roll" itself (generate a new random value, using domain vocabulary), and answer its faceValue.

Second, the new square location problem: By LRG, it's reasonable that a Board knows all its Squares. Then by Expert a Board will be responsible for knowing a new square location, given an old square location, and some offset (the dice total).

Figure 18.24 Player takes a turn by Expert.

Third, the piece movement problem: By LRG, it's reasonable for a Player to know its Piece, and a Piece its Square location (or even for a Player to directly know its Square location). Then by Expert a Piece will set its new location, but it may receive that new location from its owner, the Player.

Who Coordinates All This?

The above three steps need to be coordinated by some object. Since the Player is responsible for taking a turn, the Player should coordinate.

The Problem of Visibility

However, that the Player coordinates these steps implies its collaboration with the Die, Board, and Piece objects. And this implies a visibility need - the Player must have an object reference to those objects.

Since the Player will need visibility to the Die, Board, and Piece objects each and every turn, we can usefully initialize the Player during startup with permanent references to those objects.

The Final Design of playGame

Based on the above design decisions, the emerging dynamic design is as shown in Figure and the static design as in Figure. Notice that each message, each allocation of responsibility, was methodically and rationally motivated by the GRASP principles. As you come to master these principles, you will be able to reason through a design and evaluate existing ones in terms of coupling, cohesion, Expert, and so forth.

Figure 18.25 Dynamic design for play Game.

Applying UML:

Notice in Figure that I show two sequence diagrams. In the top, the takeTurnmessage to a Player is not expanded. Then, in the bottom diagram, I expand the takeTurnmessage. This is a common sketching style, so that each wall diagram is not too large. The two diagrams are related informally. More formally, I could use UML sdand ref frames, which would be easy and appropriate in a UML tool; but for wall sketching, informality suffices.

  1. Notice again, with the roll and getFaceValuemessages to a Die object, the convention of drawing a loop frame around messages to a collection selection object, to indicate collection over each element in a collection.

  2. Notice the parameter fvTotin the getSquaremessage. I am informally suggesting this is the total of all the Die faceValues. This kind of informality is appropriate when we apply "UML as sketch," assuming the audience understands the context.

The Command - Query Separation Principle

Notice in Figure that the message to roll the Die is followed by a second getFace Valueto retrieve its new faceValue. In particular, the roll method is void - it has no return value. For example:

// style #1; used in the official solution public void roll()
faceValue // random num generation
}
public intgetFaceValue() {
returnfaceValue;
}

Figure 18.26 Static design for playGame.

Motivation: Why Bother?

CQS is widely considered desirable in computer science theory because with it, you can more easily reason about a program's state without simultaneously modifying that state. And it makes designs simpler to understand and anticipate. For example, if an application consistently follows CQS, you know that a query or getter method isn't going to modify anything and a command isn't going to return anything. Simple pattern. This often turns out to be nice to rely on, as the alternative can be a nasty surprise - violating the Principle of Least Surprise in software development.

Consider this contrived but explosive counter - example in which a query method violates CQS:

Missile m = new Missile();
// looks harmless to me! String name = m.getNameO;
public class Missile
{
// ...
public String getNameO
{
launch(); // launch missile!
return name;
A
} // end of class

Initialization and the 'Start Up' Use Case

The initialize system operation occurs, at least abstractly, in a Start Up use case. For this design, we must first choose a suitable root object that will be the creator of some other objects. For example, Monopoly Game is itself a good candidate root object. By Creator, the MonopolyGamecan justifiably create the Board and Players, for example - and the Board can justifiably create the Squares, for example. We could show the details of the dynamic design with UML interaction diagrams, but I'll use this case as an opportunity to show a UML dependency line stereotyped with «create», in a class diagram. Figure illustrates a static view diagram that suggests the creation logic. I ignore the fine details of the interactions. In fact, that's probably suitable, because from this UML sketch we (the developers who drew this) can pretty easily figure out the creation details while coding.

Figure 18.27 Creation dependencies.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

UML Topics