Daily Archives: 27/10/2016

Rails – Kiến trúc của Rails

Một trong những đặc điểm của Rails là bạn bị buộc phải viết chương trình theo một loạt các quy tắc nhất định, tức là bạn phải theo mô hình kiến trúc mà Rails đã đề ra, tuy nhiên những quy tắc này lại khiến việc phát triển ứng dụng trở nên dễ dàng hơn rất nhiều.

Mô hình MVC – Model, View, Controller

Mô hình MVC được Trygve Reenskaug đề ra vào năm 1979, mô hình này chia ứng dụng làm 3 phần: model, viewcontroller.

Trong đó model sẽ chịu trách nhiệm duy trì dữ liệu của ứng dụng. Đôi khi dữ liệu này chỉ tồn tại trong một thời gian ngắn, đôi khi lại được lưu trữ lâu dài trong cơ sở dữ liệu. Ở đây model không đơn thuần chỉ là dữ liệu, ứng dụng sẽ buộc phải chạy theo các quy tắc đã áp đặt lên dữ liệu đó. Chẳng hạn như chúng ta định nghĩa phiếu giảm giá cho các đơn hàng không lớn hơn 200.000đ, đó là một quy tắc và ứng dụng sẽ phải tuân thủ quy tắc đó. Và nhờ vào các quy tắc này mà dữ liệu của chúng ta không bị biến đổi một cách bất hợp lệ.

View sẽ chịu trách nhiệm tạo ra giao diện người dùng, và giao diện này sẽ dựa trên model. Ví dụ chúng ta có một website bán hàng, trên trang “Sản phẩm” chúng ta liệt kê danh sách các sản phẩm, vậy thì danh sách này sẽ lấy dữ liệu là hàng hóa được định nghĩa bởi model, view sẽ lấy dữ liệu từ model và chuyển đổi thành giao diện hiển thị lên cho người dùng. Công việc của view là chỉ có hiển thị chứ không xử lý bất kỳ thao tác nào của người dùng. Một model có thể được truy cập bởi nhiều view, chẳng hạn như website bán hàng có 2 trang là “Sản phẩm” và “Chỉnh sửa sản phẩm”, trang “Sản phẩm” sẽ truy cập model và lấy danh sách các sản phẩm rồi hiển thị cho người dùng, trong khi đó trang “Chỉnh sửa sản phẩm” cũng lấy danh sách các sản phẩm nhưng hiển thị cho người quản lý website.

Controller sẽ chịu trách nhiệm vận hành ứng dụng. Controller sẽ nhận các sự kiện từ bên ngoài, thông thường là từ người dùng, sau đó tương tác với model và gọi view tương ứng để hiển thị.

capture

Bộ ba Model, ControllerView hợp thành thành mô hình MVC. Mô hình MVC cho phép chúng ta tách ứng dụng thành các bộ phận riêng biệt, nhờ đó chúng ta có thể dễ dàng phát triển và bảo trì ứng dụng. Ruby on Rails cũng được phát triển theo mô hình MVC.

Bất cứ ứng dụng Rails nào cũng có 3 phần model, view và controller. Việc kết nối giữa 3 thành phần này đã được Rails giải quyết tự động rồi, do đó bạn chỉ cần quan tâm đến việc phát triển từng thành phần thôi.

Trong một ứng dụng Rails, một gói tin HTTP được gửi từ trình duyệt sẽ được chuyển tới các router trước tiên, đây là nơi vận chuyển các gói tin HTTP đến các phương thức nhất định (trong Rails thì phương thức hay hàm còn có tên khác là action). Phương thức đó sẽ đọc các dữ liệu có trong gói tin và có thể sẽ tương tác với model, hoặc gọi thêm các phương thức/action khác. Cuối cùng thì phương thức đầu tiên được gọi đó sẽ tính toán ra các dữ liệu khác rồi gửi cho một view nào đó để hiển thị cho người dùng.

Tính năng Object Relational Mapping

Thông thường chúng ta sẽ lưu dữ liệu trong một cơ sở dữ liệu quan hệ. Chẳng hạn như một hệ thống đặt hàng sẽ gồm có các bảng đơn hàng, sản phẩm, khách hàng

