Tạo mẫu đối tượng trong đường ray

Tram Ho

1.Mở đầu

Form object là một object dùng để quản lý độ phức tạp của các tác vụ thay đổi dữ liệu vượt quá các chức năng CRUD cơ bản. Thông thường, các tác vụ CRUD cơ bản như thêm user, sửa user, hay xóa user cần số lượng dòng code rất ít nên ta có thể đặt ở controller. Tuy nhiên, độ phức tạp sẽ phát sinh khi chức năng tạo một user còn yêu cầu tạo thêm một organization để thêm user đó vào, hoặc đối với ứng dụng e-commerce, nếu user mua một sản phẩm thì một order và một payment transaction phải được tạo ra cùng một lúc. Vì business logic phưc tạp nên số dòng code cũng như các đối tượng được tạo ra sẽ rất lớn và sẽ đẫn đến tình trạng “fat controller”. Và một “fat controller” sẽ rất khó để kiểm thử cũng như bảo trì, logic phức tạp thì sẽ dẫn đến ta phải viết nhiều test case, nhưng thường thì controller còn yêu cầu cả authentication và authorization, vậy nên khi test ta còn cần phải tạo thêm dữ liệu để pass authentication và authorization cho các test case kia, việc này là dư thừa và có thể làm chậm quá trình chạy test

Một nhược điểm khác là các logic nghiệp vụ sẽ không tái sử dụng được ở nơi khác vì nó đã được cố định tại một endpoint. Mặc dù ta có thể tách code logic ra và đưa vào các module concerns tuy nhiên nó vẫn phức tạp hơn sơ với việc sử dụng form object và về cơ bản, việc đưa logic của một class vào trong một đối tượng khác sẽ vi phạm một trong các nguyên tắc của OOP: single responsibility (S trong SOLID). Việc đưa toàn bộ logic vào một class riêng sẽ dễ dàng để tái sử dụng, test và bảo trì hơn.

2.Khi nào sử dụng form-object

Nhiều hơn một resource bị ảnh hưởng

Đây là trường hợp thường gặp nhất, theo convention các controllers và model trong rails là single resource-based. Vì vậy, khi logic nghiệp vụ yêu cầu khởi tạo hoặc sửa, xóa nhiều resource khác, thì lúc này ta nên gom các logic này vào cùng một chỗ để dễ quản lý, cách tốt nhất là sử dụng form object.

Kết hợp validation cho nhiều resource

Thông thường chũng ta thường định nghĩa các validation bên trong các active-record model. vd:

Nhưng không chỉ vậy, có một số model không phải active record cũng có thể có validation khi được khởi tạo, giả sử có một class Search, ta cần phải validate presence: true cho thuộc tính search_params, tuy nhiên không phải là một active record model nên nếu thực hiện theo cách thông thường thì phải tự implement, và việc gán thông báo lỗi cho thuộc tính search_params cũng bị hạn chế, chỉ có thể hiển thị ngoài giao diện dưới dạng flash message

Validation có ở khắp nơi trong ứng dụng của chúng ta, nhưng làm sao để xử lý validation cho nhiều model cùng lúc, nếu chỉ có một số validation chỉ cần thiết cho một số trường hợp cụt thể thì việc đặt nó bên trong model thực sự không cần thiết và việc viết test cho các validation này đôi lúc cũng gặp nhiều khó khăn.

3.Cách sử dụng form object

Cấu trúc thư mục

Form object sẽ được đặt bên trong thư mục app

Và class được đặt tên với hậ tố là _form

Tạo một class form

Tạo một class với các thuộc tính bắt buộc

Class trên so với một class ruby thuong thường thì không có sự khác biệt

Sử dụng ActiveModel::Model.

Tiếp theo, incluide module ActiveModel::Model để có thể sử dụng các phương thức có trong active model

nhờ vậy, bây giờ ta có thể sử dụng các phương thức validations methods tương tự như active record model

hoặc có thể validate với validation mà mình tự định nghĩa

Và bây giờ ta có thể lấy được thông tin error tương tự như làm với active record model, nhờ phương thức valid?

Tùy chỉnh các phương thức CRUD

Các phương thức CRUD của form object nên đi theo convention của active record object, như save , update hoặc create (hoặc save!, update! hoặc create! khi cần bắn ra exception) để sử dụng tương tự như một active record object

và ở controller ta chỉ việc implement tương tự active record object như sau

Sử dụng transaction

Vì form object sử dụng để quản lý sự ảnh hưởng của nhiều resource, việc sử dụng transaction là vô cùng cần thiết để bảo đảm tính toàn vẹn cho dữ liệu khi việc cập nhật dữ liệu của một resource nào đó bị lỗi

Kết

Form Object có thể giúp giảm thiểu một số vấn đề khác nhau khi thực hiện các dự án Rails và do đó, nó có thể chứng minh là một công cụ hữu ích cho chúng ta, ngoài ra hiện tại cũng có một gem có thể giúp ta dễ dàng áp dụng form object vào dự án là reform

Nguồn: https://nimblehq.co/blog/lets-play-design-patterns-form-objects

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo