Refactoring Task
Overview
This task focuses on improving a drawing service implementation that lacks support for undo/redo functionality.
Currently, the system does not retain any user interaction history, making it impossible to revert or reapply actions.
You'll examine how to refactor the design to enable state preservation and rollback.
Initial Code
The following example shows a DrawService
class that draws shapes (e.g., circles, squares) on a canvas.
However, the class does not store any operation history or state snapshots, so user actions cannot be undone or replayed.
- TypeScript
- PHP
- Python
class DrawService {
private canvas: string[] = [];
draw(shape: string) {
this.canvas.push(shape);
console.log(`描画: ${shape}`);
}
showCanvas() {
console.log("現在のキャンバス:", this.canvas.join(", "));
}
}
// 利用例
const drawer = new DrawService();
drawer.draw("circle");
drawer.draw("square");
drawer.showCanvas(); // circle, square
<?php
class DrawService {
private array $canvas = [];
public function draw(string $shape): void {
$this->canvas[] = $shape;
echo "描画: {$shape}\n";
}
public function showCanvas(): void {
echo "現在のキャンバス: " . implode(", ", $this->canvas) . "\n";
}
}
// 利用例
$drawer = new DrawService();
$drawer->draw("circle");
$drawer->draw("square");
$drawer->showCanvas(); // circle, square
class DrawService:
def __init__(self):
self.canvas = []
def draw(self, shape: str):
self.canvas.append(shape)
print(f"描画: {shape}")
def show_canvas(self):
print("現在のキャンバス:", ", ".join(self.canvas))
# 利用例
drawer = DrawService()
drawer.draw("circle")
drawer.draw("square")
drawer.show_canvas() # circle, square
Question 1: What are the structural problems in this code?
List and describe specific issues using the following criteria:
- State accumulates but cannot be reverted
- No operation history is stored, so rollback and redo are unsupported
- Missing common UI/UX feature: Undo/Redo
- Difficult to track or verify user actions
Question 2: How can the code be improved to support operation history and restoration?
Use the following points to organize your proposal:
- How should each operation (e.g., drawing) be stored as history?
- How should state recording and restoration (object/snapshot-based) be designed?
- Which patterns can help implement command history and rollback support?
Example: Candidate Design Patterns
Pattern Name | Purpose and Effect |
---|---|
Command | Encapsulate each user action as a command object that supports undo/redo |
Memento | Store snapshots of object state and allow complete restoration |
Prototype | Clone object states to simplify versioning and recovery |
State (helper) | Encapsulate current state as an object to support transitions and visibility |
Optional Extensions
- How should redo functionality be implemented along with undo?
- What features would be needed in real-world use cases, such as maximum history size or user-specific history?
Suggested Output Format (for review or team discussion)
- List of structural issues (3 or more)
- Refactoring strategy and reasons for selected patterns
- High-level redesign (e.g., flow of storing/restoring history, command abstraction approach)