Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sanity on Rails — How to write maintainable Rai...

Sanity on Rails — How to write maintainable Rails applications in 2017

Rails is not your application! Don’t overcomplicate your development life by trying to make everything fit within its MVC structure. A framework provides tools and abstractions, use them to build your business logic, don’t force your business logic to fit into them.

Michael Kohl

August 12, 2017
Tweet

More Decks by Michael Kohl

Other Decks in Programming

Transcript

  1. • Michael Kohl (@citizen428) • CTO @ Lockstep Labs •

    Based in Bangkok, Thailand • Ruby developer since ~2004 • Former mentor at RubyLearning Deccan RubyConf 2017 locksteplabs.com Yours truly
  2. Deccan RubyConf 2017 locksteplabs.com The problem • Recurring problems •

    Dependencies • Framework entanglement • Implicit code • Good news: easily avoidable
  3. Deccan RubyConf 2017 locksteplabs.com Dependencies • Bootstrap the app faster

    • Prevent “not invented here syndrome” • Get peer reviewed • Easily get outdated • Memory footprint & startup times • Have more dependencies
  4. Deccan RubyConf 2017 locksteplabs.com Dependencies • Be selective about dependencies

    • Look for actively maintained gems • Use gems for common tasks • Prefer developers with vested interest
  5. "A basic conceptional structure (as of ideas)" – Merriam Webster

    "A basic structure underlying a system, concept, or text." – Oxford English dictionary Deccan RubyConf 2017 locksteplabs.com Frameworks
  6. Deccan RubyConf 2017 locksteplabs.com Frameworks - Controllers • Abstracting HTTP

    communication • Authentication • Authorization • Sessions / cookies • Param validation / transformation • Redirection / rendering
  7. Deccan RubyConf 2017 locksteplabs.com Frameworks - Controllers # Actions resources

    :actions, only: [:index] namespace :actions do resource :enqueue_cvs, only: [:create] resource :import_cvs, only: [:create] resource :generate_suggestions, only: [:create] resource :logs, only: [:destroy] end # Users resources :users, except: [:new, :edit, :show] namespace :users do resources :filters, only: [:create] resources :passwords, only: [:create, :edit, :update] end
  8. Deccan RubyConf 2017 locksteplabs.com Frameworks - Models • Wrapper around

    datastore • ActiveRecord configuration • Associations • Validations • Finders / scopes • Simple accessors / mutation methods
  9. Deccan RubyConf 2017 locksteplabs.com Frameworks - Models • Extract POROs

    • Various extraction patterns • Service objects • Form objects • Query objects • many more • Use namespacing
  10. Deccan RubyConf 2017 locksteplabs.com Frameworks - Models ! tree app/services/cv

    app/services/cv "## file_mover.rb "## importer.rb "## parser.rb "## repository.rb "## suggestion_handler.rb $## viewer.rb
  11. Deccan RubyConf 2017 locksteplabs.com Frameworks - Models require_dependency 'cv' class

    Cv # Class for importing CV files into ElasticSearch in a standardized way. class Importer attr_accessor :file_name, :content, :md5sum, :file_type, :attributes, :parse def self.import(file_name, content, attr = {}) new(file_name, content, attr).import end def initialize(file_name, content, attr = {}) self.file_name = File.basename(file_name) … parse_attributes(attr) end def import add_to_es extract_plaintext parse_cv if parse end
  12. Deccan RubyConf 2017 locksteplabs.com Frameworks - Models class AbandonedTrialQuery def

    initialize(relation = Account.scoped) @relation = relation end def find_each(&block) @relation. where(plan: nil, invites_count: 0). find_each(&block) end end Credit: Code Climate
  13. Deccan RubyConf 2017 locksteplabs.com Frameworks - Views • Response generation

    • Should be mostly logic free • Rails conflates view model & template • Helpers become dumping grounds
  14. Deccan RubyConf 2017 locksteplabs.com Frameworks - Views class UserView <

    ApplicationView include ActionView::Helpers::TagHelper forward :first_name, :last_name def formatted_full_name content_tag :strong, "#{first_name} #{last_name}" end end
  15. Deccan RubyConf 2017 locksteplabs.com Implicit code • “Convention over configuration”

    • Magic: • AR configuration • Instance variables in views • Implicit code: • AR callbacks • before_action/after_action
  16. Deccan RubyConf 2017 locksteplabs.com Implicit code • Hard for newcomers

    to understand • Hard to follow code flow • Easy, not simple • Doesn’t apply in all cases
  17. Deccan RubyConf 2017 locksteplabs.com Implicit code • Be more explicit!

    • Reading is more important than writing! • POROs to encapsulate processes • Don’t try to be too clever!
  18. • Be selective when adding gems • Build business logic

    on top of what Rails provides, don’t mix it with framework code • Explicit is often better than implicit • There are no silver bullets, all software development involves tradeoffs. Deccan RubyConf 2017 locksteplabs.com Summary
  19. • How DHH Organizes His Rails Controllers
 http://jeromedalbert.com/how-dhh-organizes- his-rails-controllers/ •

    7 Patterns to Refactor Fat ActiveRecord Models
 http://blog.codeclimate.com/blog/2012/10/17/7- ways-to-decompose-fat-activerecord-models/ • Objects on Rails
 http://objectsonrails.com Deccan RubyConf 2017 locksteplabs.com Resources