CHAPTER 17
Intermediate
Repository and Dependency Injection Patterns
Updated: May 16, 2026
40 min read
# CHAPTER 17
Repository and Dependency Injection Patterns
1. Introduction
While the Gang of Four formalized the classic 23 design patterns in 1994, modern enterprise web development has evolved. Today, if you open any enterprise framework (Laravel, Spring Boot, .NET Core), you will immediately encounter two foundational architectural patterns that dictate how the entire application is structured: the Repository Pattern and Dependency Injection (DI). If a developer hardcodes SQL queries into a controller, or manually instantiates 10 nested database dependencies using thenew keyword, the application becomes an untestable, tightly coupled monolith. In this chapter, we will master modern backend architecture. We will abstract the database using Repositories, and achieve ultimate decoupling using Dependency Injection and Service Containers.
2. Learning Objectives
By the end of this chapter, you will be able to:- Define the intent and structural benefits of the Repository Pattern.
- Abstract the Data Access Layer (DAL) away from the Business Logic.
- Understand the core concept of Dependency Injection (DI) and Inversion of Control (IoC).
- Architect highly decoupled systems using Constructor Injection.
- Understand how DI facilitates isolated Unit Testing (Mocking).
3. The Repository Pattern
The Repository Pattern mediates between the domain (business logic) and data mapping layers using a collection-like interface for accessing domain objects.-
The Problem: Your
UserControllerdirectly calls$db->query("SELECT * FROM users"). Tomorrow, the CTO decides to switch from MySQL to MongoDB. You have to rewrite every single controller in your application.
-
The Solution: You create a
UserRepositoryinterface with afind($id)method. The Controller only talks to the interface. You write aMySQLUserRepositoryclass that implements the interface. The Controller has no idea *how* the data is fetched; it just knows it gets a User object.
4. Dependency Injection (DI)
Dependency Injection is a technique in which an object receives other objects that it depends on (called dependencies).-
The Problem: A
ReportServiceneeds aDatabaseand aMailer. If theReportServiceconstructor callsnew Database()andnew Mailer(), it is permanently glued to those concrete classes (violating the SOLID Dependency Inversion Principle). You cannot test theReportServicewithout actually sending a real email and hitting a real database.
-
The Solution (Constructor Injection): You pass the dependencies *into* the
ReportServicethrough its constructor.
$service = new ReportService(new Database(), new Mailer());
5. Inversion of Control (IoC) Containers
If class A needs B, and B needs C and D, manually writingnew A(new B(new C(), new D())) everywhere is exhausting.
-
The Service Container: Modern frameworks use an IoC Container. It is a massive registry. You teach the container: "Whenever a class asks for a
MailerInterface, give it an instance ofSendGridMailer." The framework magically injects the correct objects automatically.
6. UML Diagram
*Repository and DI Architecture*
text
7. Code Example (PHP)
Let's build a highly decoupled, perfectly testable architecture.
php
8. The Testing Benefit (Mocking)
BecauseUserRegistrationService depends on interfaces, Unit Testing becomes incredibly easy. You don't want your test to actually hit a real MySQL database. Instead, you create a MockUserRepository class that implements the interface but just returns dummy data instantly in memory. You inject the Mock into the Service, allowing you to test the Service's logic in 1 millisecond with zero database required.
9. Common Mistakes
-
The "Active Record" Confusion: Frameworks like Laravel use the "Active Record" pattern by default (
User::find(1)). This inherently couples your logic directly to the database ORM, bypassing the Repository pattern. While Active Record is incredibly fast for rapid prototyping, Enterprise architectures strictly prefer the decoupled Repository pattern to isolate the domain logic from the ORM.
10. Mini Project: Swap the Database
- 1. Using the code above, the CTO dictates that user data must now be fetched from an external REST API instead of MySQL.
-
2.
Create a
RestApiUserRepositoryclass that implementsUserRepository.
-
3.
In the bootstrap section, change exactly *one line of code* to inject
new RestApiUserRepository()instead of the MySQL version.
-
4.
Run the code. Notice how the
UserRegistrationServicerequired absolutely zero modifications. That is the power of decoupled architecture.
11. Practice Exercises
- 1. Define the architectural purpose of the Repository Pattern. How does it protect your core business logic from changes in third-party database drivers?
-
2.
Explain the concept of Dependency Injection. Why is injecting dependencies via a constructor vastly superior to instantiating them directly with the
newkeyword?
12. MCQs with Answers
Question 1
A developer writes a PaymentService class. Inside its constructor, it explicitly calls $this->db = new MySQLConnection(). Which SOLID principle has the developer violently violated, making the class permanently coupled to MySQL and impossible to isolate for unit testing?
Question 2
Modern enterprise frameworks utilize a centralized registry to automatically manage object instantiation and automatically inject required interfaces into class constructors. What is this architectural component called?
13. Interview Questions
- Q: Explain how Dependency Injection facilitates rapid, isolated Unit Testing. Walk me through the concept of "Mocking" an interface.
- Q: Compare the "Active Record" pattern with the "Repository" pattern for database access. If you are building a massive, 10-year enterprise SaaS application, which pattern would you choose and why?
- Q: Walk me through the mechanics of an IoC (Inversion of Control) Container. How does a framework like Laravel or Spring "magically" know which concrete class to provide when a controller asks for an interface?
14. FAQs
Q: Is Dependency Injection the same as the Dependency Inversion Principle (DIP)? A: No, but they are closely related. DIP is the *concept* (depend on abstractions, not concretions). Dependency Injection is the *technique* used to achieve DIP (passing those abstractions into the constructor).15. Summary
In Chapter 17, we engineered the foundation of modern backend architecture. We deployed the Repository pattern to build an impenetrable wall between our pristine business logic and the messy realities of SQL queries and database drivers. We mastered Dependency Injection, permanently eradicating the hardcodednew keyword from our domain services. By injecting interfaces rather than concrete classes, we achieved ultimate architectural decoupling, allowing us to swap databases instantly and execute isolated, lightning-fast unit tests. This is how enterprise software is built.