Domain Driven Design in Rails

  • View
    197

  • Download
    20

Embed Size (px)

DESCRIPTION

Presentation on SolutionCamp 2014 in Hamburg. Domain Driven Design with Ruby on Rails. What can we do with the stuff Rails/Ruby gives us.

Text of Domain Driven Design in Rails

  • 1. Domain DrivenDesignin Ruby on RailsCreated by Angelo Maron

2. Wer bin ich?Angelo MaronSofware-Entwickler seit ca. 7 Jahren (Ruby on Rails)bei AKRA seit 2,5 JahrenXing: https://www.xing.com/profile/Angelo_MaronTwitter: @MrRaffnix 3. Agenda1. MVC & Rails2. Domain Driven Design3. Domain Driven Design in Rails4. Zusammenfassung 4. MVC(Model View Controller)Wikipedia:Der englischsprachige Begriff "model viewcontroller" (MVC) ist ein Muster zurStrukturierung von Software-Entwicklung in diedrei Einheiten Datenmodell (engl. model),Prsentation (engl. view) undProgrammsteuerung (engl. controller). 5. Ruby on RailsRuby on Rails ist ein in der Programmiersprache Rubygeschriebenes und quelloffenes Web Application Framework.wird dieses Jahr 10 Jahre alt.basiert auf dem MVC-PatternPrinzipien:Don't repeat yourself (DRY)Convention over Configuration 6. !Convention! 7. MVC in Ruby on RailsM odel: ActiveRecordV iew: ActionViewC ontroller: ActionController 8. Fat Model, Skinny Con-troller(1)"Im Zusammenspiel von Controller und Model,versuche im Controller nur das Objekt zuinstanzieren und einen Methodenaufrufdurchzufhren. Der Rest wird im Modeldefiniert." 9. Fat Model, Skinny Con-troller(2)def index@published_posts = Post.all.where('published_at ?', Time.now)enddef index@published_posts = Post.all_published@unpublished_posts = Post.all_unpublishedend 10. ProblematikMit zunehmenden Anforderungen werden knnen die folgendenProblematiken auftreten:Die Model-Dateien werden immer grer (500+ Zeilen)Die Actions der Controller werden immer grer (30+ Zeilen)Dies fhrt zur Verschlechterung der Testbarkeit, Wartbarkeit undVerstndnis des Codes.Daher habe ich versucht nach den folgenden Regeln zu arbeiten.(nach Sandy Matz)Eine Klasse hat maximal 100 Zeilen.Eine Methode hat maximal 5 Zeilen.--> Domain Driven Design 11. Domain Driven DesignDomain-Driven Design (DDD) ist eineHerangehensweise an die Modellierungkomplexer objektorientierter Software. DieModellierung der Software wird dabeimageblich von den umzusetzendenFachlichkeiten der Anwendungsdomnebeeinflusst. 12. Warum DDD?1. Fachliche Begrifflichkeiten und Codestruktur angleichen.2. kleinere Dateien (bessere Wartbarkeit)3. hhere Codeunabhngigkeit (bessere Wartbarkeit)4. Bessere Testbarkeit (durch kleinere Klassen) 13. Domain-Driven Design inRailsRails HelpersConcernsService ObjectsPresenter ObjectsStrukturierte NamensrumeDecorator Pattern 14. Rails HelpersInterne Struktur von Rails um Funktionen fr views zur Verfgungzu stellen.Funktionen um komplexen Code aus der View zu halten.Sich wiederholende Funktionen wieder zu verwenden.Persnlich: (erinnert mich an funktionale Programmierung) 15. Beispiel Rails Helper (1)

16. Beispiel Rails Helper (2)module UserHelperdef user_picture_path(user)if user.image.present?user.image.pathelseasset_path('default_profile.png')endendend

