0
0
Lập trình
Hưng Nguyễn Xuân 1
Hưng Nguyễn Xuân 1xuanhungptithcm

So sánh MVC và MVVM: Hiểu rõ sự khác biệt

Đăng vào 6 tháng trước

• 6 phút đọc

So sánh MVC và MVVM: Hiểu rõ sự khác biệt

Nhiều lập trình viên thấy MVC dễ hiểu nhưng MVVM lại khó khăn hơn, tuy nhiên lại có ý kiến cho rằng MVVM vượt trội hơn so với MVC. Một lý do chính cho sự khác biệt này là các chữ cái viết tắt MVC và MVVM mô tả vai trò, không phải thứ tự (hoặc pipeline) của đầu vào và cập nhật.

Mô hình Tư duy Thay thế: ICMV và IVVMM

MVC (vai trò vs luồng)

  • Vai trò (tên): Model – View – Controller
  • Luồng thực tế: Nhập liệu → Controller → Model → View
  • Thay vì nghĩ đến MVC, hãy coi đây là ICMV cho thứ tự luồng.

MVVM (vai trò vs luồng)

  • Vai trò (tên): Model – View – ViewModel
  • Luồng thực tế: Nhập liệu → View ↔ ViewModel ↔ Model
  • Các luồng ↔ được quản lý tự động với "data binding"
  • Thay vì MVVM, hãy coi đây là IVVMM.

Để giải quyết sự không khớp giữa tên gọi MVC/MVVM và thứ tự luồng dữ liệu, việc nghĩ về chúng như là ICMVIVVMM có thể giúp ích rất nhiều.

Ví dụ tối thiểu về MVC

Controller cập nhật mô hình, sau đó đẩy dữ liệu đến view.

csharp Copy
// Mô hình
public class Person { public string Name { get; set; } }

// View
public class PersonView
{
    public void Show(string name) => Console.WriteLine($"Tên: {name}");
}

// Controller
public class PersonController
{
    private readonly Person _model;
    private readonly PersonView _view;

    public PersonController(Person model, PersonView view)
    {
        _model = model;
        _view = view;
    }

    public void SetName(string name) => _model.Name = name;
    public void UpdateView() => _view.Show(_model.Name);
}

// Sử dụng
class Program
{
    static void Main()
    {
        var model = new Person();
        var view = new PersonView();
        var controller = new PersonController(model, view);

        controller.SetName("Alice");
        controller.UpdateView();  // Xuất ra: Tên: Alice
    }
}

Lưu ý: Controller điều phối; view là thụ động.

Ví dụ tối thiểu về MVVM (sử dụng Microsoft WPF)

View ràng buộc vào các thuộc tính trên ViewModel; sự thay đổi được truyền qua INotifyPropertyChanged.

ViewModel + Mô hình (C#)

csharp Copy
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class Person { public string Name { get; set; } = ""; }

public class PersonViewModel : INotifyPropertyChanged
{
    private readonly Person _model;
    private string _name;

    public PersonViewModel(Person model)
    {
        _model = model;
        _name = model.Name;
    }

    public string Name
    {
        get => _name;
        set
        {
            if (_name == value) return;
            _name = value;
            _model.Name = value;      // giữ cho mô hình đồng bộ
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string p = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
}

View (XAML)

xml Copy
<Window x:Class="Demo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MVVM Demo" Height="120" Width="280">
  <StackPanel Margin="12">
    <TextBlock Text="Tên:" Margin="0,0,0,6"/>
    <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
    <TextBlock Text="{Binding Name}" Margin="0,8,0,0"/>
  </StackPanel>
</Window>

Code-Behind của Window (Thiết lập DataContext)

csharp Copy
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new PersonViewModel(new Person { Name = "Alice" });
    }
}

Lưu ý: View gắn bó với Name. Nhập liệu cập nhật ViewModel (và mô hình). Khi ViewModel nâng PropertyChanged, giao diện tự động làm mới. Không cần gọi controller một cách rõ ràng.

Những điều cần lưu ý

  • MVC: Controller điều khiển thứ tự; View cập nhật cuối cùng.
  • MVVM: Binding giữ cho View và ViewModel đồng bộ; thay đổi chảy theo cả hai hướng.

Các chữ cái viết tắt mô tả các phần, không phải thứ tự. Nghĩ về chúng như là ICMV so với IVVMM làm rõ luồng thực thi.

Tại sao chọn MVVM?

Lợi ích chính so với MVC

1. Kiểm thử độc lập logic

Trong MVC, logic thường nằm trong controller và gắn bó với vòng đời của view. Trong MVVM, ViewModel bao gồm các lớp tiêu chuẩn thực hiện các thuộc tính và lệnh, cho phép kiểm thử đơn vị mà không cần phụ thuộc vào framework giao diện người dùng.

2. Tách biệt rõ ràng các mối quan tâm

  • MVC: Controller quyết định cái gì được hiển thị, thường với các cuộc gọi view trực tiếp, làm rối rắm UI và luồng điều khiển.
  • MVVM: View chỉ xử lý hình ảnh; ViewModel cung cấp dữ liệu và hành động; Model chứa dữ liệu nguyên chất.

3. Binding dữ liệu khai báo

Sự thay đổi trong ViewModel tự động cập nhật View, và ngược lại. Điều này giảm thiểu các thao tác thủ công như "đẩy giá trị này vào textbox" hoặc "đọc textbox này trở lại mô hình".

4. Tái sử dụng ViewModels (cho các tình huống đa nền tảng)

Bạn có thể gắn bó cùng một ViewModel với các view khác nhau (ứng dụng desktop, ứng dụng di động, bộ kiểm tra). Trong MVC, các controller khó tái sử dụng do sự gắn bó chặt chẽ với view của chúng. Lợi thế này chỉ có giá trị khi bạn thực sự xây dựng cho nhiều nền tảng.

5. Giảm thiểu mã dư thừa cho đồng bộ trạng thái

Trong MVC, bạn liên tục viết mã để đồng bộ mô hình ↔ view. Trong MVVM, binding tự động xử lý điều này, giảm thiểu mã kết dính.

Các yếu tố cân nhắc

Nhược điểm

  • Đường cong học tập dốc hơn: Hệ thống binding có thể cảm thấy "vô hình" so với mã controller rõ ràng.
  • Phức tạp trong việc gỡ lỗi: Các lỗi trong binding hoặc sự kiện PropertyChanged khó theo dõi hơn.

Vì những lý do này, MVVM có thể trở nên quá mức cho các dự án nhỏ. Đối với các ứng dụng đơn giản, MVC có thể dễ hiểu hơn.

Tóm tắt

  • MVC: Hiệu quả cho các ứng dụng phía máy chủ và các tình huống yêu cầu luồng điều khiển rõ ràng, nhưng có thể tạo ra sự gắn bó chặt chẽ và thách thức trong việc kiểm thử.
  • MVVM: Có giá trị cho các giao diện người dùng dựa trên dữ liệu cho desktop/mobile với các framework binding mạnh mẽ, nhưng tăng thêm độ phức tạp và có thể làm giảm hiệu suất.
  • Ngữ cảnh quan trọng: Chọn dựa trên nền tảng, chuyên môn của đội ngũ, độ phức tạp của ứng dụng và yêu cầu về hiệu suất thay vì chỉ theo các khuyến nghị chung.

Ghi chú: Các framework hiện đại thường triển khai các phương pháp lai kết hợp các yếu tố của nhiều mẫu. Các ví dụ được trình bày ở đây chủ yếu đại diện cho các triển khai truyền thống trong ngữ cảnh .NET/C#.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào