You Shouldn't Always Use SOLID in Swift

You Shouldn't Always Use SOLID in Swift


swift solid architecture ios oop

You can’t write every class according to SOLID. You shouldn’t. That’s the first truth.

Why?

SOLID is a set of five principles for object-oriented design. They’re good tools—but bad dogma. Misusing them leads to abstraction soup, unnecessary interfaces, and enough boilerplate to choke your productivity.

Let’s break them down with real Swift code.


🧍 S – Single Responsibility Principle (SRP)

“A class should have one reason to change.”

✅ Smart SRP

class LoginValidator {
    func isValid(email: String, password: String) -> Bool {
        return email.contains("@") && password.count >= 8
    }
}

❌ Overkill SRP

class EmailValidator {}
class PasswordValidator {}
class LoginLogger {}
class LoginController {}

Now you’ve got four files just to log in.

Use SRP when: Logic is complex and responsibilities are real.

Avoid it when: Splitting hurts readability more than it helps.


🔐 O – Open/Closed Principle (OCP)

“Open for extension, closed for modification.”

✅ Swift Example

protocol PaymentMethod {
    func pay(amount: Double)
}

class ApplePay: PaymentMethod {
    func pay(amount: Double) {
        print("Paid \(amount) with Apple Pay")
    }
}

class CreditCard: PaymentMethod {
    func pay(amount: Double) {
        print("Paid \(amount) with Credit Card")
    }
}

class CheckoutService {
    private let method: PaymentMethod

    init(method: PaymentMethod) {
        self.method = method
    }

    func checkout(amount: Double) {
        method.pay(amount: amount)
    }
}

Add new payment types without touching CheckoutService.

Use OCP when: You’re building for future change.

Avoid it when: You’re guessing.


🪂 L – Liskov Substitution Principle (LSP)

“Subclasses should be substitutable for their base classes.”

❌ Broken LSP

class Bird {
    func fly() {
        print("Flying")
    }
}

class Ostrich: Bird {
    override func fly() {
        fatalError("Ostriches can't fly")
    }
}

✅ Fix with Composition

protocol CanFly {
    func fly()
}

class Sparrow: CanFly {
    func fly() { print("Sparrow flying") }
}

Use LSP when: Subclasses are truly interchangeable.

Avoid it when: You’re forcing a relationship just to reuse code.


🧩 I – Interface Segregation Principle (ISP)

“Don’t force clients to depend on interfaces they don’t use.”

✅ Lean Interfaces

protocol Printer {
    func printDocument()
}

protocol Scanner {
    func scanDocument()
}

class SimplePrinter: Printer {
    func printDocument() {}
}

❌ Bloated Interface

protocol OfficeMachine {
    func printDocument()
    func scanDocument()
    func faxDocument()
}

class BudgetPrinter: OfficeMachine {
    func printDocument() {}
    func scanDocument() { fatalError("Not supported") }
    func faxDocument() { fatalError("Not supported") }
}

Use ISP when: Your consumers vary wildly in usage.

Avoid it when: One class owns everything already.


🔌 D – Dependency Inversion Principle (DIP)

“Depend on abstractions, not concretions.”

✅ Swift Protocol-Based DIP

protocol DataStore {
    func save(data: String)
}

class LocalStorage: DataStore {
    func save(data: String) {
        print("Saved: \(data)")
    }
}

class ProfileManager {
    let store: DataStore

    init(store: DataStore) {
        self.store = store
    }

    func updateProfile(name: String) {
        store.save(data: name)
    }
}

Use DIP when: You need testability and flexibility.

Avoid it when: You’re just mocking one thing that won’t change.


⚖️ So, Why Not Always Use SOLID?

  • It adds complexity.
  • It creates abstraction overhead.
  • It slows down teams who just want to ship.
  • It solves problems you don’t have—yet.

✅ Use SOLID When:

  • You’re building a large, long-lived system
  • You expect constant requirement changes
  • You’re collaborating with other developers

❌ Ignore SOLID When:

  • You’re prototyping or hacking
  • You’re building a small, stable app
  • You’re applying it just to feel “enterprisey”

🧽 Summary

Writing every class according to SOLID is like wearing a tuxedo to clean your garage. You’ll look fancy but feel stupid.

Use SOLID when it makes things better.
Ignore it when it makes things worse.


📚 Further Reading