DCI And Rails (Jakarta.rb February 2014)

DCI And Rails (Jakarta.rb February 2014)

My presentation during Jakarta.rb meetup on February 2014 about "DCI and Rails"

0fe18dfd87b3e48c0a45280e07cf96c6?s=128

Giovanni Sakti

February 19, 2014
Tweet

Transcript

  1. Hi, my name is Giovanni Jakarta.rb February 2014

  2. I Work for…

  3. None
  4. Thanks!!

  5. I’m having problem with remembering people faces and names !

    self-diagnosed with mild OCD ! 70% of my time during work is spent on reviewing codes from collaborators 6JKUKUOG
  6. My Main Concern Ensure that codes is as comprehendible as

    possible, make sure that any people whom participate in the project can understand and contribute effortlessly even though the project grows larger and larger and larger ! RGTHQTOCPEGOC[GXGPDGCUGEQPFEKVK\GPKPUQOGECUG
  7. None
  8. Today

  9. DCI (a.k.a Data Context Interaction) by Trygve Reenskaug KPECUG[QWFQPņVMPQYVJKUCYGUQOGOCPJGņU CNUQVJGQPGYJQOKPXGPVGF/8%DVY

  10. I’m (currently) not a DCI proponent ! I’m (still) not

    using it for production (only experimenting with it) ! I understand that Rails still can’t support it 100% yet
  11. $WVOCP +ņOKPVTKIWGF

  12. Common Rails developer evolution on “where to put my logic?”

    ! QTKPUGTVCP[QVJGTYGD/8%HTCOGYQTMU .GVņUVCMGCNQQMCV
  13. Put logic everywhere.. in views in controllers etc… #TG[QWUWTGKVņUPQVLWUV[QW)KQ!

  14. <% people = Person.where("added_at > ? AND deleted = ?",

    Time.now.utc, false).order("last_name, first_name") %> <% people.reject { |p| p.address.nil? }.each do |person| %> <div id="person-<%= person.new_record? ? "new" : person.id %>"> <span class="name"> <%= person.last_name %>, <%= person.first_name %> </span> <span class="age"> <%= (Date.today - person.birthdate) / 365 %> </span> </div> <% end %>
  15. Keep logic out from views DWVUVKNNRWVCNQVQH NQIKEKPEQPVTQNNGTU

  16. <% @people.each do |person| %> <div id="person-<%= person.new_record? ? "new"

    : person.id %>"> <span class="name"> <%= person.last_name %>, <%= person.first_name %> </span> <span class="age"> <%= (Date.today - person.birthdate) / 365 %> </span> </div> <% end %> class PeopleController < ActionController::Base def index @people = Person.where("added_at > ? AND deleted = ?", Time.now.utc, false).order("last_name, first_name") @people = @people.reject { |p| p.address.nil? } end end
  17. “Fat model, skinny controller” *GTGKUVJGOCPVTCVJCVYG MPQYCPFNQXG

  18. class Person < ActiveRecord::Base def self.find_recent people = Person.where("added_at >

    ? AND deleted = ?", Time.now.utc, false).order("last_name, first_name") people = people.reject { |p| p.address.nil? } end ! def name "#{last_name}, #{first_name}" end ! def age (Date.today - person.birthdate) / 365 end ! def pseudo_id new_record? ? "new" : id end end
  19. <% @people.each do |person| %> <div id="person-<%= person.pseudo_id %>"> <span

    class="name"><%= person.name %></span> <span class="age"><%= person.age %></span> </div> <% end %> class PeopleController < ActionController::Base def index @people = Person.find_recent end end
  20. But, was anything fat ever good in our app codebase?

    ! +UVKNNFQPņVMPQYVJGCPUYGTHQTVJKU
  21. Class  User  <<  ActiveRecord::Base   !   def  process1_method1  

      …     end   !   def  process1_method2     …     end   ! end
  22. Class  User  <<  ActiveRecord::Base   !   def  process1_method1  

      …     end   !   def  process1_method2     …     end   !   def  process2_method1     …     end   !   def  process2_method2     …     end   ! end
  23. Class  User  <<  ActiveRecord::Base   !   def  process1_method1  

      …     end   !   def  process1_method2     …     end   !   def  process2_method1     …     end   !   def  process2_method2     …     end   !   def  process1_method3     …     end   !   def  process1_method4     …     end   !   def  process3_method1     …     end   !   def  process3_method2     …     end   ! end
  24. Class  User  <<  ActiveRecord::Base   !   def  process1_method1  

      …     end   !   def  process1_method2     …     end   !   def  process2_method1     …     end   !   def  process2_method2     …     end   !   def  process1_method3     …     end   !   def  process1_method4     …     end   !   def  process3_method1     …     end   !   def  process3_method2     …     end   !   def  process1_method1     …     end   !   def  process1_method2     …     end   !   def  process2_method1     …     end   !   def  process2_method2     …     end   !   def  process1_method3     …     end   !   def  process1_method4     …     end   !   def  process3_method1     …     end   !   def  process3_method2     …     end   !   def  process1_method1     …     end   !   def  process1_method2     …     end   !   def  process2_method1     …     end   !   def  process2_method2     …     end   !   def  process1_method3     …     end   !   def  process1_method4     …     end   !   def  process3_method1     …     end   !   def  process3_method2     …     end   ! end
  25. Difficult to comprehend due to too much information in model…

  26. ActiveSupport::Concern  !!!

  27. Class  User  <<  ActiveRecord::Base     include  Commentable    

    include  Taggable     include  Manageable     include  ShoppingCartable     include  BlahBlah     …etc   end
  28. 9JCVņUYTQPIYKVJVJKU! Class  User  <<  ActiveRecord::Base     include  Commentable  

      include  Taggable     include  Manageable     include  ShoppingCartable     include  BlahBlah     …etc   end
  29. Developer still have to makes sense what goes where !

    Business Process cannot be evaluated procedurally
  30. Wait.. ! If we use BDD we can see and

    build business processes using the integration test, right?
  31. Wait.. ! If we use BDD we can see and

    build business processes using the integration test, right? 6JCVKU%QTTGEV
  32. We can actually stop here. +H[QWFQňHCVOQFGNUUMKPP[EQPVTQNNGTUʼnWUGCEVKXGUWRRQTVEQPEGTP CPFRTCEVKEG$&&VJGPEQPITCVWNCVKQPU[QWņTGNKXKPIQPVJGGFIG

  33. But what’s DCI actually all about then?

  34. DCI is about assigning roles to a model in a

    context /[WPFGTUVCPFKPIQH&%+ EQPVGZV#-#WUGTUVQT[
  35. A model must not have any business process related methods..

    ! business process and model must be tightly separated..
  36. Wait Whaaaaaat ?..

  37. Class  User  <<  ActiveRecord::Base     include  Commentable    

    include  Taggable     include  Manageable     include  ShoppingCartable     include  BlahBlah     …etc   end ;GCJVJKUKUYTQPIKP&%+
  38. So where should we put our code then? ! not

    in views.. not in controllers.. not in models.. not in concerns..
  39. We’ll have new kind of codes: Roles and Contexts

  40. class User < ActiveRecord::Base validates :name, :presence => true end

    ! class Book < ActiveRecord::Base validates :title, :presence => true end 6JKUKUQWTOQFGNU
  41. module Customer def add_to_cart(book) self.cart << book end end 6JKUKUQWTTQNG

  42. 6JKUKUQWTEQPVGZV class AddToCartContext attr_reader :user, :book ! def self.call(user, book)

    AddToCartContext.new(user, book).call end ! def initialize(user, book) @user, @book = user, book @user.extend Customer end ! def call @user.add_to_cart(@book) end end
  43. class BookController < ApplicationController def add_to_cart AddToCartContext.call(current_user, Book.find(params[:id])) end end

    6JKUKUQWTEQPVTQNNGT
  44. That my friends, was DCI…

  45. Something not right..

  46. class AddToCartContext attr_reader :user, :book ! def self.call(user, book) AddToCartContext.new(user,

    book).call end ! def initialize(user, book) @user, @book = user, book @user.extend Customer end ! def call @user.add_to_cart(@book) end end
  47. class AddToCartContext attr_reader :user, :book ! def self.call(user, book) AddToCartContext.new(user,

    book).call end ! def initialize(user, book) @user, @book = user, book @user.extend Customer end ! def call @user.add_to_cart(@book) end end 2GTHQTOCPEGRTQDNGOJGTG
  48. What I showed you was not an official method to

    do DCI in Rails. ! In fact, no official method exist yet.
  49. DHH is against DCI? 9JCV4CKNU%TGCVQTUCKFŎ

  50. None
  51. “This approach to breaking up domain logic into concerns is

    similar in some ways to the DCI notion of Roles. It doesn’t have the run-time mixin acrobatics nor does it have the “thy models shall be completely devoid of logic themselves” prescription, but other than that, it’ll often result in similar logic extracted using similar names.”
  52. But..

  53. Imagine a time when business process related code can be

    placed exactly within the actual code (not the test). ! And tightly separated from the model. 9GNN+ņOIQPPCNQUGO[LQDDGECWUGO[ENKGPVUECPEQFG EQORNKECVGFDWUKPGUURTQEGUUD[VJGOUGNXGUKHVJCVJCRRGPU
  54. Conclusion

  55. Ruby and Rails still have long ways to go to

    support DCI completely ! But you can still use it now if you want to.. (QQFHQTVJQWIJVU
  56. Some says SCALA is well-suited for DCI (QQFHQTVJQWIJVU

  57. http://signalvnoise.com/posts/3372-put-chubby-models-on- a-diet-with-concerns ! http://www.sitepoint.com/dci-the-evolution-of-the-object- oriented-paradigm/ ! http://mikepackdev.com/blog_posts/24-the-right-way-to- code-dci-in-ruby ! http://dec0de.me/2013/02/dci-performance/

    ! “Clean Ruby v0.9” - Jim Gay 4GHGTGPEGU
  58. Thanks!! Okay, that’s all lads..

  59. Question? @giosakti - mightygio.com - starqle.com