CompSci 308 Spring 2023 |
Advanced Software Design and Implementation |
This exercise is intended to help you to learn to critically read code, understand its purpose, and identify ways to make it more readable and changeable by improving its design using shorter methods and multiple classes. Along the way, start to build a sense of a reader's expectations about code and what makes one piece of code better than another given a specific set of design goals.
At the end of lab, use Gitlab's Merge Request from your forked repository's master
branch back to the original organization repository's master
branch to submit your group's answers to the discussion questions and your refactored code. Make sure the Title of your Merge Request is of the form "lab_hangman - everyone's NetIDs".
You only need to create one Merge Request, no matter how many commits you make, and you do not worry about potential conflicts since your request will not be approved (it is just an easy way for us to see what changes you made).
Here is a review of the steps you will use to work with GIT during lab (as distinct from assigned team projects):
lab_hangman
into their own repository to allow pushing your group's changes
Project Information → Members
(in the upper left corner) to add your partner so both people in the group can access the same repositoryMaintainer
role in the project and choose Add to Project
git clone
to copy the one forked repository to their individual machines so they can work on their own separate copiesOpen
the cloned folder to create a new project on their personal machineDISCUSSION.md
file included in the repositoryDISCUSSION.md
using Gitlab's Markdown formatgit add
changed files
git commit -m
to describe your changes
git push
changes back to Gitlab
git pull
changes from Gitlab back to the local machine (if you are not sharing a single project using IntelliJ's Code With Me feature)
DISCUSSION.md
using Gitlab's Markdown formatLabs in this course expect you to work either in pairs or with your project team.
Professionally, this practice is called Pair Programming: working closely with another programmer, sharing a "single computer" that we will simulate using a shared repository or IntelliJ's Code With Me feature. To ensure both people do some coding, you will switch which person actually writes the code every 10-15 minutes (in industry this switch happens only 1-3 times per day). The person who is not actively coding can be advising, suggesting better names, looking up documentation, or searching the Internet for solutions to small problems you are likely to face, but not multi-tasking (i.e., doing their own work or socializing).
The game of Hangman is a popular assignment given in CompSci 101 currently, and CompSci 201 previously. It is typically given in multiple parts based on what concept students are learning in the course, but the instructions tend to be the same: copy your previous version and update it to implement new kinds of players (either a guesser or secret word keeper). To simulate this in lab, there are two similar versions of the game that include four different kinds of players:
The goal of this exercise is to use the commonalities and differences between the two game classes in the package game
to identify what code is specific to guessers and secret word keepers (or generally, players) and extract that code into separate classes with methods that can be called from the game code instead of being included as part of the game class. In the end, instead of two classes with heavily duplicated code with no clear intentionality, you should have the following classes that represent distinct concepts with no duplicated code:
HangmanGame
Guesser
SecretKeeper
Removing the duplication and decomposing one conceptual class into three will also improve the overall design by separating the game rules from the player logic so that they can be changed more easily and independently.
Note you only need to consider the code in the game
package, not the util
package.
Examine the code from the perspective of how readable it is (i.e., is it easy to find or understand important parts of the code, does it do what you expect, does it require more or fewer comments). While studying this code, also note any good things about the code, that you might keep in the final version as well as smells in the code. If you have any questions about how it works, note those as well and talk to one of the Teaching Team to get your question resolved.
To begin discussing the code's design, spend some time evaluating the code using the following questions as a guide:
To help identify candidate code within each game that could be turned into methods to represent a player's behavior, describe how would you make a new game using the current design with two new kinds of players:
For this discussion, do not worry about the exact Java code needed to implement these players, just identifying what lines in one of the game classes needs to be changed to implement two new players described above. To guide your discussion, consider the following questions:
Window → Editor Tabs → Split Right
to view the two classes side by side)?play()
is composed of several steps, which ones are essential to the game's rules and which to the two kinds of players' actions?handleGuess()
is composed of several steps, which ones are essential to the game and which to the players?HangmanGame
, Guesser
, or SecretKeeper
) should be responsible for these instance variables (and why): mySecretWord
, myNumGuessesLeft
, myDisplayWord
, and myLettersLeftToGuess
?Refactoring is the practice of updating a program to improve its design and maintainability without changing its current functionality. An example of refactoring is creating a single method or class that replaces two or more sections of similar code because it reduces the amount of duplicate code within the program or makes the code easier to debug and test.
Your group may create any new methods or classes you want to help improve the program. Justify each change you make by explaining specifically how it improves the code in comments within the code. Justifications should refer specifically to principles discussed in class or the reading rather than using terms like "clearly/obviously", "good/sucks", or "like/hate".
Periodically create commits that represent a related set of changes (i.e., not just at the end of the lab or only each time you switch roles). After you think you have completed a reasonable goal, make a GIT commit
with an appropriate comment (there should be at least four commits in your project history). After every two commits, push
your changes up to Gitlab so your online repository reflects the work you have done in lab today and switch which person in the Programming Pair is typing.
Examine the given program and refactor it based on your group's discussion using the following steps (you should focus primarily on moving existing code rather than creating any new code):
HangmanGame
, and extract the code you identified in your discussion that represent potential player code into methods for your new classesGuesser
class that implements interactive guessing and update the HangmanGame
class to use it in place of its own code and update the Main
class to create the classes appropriatelySecretKeeper
class that implements choosing a random secret word and update the HangmanGame
class to use it in place of its own code and update the Main
class to create the classes appropriatelyGuesser
class to implement choosing letters automatically by commenting out the interactive code — so no changes should need to be made to the HangmanGame
or Main
classes (we will see a better way to handle this next week)SecretKeeper
class to implement changing the secret word after each guess by commenting out the interactive code — so no changes should need to be made to the HangmanGame
or Main
classes (again, we will see a better way to handle this next week)After you have done as much as you think is reasonable, describe as concretely as you can how to implement these changes using this new version of the code:
main()
method, not copying any existing classes.Finally, consider the following questions: