Taking a closer look at MVC
MVC is an architectural pattern.
During your software engineering lifecycle, you will see multiple problems coming up related to code organization, code structure, object creation. To resolve these issues, you get patterns. Design patterns are nothing but solutions to these problems. MVC is one of the design pattern.
MVC defines how your backend architecture works.
Components of MVC
Model (M): Represents the data and business logic.
View (V): Represents the user interface what user sees.
Controller (C): Acts as an intermediary between Model and View, handling user input and updating the Model and View accordingly.
Understanding MVC in Restaurant Analogy
In a restaurant, the process of ordering and serving food can be broken down into three main roles that align with the MVC components:
Model (Chefs):
- The chefs in the kitchen are responsible for preparing the food. They follow recipes (business logic) to create dishes (data).
View (Food):
- The food served to the customers represents the View. It is the final product that the customers see and interact with.
Controller (Waiters):
- The waiters act as the Controllers. They take orders from the customers and communicate them to the chefs. Once the food is ready, they bring it back to the customers.
Problems with MVC
One of the most common problem with MVC is one of the layer gets bulky. Let's understand it with the example of GPay:
Scenario: Initiating a Payment
User Action: A user initiates a payment through the GPay app.
Controller: The Controller receives the payment request. It needs to:
Validate the payment details.
Check the user's account balance.
Process the payment through the payment gateway.
Update the transaction history.
Notify the user of the payment status.
Model: The Model handles the business logic for each of these steps. However, if the Controller is responsible for doing all these interactions, it can become very complex and difficult to manage.
Potential Issues
Complexity: As the application grows, It will be hard to maintain controllers.
Testing: Bulky Controllers can be difficult to test because they handle multiple responsibilities.
Tight Coupling: The Controller might become tightly coupled with the Model and View, making it harder to make changes in one part of the application without affecting others.
Solution : Enhanced MVC
We can Separate the responsibility concerns into multiple layers.
i) Routing layer:
It defines if a request comes, where it should be handled.
ii) Validation layer:
It validates the request and let the request go through if it’s a valid request. Otherwise it can throw an error from there.
iii) Controller layer:
Takes your request to business logic part and prepares what response to give back to users.
iv) Service layer:
Handles all your business logic.
v) DAO/Repository layer:
Interacts with database like reading from database, writing to database, deleting data from database etc.
vi) Model/Entities layer:
Contains the logic to understand how the data is represented in your database. Represent the logical view of the schema. Java/JS doesn’t understand tables. It understands classes and objects. This thing is stored in model/entity layer.
vii) Views:
In modern applications, generally views are developed as separate projects using modern frontend technologies like react, next, angular, etc. And that frontend make API calls to our backend.
viii) Third Party Services:
We might be using external services. e.g. Using Stripe API, Twilio API, Razorpay API. So our service layer can directly interact with the third party services.
Brief note on why separate concerns of repository layer and service layer
Separating the repository layer from the service layer is crucial for several reasons:
The repository layer handles database interactions, while the service layer manages business logic. This separation ensures that each layer focuses on a single responsibility, making the codebase more modular and easier to maintain.
If your business logic is tightly coupled with database interactions, scaling or changing your database can become problematic.
Keeping these layers separate allows you to change or upgrade your database without extensive rewrites of your business logic.
Example
Consider an application initially using SQLite. If the business logic is strongly coupled with SQLite-specific database interactions(We have written core SQL queries), switching to MySQL would require significant changes to both the database code and the business logic. If we have separate layer for interacting with database, we just have to modify the repository layer and all other layer can be remained as it is.
This separation of concerns ultimately leads to a more maintainable, scalable, and flexible application architecture.
Subscribe to my newsletter
Read articles from Pratham Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Pratham Patel
Pratham Patel
I am CS undergraduate student exploring web development.