MVC is a software architectural pattern that separates an application into three interconnected components: Model (data), View (UI), and Controller (logic). This separation of concerns makes code more maintainable, testable, and scalable.
+-------------+ user intent +--------------+
| VIEW | ◀--------------- | CONTROLLER |
+-------------+ +--------------+
▲ |
| render | mutates / queries
| ▼
+-------------+ change notification +-------------+
| BROWSER |◀---------------------- | MODEL |
+-------------+ +-------------+
Mental hook: Model is truth, View is paint, Controller is the conductor.
<ul id="todoView"></ul> <input id="newTodo" placeholder="Add item" /> <button id="addBtn">Add</button>
// Model class TodoStore { #items = []; #listeners = []; add(text) { this.#items.push({ id: Date.now(), text, done: false }); this.#notify(); } toggle(id) { this.#items = this.#items.map(it => it.id === id ? { ...it, done: !it.done } : it); this.#notify(); } onChange(fn) { this.#listeners.push(fn); } get items() { return [...this.#items]; } #notify() { this.#listeners.forEach(fn => fn()); } } // View function renderList(store, ul) { ul.innerHTML = ""; store.items.forEach(item => { const li = document.createElement("li"); li.textContent = (item.done ? "✔️ " : "") + item.text; li.onclick = () => controller.toggleItem(item.id); // delegate to controller ul.appendChild(li); }); } // Controller const store = new TodoStore(); const ul = document.getElementById("todoView"); const input = document.getElementById("newTodo"); const addBtn = document.getElementById("addBtn"); const controller = { init() { store.onChange(() => renderList(store, ul)); addBtn.onclick = () => { if (input.value.trim()) store.add(input.value.trim()); input.value = ""; }; }, toggleItem(id) { store.toggle(id); } }; controller.init();
Key take‑aways:
| Framework | View | Controller | Model |
|---|---|---|---|
| Backbone | Backbone.Viewtemplates | Backbone.Router& callback methods | Backbone.Model / Collection |
| Angular (v2+) | Template HTML | Component class (methods) | Service / RxJS store |
| React + Redux | JSX function/component | Action creators / dispatchers | Redux store (reducers) |
| Svelte | Template syntax | Component <script>(event handlers) | Store module (writable/derived) |
Observation: Modern libraries often collapse View+Controller into a component , pushing state to specialized stores.
.innerHTML += … inside Models.| Question | Winning Approach |
|---|---|
| "How is React not true MVC?" | Show that React collapses C+V in a component; external store (Redux) acts as Model. |
| "Why avoid fat controllers?" | Hurts reusability, testability; push rules to Model, formatting to View. |
| "How does two‑way binding in Angular relate to MVC?" | It shortcuts Controller; View <-> Model updates auto, which can cause hidden coupling. |
Pro‑Tip: Walk through a bug trace: “A checkbox click toggles state -> Controller dispatches action -> Model updates store -> View re‑renders via subscription.” Interviewers like end‑to‑end clarity.
For small SPA prototypes, prefer component‑centric patterns (MVU, MVVM) to reduce boilerplate.
MVC divides application logic into Model, View, and Controller, enabling testable, maintainable UIs—especially when multiple views share state. Master the why and how behind MVC, and you'll shine in front‑end interviews when asked to architect anything beyond a toy component.
Happy structuring! 🏗️
Test your understanding with 3 quick questions