17. Domain-Driven Design inRailsRails HelpersConcernsService ObjectsPresenter ObjectsStrukturierte NamensrumeDecorator Pattern 18. Rails ConcernsRails Concerns ist eine Mglichkeit Code in Module auszulagern,die man ber ein include in ein beliebiges Model inkludieren kann.Dieses hat folgende Anwendungsmglichkeiten:1. Aufteilen des Codes eines Models in mehrere Dateien2. Auslagerung von Mechanismen/Pattern zur WiederverwendungRails bietet hier ein hauseigenes Konzept:ActiveSupport::Concern 19. Beispiel Rails Concerns (1)class Article < ActiveRecord::Basebelongs_to :create_user, class_name: 'User'belongs_to :update_user, class_name: 'User'endclass Job < ActiveRecord::Basebelongs_to :create_user, class_name: 'User'belongs_to :update_user, class_name: 'User'end 20. Beispiel Rails Concerns (2)module Trackableextend ActiveSupport::Concernincluded dobelongs_to :create_user, class_name: 'User'belongs_to :update_user, class_name: 'User'endendclass Article < ActiveRecord::Baseinclude Trackableendclass Job < ActiveRecord::Baseinclude Trackableend 21. Domain-Driven Design inRailsRails HelpersConcernsService ObjectsPresenter ObjectsStrukturierte NamensrumeDecorator Pattern 22. Service ObjectsVerlagerung bestimmter Funktionen eines Anwendungsfall in eineigenes Objekt, dass genau diese Funktionen zur Verfgung stellt.zum Beispiel:SearchService (Suchkomponente)InvoiceService (Rechnungserstellung)RegistrationService (RegistrierungsValidierung) 23. Beispiel Service Object (1)class Article < ActiveRecord::Basedef search(term, options = {})# execute searchenddef admin_search(term, options = {})# execute search from admin perspectiveendenddef Job < ActiveRecord::Basedef search(term, options = {})# execute searchenddef admin_search(term, options = {})# execute search from admin perspectiveendend 24. Beispiel Service Object (2)class SearchServicedef self.article_search(term, options = {})# execute search hereenddef self.job_search(term, options = {})# execute search hereendendclass AdminSearchServicedef self.article_search(term, options = {})# execute search hereenddef self.job_search(term, options = {})# execute search hereendend 25. Domain-Driven Design inRailsRails HelpersConcernsService ObjectsPresenter ObjectsStrukturierte NamensrumeDecorator Pattern 26. Presenter ObjectsOft haben Get-Operationen komplexe Analyse von Parametern,um die genau angeforderten Objekte anzuzeigen. Hier gibt es einegute Mglichkeit, diese in eigene Objekte auszulagern. 27. Beispiel Presenter Object(1)class JobController < ApplicationController::Basedef index@jobs = Job.active.preload(:items)if params[:state]@jobs = @jobs.by_state(params[:state])endif params[:order]order_string = "#{params[:order]} #{params[:dir].presence || 'asc'}"@jobs = @jobs.order(order_string)end@jobs = @jobs.page(params[:page].presence || 1).per(params[:per].presence || 10)endend 28. Beispiel Presenter Object(2)class JobController < ApplicationController::Basedef index@jobs = JobPresenter.get_all(params)endendclass JobPresenterdef self.get_all(params)self.new(params).get_allenddef new(params)@params = paramsenddef get_alljobs = Job.active.preload(:items)if @params[:state]jobs = jobs.by_state(@params[:state])e n d 29. Domain-Driven Design inRailsRails HelpersConcernsService ObjectsPresenter ObjectsStrukturierte NamensrumeDecorator Pattern 30. Strukturierte Namen-srumeStrukturierung aller Objekte (Models, Services, Presenters,Decorators, Controllers usw.) in Domain-basierte Namespaces.Dies hat folgende Vorteile:Code-Unabhngigkeitkleinere Dateienbessere Abbildung der Businessdomne im Code. 31. Beispiel Namensrume (1)class Job < ActiveRecord::Basedef self.all_for_admins#execute query hereenddef self.all_for_moderators# execute query hereenddef self.all_for_visitors#execute query hereendend 32. Beispiel Namensrume (2)module Adminsclass Jobdef self.all#execute query hereendendendmodule Moderatorsclass Jobdef self.all#execute query hereendendendmodule Visitorsclass Jobdef self.all#execute query hereendendend 33. Domain-Driven Design inRailsRails HelpersConcernsService ObjectsPresenter ObjectsStrukturierte NamensrumeDecorator Pattern 34. Decorators in Rails (1) 35. Decorators in Rails (2) 36. Beispiel Decorator (1)class UserController < ApplicationController::Basedef show@user = User.find(params[:id])endend

Erstellt am: