Lesson 2 of 30
Why big apps separate 'what the data is' from 'how it looks' — and how that one idea shows up as MVC, then Flux/Redux, then React's own one-way data flow.
14 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 2
Why can `fetchUsers()` in the separated example be tested with no browser at all, while the tangled `loadAndShowUsers()` version can't?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A strong answer covers
Likely follow-ups
MVC (Model–View–Controller) is the classic answer to one problem: keep "what the data is and how it changes" (Model) separate from "how it's displayed" (View), with something (a Controller) deciding what happens in response to input. The exact shape has changed a lot since — MVVM, Flux, Redux — but every variant is solving the same problem: don't let display logic and data logic become the same tangled thing.
You've already seen a version of this: props's one-way data flow (data down, changes only via a callback) is this exact idea, applied to one component. Flux/Redux apply it to an entire app's shared state.
// ❌ tangled: fetching, deciding, and rendering are one blob
async function loadAndShowUsers() {
const res = await fetch("/api/users");
const users = await res.json();
document.querySelector("#list").innerHTML = users
.map((u) => `<li onclick="deleteUser(${u.id})">${u.name}</li>`)
.join("");
}
// ✅ separated: data layer and view layer don't know about each other
async function fetchUsers() { // data layer
const res = await fetch("/api/users");
return res.json();
}
function renderUserList(users, onDelete) { // view layer
return users.map((u) => `<li data-id="${u.id}">${u.name}</li>`).join("");
}
fetchUsers can be tested with no browser at all — it's just a function returning data. renderUserList can be tested by handing it fake data — it never has to know where that data came from. Neither can break the other.
Model: the data and business logic — knows nothing about how it's displayed.
"How would you structure a large app's state?" tests whether you understand why the separation exists — testability, debuggability, and reuse — not whether you can name MVC's three letters. Tying it back to the one-way data flow you already know from props is what shows real understanding instead of memorized vocabulary.