Jak (nie) używać Service Object

Jak (nie) używać Service Object

794f638b6f7f5132d5a13230e61c9db2?s=128

Krzysztof Wawer

November 19, 2014
Tweet

Transcript

  1. Jak (nie) używać Service Object Krzysztof Wawer

  2. O mnie Krzysztof Wawer krzysztof.wawer@gmail.com Github: wafcio Twitter: @KrzysztofWawer Neubloc

    Polska
  3. Na początku było … The Rails Way

  4. 7 Patterns to Refactor Fat ActiveRecord Models Value Objects Service

    Objects Form Objects Query Objects http:/ /blog.codeclimate.com/blog/2012/10/17 /7-ways-to-decompose-fat-activerecord-models/ View Model Objects Policy Objects Decorators
  5. Struktura aplikacji

  6. 1. Nazwy klass

  7. Nazwy klass, modułów w Ruby on Rails Kontrolery: HomeController, UsersController,

    … Helpery: HomeHelper, UsersHelper, … Modele: User, ...
  8. Nazwy klass w Service Object Form Object: UserForm Service Object:

    UserAuthenticator => UserAuthenticatorService UserAuthenticator => User::Authenticator UserAuthenticator => User::AuthenticatorService
  9. Dlaczego stosować rozróżnienia w nazwach klas ? Klasy: • Product

    • ProductFirmware • ProductModel • ProductState • ProductType • ProductCreator • ProductFinder Klasy: • Quality • QualityComment • QualityHasSerialNumber • QualityType Które klasy są modelami, a które są klasami Service Object ?
  10. Dlaczego stosować rozróżnienia w nazwach klas ? Klasy: • Product

    • ProductFirmware • ProductModel • ProductState • ProductType • ProductCreator • ProductFinder Klasy: • Quality • QualityComment • QualityHasSerialNumber • QualityType Które klasy są modelami, a które są klasami Service Object ?
  11. 2. Ograniczenie liczby wywołań Service Objectów

  12. Sieci Komputerowe - hop

  13. Service Object

  14. 3. Form Object - kiedy używać ?

  15. Form Object - kiedy używać ? Użytkownik: • rejestracja (wymaga

    hasła) • aktualizacja profilu (nie wymaga hasła) • zmiana hasła (wymaga hasła)
  16. Form Object - kiedy używać ? Nie używać modelu ORM

    jako formularz Zalety: izolacja pozostałych funkcjonalności szybsze testowanie obiektu Wady: duplikacja walidacja, dwustopniowa walidacja więcej kodu
  17. 4. Service Object ≠ Interactor

  18. Service Object class SessionsController < ApplicationController def create user =

    User.where(email: params[:email]).first if UserAuthenticator.new(user).authenticate(params[:password]) self.current_user = user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end
  19. Service Object class SessionsController < ApplicationController def create user =

    User.where(email: params[:email]).first if UserAuthenticator.new(user).authenticate(params[:password]) self.current_user = user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end
  20. Clean Architecture

  21. Interactor class SessionsController < ApplicationController def create UserAuthenticatorInteractor.new(self).run(params[:password]) end def

    create_succeeded(user, message) self.current_user = user redirect_to dashboard_path end def create_failed(message) flash[:alert] = message render "new" end end October CincyRb - Jim Weirich on Decoupling from Rails
  22. class SessionsController < ApplicationController def create UserAuthenticatorInteractor.new(self).run(params[:password], success: ->(user, message)

    { self.current_user = user redirect_to dashboard_path }, failure: ->(message) { flash[:alert] = message render "new" }) end end Interactor October CincyRb - Jim Weirich on Decoupling from Rails
  23. 5. View Models Object - brzydka nazwa

  24. View Model Object… grr Problem z nazwą typu obiektów: Presenter,

    FormObject, View, ViewModel • Presenter - Jay Fields (http:/ /blog.jayfields.com/2007 /03/ rails-presenter-pattern.html) „The Presenter pattern addresses bloated controllers and views containing logic in concert by creating a class representation of the state of the view. An architecture that uses the Presenter pattern provides view specific data as attributes of an instance of the Presenter. The Presenter's state is an aggregation of model and user entered data.”
  25. View Model Object… grr class Statistic def initialize(params) ... end

    def users ... end def products ... end ... end
  26. View Model Object… grr View Model => Presenter

  27. 6. Era CanCana za nami

  28. Policy Object CanCan (ostatni commit 6 września 2013) accessible_by -

    problematyczne działanie konstrukcja reguł w ability.rb uzależniona od używanego ORMa (ActiveRecord, DataMapper, Mongoid) Helpery Policy Object niezależny od ORMa używany tylko do pojedynczych obiektów a nie do kolekcji
  29. Policy Object https:/ /github.com/elabs/pundit

  30. Policy Object Gemy wspomagających integrację z aplikacją: Pundit (https:/ /github.com/elabs/pundit)

    Allowy (https:/ /github.com/dnagir/allowy)