agentsclimarketplace

Refactoring simplifying conditionals

Skill lifeodyssey/craftsmanship-skills/skills/refactoring-simplifying-conditionals

Agent Skills distilled from Clean Code & Refactoring. Install: npx skills add lifeodyssey/craftsmanship-skills

Install
npx -y skills add lifeodyssey/craftsmanship-skills --skill refactoring-simplifying-conditionals

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Techniques for simplifying conditional logic: Decompose Conditional, Consolidate Conditional Expression, Consolidate Duplicate Conditional Fragments, Remove Control Flag, Replace Nested Conditions with Guard Clauses, Replace Conditional with Polymorphism. All with Python before/after examples.

SKILL.md

10.8 KB, as published. Nobody here has run it

Simplifying Conditional Expressions

Conditional logic is often the hardest code to follow. These refactorings make conditionals clearer, flatter, and more expressive.

When to Use This Skill

Triggers:

  • Nested if/else blocks are hard to follow
  • Conditional expressions are long and complex
  • The same code appears in multiple branches of a conditional
  • A boolean flag controls flow through a loop or method
  • A growing chain of if-elif-else or switch/match statements
  • Conditional logic varies by type but the types don't use polymorphism

Don't Triggers:

  • The problem is that a method is too long in general (use refactoring-composing-methods)
  • The problem is about which class the logic belongs in (use refactoring-moving-features)
  • You're trying to identify what's wrong at a high level (use refactoring-code-smells)

Decompose Conditional

Problem: You have a complicated conditional (if-then-else) expression.

Solution: Extract the condition, the then-branch, and the else-branch into their own methods.

# BEFORE — complex conditional inlined
def calculate_charge(self, quantity, date):
    if date.before(SUMMER_START) or date.after(SUMMER_END):
        return quantity * self._winter_rate + self._winter_service_charge
    else:
        return quantity * self._summer_rate
# AFTER — each part named for what it means
def calculate_charge(self, quantity, date):
    if self._is_winter(date):
        return self._winter_charge(quantity)
    else:
        return self._summer_charge(quantity)

def _is_winter(self, date):
    return date.before(SUMMER_START) or date.after(SUMMER_END)

def _winter_charge(self, quantity):
    return quantity * self._winter_rate + self._winter_service_charge

def _summer_charge(self, quantity):
    return quantity * self._summer_rate

Steps:

  1. Extract the condition into a method named for what it checks.
  2. Extract the then-branch into a method named for what it does.
  3. Extract the else-branch into a method named for what it does.
  4. Replace the conditional with calls to these methods.

Consolidate Conditional Expression

Problem: You have a sequence of conditional tests that all result in the same action.

Solution: Combine them into a single conditional with a logical operator.

# BEFORE — separate conditions, same result
def calculate_shipping(self, order):
    if order.is_expired:
        return 0
    if order.is_digital:
        return 0
    if order.is_free_shipping:
        return 0
    return order.weight * SHIPPING_RATE
# AFTER — consolidated into one check
def calculate_shipping(self, order):
    if order.is_expired or order.is_digital or order.is_free_shipping:
        return 0
    return order.weight * SHIPPING_RATE

Reverse case: If conditions are combined but shouldn't be, extract them into separate methods for clarity.

# BEFORE — combined but the reasons are different
def get_discount(self, customer):
    if customer.is_vip or customer.referral_count > 5:
        return 0.15
    return 0.0
# AFTER — separate conditions for separate reasons
def get_discount(self, customer):
    if self._has_vip_discount(customer):
        return 0.15
    if self._has_referral_discount(customer):
        return 0.15
    return 0.0

def _has_vip_discount(self, customer):
    return customer.is_vip

def _has_referral_discount(self, customer):
    return customer.referral_count > 5

Steps:

  1. Verify that the conditions don't have side effects.
  2. Combine the conditions using and or or.
  3. Test.

Consolidate Duplicate Conditional Fragments

Problem: The same code appears in all branches of a conditional expression.

Solution: Move the duplicated code outside the conditional.

# BEFORE — discount calculation duplicated in both branches
def calculate_total(self, customer, order):
    if customer.is_vip:
        discount = order.total * 0.1
        order.total -= discount
        self._send_receipt(order)
    else:
        discount = order.total * 0.05
        order.total -= discount
        self._send_receipt(order)
# AFTER — common code moved after the conditional
def calculate_total(self, customer, order):
    if customer.is_vip:
        discount = order.total * 0.1
    else:
        discount = order.total * 0.05
    order.total -= discount
    self._send_receipt(order)

Also works for code at the beginning of branches:

# BEFORE — common code at start of each branch
def process(self, data):
    if data.is_valid:
        sanitized = self._sanitize(data)
        self._transform(sanitized)
    else:
        sanitized = self._sanitize(data)
        self._log_error(sanitized)
