Skip to content

refactor: Redesign Complicated Command Logic #42

@FlysonBot

Description

@FlysonBot

Command and input handling like the following had repeately occured in the codebase. It is a good idea to redesign them to reduce the complexity.

def obtain_guess(self) -> Union[tuple, str]:
valid_guess = ValidCombination(
number_of_dots=self.game_state.number_of_dots,
number_of_colors=self.game_state.number_of_colors,
)
while True:
guess = input("Enter your guess: ")
if guess == "?":
hint = f"""
Enter a {self.game_state.number_of_dots}-digit number with digit ranging from 1 to {self.game_state.number_of_colors}.
For example, a 6-digit 4-color code can be 123412, or 1,2,3,4,1,2
Or, you can enter a command:
(?) for help
(d) to discard the game
(q) to save and quit
(u) to undo
(r) to redo
"""
print(hint)
continue
if guess == "d":
print("Game discarded.")
return "d"
if guess == "q": # quit
print("Game saved.")
return "q"
if guess == "u": # undo
return "u"
if guess == "r": # redo
return "r"
try:
return valid_guess.validate_value(guess)
except (TypeValidationError, InputConversionError) as e:
print(e)
print("To get more help, enter '?'")
except RangeError:
print(
f"Guess must consist of {self.game_state.number_of_dots} integers in range [1, {self.game_state.number_of_colors}]"
)
print("To get more help, enter '?'")

One idea might be to refer to the Chain of Responsibility and the Command design pattern. For example, we can set up 2 variables, one storing the next handler/command while the other store the result from the current handler. While the next handler is not None, we keep calling the next handler with the result, and update both the handler and the result. This way we can dynamically generate a chain of actions/events that allows for complex branching in a way that still have high readability, maintainability, and low complexity. This also avoids stack overthrow when forming infinite loop (i.e. user keep undoing and redoing).

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

Status

Ready

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions