Pro Yearly is on sale from $80 to $50! »

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

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.

B3881a28fe402dd2d1de44717486cae8?s=128

Michael Kohl

August 12, 2017
Tweet

Transcript

  1. Sanity on Rails Michael Kohl Deccan RubyConf 2017

  2. • 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
  3. Deccan RubyConf 2017 locksteplabs.com The problem

  4. Deccan RubyConf 2017 locksteplabs.com The problem • Recurring problems •

    Dependencies • Framework entanglement • Implicit code • Good news: easily avoidable
  5. Deccan RubyConf 2017 locksteplabs.com Dependencies

  6. 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
  7. 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
  8. Deccan RubyConf 2017 locksteplabs.com Dependencies

  9. Deccan RubyConf 2017 locksteplabs.com Dependencies

  10. Deccan RubyConf 2017 locksteplabs.com Framework entanglement

  11. "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
  12. Deccan RubyConf 2017 locksteplabs.com Frameworks - Controllers • Abstracting HTTP

    communication • Authentication • Authorization • Sessions / cookies • Param validation / transformation • Redirection / rendering
  13. 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
  14. Deccan RubyConf 2017 locksteplabs.com Frameworks - Models • Wrapper around

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

    • Various extraction patterns • Service objects • Form objects • Query objects • many more • Use namespacing
  16. 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
  17. 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
  18. Deccan RubyConf 2017 locksteplabs.com Frameworks - Models Credit: Code Climate

  19. 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
  20. Deccan RubyConf 2017 locksteplabs.com Frameworks - Views • Response generation

    • Should be mostly logic free • Rails conflates view model & template • Helpers become dumping grounds
  21. 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
  22. Deccan RubyConf 2017 locksteplabs.com Implicit code

  23. 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
  24. 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
  25. 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!
  26. • 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
  27. • 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
  28. Deccan RubyConf 2017 locksteplabs.com Thank you!