Một số nguyên tắc cần lưu ý khi lập trình Ruby on Rails
Trong bài viết này, mình xin giới thiệu các bạn một số nguyên tắc để áp dụng trong khi xây dựng ứng dụng web với Ruby on Rails. Khi mình xây dựng ứng dụng của mình tốt, nó sẽ mang những lợi như sau: Dễ dàng bảo trì (Maintainability) Dễ đọc (Readability) Elegance Phát triển nhanh hơn ...
Trong bài viết này, mình xin giới thiệu các bạn một số nguyên tắc để áp dụng trong khi xây dựng ứng dụng web với Ruby on Rails. Khi mình xây dựng ứng dụng của mình tốt, nó sẽ mang những lợi như sau:
- Dễ dàng bảo trì (Maintainability)
- Dễ đọc (Readability)
- Elegance
- Phát triển nhanh hơn (Faster development)
- DRY code
Đây là nguyên tắc viết rộng rãi nhất và thoả thuận trong cộng đồng Ruby. Hãy sử dụng 2 space indentation thay cho 4 space identation. 4 space indentation
def some_method some_var = true if some_var do_something else do_something_else end end
2 spaces indentation
def some_method some_var = true if some_var do_something else do_something_else end end
Các method nào mà trả về true hoặc false, theo convention tốt nhất trong Ruby nên viết dấu ? ở cuối với muc đích mang ý nghĩa dễ hiểu hơn. Đối với ngôn ngữ khác thì thường đặt tên như sau:
object.is_valid object.is_paid
Nhưng trong Ruby hãy viết:
object.is_valid? object.is_paid?
Đa số lập trình viên Ruby thương sử dụng each thay cho for trong vòng lặp vì nó sẽ làm cho code dể đọc, và dễ hiểu hơn.
for
for i in 1..100 ... end
each
(1..100).each do |i| ... end
Hãy sử dụng unless thay cho !if với các câu phù định. Không nên
if !true do_this end or if name != "sarmad" do_that end
Nên viết
unless true do_this end or unless name == "sarmad" do_that end
Nhưng nếu sử dụng với else thì đừng sử dụng unless ... else, hãy viết như sau: Không nên
unless user.save #throw error else #return success end
Nên viết
if user.save #return success else #throw error end
Khi lập trình, hãy đảm bảo rằng bạn không lặp lại chính mình, tránh sự trùng lặp nhiều nhất có thể. 1. Use Abstract classes: Trước khi DRY:
class Mercedes def accelerate "60MPH in 5 seconds" end def apply_brakes "stopped in 4 seconds" end def open_boot "opened" end def turn_headlights_on "turned on" end def turn_headlights_off "turned off" end end class Audi def accelerate "60MPH in 6.5 seconds" end def apply_brakes "stopped in 3.5 seconds" end def open_boot "opened" end def turn_headlights_on "turned on" end def turn_headlights_off "turned off" end end
Chúng ta thấy rằng có 3 methods trùng lặp open_boot, turn_headlights_on, and turn_headlights_off. Hãy viết lại như sau:
class Car def open_boot "opened" end def turn_headlights_on "turned on" end def turn_headlights_off "turned off" end end class Mercedes < Car def accelerate "60MPH in 5 seconds" end def apply_brakes "stopped in 4 seconds" end end class Audi < Car def accelerate "60MPH in 6.5 seconds" end def apply_brakes "stopped in 3.5 seconds" end end
2. Use Modules Chúng ta cũng có thể sử dụng Module để tránh sự trùng lặp, và để chia sẻ các trạng thái (Behavior) của module đó với các classes khác. Xem ví du sau:
class Newspaper def headline #code end def price #code end end class Book def title #code end def price #code end def total_pages #code end end
Nếu chúng ta muốn thêm một method print trong classes trên và không trùng lặp, hãy sử dụng module như sau:
module Printable def print #code end end
Trong class trên phải thêm include module đó là được:
class Newspaper include Printable ..... end class Book include Printable ..... end
Gia sử chúng ta có model Book mà có field muốn lưu trữ status là draft, completed hoặc published. Chúng ta có thể viết:
if book.status == "draft" do_something elsif book.status == "completed" do_something elsif book.status == "published" do_something end or if book.status == 0 #draft do_something elsif book.status == 1 #completed do_something elsif book.status == 2 #published do_something end
Cách viết trên thì chưa tốt lắm. Để dễ dàng và để code readable hơn, hãy sử dụng emum như sau: Trong model Book: enum status: { draft: 0, completed: 1, published: 2 } Chúng ta có thể viết ví dụ trên lại như sau:
if book.draft? do_something elsif book.completed? do_something elsif book.published? do_something end
Hãy nhớ một số nguyên tắc sau đây:
- Controllers nên chỉ thực hiện các queries đơn giản để gọi đến model. Đối với các queries hoặc logic phức tạp, hãy đưa chúng vào models. Controller nên chỉ dùng để handle các request và response.
- Các code mà không liên quan với response và request, hoặc liên quan trực tiếp với model nào đó, hãy đưa vào model.
- Việc sử lý logic hoặc queries phức tạp, và muốn dùng chung cho các model mà không muốn trùng lặp code, hãy đưa app/models/concerns directory.
- Để xử lý các thảo tác cũng như các logic phức tạp (không liên quan trực tiếp đến model nào đó) như: thảo tác: send sms or email, subscribe or push notifications, ...., hãy đưa chúng vào app/services/ directory.
Cách tốt nhất nên sử dụng I18n để xử lý các ngôn ngữ khác nhau trong ứng dụng web của bạn ngay từ khi bắt đầu project nào đó. Không nên:
<h1>Books Listing</h1> <table> <thead> <th>Name</th> <th>Author</th> </thead> <tbody> <td> Some book </td> <td> Some author </td> </tbody> </table
Nên viết:
<h1><%= t('.title') %></h1> <table> <thead> <th><%= t('.name') %></th> <th><%= t('.author') %></th> </thead> <tbody> <td> Some book </td> <td> Some author </td> </tbody> </table>
file .yml:
en: title: "Books Listing" name: "Name" author: "Author
Date.todayvà Time.now: sử dụng date và time của máy ứng đụng đang chạy. Còn Time.zone.now và Time.zone.today sử dụng timezone, date và time dựa vào cách config của bạn trong ứng dụng.
# config/application.rb: config.time_zone = ‘Eastern Time (US & Canada)'`.
View là sử dụng để hiển thị, không phải là để xử lý các logic. Vây, nên tách các logic ra khỏi view và đưa các logic đó vào trong helper hoặc sử dụng decorator. Không nên:
<% if book.published? && book.published_at > 1.weeks.ago %> <span>Recently added</span> <% end %>
Nên viết:
# Đưa logic kiểm tra vào helper module ApplicationHelper def recently_added?(book) book.published? && book.published_at > 1.weeks.ago end end # Và gọi trong view như sau <% if recently_added?(book) %> <span>Recently added</span> <% end %>
Đây là một số các nguyên tắc cơ bản cần nhớ và lưu ý khi lâp trình Ruby on Rails, và còn nhiều các nguyên tắc nữa, mình sẽ trinh bày trong bài tiếp theo. Mong rằng bài viết này sẽ giúp các bạn viết code một cách hiệu quả và tốt hơn.
References: http://rails-bestpractices.com/ https://www.sitepoint.com/10-ruby-on-rails-best-practices-3/