Refactoring Task
Overview
This task addresses a report generation process in which common logic (e.g., start/end processing)
and format-specific logic (PDF/CSV/HTML output) are tightly coupled and written together.
The goal is to improve reusability of shared steps and extensibility of format-specific behavior
by applying appropriate structural refactoring.
Initial Code
The following code generates reports in PDF, CSV, and HTML formats.
However, the format-specific logic is mixed directly with the shared steps (e.g., logging),
making the code hard to maintain and extend.
- TypeScript
- PHP
- Python
class ReportGenerator {
generatePdfReport(data: string) {
console.log("=== レポート開始 ===");
console.log(`[PDF形式] ${data}`);
console.log("=== レポート終了 ===");
}
generateCsvReport(data: string) {
console.log("=== レポート開始 ===");
console.log(`[CSV形式] ${data}`);
console.log("=== レポート終了 ===");
}
generateHtmlReport(data: string) {
console.log("=== レポート開始 ===");
console.log(`<html><body>${data}</body></html>`);
console.log("=== レポート終了 ===");
}
}
<?php
class ReportGenerator {
public function generatePdfReport(string $data): void {
echo "=== レポート開始 ===\n";
echo "[PDF形式] {$data}\n";
echo "=== レポート終了 ===\n";
}
public function generateCsvReport(string $data): void {
echo "=== レポート開始 ===\n";
echo "[CSV形式] {$data}\n";
echo "=== レポート終了 ===\n";
}
public function generateHtmlReport(string $data): void {
echo "=== レポート開始 ===\n";
echo "<html><body>{$data}</body></html>\n";
echo "=== レポート終了 ===\n";
}
}
class ReportGenerator:
def generate_pdf_report(self, data: str):
print("=== レポート開始 ===")
print(f"[PDF形式] {data}")
print("=== レポート終了 ===")
def generate_csv_report(self, data: str):
print("=== レポート開始 ===")
print(f"[CSV形式] {data}")
print("=== レポート終了 ===")
def generate_html_report(self, data: str):
print("=== レポート開始 ===")
print(f"<html><body>{data}</body></html>")
print("=== レポート終了 ===")
Question 1: What are the structural problems in this code?
Consider the following aspects when listing the issues:
- Common logic is duplicated across multiple methods
- Format-specific behavior is mixed with shared control flow
- High modification cost when adding new formats
- Hard to isolate and reuse shared steps for testing or maintenance
Question 2: How can this structure be improved for better flexibility and maintainability?
Outline your proposal considering these points:
- How can shared logic (pre/post) be separated from variable logic?
- How can the variable logic be localized, and common logic centralized?
- What structure supports a template + plugin-style composition?
Example: Candidate Design Patterns
Pattern Name | Purpose and Effect |
---|---|
Template Method | Centralizes shared behavior in a base class, allowing subclasses to override parts |
Strategy | Delegates format-specific logic to interchangeable objects |
Bridge | Separates abstraction from implementation for flexible format-function combinations |
Flyweight | Shares common state/data to reduce memory usage and instance cost |
Prototype | Allows pre-configured output logic to be cloned and customized |
Optional Extensions
- How would the design scale if new formats like Markdown, JSON, or Excel are added?
- If post-processing (e.g., save, compress, send) needs to be inserted,
which structure is most adaptable for such extensions?
Suggested Output Format (for review or team discussion)
- List of structural issues (at least 3)
- Refactoring strategy and reasoning for selected patterns
- Overview of the improved structure (abstraction of output flow, use of inheritance or delegation, etc.)