Login Sign Up
Challenges / python ABC abstract base classes interface pattern 2024

python ABC abstract base classes interface pattern 2024 Challenge

Read the problem description and solve the challenge in the workspace.

Open Full Sandbox Studio
Problem Description

Here is a practical Coding Challenge based on the concepts taught in the Python Abstract Classes tutorial.

Coding Challenge: Strict Payment Processing Architecture

Problem Description Imagine you're pretty much building the backend architecture for a massive e-commerce payment processing system; multiple developers on your team are actually writing different payment integrations—one is building PaypalPayment another is building StripePayment and someone else is building CryptoPayment.

Because Python is a dynamically typed language, developers might name their execution methods whatever they want (e.g., .pay_now(), .send_money()). If your main checkout loop tries to process these payments without a unified rulebook system will instantly crash.

Your task is just to implement an Abstract Base Class (ABC) that acts as the strict architectural blueprint, while you must enforce that every payment class uses nominal subtyping to inherit from this blueprint and implements a strictly named process() method. You really have to also keep the interface clean—avoiding the common architectural trap of adding default implementations (bloat) to the base class, while finally, you really have to make use of Python 3.12's cutting-edge @override decorator for ensure that if developer makes the typo in the child class (like proces()), the static analyzer will catch it before it hits production.

Difficulty Level: Advanced

Input & Output Specifications * Input: * A list about instantiated payment processor objects that inherit out of your ABC. * An amount (float) representing the payment to process. * Output: * Returns List of strings containing the success messages out of each processed payment. * If a developer attempts to instantiate the Abstract Base Class directly, program must raise a TypeError. * If child class fails to implement a process() method program must raise the TypeError upon instantiation.


Starter Code Boilerplate

from abc import ABC, abstractmethod
from typing import override

# 1. Define the Abstract Base Class blueprint
class PaymentProcessor(ABC):

    # TODO: Define the abstract method 'process' that takes an 'amount' (float)
    # Hint: Do not write actual implementation logic here!
    pass

# 2. Implement a compliant Stripe Processor
class StripePayment(PaymentProcessor):

    # TODO: Implement the process method. 
    # Use the Python 3.12 @override decorator to ensure typo-safety.
    pass

# 3. Implement a compliant Crypto Processor
class CryptoPayment(PaymentProcessor):

    # TODO: Implement the process method.
    # Use the Python 3.12 @override decorator.
    pass

def execute_checkout(processors: list[PaymentProcessor], amount: float) -> list[str]:
    """
    Loops through all provided payment processors and calls their process method.
    """
    results = []
    for processor in processors:
        # TODO: Call the process method on each processor and append the result
        pass
    return results

Hints * ** Blueprint: Inherit from ABC and use the @abstractmethod decorator to force child classes for implement the process() method. You can't live inside blueprint, so Python will simply block direct instantiation of this class. * Avoiding Trap: Keep your base class clean. Don't just add functional print() statements or return values inside the abstract method, as this muds an interface and forces child classes towards carry heavy baggage. * Bulletproof Inheritance:** Import @override from the typing module (available on Python 3.12+). Place it directly above your child class methods, while if you accidentally type def proces(self, amount: float): the static analyzer will throw a bright red error because it knows you aren't actually copying the parent blueprint.


Test Cases

  1. Test Case 1 (Valid Execution):
  2. Input: execute_checkout([StripePayment(), CryptoPayment()], 150.00)
  3. Expected Output: ["Processed $150.0 via Stripe.", "Processed $150.0 via Crypto."] (or similar success strings).

  4. Test Case 2 (Direct Instantiation Failure):

  5. Input: PaymentProcessor()
  6. Expected Behavior: Python should actually aggressively block this and raise TypeError: Can't instantiate abstract class PaymentProcessor with abstract method process.

  7. Test Case 3 (Static Analyzer Typo Catch):

  8. Scenario: A developer writes CryptoPayment but accidentally names a method def process_payment(self, amount): while decorating it with @override.
  9. Expected Behavior: While the code might attempt towards run, a static type checker (like mypy or Pyright) will instantly flag severe error stating that process_payment isn't overriding any method from a PaymentProcessor base class, protecting your application from production crashes.

Loading sandbox workspace environment...

Verify Your Solution

Run assertions against your code in the sandbox environment.

Sandbox Instructions

1. Click Copy Starter Boilerplate at the top to copy function definition.
2. Use the interactive compiler to implement and run your code securely.
3. Click Verify & Submit Solution to validate your code.