← Back to Python

All Topics

Advertisement

Learn/Python/Advanced Python

Refactoring - Extract Method, Rename Variable, etc

Topic: Software Engineering

Advertisement

Introduction

Refactoring is the process of restructuring existing code without changing its external behavior. It improves code readability, reduces complexity, and makes the code easier to maintain and extend.

Extract Method

Break large methods into smaller, focused methods with descriptive names.

# Before refactoring
def process_order(order):
    # Calculate total
    total = 0
    for item in order.items:
        total += item.price * item.quantity
    # Apply discount
    if order.customer.is_vip:
        total *= 0.9
    # Calculate tax
    total *= 1.1
    # Save order
    print(f"Saving order: {total}")
    # Send confirmation
    print(f"Sending email to {order.customer.email}")
    # Update inventory
    for item in order.items:
        print(f"Decrementing {item.name}")
    return total

# After refactoring
def calculate_order_total(order):
    subtotal = sum(item.price * item.quantity for item in order.items)
    return apply_discount(subtotal, order.customer)

def apply_discount(total, customer):
    return total * 0.9 if customer.is_vip else total

def calculate_final_price(order):
    return calculate_order_total(order) * 1.1

def save_order(order, total):
    print(f"Saving order: {total}")

def send_order_confirmation(order):
    print(f"Sending email to {order.customer.email}")

def update_inventory(order):
    for item in order.items:
        print(f"Decrementing {item.name}")

def process_order(order):
    total = calculate_final_price(order)
    save_order(order, total)
    send_order_confirmation(order)
    update_inventory(order)
    return total

Rename Variable

Use meaningful variable names that convey intent.

# Before
def get_stats(data):
    x = 0
    y = 0
    for i in data:
        x += i["v"]
        y += 1
    return x / y

# After
def calculate_average_value(records):
    total_value = 0
    record_count = 0
    for record in records:
        total_value += record["value"]
        record_count += 1
    return total_value / record_count

Introduce Parameter Object

Group related parameters into a class or data structure.

# Before
def create_user(name, email, phone, address, city, state, zip_code):
    print(f"Creating user: {name}, {email}, {phone}")
    print(f"Address: {address}, {city}, {state} {zip_code}")

create_user("John", "john@email.com", "123-456-7890", "123 Main St", "Boston", "MA", "02101")

# After
class Address:
    def __init__(self, street, city, state, zip_code):
        self.street = street
        self.city = city
        self.state = state
        self.zip_code = zip_code

class ContactInfo:
    def __init__(self, email, phone):
        self.email = email
        self.phone = phone

def create_user(name, contact_info, address):
    print(f"Creating user: {name}, {contact_info.email}, {contact_info.phone}")
    print(f"Address: {address.street}, {address.city}, {address.state} {address.zip_code}")

contact = ContactInfo("john@email.com", "123-456-7890")
addr = Address("123 Main St", "Boston", "MA", "02101")
create_user("John", contact, addr)

Replace Conditional with Polymorphism

Use inheritance and polymorphism instead of complex conditionals.

# Before
class PaymentProcessor:
    def process_payment(self, payment):
        if payment.type == "credit_card":
            print(f"Processing credit card: {payment.card_number}")
        elif payment.type == "paypal":
            print(f"Processing PayPal: {payment.email}")
        elif payment.type == "bank_transfer":
            print(f"Processing bank: {payment.account_number}")
        return True

# After
class Payment(ABC):
    @abstractmethod
    def process(self):
        pass

class CreditCardPayment(Payment):
    def __init__(self, card_number):
        self.card_number = card_number
    
    def process(self):
        print(f"Processing credit card: {self.card_number}")

class PayPalPayment(Payment):
    def __init__(self, email):
        self.email = email
    
    def process(self):
        print(f"Processing PayPal: {self.email}")

class BankTransferPayment(Payment):
    def __init__(self, account_number):
        self.account_number = account_number
    
    def process(self):
        print(f"Processing bank: {self.account_number}")

class PaymentProcessor:
    def process_payment(self, payment):
        return payment.process()

Practice Problems

  1. Extract a complex method into smaller, focused methods.
  2. Rename variables to be more descriptive.
  3. Group related parameters into a class.
  4. Replace a complex if-elif chain with polymorphism.
  5. Remove duplicate code using the Extract Method refactoring.

Advertisement

Advertisement

Need More Practice?

Get personalized Python help from ChatWhole's AI-powered platform.

Get Expert Help →