OPEN-CLOSED PRINCIPLE in Swift

Deepak Carpenter
Appgrid
Published in
4 min readJun 5, 2023

Open-Closed Principle (OCP) is a guiding principle that promotes these qualities by encouraging developers to design code that is open for extension but closed for modification. In this blog post, we will explore the Open-Closed Principle in Swift and demonstrate how it can be implemented using practical code examples.

In the world of software development, there are several principles that help us write clean, maintainable, and extensible code. One such principle is the Open-Closed Principle (OCP). The OCP states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. In other words, we should be able to add new functionality to our code without modifying existing code. This principle promotes code reuse, modularity, and reduces the risk of introducing bugs. In this blog post, we will explore the Open-Closed Principle in the context of Swift programming with examples.

Understanding the Open-Closed Principle: To grasp the essence of the Open-Closed Principle, let’s break it down into two key components:

  1. Open for extension: This means that our code should be easily extensible to accommodate new features or changes in requirements. We should be able to introduce new behavior without modifying the existing codebase. This is achieved by designing our code in a way that allows for easy extension through inheritance, composition, or other means.
  2. Closed for modification: Once a module, class, or function is implemented and tested, we should avoid making direct changes to it when introducing new features. Instead, we should extend or build upon the existing code, minimizing the impact on the already tested and functioning parts of the system.

Now, let’s dive into some examples to understand how we can apply the Open-Closed Principle in Swift.

Example 1: Shape Drawing Suppose we have a shape drawing application that supports various shapes like circles, squares, and triangles. We have a Shape class with a draw() method, which is overridden by each shape subclass to provide its specific implementation. To add a new shape, we can extend the Shape class and implement the draw() method accordingly. The existing code that uses the Shape class does not need to be modified.

protocol Shape {
func draw()
}

class Shape {
func draw() {
fatalError("Subclasses must implement the draw method.")
}
}

class Circle: Shape {
override func draw() {
print("Drawing a circle.")
}
}

class Square: Shape {
override func draw() {
print("Drawing a square.")
}
}

// New shape: Triangle
class Triangle: Shape {
override func draw() {
print("Drawing a triangle.")
}
}

By following the Open-Closed Principle, we extended the shape-drawing functionality without modifying the existing Shape, Circle, and Square classes.

Example 2: Payment Gateway Integration Let’s consider a payment processing system that integrates with multiple payment gateways. We have a PaymentProcessor class responsible for handling payments. Instead of modifying the existing class for each new payment gateway, we can leverage protocols and create separate payment gateway handlers. This allows us to extend the system with new payment gateways without modifying the existing code.

protocol PaymentGateway {
func processPayment(amount: Double)
}

class PaymentProcessor {
private var paymentGateway: PaymentGateway

init(paymentGateway: PaymentGateway) {
self.paymentGateway = paymentGateway
}

func processPayment(amount: Double) {
paymentGateway.processPayment(amount: amount)
}
}

class StripeGateway: PaymentGateway {
func processPayment(amount: Double) {
print("Processing payment via Stripe: $\(amount)")
// Integration with Stripe API
}
}

class PayPalGateway: PaymentGateway {
func processPayment(amount: Double) {
print("Processing payment via PayPal: $\(amount)")
// Integration with PayPal API
}
}

// New payment gateway: SquareGateway
class SquareGateway: PaymentGateway {
func processPayment(amount: Double) {
print("Processing payment via Square: $\(amount)")
// Integration with Square API
}
}

By adhering to the Open-Closed Principle, we can seamlessly add new payment gateways by implementing the PaymentGateway protocol without modifying the existing PaymentProcessor class.

Final Words:

The Open-Closed Principle is a powerful concept that encourages extensibility and maintainability in software development. By designing our code to be open for extension but closed for modification, we can easily add new features without disturbing the existing codebase. This leads to cleaner, more modular code that is less prone to bugs.

In this blog post, we explored the Open-Closed Principle in the context of Swift programming. We examined examples where the principle was applied to shape drawing and payment gateway integration scenarios. By following these examples, you can start incorporating the Open-Closed Principle into your own Swift projects, leading to more robust and flexible code.

Cheers!
Happy Coding!

--

--