# AFTER
def process(self, data):
    sanitized = self._sanitize(data)
    if data.is_valid:
        self._transform(sanitized)
    else:
        self._log_error(sanitized)

Steps:

  1. Identify code that is identical in all branches.
  2. Move it before or after the conditional.
  3. Test.

Remove Control Flag

Problem: You have a variable that acts as a control flag for a series of boolean expressions.

Solution: Use break, return, or exception handling instead.

# BEFORE — control flag used to exit loop
def find_person(self, people):
    found = False
    result = None
    for person in people:
        if not found:
            if person.name == "Don":
                result = person
                found = True
            elif person.age > 25:
                result = person
                found = True
    return result
# AFTER — return directly when found
def find_person(self, people):
    for person in people:
        if person.name == "Don":
            return person
        if person.age > 25:
            return person
    return None

Steps:

  1. Find the control flag variable.
  2. Replace assignments to the flag with break or return.
  3. Remove the flag variable and its checks.

Replace Nested Conditions with Guard Clauses

Problem: A method has conditional behavior where the normal path is nested inside exception cases.

Solution: Use guard clauses to handle exceptional cases first and return early.

# BEFORE — deeply nested, hard to follow the main path
def calculate_pay(self, employee):
    if employee.is_active:
        if employee.is_contractor:
            return employee.hourly_rate * employee.hours_workd * 0.9
        else:
            if employee.is_manager:
                return employee.salary + employee.bonus
            else:
                return employee.salary
    else:
        return 0
# AFTER — guard clauses flatten the logic
def calculate_pay(self, employee):
    if not employee.is_active:
        return 0

    if employee.is_contractor:
        return employee.hourly_rate * employee.hours_worked * 0.9

    if employee.is_manager:
        return employee.salary + employee.bonus

    return employee.salary

Steps:

  1. Identify the "special case" conditions — things that aren't the main flow.
  2. Replace each special case with a guard clause: check the condition and return early.
  3. After all guards, the remaining code is the normal flow.

When to use: When the main flow of a method is obscured by exceptional cases. If all branches are equally likely, nesting may be fine.


Replace Conditional with Polymorphism

Problem: You have a conditional that chooses different behavior depending on the type of an object.

Solution: Move each leg of the conditional into an overriding method in a subclass.

# BEFORE — switch on type
class Employee:
    def __init__(self, emp_type, salary):
        self.emp_type = emp_type
        self.salary = salary

    def calculate_bonus(self):
        if self.emp_type == "engineer":
            return self.salary * 0.1
        elif self.emp_type == "manager":
            return self.salary * 0.2
        elif self.emp_type == "sales":
            return self.salary * 0.15
        else:
            raise ValueError(f"Unknown type: {self.emp_type}")

    def get_vacation_days(self):
        if self.emp_type == "engineer":
            return 15
        elif self.emp_type == "manager":
            return 20
        elif self.emp_type == "sales":
            return 12
        else:
            raise ValueError(f"Unknown type: {self.emp_type}")
# AFTER — polymorphism eliminates the conditionals
from abc import ABC, abstractmethod

class Employee(ABC):
    def __init__(self, salary):
        self.salary = salary

    @abstractmethod
    def calculate_bonus(self) -> float: ...

    @abstractmethod
    def get_vacation_days(self) -> int: ...


class Engineer(Employee):
    def calculate_bonus(self) -> float:
        return self.salary * 0.1

    def get_vacation_days(self) -> int:
        return 15


class Manager(Employee):
    def calculate_bonus(self) -> float:
        return self.salary * 0.2

    def get_vacation_days(self) -> int:
        return 20


class Sales(Employee):
    def calculate_bonus(self) -> float:
        return self.salary * 0.15

    def get_vacation_days(self) -> int:
        return 12

Steps:

  1. Create a base class with abstract methods for each conditional branch.
  2. Create a subclass for each type. Move each leg of the conditional into the appropriate subclass.
  3. Replace the conditional with polymorphic calls.
  4. Remove the type code field from the base class.

When to use: When the same type-based conditional appears in multiple places, and especially when adding a new type requires touching every conditional. If there's only one conditional and it's unlikely to grow, a simple if/else may be clearer.


Summary Table

RefactoringProblemSolution
Decompose ConditionalComplex conditional expressionExtract condition, then, and else into named methods
Consolidate Conditional ExpressionMultiple conditions with same resultCombine with and/or
Consolidate Duplicate Conditional FragmentsSame code in all branchesMove common code outside the conditional
Remove Control FlagBoolean flag controlling flowUse break/return instead
Replace Nested Conditions with Guard ClausesNormal path buried in nestingHandle exceptions first, return early
Replace Conditional with PolymorphismSwitch on typeSubclasses override methods

Source: Martin Fowler, "Refactoring: Improving the Design of Existing Code" (2nd Edition)

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.