Sobes.tech
Middle

What is the MVVM architectural pattern?

sobes.tech AI

Answer from AI

MVVM (Model-View-ViewModel) is an architectural pattern that structures code to separate application logic into three interconnected components:

  • Model: Represents data and business logic. It is UI-independent.
  • View: Displays data from the ViewModel and sends user actions (e.g., clicks) to the ViewModel. The View is passive and contains no data processing logic.
  • ViewModel: Acts as an intermediary between the Model and the View. It provides data from the Model in a format suitable for display in the View and handles user actions, updating the Model. The ViewModel often uses data binding mechanisms for automatic View updates when data changes.

Key principles:

  • Two-way data binding: Changes in the ViewModel are automatically reflected in the View, and vice versa (when using appropriate tools).
  • Testability: The ViewModel is easy to test in isolation since it is not tied to the UI.
  • Separation of concerns: Clear separation of presentation logic, data, and business logic simplifies development and maintenance.

It is often used in applications with declarative UI, such as Vue.js, React (with some variations), Angular.

Example of a simple structure:

// Model
class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

// ViewModel
class UserViewModel {
  constructor(user) {
    this.user = user;
    this.displayName = `${user.name} (${user.age})`;
  }

  incrementAge() {
    this.user.age++;
    this.displayName = `${this.user.name} (${this.user.age})`; // Update displayName for the View
  }
}

// View (roughly, how it might look in a declarative framework)
/*
<template>
  <div>
    <p>{{ userViewModel.displayName }}</p>
    <button @click="userViewModel.incrementAge()">Increase Age</button>
  </div>
</template>

<script>
import { User } from './model';
import { UserViewModel } from './viewModel';

export default {
  data() {
    return {
      userViewModel: new UserViewModel(new User('Ivan', 30))
    };
  }
}
</script>
*/