Tuy nhiên cơ sở dữ liệu quan hệ lại thường không mấy liên quan tới lập trình hướng đối tượng, chẳng hạn như trong SQL bạn có thể thực hiện các câu truy vấn để trích xuất các tập dữ liệu có liên quan với nhau rất dễ dàng, nhưng để làm việc này trong hướng đối tượng rất khó. Chẳng hạn việc tìm một tập các sản phẩm có giá < 2.000.000đ thuộc danh mục máy tính được đăng vào năm 2016 rất dễ trong SQL, nhưng lại rất khó trong code Ruby.

Chính vì vậy mà nhóm phát triển đã cho ra đời một tính năng hỗ trợ việc chuyển đối dữ liệu quan hệ sang các đối tượng một cách dễ dàng đó là tính năng Object Relational Mapping (ORM)

Các thư viện ORM sẽ làm công việc chuyển đổi các bảng trong CSDL sang các lớp. Ví dụ như trong CSDL có bảng Order (đơn hàng) thì ORM sẽ tạo một lớp có tên Order trong Ruby, các dòng trong bảng sẽ là các đối tượng của lớp đó, các thuộc tính của lớp sẽ tương ứng với các cột trong bảng. Ngoài ra ORM sẽ định nghĩa các phương thức để chúng ta có thể đọc ghi dữ liệu một cách dễ dàng. Ví dụ chúng ta sẽ có các đoạn code dạng như sau:

order = Order.find(1)
...
Order.where(:name => 'phocode').each do |order|
    order.payment = "Paypal"
    order.save
end

Active Record

Active Record là bộ phận thực hiện chức năng ORM trong Rails, bao gồm việc tạo lớp từ các bảng, tạo đối tượng từ các dòng trong bảng, tạo thuộc tính từ các cột. Dưới đây là đoạn code ví dụ:

require 'active_record'

class Order < ActiveRecord::Base
end

order = Order.find(1)
order.pay_type = "Paypal"
order.save

Trong ví dụ trên, lớp Order có phương thức find() dùng để tìm một đối tượng có id1, ngoài ra chúng ta còn có thể chỉnh sửa thuộc tính pay_type, đoạn code trên chỉ là ví dụ nhỏ, trên thực tế chúng ta còn phải làm nhiều thứ nữa.

Action Pack

Như chúng ta đã biết, controller sẽ gửi dữ liệu cho view, nhận và xử lý sự kiện từ view, do đó view và controller khá “thân thiết” với nhau. Chính vì vậy mà bộ phận xử lý controller và view được gộp lại làm một và được gọi là Action Pack. Bạn đừng hiểu lầm là chúng ta sẽ viết  code cho view và controller chung một chỗ, ở đây chẳng qua chỉ là chúng được vận hành bởi cùng một thứ mà thôi.

View

Trong Rails thì view có nhiệm vụ tạo ra các đoạn code HTML để hiển thị lên trình duyệt của người dùng, thông thường code HTML này có kèm theo dữ liệu được tạo ra từ các phương thức trong controller.

Các dữ liệu được tạo ra sẽ được tạo ra từ các template, bạn cứ hình dung đây giống như là một trình thông dịch nhỏ khác là được. Hiện có 3 loại template trong Rails là Embedded Ruby (ERb), XML Builder và RJS.

Trong đó ERb là phổ biến nhất, code ERb sẽ được nhúng chung với code HTML, nếu bạn đã từng làm việc với PHP hay JSP (Java) thì bạn sẽ thấy quen thuộc. Mặc dù code kiểu này rất linh hoạt nhưng đa phần người ta nghĩ rằng việc trộn chung công việc giữa các thành phần khác nhau là không nên.

Controller

Phần controller trong Rails là bộ phận trung tâm, có nhiệm vụ xử lý tương tác giữa người dùng, view và model. Tuy nhiên chúng ta sẽ chỉ tập trung vào việc phát triển các tính năng của website, còn việc kết nối giữa các thành phần này sẽ được Rails giải quyết, chúng ta không cần quan tâm.

Cơ bản thì controller hỗ trợ các tính năng sau:

  • Định tuyến (routing) các URL tới các phương thức/hàm/action tương ứng. Ngoài ra controller còn định nghĩa các URL có cấu trúc thân thiện, dễ nhìn
  • Quản lý cache, giúp tăng hiệu năng của hệ thống
  • Quản lý các module hỗ trợ, giúp mở rộng các tính năng của template
  • Quản lý session, giúp theo dõi các hoạt động đang diễn ra trên ứng dụng