12/08/2018, 14:35

10 lỗi hay gặp nhất của Rails Developers

Ruby on Rails ("Rails") là một framework mã nguồn mở phổ biến, dựa trên ngôn ngữ lập trình Ruby mà cố gắng đơn giản hóa và tinh giản quá trình phát triển ứng dụng web. Rails được xây dựng trên nguyên tắc quy ước về cấu hình. Đơn giản chỉ cần đặt, điều này có nghĩa rằng, theo mặc định, Rails giả ...

Ruby on Rails ("Rails") là một framework mã nguồn mở phổ biến, dựa trên ngôn ngữ lập trình Ruby mà cố gắng đơn giản hóa và tinh giản quá trình phát triển ứng dụng web. Rails được xây dựng trên nguyên tắc quy ước về cấu hình. Đơn giản chỉ cần đặt, điều này có nghĩa rằng, theo mặc định, Rails giả định các nhà phát triển chuyên môn của mình sẽ làm theo "tiêu chuẩn" qui ước thực hành tốt nhất (cho những thứ như đặt tên, cấu trúc mã, vv), và nếu bạn làm, mọi thứ sẽ làm việc cho bạn "tự động một cách thần kỳ "mà bạn không cần phải xác định những chi tiết này. Trong khi model này có ưu điểm của nó nhưng cũng không phải không có những cạm bẫy của nó. Đáng chú ý nhất, những "điểu thần kỳ" xảy ra đằng sau cảnh tượng trong khuôn khổ đôi khi có thể dẫn đến bứt phá giả, nhầm lẫn, và "cái quái gì đang xảy ra?" các loại của các vấn đề. Nó cũng có thể có những tác động không mong muốn đối với an ninh và năng suất.

Theo đó, trong khi Rails là dễ sử dụng, nó cũng không khó để sử dụng sai. Nhưng bài viết này nhìn vào 10 vấn đề phổ biến của Rails, bao gồm cả làm thế nào để tránh chúng và những vấn đề mà chúng gây ra.

Sai lầm phổ biến 1: Đưa quá nhiều logic trong controller

Rails được dựa trên kiến ​​trúc MVC. Trong cộng đồng Rails, chúng tôi đã nói về fat model, skinny controller một thời bây giờ, nhưng nhiều ứng dụng Rails gần đây tôi kế thừa đã vi phạm nguyên tắc này. Đó là tất cả quá dễ dàng để di chuyển view logic(mà tốt hơn là được đặt trong một helper), hoặc tên miền / model logic, vào controller.

Vấn đề là đối tượng điều khiển sẽ bắt đầu vi phạm các single responsibility principle làm cho tương lai trở nên khó khăn cơ sở mã hóa và dễ bị lỗi. Nói chung, các loại chỉ logic bạn nên có trong controller của bạn là:

  • Session và cookie handling. Điều này cũng có thể bao gồm xác thực / uỷ quyền hoặc bất kỳ quá trình cookie bổ sung nào mà bạn cần phải làm.

  • Lựa chọn model: Logic cho việc tìm kiếm các đối tượng model phù hợp cho các thông số thông qua trong từ yêu cầu. Theo lý tưởng này nên tìm đến một phương pháp đơn lẻ thiết lập một biến dụ được sử dụng sau này để hoàn lại lại đáp trả.

  • Quản lý parameter request: Thu thập các parameter request và tìm một model thích hợp để duy trì chúng.

  • Hoàn trả / chuyển hướng: Hoàn trả kết quả (html, xml, json, vv) hoặc chuyển hướng, phù hợp.

Trong khi điều này vẫn đẩy các giới hạn của single responsibility principle, đó là sắp xếp của mức tối thiểu mà các khuôn khổ Rails đòi hỏi chúng ta phải có trong controller.

Sai lầm phổ biến 2: Đưa quá nhiều logic vào View

Phương pháp mẫu out-of-the-box Rails, ERB, là một cách tuyệt vời để xây dựng các trang web có nội dung đa dạng. Tuy nhiên, nếu bạn không cẩn thận, bạn có thể sớm kết thúc với một tập tin lớn là kết hợp của mã HTML và mã Ruby có thể là khó khăn để quản lý và duy trì. Đây cũng là một khu vực mà có thể dẫn đến rất nhiều sự lặp lại, dẫn đến vi phạm nguyên tắc DRY (không lặp lại chính mình).

Điều này có thể biểu hiện chính nó trong một số cách. Một là sử dụng quá nhiều điều kiện logic trong các view. Như một ví dụ đơn giản, hãy xem xét một trường hợp mà trong đó chúng tôi có một phương thức CURRENT_USER sẵn có mà trở về hiện đang đăng nhập người dùng. Thông thường, sẽ kết thúc được cấu trúc logic có điều kiện như thế này trong tập tin views:

<h3>
Welcome,
<% if current_user %>
<%= current_user.name %>
<% else %>
Guest
<% end %>
</h3>

Một cách tốt hơn để xử lý những điều như thế này là đảm bảo đối tượng được trả về bởi CURRENT_USER là luôn được set, cho dù ai đó đăng nhập hay không, và nó sẽ trả lời các phương thức sử dụng ở view một cách hợp lý (đôi khi được set là null). Ví dụ, bạn có thể xác định các helper CURRENT_USER trong app / controllers / application_controller như thế này:

require 'ostruct'

helper_method :current_user

def current_user
@current_user ||= User.find session[:user_id] if session[:user_id]
if @current_user
@current_user
else
OpenStruct.new(name: 'Guest')
end
End

Điều này sau đó sẽ cho phép bạn thay thế các ví dụ view code trước đó với một dòng này mã đơn giản:

<h3>Welcome, <%= current_user.name -%></h3>

Một vài các bài thực hành rails được tiến cử tốt nhất thêm vào là:

  • Sử dụng view layouts và partials một cách thích hợp để đóng gói những thứ được lặp đi lặp lại trên các trang của bạn.
  • Sử dụng các cách trình bày/ cách trang trí như Draper gem để đóng gói view-building logic trong đối tượng Ruby. Bạn có thể sau đó thêm các phương pháp vào trong mục tiêu thể hiện tổ chức logic mà bạn có thể cho vào view code của bạn

Sai lầm phổ biến thứ 3: Đặt quá nhiều logic trong Model

Đưa ra chỉ dẫn cho việc tối thiếu logic trong views và controllers, phần còn lại trong kiến trúc MCV liệu có phải cho quá nhiều logic trong model?

Không hẳn vậy.

Nhiều nhà phát triển Rails thực sự mắc sai lầm và kết thúc sa lầy mọi thứ trong model Active record của họ dẫn đến tập tin mông không chỉ vi phạm các nguyên tắc responsibility duy nhất mà còn là một cơn ác mộng bảo trì.

Chức năng như tạo ra các thông báo email, giao tiếp với các dịch vụ bên ngoài, chuyển đổi sang các định dạng dữ liệu khác và như thế không có nhiều điều để làm với responsibility chính của một model ActiveRecord mà nên làm ít hơn việc tìm kiếm và theo dai dẳng dữ liệu trong một cơ sở dữ liệu.

Vì vậy, nếu logic không nên đi trong View, và nó không nên đi trong controllers, và nó không nên đi trong các model, vậy, nó nên ở trong đâu?

Tham gia đối tượng thuần Ruby (POROs). Với một khung thông minh như Rails, các nhà phát triển mới thường miễn cưỡng sáng tạo các lớp học riêng của họ ở ngoài khung. Tuy nhiên chuyển logic ra khỏi model sang Poros thường chỉ là cái các nhà thông thái yêu cầu để tránh các models bị phức tạp hóa. Với POROs, bạn có thể đóng gói các thứ như các thông báo emailhay tương tác API vào các lớp học riêng của họ hơn là gắn chúng vào các model Active Record.

Vì vậy, với ý nghĩ đó, nói chung, logic duy nhất mà nên ở lại trong model của bạn là:

  • Cấu hình ActiveRecord (tức là, mối quan hệ và kiểm chứng thực)

  • Phương pháp đột biến đơn giản để đóng gói cập nhật một số ít các thuộc tính và lưu chúng vào cơ sở dữ liệu

  • Thêm vào các lớp bao bọc để ẩn các thông tin model nội bộ (vd: Một phương thức full_name bao gồm trường first_name và last_name trong cơ sở dữ liệu)

Các queries rắc rối (vd: phức tạp hơn find); nói chung, bạn không nên sử dụng phương thức where, hay bất kỳ các phương pháp xây dựng câu hỏi như vậy, bên ngoài bản thân model.

Sai lầm phổ biến thứ 4: Sử dụng các lớp helper chung chung lộn xộn

