The Basics of MVC in Rails: Skinny Everything
Model-View-Controller (MVC) là một mẫu thiết kế (design pattern) cho cấu trúc hệ thống của phần mềm. Thiết kế MVC tách biệt xử lý logic của ứng dụng và giao diện người dùng. MVC là viết tắt cho Model, View và Controller, là ba thành phần chính của cấu trúc ứng dụng web MVC. Mỗi một thành phần đó có ...
Model-View-Controller (MVC) là một mẫu thiết kế (design pattern) cho cấu trúc hệ thống của phần mềm. Thiết kế MVC tách biệt xử lý logic của ứng dụng và giao diện người dùng. MVC là viết tắt cho Model, View và Controller, là ba thành phần chính của cấu trúc ứng dụng web MVC. Mỗi một thành phần đó có vai trò vận hành như một đơn vị riêng biệt. Sự riêng biệt của các thành phần MVC là sự quan trọng trong việc bảo trì và kiểm thử ứng dụng. Chúng ta có thể thường nghe cách tốt nhất để viết code sạch và ngắn gọn trong Rails là theo cách tiếp cận là "Fat Models và Skinny Controller" hay làm models trở nên cồng kềnh còn controllers thì đơn giản ngắn gọn, và cách này cũng đề cập tới việc làm thế nào để Model và Controller trong một kiến trúc MVC trở nên lý tưởng để làm việc với nhau. Làm cho Controller đơn giản "skinny" hay có nghĩa là tất cả xử lý logic không quan trọng được đưa vào Model, nó sẽ làm đơn giản hơn cho testing và bảo trì. Tuy nhưng, chúng tôi đưa ra gợi ý về cách đưa chúng trở nên "skynny" tới một tầm cao hơn nữa: làm cho Models và Controller trở nên đơn giản. Thường thì chúng ta sẽ tập trung vào Models và Controllers, nhưng View sẽ có gì thay đổi? View cũng có có thể trở nên phức tạp, và chúng ta tin rằng View cũng có thể trở nên đơn giản.
Chức năng của mỗi thành phần trong kiến trúc MVC
Để có thể hiểu chính xác tại sao chúng ta nên giữ các thành phần MVC đơn giản, chúng ta cần phải làm rõ vai trò của mỗi thành phần là gì.
Models
Models là một tầng xử lý nằm giữa database và một chương trình, phần sẽ chứa xử lý logic liên quan đến một thực thể xác định. Mỗi Model là một mô tả cho một thực thể riêng biệt và sự liên kết thực thể đó với thực thể khác. Models thường được gọi tới bởi Controllers. Ví dụ như trường hợp một người dùng muốn đăng ký tài khoản mới. Người dùng phải nhập thông tin bao gồm email, tên đăng nhập username và một mật khẩu. Tất cả những dữ liệu thuộc tính đó được nhận bởi Controller và Controller sẽ thử tạo một user mới (trong cấu trúc MVC, user này là một khái niệm như một bản ghi Model). Model sẽ kiểm tra dữ liệu là hợp lệ hay không: email có đúng format hay mật khẩu có đủ bảo mật, hay email và tên đăng nhập đã tồn tại trước đó hay chưa. Nếu kiểm tra dữ liệu là hợp lệ, Model đó sẽ lưu dữ liệu lại vào database và hàm callback after_save được mặc định gọi đến sau khi lưu thành công. Một ví dụ của một callback là gửi email thông báo việc đăng ký thành công tới người dùng đăng ký. Ngược lại nếu kiểm tra dữ liệu là không hợp lệ, Model đó sẽ trả về một đối tượng thông báo lỗi, và đối tượng lỗi này có thể sử dụng để hiển thị thông báo cho người dùng biết thông tin đăng ký không hợp lệ và vì sao không hợp lệ.
Controllers
Controllers có nhiệm vụ để đọc dữ liệu vào (các requests), chọn hành động xử lý tương ứng và trả về dữ liệu kết quả. Ví dụ, một Controller nhận dữ liệu từ một client, và chọn hành động tương ứng thực hiện. Sau khi nhận dữ liệu (tham số parameters), Controller đó sẽ thực hiện các hành động theo sau:
- Xác thực Authentication: kiểm tra xem người dùng đã được đăng nhập chưa
- Ủy quyền Authorization: Controller kiểm tra người dùng có quyền thực hiện hành động đó hay không
- Lọc những dữ liệu được cho phép từ tất cả các tham số mà Controller nhận được
- Gọi các phương thức từ Models hoặc services
- Quyết định định dạng dữ liệu nào trả về lại cho client (JSON, HTML, PDF, XML) và chọn đúng View để hiển thị.
View
Một View là hình ảnh hóa cho một trạng thái đối tượng Model đi kèm. Đơn giản một View sẽ mô tả những gì mà người dùng sẽ được thấy. Nó là một thành phần duy nhất trong kiến chúc MVC mà người dùng tương tác trực tiếp. Ví dụ, một Controller chọn một bảng mẫu template để mô tả những gì mà người dùng đăng lên, hiển thị nó trong một layout cụ thể. View đó sẽ hiển thị thông tin người dùng và chứa vài phần tử HTML ví dụ như liên kết tới các bài đăng khác và một form để tạo một bài đăng mới.
Điều gì sẽ xảy ra nếu một thành phần MVC làm những việc của thành phần khác?
- Nó sẽ làm cho khó có thể bảo trì code trong trường hợp khi Controller chứa nhiều những phương thức mà không liên quan tới hành động actions.
- Kiểm thử testing sẽ là không thể, như viết Unit Tests có nghĩa kiểm tra classes và modules mà đảm nhiệm một chức năng cụ thể. Nó khó có thể kiểm tra một chuỗi các phương thức gọi trong "spaghetti code" (code rối bao gồm nhiều đối tượng và phương thức không được cấu trúc)
- Mỗi một lớp nên đảm nhiệm một vai trò riêng biệt trong toàn bộ chức năng mà phần mềm cùng cấp. Controller bắt đầu với những xử lý logic mà không thuộc về nó hay view có thể chứa những tính toán là thứ không được khuyến khích trong MVC.
Làm thế nào để làm các thành phần MVC trở nên "Skinny"?
Để khiến cho Models, Views, Controllers trở nên đơn giản và chuẩn hóa, chúng ta phải liên tục refactor hay tái cấu trúc trên code đã được viết. Trong quá trình tái cấu trúc sẽ không được thay đổi bất kỳ các phản hồi tương tác với bất kỳ hành động nào của người dùng cuối, việc làm đó sẽ giữ cho code dễ đọc, dễ bảo trì, dễ dàng để kiểm thử đem lại nhiều lợi ích cho lập trình viên Tái cấu trúc lại code được thực hiện dựa trên nhiều những quy ước, chúng ta có thể sử dụng một vài mẫu thiết kế hay design patterns bao gồm
- Service Objects (and Interactor Objects)
- Value Objects
- Form Objects
- Query Objects
- View Objects (Serializer/Presenter)
- Policy Objects
- Decorators Để có thể hiểu thêm về các mẫu thiết kế này, bạn có thể tham khảo tại bài viết 7 Design Patterns to Refactor MVC Components in Rails
Refs
The Basics of MVC in Rails: Skinny Everything