Posts

Dependency Inversion Principle (DIP)

Definition High-level modules should not depend on low-level modules. Both should depend on abstractions. 👉 Depend on interfaces/abstractions, not concrete classes. Purpose Reduce tight coupling Improve flexibility Enable dependency injection Make unit testing easier Build scalable architecture Bad Example ❌ Low-Level Class public class SqlRepository { public void Save() { Console.WriteLine("Saved to SQL"); } } High-Level Class public class InvoiceService { private readonly SqlRepository _repository = new SqlRepository(); public void CreateInvoice() { _repository.Save(); } } Problem InvoiceService directly depends on: SqlRepository If database changes: MongoDB PostgreSQL MySQL 👉 High-level code must change. This creates: Tight coupling Difficult testing Poor scalability Good Example ✅ Step 1: Abstraction public interface IReposi...

Interface Segregation Principle (ISP)

Definition Clients should not be forced to depend on interfaces they do not use. 👉 Prefer small focused interfaces instead of one large interface. Purpose Reduce unnecessary implementation Keep interfaces clean Improve flexibility Avoid unused methods Build modular systems Bad Example ❌ Large Interface public interface IWorker { void Work(); void Eat(); } Human Worker public class Human : IWorker { public void Work() { Console.WriteLine("Human Working"); } public void Eat() { Console.WriteLine("Human Eating"); } } Robot Worker public class Robot : IWorker { public void Work() { Console.WriteLine("Robot Working"); } public void Eat() { throw new Exception( "Robot doesn't eat" ); } } Problem Robot forced to implement: Eat() even though it doesn't need it. 👉 Violates IS...

Liskov Substitution Principle (LSP)

Definition Objects of a derived class should be replaceable with objects of the base class without breaking application behavior. 👉 Child class should behave properly like parent class. Purpose Ensure proper inheritance Avoid incorrect subclass behavior Improve polymorphism Prevent runtime issues Build reliable OOP design Bad Example ❌ Parent Class public class Bird { public virtual void Fly() { Console.WriteLine("Bird Flying"); } } Child Class public class Ostrich : Bird { public override void Fly() { throw new Exception("Ostrich can't fly"); } } Problem Bird bird = new Ostrich(); bird.Fly(); ❌ Runtime failure. 👉 Child class breaks parent behavior. This violates LSP. Good Example ✅ Base Interface public interface IBird { void Eat(); } Flying Bird Interface public interface IFlyingBird { void Fly(); } Sparrow public class Sparrow : IB...

Open/Closed Principle (OCP)

