HackIndia Logo
HackathonsNewsSkillsGrowth
HackIndia LogoContact: +91 9910125804

General

  • Companies
  • Colleges
  • Board of Advisors
  • Brand Ambassadors
  • FAQ
  • Contact
  • Report a Bug

Hackathons

  • Upcoming Hackathons
  • Judges
  • Mentors
  • Partners
  • Participating Colleges

Resources

  • About Us
  • Branding
  • Latest News
  • Growth
  • Skills
  • Ecosystem
  • Forum
  • Ideas
  • Prompt Optimizer
  • How to earn XP

© 2026 HackIndia. All rights reserved.

Privacy PolicyTerms of ServiceCode of ConductSitemap

Build 2.139 · 09 Nov 2026, 10:59 UTC

    HackIndia
    HackathonsNewsInternshipsSkillsGrowth
    Working towardsDesign Patterns
    0%

    0 of 10 steps done · +100 XP · +50 SHARP when it is yours

    1. 1Spot pattern-shaped problems5 min · +10 XP · +5 SHARP
    2. 2Create objects with factories5 min · +10 XP · +5 SHARP
    3. 3Swap behavior with strategy5 min · +10 XP · +5 SHARP
    4. 4React to events with observer4 min · +10 XP · +5 SHARP
    5. 5Use singleton with caution4 min · +10 XP · +5 SHARP
    6. 6Bridge boundaries with adapter and repository5 min · +10 XP · +5 SHARP
    7. 7Wire code using dependency injection5 min · +10 XP · +5 SHARP
    8. 8Ship your pattern refactor repo5 min · +10 XP · +5 SHARP
    9. The check10 questions, 7 to pass · +10 SHARP
    10. Hand in the taskA project that uses the skill
    11. Skill and certificate+100 XP · +50 SHARP
    Lesson 7 of 8 5 min

    Design Patterns

    Wire code using dependency injection

    • +10 XP for this lesson
    • +100 XP when the skill is proved
    • 2 learning it right now
    In 30 seconds
    • Pass dependencies into a class instead of creating them inside it.
    • Refactor hard-coded services into small, testable wiring code.
    Show DI clearly in your repo without adding a large framework.
    Key point

    One idea

    Dependency injection means an object receives what it needs from the outside. It does not create or search for those dependencies itself.

    Use it when a class is stuck to a real database, payment API, email sender, clock, or AI client, and you want to swap that dependency for tests or local demos.

    Where DI fits

    You already used adapter and repository to hide boundaries. DI is how you connect those boundaries to the rest of the app.

    Think of it as wiring. Your business code says, “I need a PaymentGateway.” The app startup decides whether that is Razorpay, a fake UPI gateway, or a test double.

    Common mistake

    Common mistake

    Do not add DI just to look senior. If a class only uses normal values like strings or numbers, passing them is enough.

    Also avoid a DI framework in a small hackathon repo unless your stack already uses one. Manual wiring in one file is easier for reviewers to understand.

    Example

    Before: hard-coded

    This checkout service creates its own gateway. Now every test touches the real gateway shape, and you cannot run a clean offline demo.

    class RazorpayGateway {
      async charge(amountRupees, userId) {
        // call payment provider here
        return { ok: true, paymentId: "pay_123" };
      }
    }
    
    class CheckoutService {
      constructor() {
        this.gateway = new RazorpayGateway();
      }
    
      async buyCourse(userId, amountRupees) {
        const result = await this.gateway.charge(amountRupees, userId);
        if (!result.ok) throw new Error("Payment failed");
        return result.paymentId;
      }
    }
    
    module.exports = { CheckoutService };
    Example

    After: injected

    Now CheckoutService depends on a role, not a concrete class. The app wires the real gateway. Tests can pass a fake.

    class CheckoutService {
      constructor(paymentGateway) {
        this.paymentGateway = paymentGateway;
      }
    
      async buyCourse(userId, amountRupees) {
        const result = await this.paymentGateway.charge(amountRupees, userId);
        if (!result.ok) throw new Error("Payment failed");
        return result.paymentId;
      }
    }
    
    class RazorpayGateway {
      async charge(amountRupees, userId) {
        return { ok: true, paymentId: "pay_123" };
      }
    }
    
    class FakePaymentGateway {
      async charge(amountRupees, userId) {
        return { ok: true, paymentId: "fake_payment" };
      }
    }
    
    // app.js: production wiring
    const checkout = new CheckoutService(new RazorpayGateway());
    
    // checkout.test.js: test wiring
    const testCheckout = new CheckoutService(new FakePaymentGateway());
    
    module.exports = { CheckoutService, RazorpayGateway, FakePaymentGateway };
    Your to-do

    Refactor safely

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Tip

    Use AI carefully

    Ask an AI tool: “Refactor this class to use constructor dependency injection. Do not change behavior. Keep the wiring explicit.”

    Check that it did not rename public methods, hide wiring in global state, or add a DI container package you did not ask for.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Quick check

    0 of 2 right
    1.Your service creates a Razorpay client inside its constructor, making tests call real payment code. What refactor fits best?
    2.In a small hackathon repo, where should you usually wire injected dependencies?

    Answer the quick check to finish this lesson.

    ← Lesson 6Skip to lesson 8 →
    Working towards
    Design Patterns +100 XP

    0 of 8 lessons done · proved by a project that uses the skill

    See the track