Lỗi này thực sự là một hệ quả tất yếu của sai lầm thứ # 3 trên đây. Như đã thảo luận, các khuôn khổ Rails đặt một sự nhấn mạnh vào các thành phần được đặt tên (ví dụ, model, view và điều khiển) của một khung MVC. Có các định nghĩa khá tốt của các loại thuộc trong các lớp của mỗi thành phần này, nhưng đôi khi chúng ta có thể cần những phương pháp mà dường như không phù hợp với bất kỳ của ba thành phần trên.

Rails máy phát điện thuận tiện xây dựng một thư mục helper và một lớp helper mới để đi với mỗi tài nguyên mới, chúng tôi tạo ra. Nó trở nên quá hấp dẫn, tuy nhiên, để bắt đầu nhồi bất kỳ chức năng không chính thức phù hợp với các model, view, hoặc điều khiển vào các lớp helper.

Trong khi Rails chắc chắn là MVC-trung tâm, không có gì ngăn cản bạn từ việc tạo ra loại của riêng bạn của các lớp và thêm thư mục thích hợp để giữ mã cho những lớp học. Khi bạn có chức năng bổ sung, suy nghĩ về những phương pháp nhóm lại với nhau và tìm thấy tên tốt cho các lớp học mà giữ các phương pháp đó. Sử dụng một khuôn khổ toàn diện như Rails không phải là một cái cớ để cho mục đích tốt định hướng thiết kế hoạt động tốt nhất đi bên cạnh.

Sai lầm phổ biến thứ 5: Sử dụng quá nhiều gem

Ruby on rails được hỗ trợ rất nhiều từ 1 lượng vô cùng phong phú các Gem, nó giúp cho các lập trình viên xử lý các vấn đề phức tạp 1 cách rất dễ dàng thông qua việc cài gem chứ không phải thêm những logic phức tạp vào dự án. Tuy nhiên không phải lúc nào ta cũng được lạm dụng. Nhiều khi việc làm dụng dùng Gem làm cho số lượng Gem file quá lớn so với những function mà ta sử dụng từ chúng.

Điều này sẽ gây ra một số vấn đề:

Sử dụng nhiều gem làm ứng dụng của ta nặng hơn mức cần thiết và tất nhiên ảnh hướng đến performance, ngốn ram và tất nhiên là tăng chi phí của hệ thống. Khởi đônhgj chậm, load chậm và khi chạy automation test cũng chậm. Mỗi gem bạn cài thì thường sẽ cài thêm một số gem dependency. Ví dụ nếu cài gem rails_admin thì bạn đã cài thêm 11 gem đi kèm với nó.

Sai lầm phổ biến thứ 6: Bỏ qua file log

Có thể hầu hết lập trình viên đều biết các file log được lưu trong thư mục logs, đối với từng môi trường development hay production nhưng nhiều khi họ lại chẳng mấy khi xem chúng.

Rails hỗ trợ mọi thứ thật tuyệt vời. Chỉ cần khai báo relation trong model là ta có thể truy xuất dữ liệu một cách dễ dàng từ bất cứ đâu. Tuy nhiên ta lại ko biết thực sự về bản chất nó đã chạy câu lệnh SQL như thế nào. Ví dụ khi gặp phải vấn đề n+1query thì nếu không đọc log thì ta sẽ không biết dò thế nào mà xử lý.

Ví dụ bạn cần query để hiển thị tất cả các comment của post:

def comments_for_top_three_posts
  posts = Post.limit(3)
  posts.flat_map do |post|
    post.comments.to_a
  end
end

Và khi gọi hàm trên, log sẽ như sau

Started GET "/posts/some_comments" for 127.0.0.1 at 2014-05-20 20:05:13 -0700
Processing by PostsController#some_comments as HTML
  Post Load (0.4ms)  SELECT "posts".* FROM "posts" LIMIT 3
  Comment Load (5.6ms)  ELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ?  [["post_id", 1]]
  Comment Load (0.4ms)  SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ?  [["post_id", 2]]
  Comment Load (1.5ms)  SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ?  [["post_id", 3]]
  Rendered posts/some_comments.html.erb within layouts/application (12.5ms)
Completed 200 OK in 581ms (Views: 225.8ms | ActiveRecord: 10.0ms)

nhìn vào log ta sẽ thấy có vấn đề n+1 query. Vậy từ đó ta có thể tìm đc cách khắc phục tình trạng này để tăng tốc độ app và xem lại log.

def comments_for_top_three_posts
  posts = Post.includes(:comments).limit(3)
  posts.flat_map do |post|
    post.comments.to_a
  end
