Coupling — what it is and why low coupling is desirable
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
Coupling measures how much one component relies on another component's decisions. That can include a Java type, a JSON schema, call order, shared database table, or timing behavior. Higher coupling raises the cost and risk of changing either side, while lower coupling keeps the dependency narrow and stable.
For example, OrderService calling vendor-specific methods throughout its business may bind business closely to that vendor. Depending on a small Notifier contract can contain that detail, but only if the contract truly expresses what ordering needs. I do not say every concrete class or every new is tight coupling: creating Money is ordinary, and application wiring must construct concrete objects somewhere. I look at what changes together and which knowledge crosses the boundary.
Coupling — what it is and why low coupling is desirable
Direct Answer
Coupling is the degree to which one module relies on another module's contract, data, timing, or implementation choices. Higher coupling increases the chance that a change spreads, but it does not mean every change forces edits. Low coupling means dependencies are limited and stable—not that classes are independent or use interfaces everywhere.
Code Example
// TIGHT COUPLING - OrderService directly creates EmailNotifier
class OrderServiceTight {
private EmailNotifier notifier = new EmailNotifier(); // hard dependency
public void placeOrder(Order order) {
// process order
notifier.sendEmail(order.getCustomerEmail(), "Order confirmed");
}
}
// LOOSE COUPLING - OrderService depends on interface
interface NotificationService {
void notify(String recipient, String message);
}
@Service
class OrderService {
private final NotificationService notifier; // depends on abstraction
public OrderService(NotificationService notifier) { // injected by Spring
this.notifier = notifier;
}
public void placeOrder(Order order) {
// process order
notifier.notify(order.getCustomerEmail(), "Order confirmed");
}
}
@Service
class EmailNotifier implements NotificationService {
public void notify(String recipient, String message) {
// send email implementation
}
}
Common Mistakes & Pitfalls
- Calling every dependency bad: useful collaboration is necessary.
- Equating
newwith tight coupling: constructing values or wiring at the application edge is normal. - Creating one interface per class: an interface that copies the implementation may add no boundary.
- Saying low-coupled modules change independently: shared contracts still coordinate their evolution.
- Looking only at Java imports: schemas, protocols, timing, and shared data can be stronger coupling.
Check your understanding
Answer these without looking back at the article.
- What is the difference between tight and loose coupling?
- How does coupling relate to the Dependency Inversion Principle?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.