Day 5 of 5

MVC and Architecture

MVC (Model-View-Controller) separates data, presentation, and logic. Today you will implement MVC in a vanilla TypeScript app and see how Express and React map to the same concerns.

typescript
// Model — pure data + business rules
class TodoModel {
  private todos: Todo[] = [];

  getAll() { return [...this.todos]; }

  add(text: string): Todo {
    const todo = { id: Date.now(), text, done: false };
    this.todos.push(todo);
    return todo;
  }

  toggle(id: number) {
    const todo = this.todos.find(t => t.id === id);
    if (todo) todo.done = !todo.done;
  }

  delete(id: number) {
    this.todos = this.todos.filter(t => t.id !== id);
  }
}

// View — renders HTML, emits user events
class TodoView {
  private addBtn = document.getElementById('add-btn')!;
  private input = document.getElementById('new-todo') as HTMLInputElement;
  private list = document.getElementById('todo-list')!;

  onAdd?: (text: string) => void;

  constructor() {
    this.addBtn.addEventListener('click', () => {
      this.onAdd?.(this.input.value);
      this.input.value = '';
    });
  }

  render(todos: Todo[]) {
    this.list.innerHTML = todos.map(t => \`
      <li data-id="\${t.id}" class="\${t.done ? 'done' : ''}">
        \${t.text}
      </li>\`).join('');
  }
}

// Controller — connects Model and View
class TodoController {
  constructor(private model: TodoModel, private view: TodoView) {
    this.view.onAdd = (text) => {
      this.model.add(text);
      this.view.render(this.model.getAll());
    };
    this.view.render(this.model.getAll());
  }
}

new TodoController(new TodoModel(), new TodoView());
Tip: Express maps naturally: Routes = Controller, Mongoose models = Model, response.json() = View. React maps: Components = View, hooks = Controller, stores/context = Model.

Exercise: Refactor a Spaghetti App into MVC

  1. Take a single-file To-do app with mixed concerns
  2. Extract all data operations into a Model class
  3. Extract all DOM manipulation into a View class
  4. Create a Controller that wires them together
  5. Verify each class can be unit-tested independently

Day 5 Summary

Finished this lesson?