end

và log

Started GET "/posts/some_comments" for 127.0.0.1 at 2014-05-20 20:05:18 -0700
Processing by PostsController#some_comments as HTML
  Post Load (0.5ms)  SELECT "posts".* FROM "posts" LIMIT 3
  Comment Load (4.4ms)  SELECT "comments".* FROM "comments" WHERE"comments "."post_id" IN (1, 2, 3)
  Rendered posts/some_comments.html.erb within layouts/application (12.2ms)
Completed 200 OK in 560ms (Views: 219.3ms | ActiveRecord: 5.0ms)

Đó chỉ là một ví dụ cho vấn đề n+1 query. Rõ ràng việc đọc log giúp ta có thể xem lại và kiểm tra xem hệ thống hoạt động có trơn tru hay ko.

Sai lầm phổ biến thứ 7: Thiếu kiểm tra tự động

Ruby và Rails cung cấp khả năng kiểm tra tự động mạnh mẽ theo mặc định. Nhiều nhà phát triển Rails viết bài kiểm tra rất phức tạp sử dụng TDD và phong cách BDD và sử dụng các khuôn khổ kiểm tra mạnh mẽ hơn với gems như rspec và cucumber.

Mặc dù cách dễ dàng là để thêm kiểm tra tự động cho ứng dụng bản đồ của bạn, tuy nhiên, tôi đã rất ngạc nhiên một cách khó chịu bởi có bao nhiêu dự án tôi đã thừa hưởng hoặc tham gia hợp có nghĩa là không có bài kiểm tra viết (hoặc ít nhất, rất ít) bởi trước nhóm phát triển. Trong khi có rất nhiều cuộc tranh luận về cách toàn diện thử nghiệm của bạn nên được, nó là khá rõ ràng rằng ít nhất một số thử nghiệm tự động nên tồn tại cho mọi ứng dụng.

Như một quy luật chung của ngón tay cái, cần có ít nhất một thử nghiệm tích hợp mức cao bằng văn bản đối với từng hành động trong bộ điều khiển của bạn. Tại một số điểm trong tương lai, khác Rails nhà phát triển có thể sẽ muốn mở rộng hoặc thay đổi mã, hoặc nâng cấp một phiên bản Ruby hay Rails, và khuôn khổ kiểm tra này sẽ cung cấp cho họ một cách rõ ràng về xác minh rằng các chức năng cơ bản của ứng dụng đang làm việc. Một lợi ích bổ sung của phương pháp này là nó cung cấp cho các nhà phát triển trong tương lai với một phân định rõ ràng của bộ sưu tập đầy đủ các chức năng được cung cấp bởi các ứng dụng.

Sai lầm phổ biến thứ 8: Chặn trong các cuộc gọi đến các dịch vụ từ bên ngoài

các nhà cung cấp dịch vụ bên thứ 3 của Rails thường làm cho nó rất dễ dàng để tích hợp các dịch vụ của họ vào ứng dụng của bạn thông qua gems bọc các API của họ. Nhưng điều gì sẽ xảy ra nếu dịch vụ bên ngoài của bạn bị ngừng hoặc bắt đầu chạy rất chậm?

Để tránh chặn các cuộc gọi, thay vì gọi các dịch vụ trực tiếp trong ứng dụng rails của bạn trong suốt quá trình bình thường của một yêu cầu, bạn nên di chuyển chúng đến một số dịch vụ nối đuôi nhau công việc nền nơi khả thi. Một số gems phổ biến được sử dụng trong các ứng dụng Rails cho mục đích này bao gồm:

  • Trì hoãn công việc
  • Resque
  • Sidekiq

Trong trường hợp đó là không thực tế hoặc không khả thi để ủy thác quá trình cho một hàng công việc nền, sau đó bạn sẽ cần phải chắc chắn rằng ứng dụng của bạn đã xử lý lỗi đầy đủ và chuyển đổi dự phòng cho những tình huống không thể tránh khỏi khi các dịch vụ bên ngoài đi xuống hoặc là vấn đề kinh nghiệm . Bạn cũng nên thử nghiệm ứng dụng của bạn mà không có dịch vụ bên ngoài (có thể bằng cách loại bỏ server ứng dụng của bạn từ mạng) để xác minh rằng nó không gây ra bất kỳ hậu quả không lường trước được.

Sai lầm phổ biến 9: Gắn kết với sự chuyển cơ sở dữ liệu hiện có

