Refactoring Task
Overview
This task focuses on the purchase process where the function completePurchase()
manually orchestrates a sequence of operations—inventory check, payment, and receipt issuance.
You'll examine how to refactor this design by applying abstraction and responsibility separation principles.
Initial Code
The following code shows a purchase workflow using multiple service classes.
However, the entire logic is exposed in the calling function, making the structure hard to reuse, test, or extend.
- TypeScript
- PHP
- Python
class InventoryChecker {
check(productId: string): boolean {
console.log(`在庫確認: ${productId}`);
return true;
}
}
class PaymentGateway {
pay(amount: number): boolean {
console.log(`支払い処理: ¥${amount}`);
return true;
}
}
class ReceiptPrinter {
print(productId: string, amount: number) {
console.log(`領収書発行: 商品=${productId}, 金額=¥${amount}`);
}
}
function completePurchase(productId: string, amount: number) {
const checker = new InventoryChecker();
const payment = new PaymentGateway();
const printer = new ReceiptPrinter();
if (checker.check(productId)) {
if (payment.pay(amount)) {
printer.print(productId, amount);
}
}
}
<?php
class InventoryChecker {
public function check(string $productId): bool {
echo "在庫確認: {$productId}\n";
return true;
}
}
class PaymentGateway {
public function pay(int $amount): bool {
echo "支払い処理: ¥{$amount}\n";
return true;
}
}
class ReceiptPrinter {
public function print(string $productId, int $amount): void {
echo "領収書発行: 商品={$productId}, 金額=¥{$amount}\n";
}
}
function completePurchase(string $productId, int $amount): void {
$checker = new InventoryChecker();
$payment = new PaymentGateway();
$printer = new ReceiptPrinter();
if ($checker->check($productId)) {
if ($payment->pay($amount)) {
$printer->print($productId, $amount);
}
}
}
class InventoryChecker:
def check(self, product_id: str) -> bool:
print(f"在庫確認: {product_id}")
return True
class PaymentGateway:
def pay(self, amount: int) -> bool:
print(f"支払い処理: ¥{amount}")
return True
class ReceiptPrinter:
def print(self, product_id: str, amount: int):
print(f"領収書発行: 商品={product_id}, 金額=¥{amount}")
def complete_purchase(product_id: str, amount: int):
checker = InventoryChecker()
payment = PaymentGateway()
printer = ReceiptPrinter()
if checker.check(product_id):
if payment.pay(amount):
printer.print(product_id, amount)
Question 1: What are the structural problems in this code?
Identify and describe the issues using the following criteria:
- The caller has direct knowledge of multiple services (tight coupling)
- Control flow, branching, and error handling are concentrated in one place
- Difficult to reuse or rearrange the logic
- Violates SRP (Single Responsibility Principle) and lacks change tolerance
Question 2: How can this structure be improved for better flexibility and maintainability?
Organize your proposal using the following perspectives:
- Where should the control flow logic be delegated (caller / dedicated service / wrapper)?
- Can the caller be simplified to handle only minimal interaction?
- How can the structure support future changes (inserting or replacing steps)?
Example: Candidate Design Patterns
Pattern Name | Purpose and Effect |
---|---|
Facade | Consolidates a complex series of operations behind a simple interface |
Proxy | Allows pre/post processing like logging, authentication, etc., around core logic |
Command | Encapsulates each step as a command that can be executed, recorded, or undone |
Iterator | Enables sequential execution of steps with flexible ordering and structure changes |
Optional Extensions
- If the flow needs to support extra steps like notification or point rewards, how can this be achieved without modifying existing code?
- If this purchase logic is reused across multiple channels (e.g., Web, batch), what differences should be expected in the way it is invoked?
Suggested Output Format (for review or team discussion)
- List of design problems (3 or more)
- Refactoring strategy and reasoning for pattern selection
- Overview of the improved structure (separation of responsibilities, encapsulated logic, etc.)