Continuing with the example in [Design → Modeling → Modeling a Solution → Basic], next let us model how the TextUi
interacts with the Logic
to support the mark and clear operations until the game is won or lost.
Design → Modeling → Modeling Behaviors → Sequence Diagrams → Basic
Design → Modeling → Modeling Structures → Class Diagrams → Basic
Design → Modeling → Modeling a Solution →
As mentioned in [Design → Modeling → Modeling a Solution → Introduction], this is the Minesweeper design you have come up with so far. Our objective is to analyze, evaluate, and refine that design.
Textbook
Design → Modeling → Modeling a Solution →
You can use models to analyze and design software before you start coding.
Suppose you are planning to implement a simple minesweeper game that has a text based UI and a GUI. Given below is a possible OOP design for the game.
Before jumping into coding, you may want to find out things such as,
- Is this class structure able to produce the behavior you want?
- What API should each class have?
- Do you need more classes?
To answer these questions, you can analyze how the objects of these classes will interact with each other to produce the behavior you want.
Let us start by modeling a sample interaction between the person playing the game and the TextUi
object.
newgame
and clear x y
represent commands typed by the Player
on the TextUi
.
How does the TextUi
object carry out the requests it has received from the player? It would need to interact with other objects of the system. Because the Logic
class is the one that controls the game logic, the TextUi
needs to collaborate with Logic
to fulfill the newgame
request. Let us extend the model to capture that interaction.
W
= Width of the minefield; H
= Height of the minefield
The above diagram assumes that W
and H
are the only information TextUi
requires to display the minefield to the Player
. Note that there could be other ways of doing this.
The Logic
methods you conceptualized in our modeling so far are:
Now, let us look at what other objects and interactions are needed to support the newGame()
operation. It is likely that a new Minefield
object is created when the newGame()
method is called.
Note that the behavior of the Minefield
constructor has been abstracted away. It can be designed at a later stage.
Given below are the interactions between the player and the TextUi
for the whole game.
Note that using sequence diagramsa similar technique can be used when discovering/defining the architecture-level APIs.
Defining the architecture-level APIs for a small Tic-Tac-Toe game:
This interaction adds the following methods to the Logic
class:
clearCellAt(int x, int y)
markCellAt(int x, int y)
getGameState(): GAME_STATE (GAME_STATE: READY, IN_PLAY, WON, LOST, …)
And it adds the following operation to Logic API:
getAppearanceOfCellAt(int,int): CELL_APPEARANCE (CELL_APPEARANCE: HIDDEN, ZERO, ONE, TWO, THREE, …, MARKED, INCORRECTLY_MARKED, INCORRECTLY_CLEARED)
In the above design, TextUi
does not access Cell
objects directly. Instead, it gets values of type CELL_APPEARANCE
from Logic
to be displayed as a minefield to the player. Alternatively, each cell or the entire minefield can be passed directly to TextUi
.
Here is the updated class diagram:
The above is for the case when Actor Player
interacts with the system using a text UI. Additional operations (if any) required for the GUI can be discovered similarly.
Suppose Logic
supports a reset()
operation. You can model it like this:
Our current model assumes that the Minefield
object has enough information (i.e. H, W, and mine locations) to create itself.
An alternative is to have a ConfigGenerator
object that generates a string containing the minefield information as shown below.
In addition, getWidth()
, getHeight()
, markCellAt(x,y)
and clearCellAt(x,y)
can be handled like this.
The updated class diagram:
How is the getGameState()
operation supported? Given below are two ways (there could be other ways):
- The
Minefield
class knows the state of the game at any time. The Logic
class retrieves it from the Minefield
class as and when required.
- The
Logic
class maintains the state of the game at all times.
Here’s the SD for option 1.
Here’s the SD for option 2. Assume that the game state is updated after every mark/clear action.
It is now time to explore what happens inside the Minefield
constructor. One way is to design it as follows.
Now let us assume that Minesweeper
supports a ‘timing’ feature.
Updated class diagram:
When designing components, it is not necessary to draw elaborate UML diagrams capturing all details of the design. They can be done as rough sketches. For example, draw sequence diagrams only when you are not sure which operations are required by each class, or when you want to verify that your class structure can indeed support the required operations.