Cơ chế di chuyển cơ sở dữ liệu Rails 'cho phép bạn tạo ra các hướng dẫn để tự động thêm và loại bỏ các bảng và các hàng cơ sở dữ liệu. Kể từ khi các tập tin có chứa các di chuyển được đặt tên một cách tuần tự, bạn có thể đưa chúng trở lại từ đầu để mang lại một cơ sở dữ liệu rỗng vào giản đồ tương tự như sản xuất. Điều này do đó là một cách tuyệt vời để quản lý thay đổi dạng hạt vào lược đồ cơ sở dữ liệu của ứng dụng của bạn và tránh các vấn đề Rails.

Trong khi điều này chắc chắn hoạt động tốt ở phần đầu của dự án của bạn, như thời gian đi về, quá trình tạo cơ sở dữ liệu có thể mất nhiều thời gian và đôi khi sự di chuyển được đặt không đúng chỗ, đưa ra trong trật tự, hay giới thiệu từ các ứng dụng Rails khác sử dụng các máy chủ cơ sở dữ liệu tương tự.

Rails tạo ra một đại diện của giản đồ hiện tại của bạn trong một tập tin gọi là db / schema.rb (theo mặc định) mà thường được cập nhật khi di cư cơ sở dữ liệu đang chạy. Các tập tin schema.rb thậm chí có thể được tạo ra khi không có di cư có mặt bằng cách chạy db rake: schema: bãi nhiệm. Một Rails sai lầm phổ biến là để kiểm tra một di dân mới vào repo nguồn của bạn nhưng không phải là tập tin schema.rb cập nhật tương ứng.

Khi sự di chuyển đã vượt khỏi tầm tay và mất quá lâu để chạy, hoặc không còn tạo ra cơ sở dữ liệu đúng cách, phát triển không nên sợ để xóa khỏi thư mục di cư cũ, đổ một sơ đồ mới, và tiếp tục vào từ đó. Thiết lập một môi trường phát triển mới sau đó sẽ yêu cầu một db rake: schema: tải trọng hơn là rake db:migrate mà hầu hết các nhà phát triển dựa vào.

Sai lầm phổ biến thứ 10: Kiểm tra thông tin nhạy cảm trong các source code repositories

Framwork Rails làm cho dễ dàng trong việc tạo nên các ứng dụng bảo mật không chịu ảnh hưởng đến các cách tấn công. Một số trong số này được thực hiện bằng cách sử dụng mã bảo mật để đảm bảo một phiên làm việc với một trình duyệt. Mặc dù dấu hiệu này hiện đang được lưu trữ trong file config / secrets.yml, và tập tin mà đọc mã thông báo từ một môi trường đa dạng cho các máy chủ sản xuất, phiên bản trước đây của Rails bao gồm các mã thông báo trong config / initializers / secret_token.rb. File này thường được kiểm tra một cách sai sót vào kho lưu trữ mã nguồn với phần còn lại của ứng dụng của bạn, và khi điều này xảy ra, bất cứ ai có quyền truy cập vào kho lưu trữ có thể dễ dàng thỏa hiệp tất cả người dùng của ứng dụng của bạn.

Do đó bạn nên chắc chắn rằng cấu hình kho tập tin của bạn (ví dụ, .gitignore cho người dùng git) loại trừ các tập tin với thẻ của bạn. sau đó các máy chủ sản xuất của bạn có thể nhận thẻ của họ từ một môi trường đa dạng hoặc từ một cơ chế giống như những dotenv gem cung cấp.

Tóm lại bài hướng dẫn:

Rails là một framwork hiệu quả che dấu được nhiều chi tiết xấu cần thiết để xây dựng một Robust web applicationg. Trong khi nó làm sự phát triển ứng dụng web rails nhanh hơn nhiều, các nhà phát triển nên lưu tâm vào các thiết kế tiềm năng và các lỗi mã hóa, đảm bảo rằng các ứng dụng của họ mở rộng và duy trì dễ dàng khi chúng phát triển. Các nhà phát triển cũng nên nhận thức các vấn đề có thể khiển các ứng dụng của họ nhập hơn,ít tin cậy hơn, và ý bảo mật hơn. Điều quan trọng để thực hiện framwork và đảm bảo bạn hiểu đầy đủ kiến trúc, thiết kế và sự đánh đổi mã hóa mà bạn đang tạo quá quá trình phát triển, để giúp đảm bảo chất lượng cao và ứng dụng thể hiện tốt.

0