DEV Community

vinaykumar0339
vinaykumar0339

Posted on • Edited on

#1 Single Responsibility Principle ['S' in SOLID]

SRP - Single Responsibility Principle
The Single Responsibility Principle is the first principle in the Solid Design Principles.

  1. A class should have only one reason to change.
  2. Each class should focus on a single job or responsibility.

Violating SRP:

class BankAccount {
    var accountNumber: String
    var balance: Double

    init(accountNumber: String, balance: Double) {
        self.accountNumber = accountNumber
        self.balance = balance
    }

    func deposit(amount: Double) {
        balance += amount
        print("Deposited \(amount). New balance is \(balance)")
    }

    func withDraw(amount: Double) {
        if (balance >= amount) {
            balance -= amount
            print("Withdrew \(amount). New balance is \(balance)")
        } else {
            print("Handling the insufficient balance.")
        }
    }

    func printStatement() {
        print("Account Statement for \(accountNumber): Balance is \(balance)")
    }

    func notifyUser() {
        print("Notifying user of transaction for account \(accountNumber)")
    }
}

// Usage
print("Before Applying SRP:")
let bankAccount = BankAccount(accountNumber: "BANK123", balance: 1000)
bankAccount.deposit(amount: 100)
bankAccount.withDraw(amount: 500)
bankAccount.withDraw(amount: 3000)
bankAccount.printStatement()
bankAccount.notifyUser()
Enter fullscreen mode Exit fullscreen mode

Adhering to SRP
To adhere to SRP, separate the responsibilities into different classes:

class BankAccountWithSRP {
    var accountNumber: String
    var balance: Double

    init(accountNumber: String, balance: Double) {
        self.accountNumber = accountNumber
        self.balance = balance
    }

    func deposit(amount: Double) {
        balance += amount
        print("Deposited \(amount). New balance is \(balance)")
    }

    func withDraw(amount: Double) {
        if (balance >= amount) {
            balance -= amount
            print("Withdrew \(amount). New balance is \(balance)")
        } else {
            print("Handling the insufficient balance.")
        }
    }
}

class StatementPrinter {
    func printStatement(for account: BankAccountWithSRP) {
        print("Account Statement for \(account.accountNumber): Balance is \(account.balance)")
    }
}

class NotificationService {
    func notifyUser(for account: BankAccountWithSRP) {
        print("Notifying user of transaction for account \(account.accountNumber)")
    }
}

// Usage
print("\n\nAfter Applying SRP:")
let bankAccountSRP = BankAccountWithSRP(accountNumber: "BANK123", balance: 1000)
bankAccountSRP.deposit(amount: 500)
bankAccountSRP.withDraw(amount: 700)
bankAccountSRP.withDraw(amount: 3000)

let statementPrinter = StatementPrinter()
let notificationService = NotificationService()

statementPrinter.printStatement(for: bankAccountSRP)
notificationService.notifyUser(for: bankAccountSRP)
Enter fullscreen mode Exit fullscreen mode

Benefits of Adhering to SRP:

  1. Improved Readability:

    • Each class has a clear and focused responsibility, making the code easier to understand.
  2. Enhanced Maintainability:

    • Changes to statement printing or notification logic do not affect the BankAccount class.
  3. Increased Reusability:

    • The StatementPrinter and NotificationService classes can be reused independently in other application parts.
  4. Simplified Testing:

    • Each class can be tested independently, making unit testing more straightforward.

Drawbacks:

  1. More Classes:
    • Can lead to many small classes.
  2. Complex Dependency Management:
    • More dependencies to manage.
  3. Design and Refactoring Overhead:
    • Requires more effort to design and refactor.
  4. Risk of Over-Engineering:
    • Can make simple problems overly complex.
  5. Performance Considerations:
    • More object creation and method calls.

Mitigating Drawbacks:

  1. Balanced Approach:
    • Apply SRP judiciously.
  2. Effective Documentation:
    • Clear Documentation helps navigate the codebase.
  3. Use Patterns and Frameworks:
    • Design patterns and dependency management tools can help.
  4. Team Alignment:
    • Ensure the team has a shared understanding of SRP.
  5. Performance Profiling:
    • Profile and optimize performance as needed.

Conclusion:
By understanding and applying the Single Responsibility Principle thoughtfully, you can create more maintainable, understandable, and flexible software.

Open/Close Principle
Check My GitHub Swift Playground Repo.

Top comments (0)

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay