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/