MVC stands for Model View Controller. It is a software architecture pattern commonly used in web development. However, it is not limited to web development. MVC helps to separate concerns, functions, and services.
in this example we also use a service for more separation and call the service in our Controller.
Our controller receives an input we call the service and pass the input, we receive the output and return the output to the user
Model:
- Represents the data structure and business logic
- mostly this is a Class
View (UI):
- The user interface
- contains all the styling and components of the UI
Controller:
- Handles user input and updates the model and view
- delegate of tasks
Services:
- Database calls
- computations
- User specific functions / Data handling / etc …
Model
// Model Class
package com.example.demo.model;
public class User {
private String name;
private int age;
// Constructor
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getters and setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Service
package com.example.demo.service;
import com.example.demo.model.User;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
@Service
public class UserService {
public List<User> getAllUsers() {
return Arrays.asList(
new User("Alice", 30),
new User("Bob", 25)
);
}
}
Controller
package com.example.demo.controller;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/")
public String index(Model model) {
model.addAttribute("users", userService.getAllUsers());
return "index"; // Returns the name of the HTML template
}
}
View
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User List</title>
</head>
<body>
<h1>User List</h1>
<ul>
<!-- Loop through the list of users -->
<th:block th:each="user : ${users}">
<li th:text="${user.name} + ' - ' + ${user.age}"></li>
</th:block>
</ul>
</body>
</html>
This can also be done as an API call when front and back-end are separated. This API call returns JSON (when you change the controller return option to JSON)
// Fetch users from the API
async function fetchUsers() {
try {
const response = await fetch('http://localhost:3000/api/users');
if (!response.ok) throw new Error('Failed to fetch users');
const users = await response.json();
// Render the user list
const userList = document.getElementById('userList');
userList.innerHTML = ''; // Clear previous content
users.forEach(user => {
const listItem = document.createElement('li');
listItem.textContent = `${user.name} (${user.age} years old)`;
userList.appendChild(listItem);
});
} catch (error) {
console.error('Error fetching users:', error);
}
}
// Call the function when the page loads
fetchUsers();
Why use MVC
MVC ensures that applications are structured, maintainable, and scalable. It encourages clean separation of concerns, making it easier to develop robust, reusable, and testable software. This is why MVC is a go-to pattern for many developers.
Example scenarios
Consider an e-commerce application:
- Model: Handles database queries (e.g., retrieving product details).
- View: Displays the product details to the user.
- Controller: Handles user actions and pass it to the service (e.g., “Add to Cart” or “Search Products”) search service / cart service.
By using MVC:
- Adding a new feature, like a product recommendation, requires changes primarily in the Controller and View.
- When using a service, changes can be done in the service class
- Changing the database schema affects only the Model.
1. Separation of Concerns
- MVC separates the application into three interconnected components:
- Model: Manages the data, logic, and rules.
- View: Displays the data (UI/UX).
- Controller: Handles user input and updates both the Model and the View.
- This separation makes the codebase easier to manage, understand, and scale.
2. Improved Maintainability
- Changes to one component (e.g., updating the UI) don’t directly affect others.
- Developers can modify or extend individual parts (Model, View, or Controller) without impacting the entire application.
3. Reusability
- Components in MVC are modular:
- Model: Can be reused for multiple views (e.g., a mobile app and a web app).
- View: Can display data from different models.
- Controller: Can reuse logic across different views.
4. Parallel Development
- Teams can work simultaneously on different components:
- Designers work on the View (UI/UX).
- Developers focus on the Model and Controller.
- This speeds up the development process.
5. Scalability
- MVC makes it easier to scale applications by:
- Adding more features without tightly coupling code.
- Allowing for changes in one layer without disrupting others.
6. Testability
- Each layer can be tested independently:
- Test Models for data handling.
- Test Controllers for logic and routing.
- Test Views for rendering data correctly.
7. Flexibility
- The View can be updated without altering the underlying logic (Controller and Model).
- Allows for different user interfaces (e.g., desktop, mobile, APIs) to use the same business logic.
8. Industry Standard
- MVC is a widely adopted architectural pattern in many frameworks and languages:
- Java: Spring MVC, Struts.
- JavaScript: Angular, React (in a way), Vue.js.
- Python: Django, Flask.
- Ruby: Ruby on Rails.
- Adhering to an industry standard ensures compatibility with tools, libraries, and best practices.