> 백엔드 개발 > 파이썬 튜토리얼 > Python: 패턴으로 리팩토링

Python: 패턴으로 리팩토링

Susan Sarandon
풀어 주다: 2025-01-16 13:10:58
원래의
896명이 탐색했습니다.

Python: Refactoring to Patterns

사진: Patric Ho

이 간결한 가이드는 Python 코드 냄새를 해당 디자인 패턴 솔루션에 매핑합니다.

<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>
로그인 후 복사

Python의 리팩토링 예제

이 프로젝트는 Refactoring to Patterns(Joshua Kerievsky)의 리팩토링 예제를 Python으로 변환합니다. 각 예에서는 개선 사항을 강조하는 원본 코드와 리팩터링된 코드를 보여줍니다. 리팩토링 프로세스에는 UML 다이어그램을 해석하고 Java 코드를 Python의 뉘앙스에 맞게 조정하는 작업(순환 가져오기 및 인터페이스 처리)이 포함되었습니다.

예: 작성 방법

"Compose Method" 리팩토링은 더 작고 의미 있는 메서드를 추출하여 복잡한 코드를 단순화합니다.

<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>
로그인 후 복사

예: 다형성(테스트 자동화)

이 예는 재사용성을 위해 테스트 설정을 추상화하여 테스트 자동화의 다형성을 보여줍니다.

<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>
로그인 후 복사

예: 방문자 패턴

방문자 패턴은 클래스와 메소드를 분리합니다.

<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>
로그인 후 복사

결론

리팩토링을 통해 디자인 패턴을 학습하는 이 실용적이고 실무적인 접근 방식은 이해를 크게 향상시킵니다. 코드를 번역하는 동안 직면한 어려움은 이론적 지식을 확고히 합니다.

위 내용은 Python: 패턴으로 리팩토링의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