Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Kết nối Rails App với Redis: Pattern đã chứng minh cho truy cập dữ liệu hiệu quả

Khi viết Rails app, bạn có thể gặp vấn đề giải quyết dễ hơn với data store khác. Ví dụ, bạn có leaderboard xếp hạng user theo điểm trả lời câu hỏi. Với Redis Sorted Sets, nhiều implementation đã làm sẵn. Tuyệt! Nhưng bạn đặt code tương tác Redis ở đâu?

Model User có thể nói chuyện với Redis:

class User < ActiveRecord::Base def award_points(points) Redis.current.zincrby("leaderboard", points, id) end end 

Nhưng giờ model User giữ trách nhiệm represent user, nói chuyện với Redis, và quản lý leaderboard! Điều này làm User khó hiểu và khó test hơn, ngược lại điều bạn muốn.

Thay vào đó, bạn có thể wrap Redis request trong object mới đại diện cho việc bạn dùng Redis cho gì. Ví dụ, bạn có thể tạo class Leaderboard wrap Redis communication, không inherit từ ActiveRecord::Base, nhưng vẫn sống trong thư mục app/models. Trông như sau:

app/models/leaderboard.rb
class Leaderboard def award_points_to_user(user_id, points) Redis.current.zincrby("leaderboard", points, user_id) end end 
app/models/user.rb
class User < ActiveRecord::Base def award_points(leaderboard, points) leaderboard.award_points_to_user(id, points) end end 

Cả hai class có thể sống trong app/models, nhưng giờ bạn không làm ô nhiễm ActiveRecord model với logic thêm. Class Leaderboard quản lý giao tiếp Redis, nên class User không còn quan tâm leaderboard implement như thế nào. Điều này cũng làm test dễ dàng hơn.

Bạn có nhiều lợi ích khi tạo class mới cho trách nhiệm mới, và app/models là nơi tuyệt vời giữ chúng. Bạn nhận lợi ích nhờ service khác cho implementation feature, đồng thời giữ code dễ làm việc.

Thử ngay

Bạn có nghĩ ra network service communication nào được gọi trực tiếp từ ActiveRecord model, controller, hoặc view? Hãy thử chuyển code đó vào non-ActiveRecord data model, và xem code có dễ hiểu, dễ làm việc, dễ test hơn không. Sau đó, email cho tôi biết kết quả!

Chỉ nhớ:

Tất cả vấn đề trong khoa học máy tính có thể giải quyết bằng thêm một level of indirection.

— David Wheeler

…trừ vấn đề quá nhiều layer of indirection.

— Kevlin Henney