The Basics of MVC in Rails: Skinny Everything

Model - View - Controller (MVC) là một design pattern để cấu trúc hệ thống phần mềm. MVC pattern phân tách logic ứng dụng từ giao diện người dùng (user interface). MVC: Model, View, Controller là 3 thành phần chính của kiến trúc ứng dụng web. Mỗi thành phần này nên hoạt động như các đơn vị rời rạc. Tính rời rạc của các thành phần trong MVC pattern là rất quan trọng đối với việc bảo trì và kiểm thử ứng dụng.

Chúng ta thường nghe nói rằng: Cách tiếp cận tốt nhất để viết code rõ ràng và ngắn gọn trong Rails là theo phương pháp Fat Models and Skinny Controllers, dùng để mô tả ModelController trong kiến trúc MVC nên làm việc với nhau như thế nào. Skinny Controller có nghĩa là tất cả những logic không quan trọng sẽ chuyển sang Model, điều này sẽ đơn giản hóa việc kiểm tra và bảo trì. Tuy nhiên, trên thực tế chúng ta cần Skinny cho tất cả 3 thành phần Model, View, Controller trong ứng dụng của bạn.

Chức năng của mỗi thành phần trong kiến trúc MVC là gì?

Để hiểu được rõ ràng lý do vì sao chúng ta cần Skinny tất cả các thành phần trong kiến trúc MVC, trước tiên cần làm rõ những gì mà mỗi thành phần này chịu trách nhiệm:

Model

Model là tầng (layer) nằm giữa database và ứng dụng, nó lưu trữ business logic liên quan đến một thực thể (entity) cụ thể. Mỗi Model chịu trách nhiệm cho một entity khác nhau, và để kết nối thực thể này với thực thể khác.

Ví dụ: Người dùng muốn đăng ký tài khoản trên một ứng dụng nào đó

  • Nhập email/username và password
  • Tất cả các thông tin này được nhận bởi Controller, nó sẽ cố gắng tạo ra một người dùng (user) mới (trong kiến trúc MVC, user này được khái niệm hóa với tên gọi là Model Record)
  • Validation: kiểm tra email nhập vào có đúng định dạng hay không, password có đủ an toàn không hay email đã tồn tại trong hê thống hay chưa
  • Nếu xác nhận các thông tin là hợp lệ, Model kiểm tra tồn tại dữ liệu trong database và một callback after_save được kích hoạt. (Ví dụ về callback: một email thông báo được gửi cho user đăng ký để xác nhận tài khoản)
  • Nếu xác nhận thất bại, Model trả về một đối tượng lỗi, có thể được render và hiển thị cho user

Controller

Controller chịu trách nhiệm cho việc đọc dữ liệu đầu vào (input data) - requests, lựa chọn action phù hợp (business action), và trả về kết quả dữ liệu đầu ra (output data) - response

Ví dụ: Controller nhận data từ client, và định hướng lựa chọn action phù hợp đang tồn tại trong Controller. Trên cơ sở các tham số nhận được, Controller thực hiện các action sau:

  • Authentication - xác thực: Controller kiểm tra nếu user đã login và hệ thống và đang làm việc tại thời điểm hiện tại của ứng dụng
  • Authorization - cấp quyền: Controller kiểm tra user được phép thực hiện những action nào
  • Filtration: Lọc các tham số đầu vào (permitted_attributes)
  • Gọi các methods trong Models hoặc Services
  • Xác định format trả về cho client (JSON, HTML, PDF, XML) và chọn View tương ứng

View

Viewhình ảnh hóa của trạng thái Model được đính kèm

Ví dụ: Controller lựa chọn template để đại diên cho user post và insert nó vào bố cục thích hợp. View hiển thị các thông tin của người dùng và chứa các phần tử html (html elements), như là link đến bài post, và form để tạo mới bài post

Điều gì sẽ xảy ra nếu một trong các thành phần của kiến trúc MVC không làm việc?

  • Điều này sẽ trở nên khó khăn trong việc bảo trì code, trường hợp controller có chứa lượng lớn các methods mà nó thực thi các action không liên quan.
  • Việc kiểm thử cũng hầu như không thể, Unit test có nghĩa là testing các classes và modules đảm nhiệm các chức năng cụ thể. Điều này là rất khó để theo dõi lời gọi các phương thức trong spaghetti code (code rối bao gồm nhiều object và methods khó, không có cấu trúc).
  • Mỗi class nên chịu trách nhiệm duy nhất về một phần của toàn bộ chức năng được cung cấp bới phần mềm. Tuy nhiên, thường thì Controller cũng bao gồm cả business logic mà nó không thuộc về hoặc thậm chí logic trong View. Model có thể bao gồm logic không liên quan, và View cũng có thể chứa các tính toán bên trong.

=> Nguyên tắc chính ta cần tuân theo để tránh Fat MVC : "Everyone should mind their own business."

Vậy làm thế nào để "Skinny MVC"?

Không còn cách nào khác, chúng ta cần refactor code liên tục (refactor là quá trình là cơ cấu lại code hiện có). Mặc dù việc sắp xếp lại code không làm thay đổi bất kỳ điều gì cho người dùng cuối (end user), tuy nhiên nó giúp giữ cho code luôn rõ ràng, sạch sẽ, dễ bảo trì và dễ kiểm thử, điều này hoàn toàn có lợi cho các nhà phát triển.

Chúng ta có thể sử dụng đa dạng design pattern để hỗ trợ chúng ta trong quá trình refactor:

  • Service Objects (and Interactor Objects)
  • Value Objects
  • Form Objects
  • Query Objects
  • View Objects (Serializer/Presenter)
  • Policy Objects
  • Decorators

Tài liệu tham khảo

https://www.sitepoint.com/the-basics-of-mvc-in-rails-skinny-everything/