Home >Backend Development >Python Tutorial >Python: Refactoring to Patterns
This concise guide maps Python code smells to their corresponding design pattern solutions.
<code class="language-python">class CodeSmellSolutions: DUPLICATED_CODE = [ "form_template_method", "introduce_polymorphic_creation_with_factory_method", "chain_constructors", "replace_one__many_distinctions_with_composite", "extract_composite", "unify_interfaces_with_adapter", "introduce_null_object", ] LONG_METHOD = [ "compose_method", "move_accumulation_to_collecting_parameter", "replace_conditional_dispatcher_with_command", "move_accumulation_to_visitor", "replace_conditional_logic_with_strategy", ] CONDITIONAL_COMPLEXITY = [ # Complex conditional logic "replace_conditional_logic_with_strategy", "move_emblishment_to_decorator", "replace_state_altering_conditionals_with_state", "introduce_null_object", ] PRIMITIVE_OBSESSION = [ "replace_type_code_with_class", "replace_state_altering_conditionals_with_state", "replace_conditional_logic_with_strategy", "replace_implict_tree_with_composite", "replace_implicit_language_with_interpreter", "move_emblishment_to_decorator", "encapsulate_composite_with_builder", ] INDECENT_EXPOSURE = [ # Lack of information hiding "encapsulate_classes_with_factory" ] SOLUTION_SPRAWL = [ # Scattered logic/responsibility "move_creation_knowledge_to_factory" ] ALTERNATIVE_CLASSES_WITH_DIFFERENT_INTERFACES = [ # Similar classes, different interfaces "unify_interfaces_with_adapter" ] LAZY_CLASS = [ # Insufficient functionality "inline_singleton" ] LARGE_CLASS = [ "replace_conditional_dispatcher_with_command", "replace_state_altering_conditionals_with_state", "replace_implict_tree_with_composite", ] SWITCH_STATEMENTS = [ # Complex switch statements "replace_conditional_dispatcher_with_command", "move_accumulation_to_visitor", ] COMBINATION_EXPLOSION = [ # Similar code for varying data "replace_implicit_language_with_interpreter" ] ODDBALL_SOLUTIONS = [ # Multiple solutions for same problem "unify_interfaces_with_adapter" ]</code>
Refactoring Examples in Python
This project translates refactoring examples from Refactoring to Patterns (Joshua Kerievsky) into Python. Each example shows original and refactored code, highlighting improvements. The refactoring process involved interpreting UML diagrams and adapting Java code to Python's nuances (handling cyclic imports and interfaces).
Example: Compose Method
The "Compose Method" refactoring simplifies complex code by extracting smaller, more meaningful methods.
<code class="language-python"># Original (complex) code def add(element): readonly = False size = 0 elements = [] if not readonly: new_size = size + 1 if new_size > len(elements): new_elements = [] for i in range(size): new_elements[i] = elements[i] # Potential IndexError elements = new_elements size += 1 elements[size] = element # Potential IndexError # Refactored (simplified) code def is_at_capacity(new_size, elements): return new_size > len(elements) def grow_array(size, elements): new_elements = [elements[i] for i in range(size)] # List comprehension for clarity return new_elements def add_element(elements, element, size): elements.append(element) # More Pythonic approach return len(elements) -1 def add_refactored(element): readonly = False if readonly: return size = len(elements) new_size = size + 1 if is_at_capacity(new_size, elements): elements = grow_array(size, elements) size = add_element(elements, element, size) </code>
Example: Polymorphism (Test Automation)
This example demonstrates polymorphism in test automation, abstracting test setup for reusability.
<code class="language-python"># Original code (duplicate setup) class TestCase: pass class DOMBuilder: def __init__(self, orders): pass def calc(self): return 42 class XMLBuilder: def __init__(self, orders): pass def calc(self): return 42 class DOMTest(TestCase): def run_dom_test(self): expected = 42 builder = DOMBuilder("orders") assert builder.calc() == expected class XMLTest(TestCase): def run_xml_test(self): expected = 42 builder = XMLBuilder("orders") assert builder.calc() == expected # Refactored code (polymorphic setup) class OutputBuilder: def calc(self): raise NotImplementedError class DOMBuilderRefac(OutputBuilder): def calc(self): return 42 class XMLBuilderRefac(OutputBuilder): def calc(self): return 42 class TestCaseRefac: def create_builder(self): raise NotImplementedError def run_test(self): expected = 42 builder = self.create_builder() assert builder.calc() == expected class DOMTestRefac(TestCaseRefac): def create_builder(self): return DOMBuilderRefac() class XMLTestRefac(TestCaseRefac): def create_builder(self): return XMLBuilderRefac() </code>
Example: Visitor Pattern
The Visitor pattern decouples classes from their methods.
<code class="language-python"># Original code (conditional logic in TextExtractor) class Node: pass class LinkTag(Node): pass class Tag(Node): pass class StringNode(Node): pass class TextExtractor: def extract_text(self, nodes): result = [] for node in nodes: if isinstance(node, StringNode): result.append("string") elif isinstance(node, LinkTag): result.append("linktag") elif isinstance(node, Tag): result.append("tag") else: result.append("other") return result # Refactored code (using Visitor) class NodeVisitor: def visit_link_tag(self, node): return "linktag" def visit_tag(self, node): return "tag" def visit_string_node(self, node): return "string" class Node: def accept(self, visitor): pass class LinkTagRefac(Node): def accept(self, visitor): return visitor.visit_link_tag(self) class TagRefac(Node): def accept(self, visitor): return visitor.visit_tag(self) class StringNodeRefac(Node): def accept(self, visitor): return visitor.visit_string_node(self) class TextExtractorVisitor(NodeVisitor): def extract_text(self, nodes): result = [node.accept(self) for node in nodes] return result </code>
Conclusion
This practical, hands-on approach to learning design patterns through refactoring significantly enhances understanding. The challenges encountered while translating the code solidify theoretical knowledge.
The above is the detailed content of Python: Refactoring to Patterns. For more information, please follow other related articles on the PHP Chinese website!