100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What is a Tightly Coupled System?

Understand tightly coupled systems in OOP — symptoms, costs, and how dependency injection and interfaces reduce coupling, with a Java example.

easyQ123 of 226 in Object Oriented Programming Est. time: 5 minsLast updated:
Open Code Lab

Expected Interview Answer

A tightly coupled system is one where classes or modules depend heavily on each other’s concrete internal details, so a change in one nearly always forces a change in the others, making the code brittle and hard to test or reuse in isolation.

Tight coupling typically shows up as classes instantiating concrete dependencies directly with “new” instead of receiving an interface, reaching into another object’s internal fields, or knowing another class’s implementation details rather than just its public contract. Because the connection is so direct, swapping an implementation, mocking a dependency for a unit test, or reusing a class elsewhere becomes difficult without touching multiple files. Tight coupling is not always wrong in very small, stable programs, but as a system grows it multiplies the blast radius of every change and works against the open-closed principle.

    AI Mentor Explanation

    Imagine a bowler whose entire run-up is physically bolted to one specific groundsman’s exact pitch markings, so the bowler cannot perform on any other ground without the groundsman personally re-marking it identically. Any change to the pitch layout breaks the bowler’s technique completely. That direct, non-negotiable dependency on one specific implementation, rather than a general rule like “bowl from behind the crease,” is what tight coupling looks like in code — a class hard-wired to one concrete collaborator’s exact internals.

    Step-by-Step Explanation

    1. Step 1

      Spot direct instantiation

      A class creates its dependencies with “new ConcreteClass()” instead of receiving an abstraction.

    2. Step 2

      Spot reliance on internals

      A class reaches into another object’s fields or implementation details, not just its public methods.

    3. Step 3

      Trace the ripple effect

      Changing the dependency’s internals forces changes across every class that touches it directly.

    4. Step 4

      Recognize the testing cost

      The dependency cannot be swapped for a mock or fake without modifying the dependent class’s code.

    What Interviewer Expects

    • A clear definition centered on dependency on concrete implementation details
    • Concrete symptoms: direct “new”, reaching into internals, no interfaces
    • Understanding of the practical cost: brittleness, hard to test, hard to reuse
    • Awareness that some coupling is unavoidable, and the goal is minimizing unnecessary coupling

    Common Mistakes

    • Describing tight coupling only vaguely as “bad code” without naming the mechanism
    • Confusing coupling with cohesion (they are different, related concepts)
    • Claiming all coupling is always bad in every context
    • Not connecting the concept to concrete symptoms like “new” calls or missing interfaces

    Best Answer (HR Friendly)

    A tightly coupled system is one where classes depend directly on each other’s specific implementation rather than a general contract, so changing one class often breaks several others. It usually shows up as classes creating their own dependencies directly instead of receiving them, which makes the code harder to test and reuse independently.

    Code Example

    Tight coupling versus a decoupled alternative
    // Tightly coupled: OrderService is hard-wired to EmailNotifier
    class OrderService {
        private EmailNotifier notifier = new EmailNotifier(); // concrete, direct
    
        void placeOrder() {
            notifier.sendEmail("Order placed");
        }
    }
    
    // Decoupled: OrderService depends on an abstraction, not a concrete class
    interface Notifier {
        void send(String message);
    }
    
    class OrderServiceDecoupled {
        private final Notifier notifier;
    
        OrderServiceDecoupled(Notifier notifier) { // injected, swappable
            this.notifier = notifier;
        }
    
        void placeOrder() {
            notifier.send("Order placed");
        }
    }

    Follow-up Questions

    • How does dependency injection help reduce tight coupling?
    • What is the difference between coupling and cohesion?
    • How does depending on an interface instead of a concrete class reduce coupling?
    • Is tight coupling always bad? When might it be acceptable?

    MCQ Practice

    1. Which is the strongest symptom of tight coupling?

    Direct instantiation of concrete classes and reliance on their internals is the hallmark symptom of tight coupling.

    2. What is the main practical cost of tight coupling?

    Tight coupling makes changes ripple widely and makes isolated unit testing difficult without touching multiple classes.

    3. Which technique most directly reduces tight coupling?

    Depending on abstractions (interfaces) and injecting implementations decouples a class from concrete details.

    Flash Cards

    Tight coupling, one line?Classes depend directly on each other’s concrete implementation details, not a general contract.

    Common symptom?A class instantiates its own dependency with “new” instead of receiving it.

    Main cost?Changes ripple across classes and dependencies are hard to mock or swap in tests.

    Common fix?Program to an interface and inject the implementation (dependency injection).

    1 / 4

    Continue Learning