# MVC Architecture (Model-View-Controller)

## 📚 สารบัญ

1. [หลักการพื้นฐาน](#หลักการพื้นฐาน)
2. [โครงสร้าง MVC](#โครงสร้าง-mvc)
3. [ข้อดี และข้อเสีย](#ข้อดี-และข้อเสีย)
4. [MVC Flow](#mvc-flow)
5. [Code Examples](#code-examples)
6. [Real World Examples](#real-world-examples)
7. [Best Practices](#best-practices)

---

## 🎯 หลักการพื้นฐาน

### MVC Architecture คืออะไร?

**นิยาม:** สถาปัตยกรรมที่แบ่งแอปพลิเคชันออกเป็น 3 ส่วน:

- **Model:** ข้อมูลและ business logic
- **View:** การแสดงผล (UI)
- **Controller:** ตัวจัดการ request และ response

### ประวัติศาสตร์

```
1978: Introduced by Trygve Reenskaug (Smalltalk)
↓
1988: Used in web frameworks (Ruby on Rails)
↓
2000s: Standard in web development
↓
2010s-Present: Still widely used, evolved
```

### หลักการหลัก

```
1️⃣  Separation of Concerns
   - Model: Business logic
   - View: Presentation
   - Controller: Flow control
   - Each has specific responsibility

2️⃣  Data-View Separation
   - View doesn't know about data structure
   - Model doesn't know how it's displayed
   - Easy to change UI without changing logic

3️⃣  Reusability
   - Controllers reusable with different views
   - Models reusable with different controllers
   - Views can be swapped

4️⃣  Testability
   - Models tested separately
   - Controllers tested with mock views
   - Views tested independently
```

---

## 🏗️ โครงสร้าง MVC

### MVC Components

```
┌─────────────────────────────────────────────────┐
│                  CLIENT (Browser)               │
│              ┌─────────────────────┐            │
│              │  HTML / CSS / JS    │            │
│              └──────────┬──────────┘            │
└─────────────────────────┼────────────────────────┘
                          │ HTTP Request
                          ↓
┌─────────────────────────────────────────────────┐
│            SERVER (Express.js)                  │
│                                                 │
│  ┌─────────────────────────────────────────┐   │
│  │ CONTROLLER                              │   │
│  │ ┌─────────────────────────────────────┐ │   │
│  │ │ 1. Receive HTTP request             │ │   │
│  │ │ 2. Parse parameters                 │ │   │
│  │ │ 3. Call Model methods               │ │   │
│  │ │ 4. Select View                      │ │   │
│  │ │ 5. Pass data to View                │ │   │
│  │ │ 6. Send HTTP response               │ │   │
│  │ └─────────────────────────────────────┘ │   │
│  └────────────┬──────────────┬──────────────┘   │
│               │              │                  │
│         calls │              │ requests data   │
│               ↓              ↓                  │
│  ┌──────────────────┐  ┌──────────────────┐   │
│  │   MODEL          │  │   VIEW           │   │
│  ├──────────────────┤  ├──────────────────┤   │
│  │ User class       │  │ Templates        │   │
│  │ ├─ createUser    │  │ ├─ user.ejs      │   │
│  │ ├─ getUser       │  │ ├─ list.ejs      │   │
│  │ ├─ updateUser    │  │ └─ form.ejs      │   │
│  │ └─ deleteUser    │  │                  │   │
│  │                  │  │ Rendering:       │   │
│  │ Database logic   │  │ ├─ Insert data   │   │
│  │ Validations      │  │ ├─ Loop through  │   │
│  │ Business rules   │  │ └─ Conditional   │   │
│  │                  │  │   display        │   │
│  └──────────────────┘  └──────────────────┘   │
└─────────────────────────────────────────────────┘
                          │ HTML Response
                          ↓
┌─────────────────────────────────────────────────┐
│           CLIENT RENDERS VIEW                   │
└─────────────────────────────────────────────────┘
```

### Detailed MVC Architecture

#### Model (ข้อมูลและ Business Logic)

```javascript
// Model: Database objects + business logic
class User {
  constructor(email, name, password) {
    this.email = email;
    this.name = name;
    this.password = password;
  }

  // Business logic
  isValidEmail() {
    return this.email.includes("@");
  }

  async save() {
    if (!this.isValidEmail()) {
      throw new Error("Invalid email");
    }
    // Save to database
    return await db.insert("users", this);
  }

  static async findById(id) {
    return await db.query("SELECT * FROM users WHERE id = ?", [id]);
  }

  static async findAll() {
    return await db.query("SELECT * FROM users");
  }
}
```

**Responsibilities:**

- Data persistence
- Business validations
- Database queries
- Object relationships

#### View (การแสดงผล)

```html
<!-- View: Templates (ejs, pug, handlebars) -->
<!DOCTYPE html>
<html>
  <head>
    <title>Users List</title>
  </head>
  <body>
    <h1>Users</h1>

    <% if (users.length === 0) { %>
    <p>No users found</p>
    <% } else { %>
    <table>
      <tr>
        <th>ID</th>
        <th>Email</th>
        <th>Name</th>
        <th>Actions</th>
      </tr>
      <% users.forEach(user => { %>
      <tr>
        <td><%= user.id %></td>
        <td><%= user.email %></td>
        <td><%= user.name %></td>
        <td>
          <a href="/users/<%= user.id %>">View</a>
          <a href="/users/<%= user.id %>/edit">Edit</a>
          <a href="/users/<%= user.id %>/delete">Delete</a>
        </td>
      </tr>
      <% }); %>
    </table>
    <% } %>

    <a href="/users/new">Add New User</a>
  </body>
</html>
```

**Responsibilities:**

- Display data
- User interface
- HTML/CSS/JavaScript
- No business logic

#### Controller (Flow Control)

```javascript
// Controller: Route handlers
class UserController {
  // GET /users - List all users
  async list(req, res) {
    try {
      const users = await User.findAll();
      res.render("users/list", { users });
    } catch (error) {
      res.status(500).render("error", { error });
    }
  }

  // GET /users/:id - Show single user
  async show(req, res) {
    try {
      const user = await User.findById(req.params.id);
      if (!user) {
        return res.status(404).render("error", { error: "User not found" });
      }
      res.render("users/show", { user });
    } catch (error) {
      res.status(500).render("error", { error });
    }
  }

  // GET /users/new - Form to create user
  async form(req, res) {
    res.render("users/form");
  }

  // POST /users - Create new user
  async create(req, res) {
    try {
      const user = new User(req.body.email, req.body.name, req.body.password);
      await user.save();
      res.redirect(`/users/${user.id}`);
    } catch (error) {
      res.status(400).render("users/form", { error: error.message });
    }
  }

  // GET /users/:id/edit - Edit form
  async editForm(req, res) {
    try {
      const user = await User.findById(req.params.id);
      res.render("users/form", { user });
    } catch (error) {
      res.status(500).render("error", { error });
    }
  }

  // PUT /users/:id - Update user
  async update(req, res) {
    try {
      const user = await User.findById(req.params.id);
      user.email = req.body.email;
      user.name = req.body.name;
      await user.save();
      res.redirect(`/users/${user.id}`);
    } catch (error) {
      res.status(400).render("users/form", { user, error: error.message });
    }
  }

  // DELETE /users/:id - Delete user
  async delete(req, res) {
    try {
      const user = await User.findById(req.params.id);
      await user.delete();
      res.redirect("/users");
    } catch (error) {
      res.status(500).render("error", { error });
    }
  }
}

module.exports = new UserController();
```

**Responsibilities:**

- Receive HTTP requests
- Validate input
- Call model methods
- Select and render views
- Return HTTP responses

---

## ✅ ข้อดี และข้อเสีย

### ✅ ข้อดี

| ข้อดี                  | อธิบาย                          |
| ---------------------- | ------------------------------- |
| **Simplicity**         | ง่ายเข้าใจ, ทำได้เร็ว           |
| **Separation**         | ชัดเจน separation of concerns   |
| **Reusability**        | Controllers/Views reusable      |
| **Testing**            | Model ทดสอบแยกจาก UI            |
| **Rapid Development**  | Quick to prototype              |
| **Familiar**           | Standard pattern, wide adoption |
| **Scalable to Medium** | Good for small-medium projects  |
| **Team Organization**  | Clear role division             |

### ❌ ข้อเสีย

| ข้อเสีย                  | อธิบาย                             |
| ------------------------ | ---------------------------------- |
| **Fat Models**           | Models can become bloated          |
| **Fat Controllers**      | Controllers can grow large         |
| **View Logic**           | Templates can have business logic  |
| **Monolithic**           | Difficult to scale to many servers |
| **Tight Coupling**       | Models ↔ Controllers coupled       |
| **Limited Testing**      | Integration testing difficult      |
| **Migration Difficulty** | Hard to evolve to microservices    |
| **Performance**          | Single database bottleneck         |

### เมื่อไดควรใช้ MVC?

```
✅ ใช้เมื่อ:
- Traditional web applications
- Server-side rendering needed
- Small-medium projects
- Fast prototyping
- Limited team
- Simple business logic
- HTML-based user interfaces

❌ ไม่ใช้เมื่อ:
- Single Page Applications (SPAs)
- Microservices architecture
- Need independent scaling
- Multiple client types
- High-traffic systems
- Real-time applications
- GraphQL API
```

---

## 🔄 MVC Flow

### Typical MVC Request-Response Cycle

```
1. USER INTERACTION
   User clicks: "Edit Profile"
   └─ Browser: GET /users/5/edit

2. ROUTING
   Express routes to: UserController.editForm(req, res)

3. CONTROLLER
   UserController.editForm():
   ├─ Extract ID from req.params
   ├─ Call Model.findById(5)
   └─ Pass to view

4. MODEL
   User.findById(5):
   ├─ Query database
   ├─ Validate permissions
   └─ Return user object

5. CONTROLLER
   UserController.editForm() continues:
   └─ Call: res.render('users/edit', { user })

6. VIEW
   Template 'users/edit.ejs':
   ├─ Receive user object
   ├─ Render form with user data
   ├─ Generate HTML

7. RESPONSE
   Controller sends HTML to browser

8. BROWSER
   ├─ Renders HTML
   ├─ Shows edit form
   └─ User modifies and submits

9. POST REQUEST
   User submits form:
   └─ Browser: POST /users/5
   └─ Form data in body

10. CONTROLLER
    UserController.update():
    ├─ Extract form data
    ├─ Validate input
    └─ Call Model.update()

11. MODEL
    User.update():
    ├─ Validate business rules
    ├─ Update database
    └─ Return updated user

12. RESPONSE
    Redirect: res.redirect('/users/5')

13. BROWSER
    ├─ Follow redirect
    └─ Show updated user profile
```

### Data Flow Diagram

```
Request Flow:
┌─────────┐
│ Browser │ HTTP GET /users/5/edit
└────┬────┘
     ↓
┌──────────────────────────────────┐
│ Express Router                   │
│ Maps route to controller method  │
└────┬─────────────────────────────┘
     ↓
┌──────────────────────────────────┐
│ UserController.editForm()        │
│ - Receive request                │
│ - Extract parameters (id=5)      │
│ - Call Model                     │
└────┬─────────────────────────────┘
     ↓
┌──────────────────────────────────┐
│ User.findById(5)                 │
│ - Query database                 │
│ - Return user object             │
│   { id: 5, name: "John", ... }   │
└────┬─────────────────────────────┘
     ↓
┌──────────────────────────────────┐
│ UserController.editForm()        │
│ - Receive user object            │
│ - Select view: 'users/edit'      │
│ - Pass data: { user }            │
│ - Call: res.render()             │
└────┬─────────────────────────────┘
     ↓
┌──────────────────────────────────┐
│ View: users/edit.ejs             │
│ - Receive { user }               │
│ - Render HTML form               │
│ - Pre-fill with user data        │
│ - Generate HTML string           │
└────┬─────────────────────────────┘
     ↓
┌──────────────────────────────────┐
│ HTTP Response                    │
│ Content-Type: text/html          │
│ Body: <html>...</html>           │
└────┬─────────────────────────────┘
     ↓
┌─────────┐
│ Browser │ Renders HTML
└─────────┘
```

---

## 💻 Code Examples

### Complete MVC Example (Express.js)

```javascript
// ============================================
// CONFIG
// ============================================
// config/database.js
const mysql = require('mysql2/promise');

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'myapp'
});

module.exports = pool;

// ============================================
// MODEL
// ============================================
// models/User.js
const db = require('../config/database');
const bcrypt = require('bcryptjs');

class User {
  constructor(email, name, password) {
    this.email = email;
    this.name = name;
    this.password = password; // Will be hashed
  }

  // Validation
  isValid() {
    if (!this.email.includes('@')) {
      throw new Error('Invalid email format');
    }
    if (this.password.length < 8) {
      throw new Error('Password must be at least 8 characters');
    }
    if (!this.name || this.name.trim() === '') {
      throw new Error('Name is required');
    }
  }

  // Create
  async save() {
    this.isValid();

    // Hash password
    const hashedPassword = await bcrypt.hash(this.password, 10);

    const [result] = await db.query(
      'INSERT INTO users (email, name, password_hash) VALUES (?, ?, ?)',
      [this.email, this.name, hashedPassword]
    );

    this.id = result.insertId;
    return this;
  }

  // Read
  static async findById(id) {
    const [rows] = await db.query(
      'SELECT id, email, name, created_at FROM users WHERE id = ?',
      [id]
    );
    return rows.length > 0 ? rows[0] : null;
  }

  static async findAll() {
    const [rows] = await db.query('SELECT id, email, name FROM users');
    return rows;
  }

  static async findByEmail(email) {
    const [rows] = await db.query(
      'SELECT * FROM users WHERE email = ?',
      [email]
    );
    return rows.length > 0 ? rows[0] : null;
  }

  // Update
  async update() {
    this.isValid();

    await db.query(
      'UPDATE users SET email = ?, name = ? WHERE id = ?',
      [this.email, this.name, this.id]
    );

    return this;
  }

  // Delete
  async delete() {
    await db.query('DELETE FROM users WHERE id = ?', [this.id]);
  }

  // Authentication
  static async authenticate(email, password) {
    const user = await User.findByEmail(email);
    if (!user) {
      throw new Error('User not found');
    }

    const isMatch = await bcrypt.compare(password, user.password_hash);
    if (!isMatch) {
      throw new Error('Invalid password');
    }

    return user;
  }
}

module.exports = User;

// ============================================
// CONTROLLER
// ============================================
// controllers/UserController.js
const User = require('../models/User');

class UserController {
  // GET /users
  async list(req, res) {
    try {
      const users = await User.findAll();
      res.render('users/list', { users });
    } catch (error) {
      res.status(500).render('error', { error: error.message });
    }
  }

  // GET /users/:id
  async show(req, res) {
    try {
      const user = await User.findById(req.params.id);
      if (!user) {
        return res.status(404).render('error', { error: 'User not found' });
      }
      res.render('users/show', { user });
    } catch (error) {
      res.status(500).render('error', { error: error.message });
    }
  }

  // GET /users/new
  new(req, res) {
    res.render('users/form', { user: null });
  }

  // POST /users
  async create(req, res) {
    try {
      const user = new User(req.body.email, req.body.name, req.body.password);
      await user.save();
      res.redirect(`/users/${user.id}`);
    } catch (error) {
      res.status(400).render('users/form', {
        user: req.body,
        error: error.message
      });
    }
  }

  // GET /users/:id/edit
  async edit(req, res) {
    try {
      const user = await User.findById(req.params.id);
      if (!user) {
        return res.status(404).render('error', { error: 'User not found' });
      }
      res.render('users/form', { user });
    } catch (error) {
      res.status(500).render('error', { error: error.message });
    }
  }

  // PUT /users/:id
  async update(req, res) {
    try {
      const user = await User.findById(req.params.id);
      if (!user) {
        return res.status(404).render('error', { error: 'User not found' });
      }

      user.email = req.body.email;
      user.name = req.body.name;
      await user.update();

      res.redirect(`/users/${user.id}`);
    } catch (error) {
      res.status(400).render('users/form', {
        user: req.body,
        error: error.message
      });
    }
  }

  // DELETE /users/:id
  async delete(req, res) {
    try {
      const user = await User.findById(req.params.id);
      if (!user) {
        return res.status(404).render('error', { error: 'User not found' });
      }

      await user.delete();
      res.redirect('/users');
    } catch (error) {
      res.status(500).render('error', { error: error.message });
    }
  }
}

module.exports = new UserController();

// ============================================
// ROUTES
// ============================================
// routes/users.js
const express = require('express');
const router = express.Router();
const UserController = require('../controllers/UserController');

router.get('/', UserController.list.bind(UserController));
router.get('/new', UserController.new.bind(UserController));
router.get('/:id', UserController.show.bind(UserController));
router.get('/:id/edit', UserController.edit.bind(UserController));

router.post('/', UserController.create.bind(UserController));
router.put('/:id', UserController.update.bind(UserController));
router.delete('/:id', UserController.delete.bind(UserController));

module.exports = router;

// ============================================
// VIEWS
// ============================================
// views/users/list.ejs
<!DOCTYPE html>
<html>
<head>
  <title>Users</title>
  <style>
    body { font-family: Arial; }
    table { border-collapse: collapse; margin-top: 20px; }
    th, td { border: 1px solid #ddd; padding: 10px; }
    th { background-color: #f2f2f2; }
  </style>
</head>
<body>
  <h1>Users</h1>

  <% if (users.length === 0) { %>
    <p>No users found.</p>
  <% } else { %>
    <table>
      <tr>
        <th>ID</th>
        <th>Email</th>
        <th>Name</th>
        <th>Actions</th>
      </tr>
      <% users.forEach(user => { %>
        <tr>
          <td><%= user.id %></td>
          <td><%= user.email %></td>
          <td><%= user.name %></td>
          <td>
            <a href="/users/<%= user.id %>">View</a> |
            <a href="/users/<%= user.id %>/edit">Edit</a> |
            <form action="/users/<%= user.id %>" method="post" style="display:inline;">
              <input type="hidden" name="_method" value="delete">
              <button onclick="return confirm('Sure?')">Delete</button>
            </form>
          </td>
        </tr>
      <% }); %>
    </table>
  <% } %>

  <p><a href="/users/new">Add New User</a></p>
</body>
</html>

// views/users/form.ejs
<!DOCTYPE html>
<html>
<head>
  <title><%= user ? 'Edit' : 'Create' %> User</title>
</head>
<body>
  <h1><%= user ? 'Edit' : 'Create' %> User</h1>

  <% if (error) { %>
    <div style="color: red;">
      <strong>Error:</strong> <%= error %>
    </div>
  <% } %>

  <form method="post" action="<%= user ? '/users/' + user.id + '?_method=put' : '/users' %>">
    <div>
      <label>Email:</label>
      <input type="email" name="email" value="<%= user?.email || '' %>" required>
    </div>

    <div>
      <label>Name:</label>
      <input type="text" name="name" value="<%= user?.name || '' %>" required>
    </div>

    <% if (!user) { %>
      <div>
        <label>Password:</label>
        <input type="password" name="password" required>
      </div>
    <% } %>

    <button type="submit"><%= user ? 'Update' : 'Create' %></button>
    <a href="/users">Cancel</a>
  </form>
</body>
</html>

// ============================================
// MAIN APP
// ============================================
// app.js
const express = require('express');
const methodOverride = require('method-override');
const userRoutes = require('./routes/users');

const app = express();

// Middleware
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.set('view engine', 'ejs');

// Routes
app.use('/users', userRoutes);

// Error handler
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).render('error', { error: err.message });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});
```

---

## 🌍 Real World Examples

### Example 1: Ruby on Rails (Classic MVC)

```
Rails follows MVC strictly:

Model:
- app/models/user.rb
- Active Record ORM
- Validations, associations

Controller:
- app/controllers/users_controller.rb
- RESTful actions: index, show, new, create, edit, update, destroy

View:
- app/views/users/index.html.erb
- app/views/users/show.html.erb
- app/views/users/form.html.erb

Routes:
- config/routes.rb
- resources :users (generates all routes)

Result:
- Very productive framework
- Rapid development
- Clear structure
```

### Example 2: Django (Python MVC)

```
Django Framework:

Model:
- models.py - Define data structures
- Django ORM
- Automatic admin interface

View (Template in MVC):
- templates/ - HTML files
- Template language: Django Templates
- Template tags, filters

View (Logic in MVC called View):
- views.py - Handle requests/responses
- Class-based views or function-based views

URLs:
- urls.py - URL routing

Example Flow:
URL: /users/5/
 ↓
urls.py: path('users/<int:id>/', views.user_detail)
 ↓
views.py: def user_detail(request, id):
            user = User.objects.get(id=id)
            return render(request, 'user/detail.html', {'user': user})
 ↓
templates/user/detail.html:
  <h1>{{ user.name }}</h1>
  <p>{{ user.email }}</p>
```

### Example 3: Laravel (PHP MVC)

```
Laravel Framework:

Model:
- app/Models/User.php
- Eloquent ORM
- Relationships, validation

Controller:
- app/Http/Controllers/UserController.php
- Resource controller (CRUD)
- Dependency injection

Route:
- routes/web.php
- Route::resource('users', UserController)
- Automatic routes

View:
- resources/views/users/
- Blade template engine
- {{ }} for echoing variables
- @if, @foreach, etc.

Controller Example:
public function show($id)
{
    $user = User::find($id);
    return view('users.show', ['user' => $user]);
}

View Template:
<h1>{{ $user->name }}</h1>
<p>{{ $user->email }}</p>
```

---

## 🛡️ Best Practices

### 1. Fat Model, Skinny Controller

```javascript
// ✅ GOOD: Business logic in model
class User {
  isValidEmail() {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email);
  }

  async save() {
    if (!this.isValidEmail()) {
      throw new Error('Invalid email');
    }
    // Save logic
  }
}

// In Controller - just call model
async create(req, res) {
  try {
    const user = new User(req.body);
    await user.save();
    res.redirect('/users/' + user.id);
  } catch (error) {
    res.render('form', { error });
  }
}

// ❌ BAD: Business logic in controller
async create(req, res) {
  if (!req.body.email.includes('@')) {
    return res.render('form', { error: 'Invalid email' });
  }
  // ... more validation
  const user = new User(req.body);
  await db.query('INSERT INTO...');
}
```

### 2. Use Services for Complex Logic

```javascript
// ✅ GOOD: Extract to service layer
class UserService {
  async createUserWithEmail(userData) {
    // Complex logic
    const user = new User(userData);
    await user.save();

    // Send email
    await emailService.sendWelcome(user);

    // Log to analytics
    await analyticsService.log('user.created', user.id);

    return user;
  }
}

// Controller is thin
async create(req, res) {
  const user = await userService.createUserWithEmail(req.body);
  res.redirect('/users/' + user.id);
}
```

### 3. Keep Views Simple

```html
<!-- ✅ GOOD: Only display logic in view -->
<% if (user) { %>
<h1><%= user.name %></h1>
<p><%= user.email %></p>
<% } %>

<!-- ❌ BAD: Business logic in view -->
<% if (user.accountBalance > 1000 && user.membershipLevel === 'gold' &&
user.lastPurchaseDate > Date.now() - 30*24*60*60*1000) { // Complex business
logic in template } %>
```

### 4. Validation in Multiple Layers

```javascript
// ✅ GOOD: Validate at all levels

// Client-side
<input type="email" required>

// Route middleware
router.post('/users', validateInput, controller.create);

// Model
class User {
  validate() {
    if (!this.email.includes('@')) throw new Error('Invalid email');
  }
}

// Database
CREATE TABLE users (
  email VARCHAR(100) UNIQUE NOT NULL,
  CHECK (email LIKE '%@%')
);
```

### 5. Use Authentication Middleware

```javascript
// ✅ GOOD: Protect routes with middleware
const auth = require("./middleware/auth");

router.get("/:id/edit", auth, UserController.edit);
router.put("/:id", auth, UserController.update);

// Middleware
async function auth(req, res, next) {
  const token = req.cookies.token;
  if (!token) {
    return res.redirect("/login");
  }

  const user = jwt.verify(token, process.env.JWT_SECRET);
  req.user = user;
  next();
}
```

### 6. Use Response Objects

```javascript
// ✅ GOOD: Consistent response handling
class Response {
  static success(data, message = "Success") {
    return { success: true, data, message };
  }

  static error(error, statusCode = 400) {
    return { success: false, error, statusCode };
  }
}

// In controller
res.json(Response.success(user, "User created"));
```

---

## 📊 MVC Variants

### MVP (Model-View-Presenter)

```
Similar to MVC but:
- Presenter (not Controller) handles all UI logic
- View is passive (just displays)
- Model is unchanged

Use case: Desktop applications (WinForms, WPF)
```

### MVVM (Model-View-ViewModel)

```
Used in:
- WPF (Windows Presentation Foundation)
- Xamarin
- Angular applications

Features:
- Two-way data binding
- ViewModel bridges Model and View
- Automatic sync between View and ViewModel
```

---

## ✅ ตรวจสอบความเข้าใจ

**คำถามตัวเอง:**

1. ✓ MVC คืออะไร? โครงสร้าง 3 ส่วน?
2. ✓ Model หน้าที่อะไร?
3. ✓ View หน้าที่อะไร?
4. ✓ Controller หน้าที่อะไร?
5. ✓ Request flow ผ่าน MVC อย่างไร?
6. ✓ Fat Model, Skinny Controller คืออะไร?
7. ✓ เมื่อไดควรใช้ MVC?

---

## 📚 สรุป

### Key Takeaways

```
✅ MVC = Separation of concerns
✅ Simple, clear, proven pattern
✅ Good for web applications
✅ Easy to test
✅ Quick to develop
✅ Wide adoption
❌ Can become monolithic
❌ Limited scaling
❌ Not for real-time applications
```

### เมื่อใดควรเลือก MVC

```
✅ USE IF:
- Traditional web applications
- Server-side rendering
- Small-medium projects
- HTML-based UI
- Fast prototyping
- Learning/teaching
- Team familiar with MVC

❌ DON'T USE IF:
- Single Page Applications (SPAs)
- Microservices architecture
- Real-time applications
- Distributed systems
- GraphQL needed
- Multiple client types
```

---