Definition Software entities should be: Open for extension Closed for modification 👉 You should be able to add new functionality without changing existing code. Purpose Prevent breaking existing code Improve scalability Reduce bugs during changes Make systems extensible Follow clean architecture principles Bad Example ❌ public class TaxCalculator { public decimal Calculate(string type, decimal amount) { if(type == "GST") { return amount * 0.18m; } else if(type == "NoTax") { return 0; } return 0; } } Problem Whenever new tax type comes: InternationalTax ServiceTax ExportTax 👉 Existing code must be modified repeatedly. This can: Introduce bugs Break old functionality Increase complexity Good Example ✅ Step 1: Abstraction public interface ITaxStrategy { decimal Calculate(decimal amou...

Single Responsibility Principle (SRP)

h2>Definition A class should have only one responsibility or one reason to change. 👉 One class = One job. Purpose Keep classes focused Reduce complexity Improve maintainability Make code easier to test Avoid tightly coupled logic Bad Example ❌ public class InvoiceService { public void CreateInvoice() { Console.WriteLine("Invoice Created"); } public void SaveToDatabase() { Console.WriteLine("Saved to DB"); } public void SendEmail() { Console.WriteLine("Email Sent"); } } Problem This class handles: Invoice creation Database operations Email sending 👉 Multiple responsibilities. Good Example ✅ Invoice Logic public class InvoiceService { public void CreateInvoice() { Console.WriteLine("Invoice Created"); } } Database Logic public class InvoiceRepository { public void Save() { Consol...

SOLID Principles in C# / .NET

SOLID Principles in C# and .NET with Examples SOLID Principles in C# and .NET help developers build scalable, maintainable, and clean enterprise applications using object-oriented programming and ASP.NET Core. What are SOLID Principles? SOLID is a set of 5 object-oriented design principles used to build: Maintainable code Scalable applications Flexible architecture Clean and reusable systems Created by Robert C. Martin. Full Form of SOLID Letter Principle S Single Responsibility Principle O Open/Closed Principle L Liskov Substitution Principle I Interface Segregation Principle D Dependency Inversion Principle 1. Single Responsibility Principle (SRP) Definition A class should have only one reason to change. 👉 One c...

Interpreter Pattern in C# – Real-Time Example (Rule / Expression Evaluation)

Interpreter Pattern in C# – Real-Time Example (Rule / Expression Evaluation) What is Interpreter Pattern? The Interpreter Pattern is a behavioral design pattern used to interpret and evaluate language grammar, expressions, or rules. 👉 Converts expressions into executable logic. It is commonly used in: Rule engines Formula calculators Query parsers Expression evaluators Why Use Interpreter Pattern? Evaluate expressions dynamically Build rule engines Parse custom languages Simplify grammar processing Encapsulate evaluation logic Real-Time Scenario Calculator System: 10 + 5 - 3 👉 Expression needs interpretation and execution. Real-Time Example – Simple Expression Interpreter Step 1: Expression Interface public interface IExpression { int Interpret(); } Step 2: Number Expression public class NumberExpression : IExpression { private readonly int _number; public NumberExpression(int...

Visitor Pattern in C# – Real-Time Example (Adding Operations Without Modifying Objects)

What is Visitor Pattern? The Visitor Pattern is a behavioral design pattern that allows you to add new operations to existing object structures without modifying those classes. 👉 Separate: Object structure Operations/behaviors Why Use Visitor Pattern? Add new functionality easily Avoid modifying existing classes Follow Open/Closed Principle Separate business logic from objects Improve maintainability Real-Time Scenario Invoice System: Need multiple operations: PDF Export Excel Export Tax Calculation Report Generation 👉 Instead of modifying Invoice class repeatedly, use Visitors. Real-Time Example – Invoice Export System Step 1: Visitor Interface public interface IVisitor { void Visit(Invoice invoice); } Step 2: Element Interface public interface IElement { void Accept(IVisitor visitor); } Step 3: Concrete Element public class Invoice : IElement { public decimal A...

Memento Pattern in C# – Real-Time Example (Undo / Restore State)

What is Memento Pattern? The Memento Pattern is a behavioral design pattern that allows you to save and restore an object's previous state without exposing its internal details. 👉 Used mainly for: Undo Rollback Checkpoints History tracking Why Use Memento Pattern? Save object snapshots Restore previous state Implement undo/redo Maintain encapsulation Track history safely Real-Time Scenario Text Editor: User types text Save state Undo changes 👉 Restore previous version easily. Real-Time Example – Text Editor Undo Feature Step 1: Memento Class public class EditorMemento { public string Content { get; } public EditorMemento(string content) { Content = content; } } Step 2: Originator Class public class TextEditor { public string Content { get; set; } // Save state public EditorMemento Save() { return new EditorMemento(Content); ...

Iterator Pattern in C# – Real-Time Example (Sequential Collection Traversal)

What is Iterator Pattern? The Iterator Pattern is a behavioral design pattern that provides a way to access elements of a collection sequentially without exposing its internal structure. 👉 Helps traverse collections safely and uniformly. Why Use Iterator Pattern? Simplify collection traversal Hide internal collection structure Provide uniform access to elements Support custom iteration logic Improve maintainability Real-Time Scenario Examples: Pagination in APIs Traversing invoice items Navigating product lists Iterating menu items 👉 Client accesses items one by one without knowing collection internals. Real-Time Example – Product Collection Step 1: Collection Class public class ProductCollection { private readonly List<string> _products = new(); public void Add(string product) { _products.Add(product); } public Iterator GetIterator() { return new Iterator...

Template Method Pattern in C# – Real-Time Example (Algorithm Skeleton)

What is Template Method Pattern? The Template Method Pattern is a behavioral design pattern that defines the overall structure (template) of an algorithm in a base class, while allowing subclasses to implement specific steps. 👉 Common workflow stays fixed 👉 Individual steps can vary Why Use Template Method Pattern? Reuse common workflow logic Avoid duplicate code Standardize process flow Allow customizable steps Improve maintainability Real-Time Scenario Report Generation: Fetch data Format report Export report Different report types: PDF Report Excel Report 👉 Workflow is same, implementation differs. Real-Time Example – Report Generation System Step 1: Abstract Base Class public abstract class ReportGenerator { // Template Method public void GenerateReport() { GetData(); FormatReport(); ExportReport(); } protected abstract void GetData(); p...

Chain of Responsibility Pattern in C# – Real-Time Example (Request Processing Pipeline)

What is Chain of Responsibility Pattern? The Chain of Responsibility Pattern is a behavioral design pattern where a request is passed through a chain of handlers until one handler processes it. Each handler: Processes the request Or passes it to the next handler 👉 Creates a pipeline-like structure. Why Use Chain of Responsibility Pattern? Reduce tight coupling Build flexible processing pipelines Dynamically add/remove handlers Separate responsibilities cleanly Avoid large if-else chains Real-Time Scenario API Request Pipeline: Authentication Authorization Validation Logging 👉 Request passes through multiple handlers sequentially. Real-Time Example – Request Validation Pipeline Step 1: Abstract Handler public abstract class Handler { protected Handler _nextHandler; public void SetNext(Handler nextHandler) { _nextHandler = nextHandler; } public abstract void Ha...

State Pattern in C# – Real-Time Example (Behavior Based on State)

What is State Pattern? The State Pattern is a behavioral design pattern where an object changes its behavior when its internal state changes. 👉 The object behaves differently depending on its current state. It is similar to a finite state machine. Why Use State Pattern? Remove large if-else/switch statements Organize state-specific behavior Improve maintainability Make state transitions cleaner Follow Open/Closed Principle Real-Time Scenario Order Processing System: Pending Paid Shipped Delivered Cancelled 👉 Order behavior changes based on current status. Real-Time Example – Order State Workflow Step 1: State Interface public interface IOrderState { void Handle(); } Step 2: Concrete States Pending State public class PendingState : IOrderState { public void Handle() { Console.WriteLine("Order is Pending"); } } Paid State public class PaidState : IO...