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

Thách Thức Phổ Biến Ruby on Rails & Giải Pháp Thực Tế

Chào mừng đến phần cuối series Ruby on Rails Patterns and Anti-Patterns. Quite a ride writing/researching topics. Bài này cover most common problems encountered building/shipping Rails apps through the years.

Ideas ở đây apply almost anywhere in code. Coi như general ideas, không related MVC pattern. Quan tâm patterns/anti-patterns Rails MVC? Check Model, View, Controller blog posts.

Jump into general problems và takeaways.

Selfish Objects Và Law of Demeter

Law of Demeter: heuristic từ Demeter Project. Idea: objects fine miễn call one method at a time, không chain multiple method calls. In practice:

# Bad
song.label.address
# Good
song.label_address

Bây giờ song object không cần biết address từ đâu — address là responsibility của label object. Encourage chain only one method call, make objects 'selfish' - không share full info directly mà qua helper methods.

May mắn Rails không cần viết helper method per se — dùng delegate helper:

class Label < ApplicationModel
  belongs_to :song
  delegate :address, to: :song
end

Chơi với options delegate accepts trong delegate docs. Idea và execution simple. Apply Law of Demeter → reduce structural coupling. Với powerful delegate, làm fewer lines với great options.

Similar idea: Single-responsibility Principle (SRP). Module/class/function responsible cho single part of system. Cách khác:

Gather together things that change for same reasons. Separate things that change for different reasons.

Folks often different understanding SRP, nhưng idea: keep building blocks responsible cho single thing. Challenging achieve SRP khi Rails app expands, nhưng aware khi refactoring.

Khi adding features, increasing LOC, folks thường reach quick solution. Xem grabbing quick fix.

I Know A Guy (Bạn Có Cần Ruby Gem Đó Không?)

Ngày xưa Rails hot topic, boom open-source collaboration, Ruby gems mới mọc lên mọi góc (như JS libraries bây giờ nhưng smaller scale).

Common approach: find existing gem solve problem.

Không wrong với đó, nhưng advice trước khi install gem:

Hỏi bản thân:

  • Portion nào của gem features bạn sẽ dùng?
  • Có gem similar 'simpler' hoặc more up-to-date?
  • Implement feature needed easily và confidently?

Evaluate worth implementation nếu không plan dùng whole gem features. Hoặc gem implementation quá complex, believe bạn làm simpler → custom solution.

Factor khác: gem repository active như thế nào — active maintainers? Last release khi nào?

Watch out gem dependencies. Không muốn locked vào specific version dependency → luôn check Gemfile.spec. Consult RubyGems specifying gem versions.

Vẫn topic gems, related idea: 'Not Invented Here' (NIH) phenomenon applies Rails/Ruby world. Xem next section.

Not Invented Here (Có Lẽ Bạn Cần Gem Đó Sau Tất Cả?)

Couple occurrences career, experience people (me included) fall for 'NIH' syndrome. Similar 'reinventing the wheel'. Teams/orgs không trust libraries (gems) cannot control. Lack of trust trigger reinvent gem already out there.

NIH đôi khi good. In-house solution great, especially improve over existing solutions. Open-source solution → even better (look at Rails, React). Nhưng reinvent wheel for sake of it → don't. Wheel already pretty great.

Topic tricky. Nếu caught situation, hỏi:

  • Confident make better solution than existing?
  • Existing open-source differ from needs → contribute improve it?
  • Become maintainers open-source → improve nhiều developers' lives?

Nhưng sometimes phải go own way create library. Org không like licensing open-source → forced build own. Whatever you do, avoid reinventing the wheel.

Lifeguard On Duty (Over-rescuing Exceptions)

People tend rescue more exceptions than originally aimed for.

Topic code-related hơn previous. Common sense to some, nhưng seen in code. Ví dụ:

begin
  song.upload_lyrics
rescue
  puts 'Lyrics upload failed'
end

Không specify exception want rescue → catch exceptions không plan to.

Problem có thể song object là nil. Exception reported error tracker → think upload process off, actually experiencing something totally different.

Safe side: rescuing exceptions, ensure get list all exceptions might occur. Không obtain every exception → better under-rescue than over-rescue. Rescue exceptions bạn know, handle others later stage.

You Ask Too Much (Too Many SQL Queries)

Section này: web development, relational DB problem.

Bomb webserver với too many SQL queries trong 1 request. Phát sinh như thế nào? Fetch multiple records từ multiple tables trong 1 request. Nhưng most often: infamous N+1 query problem.

Models:

class Song < ApplicationRecord
  belongs_to :artist
end
class Artist < ApplicationRecord
  has_many :songs
end

Show songs trong genre với artists:

songs = Song.where(genre: genre).limit(10)
songs.each do |song|
  puts "#{song.title} by #{song.artist.name}"
end

Code trigger 1 SQL query get 10 songs. Sau đó 1 extra SQL query fetch artist cho mỗi song. Total 11 queries.

Load more songs → heavier load DB get all artists.

Alternative: dùng includes Rails:

songs = Song.includes(:artists).where(genre: genre).limit(10)
songs.each do |song|
  puts "#{song.title} by #{song.artist.name}"
end

Sau includes: chỉ 2 SQL queries, không matter how many songs. How neat.

Diagnose too many SQL queries: development. Nếu thấy group similar SQL queries fetch data từ same table → something fishy. Strongly encourage turn on SQL logging development env. Rails support verbose query logs show where query called from code.

Không thích logs hoặc muốn serious hơn → try AppSignal performance measuring và N+1 query detection. Excellent indicator issue từ N+1 query.

Sum Up

Thanks reading series. Glad bạn joined interesting ride: introducing patterns/anti-patterns Rails → exploring inside Rails MVC → final blog post general problems.

Hy vọng learned a lot, hoặc revised/established what already know. Không stress memorize all. Consult series nếu trouble any area.

Sẽ encounter cả patterns và anti-patterns vì world (software engineering especially) không ideal. Đừng worry.

Mastering patterns/anti-patterns → great software engineer. Nhưng làm bạn better: knowing when to break patterns/molds, vì no perfect solution.

Thanks again joining và reading. See you next one — cheers!

P.S. Đăng ký Ruby Magic newsletter để đọc sớm nhất!