Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Coupling in C#
Coupling in C# refers to the degree of interdependence between classes or modules in a software system. It measures how closely connected different parts of your code are to each other. Understanding coupling is crucial for writing maintainable and flexible applications.
There are two main types of coupling − tight coupling and loose coupling. The goal in good software design is to achieve loose coupling while maintaining high cohesion.
Tight Coupling
In tight coupling, classes are highly dependent on each other. When one class changes, it directly affects other classes, making the code difficult to maintain and test.
Example of Tight Coupling
using System;
public class EmailService {
public void SendEmail(string message) {
Console.WriteLine("Email sent: " + message);
}
}
public class OrderService {
private EmailService emailService;
public OrderService() {
// Tight coupling - directly instantiating EmailService
emailService = new EmailService();
}
public void ProcessOrder(string orderDetails) {
Console.WriteLine("Processing order: " + orderDetails);
emailService.SendEmail("Order confirmed: " + orderDetails);
}
}
public class Program {
public static void Main() {
OrderService orderService = new OrderService();
orderService.ProcessOrder("Product A, Quantity: 2");
}
}
The output of the above code is −
Processing order: Product A, Quantity: 2 Email sent: Order confirmed: Product A, Quantity: 2
Loose Coupling
Loose coupling minimizes dependencies between classes by using interfaces, dependency injection, or abstract classes. This makes the code more flexible, testable, and maintainable.
Example of Loose Coupling Using Interface
using System;
public interface INotificationService {
void SendNotification(string message);
}
public class EmailService : INotificationService {
public void SendNotification(string message) {
Console.WriteLine("Email sent: " + message);
}
}
public class SMSService : INotificationService {
public void SendNotification(string message) {
Console.WriteLine("SMS sent: " + message);
}
}
public class OrderService {
private INotificationService notificationService;
public OrderService(INotificationService service) {
notificationService = service;
}
public void ProcessOrder(string orderDetails) {
Console.WriteLine("Processing order: " + orderDetails);
notificationService.SendNotification("Order confirmed: " + orderDetails);
}
}
public class Program {
public static void Main() {
// Easy to switch between different notification services
INotificationService emailService = new EmailService();
OrderService orderService1 = new OrderService(emailService);
orderService1.ProcessOrder("Product A, Quantity: 2");
Console.WriteLine();
INotificationService smsService = new SMSService();
OrderService orderService2 = new OrderService(smsService);
orderService2.ProcessOrder("Product B, Quantity: 1");
}
}
The output of the above code is −
Processing order: Product A, Quantity: 2 Email sent: Order confirmed: Product A, Quantity: 2 Processing order: Product B, Quantity: 1 SMS sent: Order confirmed: Product B, Quantity: 1
Comparison
| Tight Coupling | Loose Coupling |
|---|---|
| Classes directly depend on concrete implementations | Classes depend on interfaces or abstract classes |
| Difficult to unit test (hard to mock dependencies) | Easy to unit test (can easily mock interfaces) |
| Changes in one class affect multiple classes | Changes are isolated and don't cascade |
| Low code reusability | High code reusability |
| Hard to extend or modify behavior | Easy to extend using polymorphism |
Advantages of Loose Coupling
-
Enhanced testability − You can easily mock dependencies for unit testing
-
Better maintainability − Changes in one module don't break other modules
-
Increased reusability − Components can be reused in different contexts
-
Flexibility − Easy to swap implementations without changing dependent code
-
Follows SOLID principles − Especially Dependency Inversion Principle
Conclusion
Loose coupling is a fundamental principle in software design that promotes flexibility, testability, and maintainability. By using interfaces and dependency injection, you can create systems where components are independent and can evolve separately without affecting each other.
