Đầu tiên phân loại code trong model rồi mới chọn công cụ, vì ba lựa chọn giải quyết ba vấn đề khác nhau.
*1. Concern — gom theo khía cạnh dùng lại được. Dùng khi có nhóm hành vi cùng thuộc về bản ghi và lặp lại ở nhiều model: Archivable, Sluggable, Searchable. Concern không giảm độ phức tạp*, chỉ dời code sang file khác và vẫn dùng chung state của model. Gom một mớ method chỉ dùng ở Order vào OrderStuff là dời rác chứ không refactor.
*2. Service object — gom theo hành động nghiệp vụ.* Dùng cho luồng có nhiều bước, chạm nhiều model, có side effect: CheckoutOrder, RefundOrder, CancelOrder. Mỗi service một public method, nhận input rõ ràng, trả về kết quả thành công/thất bại.
*3. Plain Ruby object (không phải AR) — gom theo khái niệm bị thiếu.* Logic tính toán thuần (tính phí ship, áp mã giảm giá, quy tắc giá) tách thành class riêng, không cần DB, test cực nhanh:
class ShippingFee
def initialize(order) = @order = order
def amount = base + weight_surcharge - discount
endThứ tự nên làm: tách logic tính toán thuần ra POR O trước (dễ và an toàn nhất) → chuyển side effect và luồng nhiều bước sang service object → cuối cùng mới dùng concern cho phần hành vi thực sự dùng chung. Query phức tạp thì tách thành scope hoặc query object riêng.
Giữ lại trong model: association, validation, scope cơ bản, và các method mô tả trạng thái ngắn (paid?, refundable?).