SlideShare une entreprise Scribd logo
1  sur  63
Télécharger pour lire hors ligne
REVOLUTION
OBIEKTOWE PODEJŚCIE
DO ROZWIĄZAŃ KOLEJOWYCH
Tomek Jasiulek
Twitter: @TomaszJasiulek
Github: tomasz-jasiulek
REVOLUTION
RAILS REVOLUTION ?
RAILS EVOLUTION ?
REWOLUCJA
EWOLUCJA
PODSTAWOWY ZESTAW NARZĘDZI
KOLEJARZA
• Kontroler / Mailer
• Model
• Widok/Szablon
• Helper
ZALETY
• Łatwe w użyciu
• Proste do nauki
• Szybki proces developmentu
• Dużo dostępnej informacji - guides,
stack-overflow, dokumentacja
• Sprawdza się w małych projektach
WADY
• Helper’y zaśmiecają globalną przestrzeń
• Przerośnięte modele
• Skomplikowany kod kontrolerów
• Łamanie SRP
• Kod Spaghetti w przypadku bardziej
skomplikowanej logiki biznesowej
• Callback hell
FAT MODEL, SKINNY CONTROLLER
• Jeszcze bardziej rozdmuchane modele
• Zgrabniejszy kod kontrolerów
• Przeniesienie problemu w inne miejsce
• No i dalej mamy kłopoty…
JAK ŻYĆ?
OOP NA RATUNEK
• SINGLE RESPONSIBILITY
• OPEN-CLOSE
• LISKOV SUBSTITUTION
• INTERFACE SEGREGATION
• DEPENDENCY INVERSION PRINCIPLE
• LAW OF DEMETER
• INHERITANCE
• COMPOSITION
• DELEGATION
“ZAAWANSOWANE” ROZWIĄZANIA
KOLEJOWE W PRAKTYCE
SPOILER:
NIE BĘDZIE DIAGRAMÓW UML
IDZIEMY NA DIETĘ… A NASZ CELTO:
• Klasy modeli ActiveRecord i tak mają dużą odpowiedzialność - nie dokładajmy im
dodaktowego ciężaru - potrzebna im dieta
• Klasy kontrolerów ActionController powinny być zgrabne, by widoczny był przepływ informacji
od żądania do odpowiedzi serwera - niekoniecznie wszystkie szczegóły logiki biznesowej
• Szablony HTML, ERB, HAML - czyste, przejrzyste, bez zbędnej logiki zaciemniającej strukturę
widoku
• Helpery - w railsach i tak jest ich dużo, nie dokładajmy specyficznych zachowań do globalnej
przestrzeni nazw
DODATKOWE SKUTKI DIETY
• Łatwiejsze testowanie aplikacji
• Oprogramowanie bardziej odporne na zmiany
• Kod rozdzielony na mniejsze i prostsze do ogarnięcia klasy o
zawężonej odpowiedzialności (klasy PORO)
CZEGO BĘDZIE WYMAGAĆ OD NAS
DIETA?
• Dyscypliny
• Myślenia
• Implementacji dodatkowych klas - w
większości PORO
DEKORATOR
• Tak naprawdę od tego wszystko się
zaczyna
• Podstawa wielu innych rozwiązań
• Rózni się tylko intencja programisty -
jego zamiar wobec dekorowanego
obiektu
DEKORATOR
• Z wykorzystaniem kompozycji dodajemy, zmieniamy lub rozszerzamy
bieżące zachowanie obiektu z poszanowaniem zasady zamknięcia -
dekorowany obiekt pozostaje nietknięty, a jednocześnie otwarty na
rozszerzenie.
• Proste w implementacji w Ruby ze względu na duck typing
PRESENTER
• Pozwalają uporządkować kod
odpowiadający za prezentację obiektu
• Odciążają klasy modelowe z metod
związanych z prezentacją danych w
określonych formatach
• Mniej helperów i metod z
przedrostkami w widokach
PRESENTER - KLASA BAZOWA
class BasePresenter
attr_reader :object, :template
alias_method :h, :template
delegate :t, :current_locale, to: :h
def initialize(object, template)
@object = object
@template = template
end
end
PRESENTER - HELPER
module ApplicationHelper
def present(object, klass = nil)
klass ||= "#{object.class}Presenter".safe_constantize
return unless klass
presenter = klass.new(object, self)
yield presenter if block_given?
presenter
end
end
PRESENTER - JAKO MODUŁ
module TaggablePresenter
def tags_section
return if object_tags.empty?
h.content_tag(:section, tags, class: 'keywords')
end
alias_method :keywords_section, :tags_section
def tags
return if object_tags.empty?
h.capture do
h.content_tag(:span) do
h.concat t('.tags') + ' '
h.concat comma_separated_linked_tags
end
end
end
alias_method :keywords, :tags
private
def object_tags
object.tags_for_locale(current_locale)
end
def linked_tags
object_tags.map do |tag|
h.link_to(tag.name, h.search_path(q: tag.name))
end
end
def comma_separated_linked_tags
separate_by_comma(linked_tags)
end
end
PRESENTER - PRZYKŁADOWA KLASA
class EventPresenter < BasePresenter
include TaggablePresenter
alias_method :event, :object
delegate :event_type, :venue, :name, to: :event
def summary
to_safe_html event.summary
end
def start_date(date_format = :medium_datetime)
if date_format.eql?(:date)
h.l event.start_date.to_date
else
h.l event.start_date, format: date_format
end
end
def description
to_safe_html event.description
end
def event_type_logo_url
h.image_url("/events/types/#{event_type_name_underscored}.png")
end
def event_type_name
event_type.name
end
def event_type_name_underscored
event_type_name.downcase.tr(' ', '_')
end
def organizer
return 'USZANOWANKO!!!' if event.organised_by_up?
event.organiser_name
end
def event_coverage
if event.event_coverage.present? && event.event_coverage.published?
event.event_coverage
end
end
private
def to_safe_html(text)
text.to_s.html_safe
end
end
PRESENTER - SZABLON HTML
- present event do |presenter|
.header
= image_tag(presenter.event_type_logo_url, alt: presenter.event_type_name)
%h3= link_to presenter.name, event
%span.date= presenter.start_date
.content
%p= presenter.summary
.details
%p
= t '.venue'
%strong= presenter.venue
%br
= t '.organiser'
%strong
= presenter.organizer
%span.more
= link_to t('.details'), event
PRESENTER - PODSUMOWANIE
Zalety:
• Jasne rozdzielenie logiki prezentacji od samej formy prezentacji(szablonu)
• Przejrzysty szablony(erb, haml itd…)
UWAGA!
• Mieszanie odpowiedzialności - presenter nie powinien tworzyć skomplikowanej
struktury HTML a jedynie formatować dane i przygotowywać do prezentacji w formie
np. HTML
SERIALIZER - KREWNIAK PRESENTER’A
GEM: ACTIVE_MODEL_SERIALIZERS
Cechy:
• Obiektowe podeście do serializacji
• Prezentuje obiekt w formacie JSON
• Idea podobna, tylko inny efekt końcowy
Zalety:
• Odciążenie modeli oraz kontrolerów od odpowiedzialności za serializację obiektów do formatu JSON
• Przeniesie tej odpowiedzialności do konkretnych klas serializerów, adekwatnych do przypadków użycia
SERVICE OBJECT
• Dedykowane klasy realizujące logikę
biznesową
• Wyciągamy logikę biznesową z
kontrolerów i modeli i enkapsulujemy ją
w postaci dedykowanych klas
• Wykorzystanie kompozycji
• Łatwe wykorzystanie klasy w innym
kontekście np. w tasku rake’owym,
workerze
SERVICE OBJECT - PRZYKŁAD
class NewsletterSubscription < ActiveRecord::Base
belongs_to :user
validates :email,
presence: true,
uniqueness: true,
format: Devise.email_regexp
validates :accept_terms,
acceptance: { accept: true }
end
class UserSubscriber
attr_accessor :user
def initialize(user)
@user = user
end
def call
subscription = NewsletterSubscription.new
subscription.user = @user
subscription.email = @user.email
subscription.subscribed = true
subscription.accept_terms = true
subscription.subscribe_date = Time.current
subscription.save!
end
end
SERVICE OBJECTS - PODSUMOWANIE
• Pozbywamy się zbędnych callbacków z modeli
• Zwiększamy czytelność kodu kontrolerów, dzięki wyodrębnieniu logiki
biznesowej w osobne miejsce
• Modele nie sprawiają niespodzianek np. w przypadku importu
(wysyłanie maili w callbackach itp.)
VALUE OBJECT
• Dedykowany klasa, która enkapsuluje wartość
oraz jej specyficzne zachowanie
• Można powiedzieć, że taki wrapper na
prymitywne wartości lub wartości
kalkulowane dynamicznie
• Nie zmieniają swojego wewnętrznego stanu
• Identyfikowany przez wartość
• Pozwala na porównywanie, sortowanie itp.
• Przykład: Fixnum, Range, Money
VALUE OBJECT - PRZYKŁAD
class Ratio
include Comparable
extend Forwardable
def_delegators :value, :zero?
attr_reader :teachers, :students, :value
def self.zero
new(0, 0)
end
def initialize(teachers, students)
@teachers = teachers.to_f
@students = students.to_f
if students == 0
@value = 0.0
else
@value = @teachers/@students
end
end
def <=>(other)
value <=> other.value
end
def to_s
"#{teachers.round}:#{students.round}"
end
end
VALUE OBJECT - INNE PRZYKŁADY
• NUMERTELEFONU - możliwość wyodrebnienia numeru
kierunkowego, pełnego numeru w postaci łańcucha tekstowego
• ADRES EMAIL - możliwość wyodrębnienia nazwy użytkownika,
domeny lub pełnego w postaci łańcucha tekstowego
VALUE OBJECT - PODSUMOWANIE
• Zachowanie pewnej klasy obiektów w jednym miejscu - a nie
rozsiane po całej aplikacji
• Ewentualne zmiany, rozszerzenia wymagają zmian tylko i wyłącznie w
jednej klasie
• Operujemy jeden poziom wyżej - operowanie na prymitywach niesie
za sobą zagrożenia i ograniczenia
ZAGADKA?
class Car < ActiveRecord::Base
enum air_conditioning: {
blank: 0,
manual: 1,
climatronic: 2
}
end
CO ZWRÓCI WYWOŁANIE:
car = Car.new
car.air_conditioning = 'climatronic'
car.present?
ROZWIĄZANIE ZAGADKI
FALSE
Pozdrawiamy core team Railsów ;)
NULL OBJECT
NA RATUNEK NULL OBJECT
• Alernatywa dla: object.nil?, object.kind_of?, object.present?
• Implementuje interfejs obiektu zastępowanego
• Obiekt zastępczy, który udaje obiekt zastępowany, gdy ten nie
istnieje(np. nie ma go w bazie/repozytorium)
NULL OBJECT - PRZYKŁAD
class SidebarPresenter < BasePresenter
def render_items
h.capture do
sidebar_items.each do |sidebar_item|
h.concat render_sidebar_item(sidebar_item)
end
end
end
def sidebar
@sidebar ||= home? ? Sidebar.home : Sidebar.primary
@sidebar ||= Domain::NullSidebar.new
end
private
def sidebar_items
sidebar.sidebar_items.includes(:sidebar_item_type)
end
def render_sidebar_item(item)
presenter = SidebarItems::PresenterFactory.create(item, h)
presenter.render_item
end
def home?
h.controller_name.eql?('home')
end
end
NULL OBJECT - PRZYKŁAD
class NullSidebar < NullObject
def sidebar_items
SidebarItem.none
end
end
class NullObject
def method_missing(*args, &block)
self
end
end
najprostsza implementacja(ma kilka wad)
NULL OBJECT - PODSUMOWANIE
• Nigdy więcej undefined method nazwa_metody for nil:NilClass
• Można skupić się na zadaniu, zamiast ciągłym sprawdzaniu wartości lub tożsamości
obiektów
UWAGA!
• Należy uważać na trudne do wykrycia błędy, która na pierwszy rzut oka wyglądają jak
normalne działanie programu
INNE ROZWIĄZANIA
FORM OBJECT
Sposób na ogarnięcie skomplikowanych formularzy i rozprawienie się z
accepts_nested_attributes_for.W skrócie klasa modelowa, ale nie
dziedzicząca po ActiveRecord::Base(tak, takie klasy też istnieją i mogą
być modelami), której obiekty trzymają stan obiektu formularza i
enkapsulują np. możliwe opcje, walidacje w danym przypadku użycia
FORM OBJECT
• ActiveModel::Model
• Virtus
• Reform
• …
QUERY OBJECT
Sposób na łańcuszek wywołań na relacjach ActiveRecord oraz na inne
skomplikowane zapytania do bazy danych.
QUERY OBJECT
@news = News.published
.with_translations(locale)
.not_promoted
.visible
.by_position
.with_tile
.merge(Tile.with_translations(locale))
.limit(limit)
QUERY OBJECT
Zasada jest prosta - wyciągamy skomplikowane zapytanie do osobnej
klasy PORO a wynik wywołania udostępniamy na zewnątrz
PODSUMOWANIE
MVCTO NIE WSZYSTKO
FAT MODEL SKINNY CONTROLLER?
NIE!
KAŻDA KLASA POWINNA SIĘ ZDROWO ODŻYWIAĆ
I BYĆ SKINNY
przynajmniej w założeniu… ;)
NIE BÓJMY SIĘ PROGRAMOWANIA
OBIEKTOWEGO
nie jest takie trudne jak się na pierwszy rzut oka wydaje
POMYŚLMY O PROGRAMISTACH,
KTÓRZY WEJDĄ PO NAS W NASZ KOD
Zróbmy wszystko, aby liczba przekleństw dążyła do zera ;)
WYKORZYSTAJMYTO CO W RAILSACH
DOBRE
ale nie ograniczajmy się tylko i wyłącznie do tego co oferują
DODAJMY SZCZYPTĘ
PROGRAMOWANIA OBIEKTOWEGO
uważając by nie przekombinować!
A POWSTANIE LEKKOSTRAWNE I
SMACZNE DANIE*
*zakładając że logika biznesowa projektu nie jest zagmatwana ;)
DZIĘKUJĘ ZA UWAGĘ
PYTANIA?

Contenu connexe

Tendances

DynamoDB – podstawy modelowania danych dla opornych
DynamoDB – podstawy modelowania danych dla opornychDynamoDB – podstawy modelowania danych dla opornych
DynamoDB – podstawy modelowania danych dla opornychThe Software House
 
Laravel Poznań Meetup #12 - "Laravel 6.0 - co nowego?"
Laravel Poznań Meetup #12 - "Laravel 6.0 - co nowego?"Laravel Poznań Meetup #12 - "Laravel 6.0 - co nowego?"
Laravel Poznań Meetup #12 - "Laravel 6.0 - co nowego?"HighSolutions Sp. z o.o.
 
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...Trójmiejska Grupa Testerska
 
Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16
Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16
Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16Krzysztof Synak
 
Niezbędnik administratora - prezentacja Bartosz Sałach
Niezbędnik administratora - prezentacja Bartosz SałachNiezbędnik administratora - prezentacja Bartosz Sałach
Niezbędnik administratora - prezentacja Bartosz SałachBartosz Sałach
 
Application in Xamarin.Forms
Application in Xamarin.FormsApplication in Xamarin.Forms
Application in Xamarin.FormsMaciej Kuchcik
 
TGT#15 - Piramida testów w praktyce (notatki z dyskusji)
TGT#15 - Piramida testów w praktyce (notatki z dyskusji)TGT#15 - Piramida testów w praktyce (notatki z dyskusji)
TGT#15 - Piramida testów w praktyce (notatki z dyskusji)Trójmiejska Grupa Testerska
 
Obiektowe tworzenie motywów z użyciem silnika szablonów Twig w WordPressie
Obiektowe tworzenie motywów z użyciem silnika szablonów Twig w WordPressieObiektowe tworzenie motywów z użyciem silnika szablonów Twig w WordPressie
Obiektowe tworzenie motywów z użyciem silnika szablonów Twig w WordPressieWordCamp Polska
 
Daj się wyręczyć - Joomla Day Polska 2014
Daj się wyręczyć - Joomla Day Polska 2014Daj się wyręczyć - Joomla Day Polska 2014
Daj się wyręczyć - Joomla Day Polska 2014Tomasz Dziuda
 
Jak zarabiać na testowaniu oprogramowania(konferencja MeeTTech Piła 27.07.2016)
Jak zarabiać na testowaniu oprogramowania(konferencja MeeTTech Piła 27.07.2016)Jak zarabiać na testowaniu oprogramowania(konferencja MeeTTech Piła 27.07.2016)
Jak zarabiać na testowaniu oprogramowania(konferencja MeeTTech Piła 27.07.2016)Dariusz Kacban
 
Równoległy rozwój Aplikacji Webowych | Codesushi
Równoległy rozwój Aplikacji Webowych | CodesushiRównoległy rozwój Aplikacji Webowych | Codesushi
Równoległy rozwój Aplikacji Webowych | CodesushiKrzysztof (Chris) Ozog
 
Sporządzanie oraz umiejętne wykorzystanie przepisów i schematów. Ansible w pr...
Sporządzanie oraz umiejętne wykorzystanie przepisów i schematów. Ansible w pr...Sporządzanie oraz umiejętne wykorzystanie przepisów i schematów. Ansible w pr...
Sporządzanie oraz umiejętne wykorzystanie przepisów i schematów. Ansible w pr...The Software House
 
Unit testing w praktyce... czyli właściwie jak?
Unit testing w praktyce... czyli właściwie jak?Unit testing w praktyce... czyli właściwie jak?
Unit testing w praktyce... czyli właściwie jak?Bartłomiej Cymanowski
 
Testy wydajnościowe - najlepsze praktyki - Kuba Gajda
Testy wydajnościowe - najlepsze praktyki - Kuba GajdaTesty wydajnościowe - najlepsze praktyki - Kuba Gajda
Testy wydajnościowe - najlepsze praktyki - Kuba GajdaBartłomiej Cymanowski
 
Minimalizowanie niepewności w Scrumie
Minimalizowanie niepewności w ScrumieMinimalizowanie niepewności w Scrumie
Minimalizowanie niepewności w ScrumieJacek Wieczorek
 

Tendances (19)

DynamoDB – podstawy modelowania danych dla opornych
DynamoDB – podstawy modelowania danych dla opornychDynamoDB – podstawy modelowania danych dla opornych
DynamoDB – podstawy modelowania danych dla opornych
 
Środowisko PWA
Środowisko PWAŚrodowisko PWA
Środowisko PWA
 
Laravel Poznań Meetup #12 - "Laravel 6.0 - co nowego?"
Laravel Poznań Meetup #12 - "Laravel 6.0 - co nowego?"Laravel Poznań Meetup #12 - "Laravel 6.0 - co nowego?"
Laravel Poznań Meetup #12 - "Laravel 6.0 - co nowego?"
 
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
 
Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16
Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16
Integracja środowiska testowego z użyciem Robot Framework, TrojQA 2014-12-16
 
Niezbędnik administratora - prezentacja Bartosz Sałach
Niezbędnik administratora - prezentacja Bartosz SałachNiezbędnik administratora - prezentacja Bartosz Sałach
Niezbędnik administratora - prezentacja Bartosz Sałach
 
Application in Xamarin.Forms
Application in Xamarin.FormsApplication in Xamarin.Forms
Application in Xamarin.Forms
 
TGT#15 - Piramida testów w praktyce (notatki z dyskusji)
TGT#15 - Piramida testów w praktyce (notatki z dyskusji)TGT#15 - Piramida testów w praktyce (notatki z dyskusji)
TGT#15 - Piramida testów w praktyce (notatki z dyskusji)
 
Obiektowe tworzenie motywów z użyciem silnika szablonów Twig w WordPressie
Obiektowe tworzenie motywów z użyciem silnika szablonów Twig w WordPressieObiektowe tworzenie motywów z użyciem silnika szablonów Twig w WordPressie
Obiektowe tworzenie motywów z użyciem silnika szablonów Twig w WordPressie
 
Daj się wyręczyć - Joomla Day Polska 2014
Daj się wyręczyć - Joomla Day Polska 2014Daj się wyręczyć - Joomla Day Polska 2014
Daj się wyręczyć - Joomla Day Polska 2014
 
Jak zarabiać na testowaniu oprogramowania(konferencja MeeTTech Piła 27.07.2016)
Jak zarabiać na testowaniu oprogramowania(konferencja MeeTTech Piła 27.07.2016)Jak zarabiać na testowaniu oprogramowania(konferencja MeeTTech Piła 27.07.2016)
Jak zarabiać na testowaniu oprogramowania(konferencja MeeTTech Piła 27.07.2016)
 
Laravel 8.0 - co nowego?
Laravel 8.0 - co nowego?Laravel 8.0 - co nowego?
Laravel 8.0 - co nowego?
 
Równoległy rozwój Aplikacji Webowych | Codesushi
Równoległy rozwój Aplikacji Webowych | CodesushiRównoległy rozwój Aplikacji Webowych | Codesushi
Równoległy rozwój Aplikacji Webowych | Codesushi
 
Sporządzanie oraz umiejętne wykorzystanie przepisów i schematów. Ansible w pr...
Sporządzanie oraz umiejętne wykorzystanie przepisów i schematów. Ansible w pr...Sporządzanie oraz umiejętne wykorzystanie przepisów i schematów. Ansible w pr...
Sporządzanie oraz umiejętne wykorzystanie przepisów i schematów. Ansible w pr...
 
Unit testing w praktyce... czyli właściwie jak?
Unit testing w praktyce... czyli właściwie jak?Unit testing w praktyce... czyli właściwie jak?
Unit testing w praktyce... czyli właściwie jak?
 
Wstęp do profilowania aplikacji
Wstęp do profilowania aplikacjiWstęp do profilowania aplikacji
Wstęp do profilowania aplikacji
 
Projektowanie i implementacja usług sieciowych
Projektowanie i implementacja usług sieciowychProjektowanie i implementacja usług sieciowych
Projektowanie i implementacja usług sieciowych
 
Testy wydajnościowe - najlepsze praktyki - Kuba Gajda
Testy wydajnościowe - najlepsze praktyki - Kuba GajdaTesty wydajnościowe - najlepsze praktyki - Kuba Gajda
Testy wydajnościowe - najlepsze praktyki - Kuba Gajda
 
Minimalizowanie niepewności w Scrumie
Minimalizowanie niepewności w ScrumieMinimalizowanie niepewności w Scrumie
Minimalizowanie niepewności w Scrumie
 

En vedette

Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng
Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng
Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng The Software House
 
Jak ugryźć Ruby, żeby nie połamać zębów?
Jak ugryźć Ruby, żeby nie połamać zębów?Jak ugryźć Ruby, żeby nie połamać zębów?
Jak ugryźć Ruby, żeby nie połamać zębów?The Software House
 
O wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyce
O wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyceO wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyce
O wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyceThe Software House
 
Gulp.js - alternatywa do Grunta
Gulp.js - alternatywa do GruntaGulp.js - alternatywa do Grunta
Gulp.js - alternatywa do GruntaThe Software House
 
Bitcoin - (nie)udany eksperyment?
Bitcoin - (nie)udany eksperyment?Bitcoin - (nie)udany eksperyment?
Bitcoin - (nie)udany eksperyment?The Software House
 
Tester - przyjaciel czy wróg programisty?
Tester - przyjaciel czy wróg programisty?Tester - przyjaciel czy wróg programisty?
Tester - przyjaciel czy wróg programisty?The Software House
 
Nie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event Sourcing
Nie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event SourcingNie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event Sourcing
Nie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event SourcingThe Software House
 
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...The Software House
 
Znaki mocy dla laików – Programowanie funkcyjne w JavaScript
Znaki mocy dla laików – Programowanie funkcyjne w JavaScriptZnaki mocy dla laików – Programowanie funkcyjne w JavaScript
Znaki mocy dla laików – Programowanie funkcyjne w JavaScriptThe Software House
 
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...The Software House
 
Red Green Hotfix – złudne poczucie bezpieczeństwa w testach
Red Green Hotfix – złudne poczucie bezpieczeństwa w testachRed Green Hotfix – złudne poczucie bezpieczeństwa w testach
Red Green Hotfix – złudne poczucie bezpieczeństwa w testachThe Software House
 
ReactPHP – reaktor jądrowy w PHP
ReactPHP – reaktor jądrowy w PHPReactPHP – reaktor jądrowy w PHP
ReactPHP – reaktor jądrowy w PHPThe Software House
 
Pi razy drzwi - o szacowaniu projektów
Pi razy drzwi - o szacowaniu projektówPi razy drzwi - o szacowaniu projektów
Pi razy drzwi - o szacowaniu projektówThe Software House
 
Angular 2.0 – Kochaj albo rzuć!
Angular 2.0 – Kochaj albo rzuć!Angular 2.0 – Kochaj albo rzuć!
Angular 2.0 – Kochaj albo rzuć!The Software House
 
Wielkie protokoły wielkich ludzi
Wielkie protokoły wielkich ludziWielkie protokoły wielkich ludzi
Wielkie protokoły wielkich ludziThe Software House
 
PSR-7 - HTTP message interfaces
PSR-7 - HTTP message interfacesPSR-7 - HTTP message interfaces
PSR-7 - HTTP message interfacesThe Software House
 

En vedette (20)

Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng
Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng
Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng
 
Jak ugryźć Ruby, żeby nie połamać zębów?
Jak ugryźć Ruby, żeby nie połamać zębów?Jak ugryźć Ruby, żeby nie połamać zębów?
Jak ugryźć Ruby, żeby nie połamać zębów?
 
O wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyce
O wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyceO wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyce
O wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyce
 
Gulp.js - alternatywa do Grunta
Gulp.js - alternatywa do GruntaGulp.js - alternatywa do Grunta
Gulp.js - alternatywa do Grunta
 
Bitcoin - (nie)udany eksperyment?
Bitcoin - (nie)udany eksperyment?Bitcoin - (nie)udany eksperyment?
Bitcoin - (nie)udany eksperyment?
 
Tester - przyjaciel czy wróg programisty?
Tester - przyjaciel czy wróg programisty?Tester - przyjaciel czy wróg programisty?
Tester - przyjaciel czy wróg programisty?
 
Nie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event Sourcing
Nie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event SourcingNie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event Sourcing
Nie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event Sourcing
 
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
 
Bestiariusza wpisy wybrane
Bestiariusza wpisy wybraneBestiariusza wpisy wybrane
Bestiariusza wpisy wybrane
 
Znaki mocy dla laików – Programowanie funkcyjne w JavaScript
Znaki mocy dla laików – Programowanie funkcyjne w JavaScriptZnaki mocy dla laików – Programowanie funkcyjne w JavaScript
Znaki mocy dla laików – Programowanie funkcyjne w JavaScript
 
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
 
PHP 7
PHP 7PHP 7
PHP 7
 
Red Green Hotfix – złudne poczucie bezpieczeństwa w testach
Red Green Hotfix – złudne poczucie bezpieczeństwa w testachRed Green Hotfix – złudne poczucie bezpieczeństwa w testach
Red Green Hotfix – złudne poczucie bezpieczeństwa w testach
 
ReactPHP – reaktor jądrowy w PHP
ReactPHP – reaktor jądrowy w PHPReactPHP – reaktor jądrowy w PHP
ReactPHP – reaktor jądrowy w PHP
 
O Electronie słów kilka
O Electronie słów kilkaO Electronie słów kilka
O Electronie słów kilka
 
Pi razy drzwi - o szacowaniu projektów
Pi razy drzwi - o szacowaniu projektówPi razy drzwi - o szacowaniu projektów
Pi razy drzwi - o szacowaniu projektów
 
Angular 2.0 – Kochaj albo rzuć!
Angular 2.0 – Kochaj albo rzuć!Angular 2.0 – Kochaj albo rzuć!
Angular 2.0 – Kochaj albo rzuć!
 
Wielkie protokoły wielkich ludzi
Wielkie protokoły wielkich ludziWielkie protokoły wielkich ludzi
Wielkie protokoły wielkich ludzi
 
Varnish
VarnishVarnish
Varnish
 
PSR-7 - HTTP message interfaces
PSR-7 - HTTP message interfacesPSR-7 - HTTP message interfaces
PSR-7 - HTTP message interfaces
 

Similaire à REvolution, czyli o bardziej obiektowym podejściu w Railsach

Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVC
Wzorce Repository, Unity of Work, Devexpress MVC  w architekturze Asp.net MVCWzorce Repository, Unity of Work, Devexpress MVC  w architekturze Asp.net MVC
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVCQuick-Solution
 
4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu -...
4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu -...4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu -...
4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu -...PROIDEA
 
Wzorce projektowe (w ASP.NET i nie tylko)
Wzorce projektowe (w ASP.NET i nie tylko)Wzorce projektowe (w ASP.NET i nie tylko)
Wzorce projektowe (w ASP.NET i nie tylko)Bartlomiej Zass
 
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?Andrzej Krzywda
 
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbaćBartosz Ratajczyk
 
Testowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStackTestowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStackThe Software House
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Cloudskraqa
 
AngularJS (nie) nadaje się do dużego projektu
AngularJS (nie) nadaje się do dużego projektuAngularJS (nie) nadaje się do dużego projektu
AngularJS (nie) nadaje się do dużego projektu3camp
 
AngularJS (nie) nadaje się do dużych pojektów.
AngularJS (nie) nadaje się do dużych pojektów.AngularJS (nie) nadaje się do dużych pojektów.
AngularJS (nie) nadaje się do dużych pojektów.Rafał Filipek
 
Podstawy programowania w Drupalu - Drupal idzie na studia - Jarosław Sobiecki
Podstawy programowania w Drupalu - Drupal idzie na studia - Jarosław SobieckiPodstawy programowania w Drupalu - Drupal idzie na studia - Jarosław Sobiecki
Podstawy programowania w Drupalu - Drupal idzie na studia - Jarosław SobieckiGrzegorz Bartman
 
Środowisko testowe pod REST-a
Środowisko testowe pod REST-aŚrodowisko testowe pod REST-a
Środowisko testowe pod REST-aFuture Processing
 
20060416 Azure Boot Camp 2016- Azure Data Lake Storage and Analytics
20060416   Azure Boot Camp 2016- Azure Data Lake Storage and Analytics20060416   Azure Boot Camp 2016- Azure Data Lake Storage and Analytics
20060416 Azure Boot Camp 2016- Azure Data Lake Storage and AnalyticsŁukasz Grala
 
Encje w drupalu - DrupalCamp Wroclaw 2015
Encje w drupalu - DrupalCamp Wroclaw 2015Encje w drupalu - DrupalCamp Wroclaw 2015
Encje w drupalu - DrupalCamp Wroclaw 2015Grzegorz Bartman
 
Angular 4 pragmatycznie
Angular 4 pragmatycznieAngular 4 pragmatycznie
Angular 4 pragmatycznieSages
 
HYC - Angular stań się kanciastym
HYC - Angular stań się kanciastymHYC - Angular stań się kanciastym
HYC - Angular stań się kanciastymDariusz Jagieło
 

Similaire à REvolution, czyli o bardziej obiektowym podejściu w Railsach (20)

Scala
ScalaScala
Scala
 
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVC
Wzorce Repository, Unity of Work, Devexpress MVC  w architekturze Asp.net MVCWzorce Repository, Unity of Work, Devexpress MVC  w architekturze Asp.net MVC
Wzorce Repository, Unity of Work, Devexpress MVC w architekturze Asp.net MVC
 
JavaScript, Moduły
JavaScript, ModułyJavaScript, Moduły
JavaScript, Moduły
 
4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu -...
4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu -...4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu -...
4Developers 2015: Baza danych w aplikacji typu SaaS - błędy w projektowaniu -...
 
Wzorce projektowe (w ASP.NET i nie tylko)
Wzorce projektowe (w ASP.NET i nie tylko)Wzorce projektowe (w ASP.NET i nie tylko)
Wzorce projektowe (w ASP.NET i nie tylko)
 
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
 
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
"Administrator z przypadku" - Jak działa SQL Server i jak o niego dbać
 
Testowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStackTestowanie rozwiązań serverless z LocalStack
Testowanie rozwiązań serverless z LocalStack
 
Podstawy ETL z SSIS
Podstawy ETL z SSISPodstawy ETL z SSIS
Podstawy ETL z SSIS
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Clouds
 
AngularJS (nie) nadaje się do dużego projektu
AngularJS (nie) nadaje się do dużego projektuAngularJS (nie) nadaje się do dużego projektu
AngularJS (nie) nadaje się do dużego projektu
 
AngularJS (nie) nadaje się do dużych pojektów.
AngularJS (nie) nadaje się do dużych pojektów.AngularJS (nie) nadaje się do dużych pojektów.
AngularJS (nie) nadaje się do dużych pojektów.
 
Podstawy programowania w Drupalu - Drupal idzie na studia - Jarosław Sobiecki
Podstawy programowania w Drupalu - Drupal idzie na studia - Jarosław SobieckiPodstawy programowania w Drupalu - Drupal idzie na studia - Jarosław Sobiecki
Podstawy programowania w Drupalu - Drupal idzie na studia - Jarosław Sobiecki
 
Środowisko testowe pod REST-a
Środowisko testowe pod REST-aŚrodowisko testowe pod REST-a
Środowisko testowe pod REST-a
 
20060416 Azure Boot Camp 2016- Azure Data Lake Storage and Analytics
20060416   Azure Boot Camp 2016- Azure Data Lake Storage and Analytics20060416   Azure Boot Camp 2016- Azure Data Lake Storage and Analytics
20060416 Azure Boot Camp 2016- Azure Data Lake Storage and Analytics
 
Encje w drupalu - DrupalCamp Wroclaw 2015
Encje w drupalu - DrupalCamp Wroclaw 2015Encje w drupalu - DrupalCamp Wroclaw 2015
Encje w drupalu - DrupalCamp Wroclaw 2015
 
Torquebox
TorqueboxTorquebox
Torquebox
 
Angular 4 pragmatycznie
Angular 4 pragmatycznieAngular 4 pragmatycznie
Angular 4 pragmatycznie
 
Mongodb with Rails
Mongodb with RailsMongodb with Rails
Mongodb with Rails
 
HYC - Angular stań się kanciastym
HYC - Angular stań się kanciastymHYC - Angular stań się kanciastym
HYC - Angular stań się kanciastym
 

Plus de The Software House

Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...The Software House
 
Jak efektywnie podejść do certyfikacji w AWS?
Jak efektywnie podejść do certyfikacji w AWS?Jak efektywnie podejść do certyfikacji w AWS?
Jak efektywnie podejść do certyfikacji w AWS?The Software House
 
O co chodzi z tą dostępnością cyfrową?
O co chodzi z tą dostępnością cyfrową?O co chodzi z tą dostępnością cyfrową?
O co chodzi z tą dostępnością cyfrową?The Software House
 
Chat tekstowy z użyciem Amazon Chime
Chat tekstowy z użyciem Amazon ChimeChat tekstowy z użyciem Amazon Chime
Chat tekstowy z użyciem Amazon ChimeThe Software House
 
Jak nie zwariować z architekturą Serverless?
Jak nie zwariować z architekturą Serverless?Jak nie zwariować z architekturą Serverless?
Jak nie zwariować z architekturą Serverless?The Software House
 
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWSAnaliza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWSThe Software House
 
Feature flags na ratunek projektu w JavaScript
Feature flags na ratunek projektu w JavaScriptFeature flags na ratunek projektu w JavaScript
Feature flags na ratunek projektu w JavaScriptThe Software House
 
Typowanie nominalne w TypeScript
Typowanie nominalne w TypeScriptTypowanie nominalne w TypeScript
Typowanie nominalne w TypeScriptThe Software House
 
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQLAutomatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQLThe Software House
 
Serverless Compose vs hurtownia danych
Serverless Compose vs hurtownia danychServerless Compose vs hurtownia danych
Serverless Compose vs hurtownia danychThe Software House
 
Testy API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciTesty API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciThe Software House
 
Jak skutecznie read model. Case study
Jak skutecznie read model. Case studyJak skutecznie read model. Case study
Jak skutecznie read model. Case studyThe Software House
 
Firestore czyli ognista baza od giganta z Doliny Krzemowej
Firestore czyli ognista baza od giganta z Doliny KrzemowejFirestore czyli ognista baza od giganta z Doliny Krzemowej
Firestore czyli ognista baza od giganta z Doliny KrzemowejThe Software House
 
Jak utrzymać stado Lambd w ryzach
Jak utrzymać stado Lambd w ryzachJak utrzymać stado Lambd w ryzach
Jak utrzymać stado Lambd w ryzachThe Software House
 
O łączeniu Storyblok i Next.js
O łączeniu Storyblok i Next.jsO łączeniu Storyblok i Next.js
O łączeniu Storyblok i Next.jsThe Software House
 
Amazon Step Functions. Sposób na implementację procesów w chmurze
Amazon Step Functions. Sposób na implementację procesów w chmurzeAmazon Step Functions. Sposób na implementację procesów w chmurze
Amazon Step Functions. Sposób na implementację procesów w chmurzeThe Software House
 
Od Figmy do gotowej aplikacji bez linijki kodu
Od Figmy do gotowej aplikacji bez linijki koduOd Figmy do gotowej aplikacji bez linijki kodu
Od Figmy do gotowej aplikacji bez linijki koduThe Software House
 

Plus de The Software House (20)

Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
 
Uszanowanko Podsumowanko
Uszanowanko PodsumowankoUszanowanko Podsumowanko
Uszanowanko Podsumowanko
 
Jak efektywnie podejść do certyfikacji w AWS?
Jak efektywnie podejść do certyfikacji w AWS?Jak efektywnie podejść do certyfikacji w AWS?
Jak efektywnie podejść do certyfikacji w AWS?
 
O co chodzi z tą dostępnością cyfrową?
O co chodzi z tą dostępnością cyfrową?O co chodzi z tą dostępnością cyfrową?
O co chodzi z tą dostępnością cyfrową?
 
Chat tekstowy z użyciem Amazon Chime
Chat tekstowy z użyciem Amazon ChimeChat tekstowy z użyciem Amazon Chime
Chat tekstowy z użyciem Amazon Chime
 
Migracje danych serverless
Migracje danych serverlessMigracje danych serverless
Migracje danych serverless
 
Jak nie zwariować z architekturą Serverless?
Jak nie zwariować z architekturą Serverless?Jak nie zwariować z architekturą Serverless?
Jak nie zwariować z architekturą Serverless?
 
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWSAnaliza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
 
Feature flags na ratunek projektu w JavaScript
Feature flags na ratunek projektu w JavaScriptFeature flags na ratunek projektu w JavaScript
Feature flags na ratunek projektu w JavaScript
 
Typowanie nominalne w TypeScript
Typowanie nominalne w TypeScriptTypowanie nominalne w TypeScript
Typowanie nominalne w TypeScript
 
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQLAutomatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
 
Serverless Compose vs hurtownia danych
Serverless Compose vs hurtownia danychServerless Compose vs hurtownia danych
Serverless Compose vs hurtownia danych
 
Testy API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciTesty API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięci
 
Jak skutecznie read model. Case study
Jak skutecznie read model. Case studyJak skutecznie read model. Case study
Jak skutecznie read model. Case study
 
Firestore czyli ognista baza od giganta z Doliny Krzemowej
Firestore czyli ognista baza od giganta z Doliny KrzemowejFirestore czyli ognista baza od giganta z Doliny Krzemowej
Firestore czyli ognista baza od giganta z Doliny Krzemowej
 
Jak utrzymać stado Lambd w ryzach
Jak utrzymać stado Lambd w ryzachJak utrzymać stado Lambd w ryzach
Jak utrzymać stado Lambd w ryzach
 
Jak poskromić AWS?
Jak poskromić AWS?Jak poskromić AWS?
Jak poskromić AWS?
 
O łączeniu Storyblok i Next.js
O łączeniu Storyblok i Next.jsO łączeniu Storyblok i Next.js
O łączeniu Storyblok i Next.js
 
Amazon Step Functions. Sposób na implementację procesów w chmurze
Amazon Step Functions. Sposób na implementację procesów w chmurzeAmazon Step Functions. Sposób na implementację procesów w chmurze
Amazon Step Functions. Sposób na implementację procesów w chmurze
 
Od Figmy do gotowej aplikacji bez linijki kodu
Od Figmy do gotowej aplikacji bez linijki koduOd Figmy do gotowej aplikacji bez linijki kodu
Od Figmy do gotowej aplikacji bez linijki kodu
 

REvolution, czyli o bardziej obiektowym podejściu w Railsach

  • 1. REVOLUTION OBIEKTOWE PODEJŚCIE DO ROZWIĄZAŃ KOLEJOWYCH Tomek Jasiulek Twitter: @TomaszJasiulek Github: tomasz-jasiulek
  • 5. PODSTAWOWY ZESTAW NARZĘDZI KOLEJARZA • Kontroler / Mailer • Model • Widok/Szablon • Helper
  • 6. ZALETY • Łatwe w użyciu • Proste do nauki • Szybki proces developmentu • Dużo dostępnej informacji - guides, stack-overflow, dokumentacja • Sprawdza się w małych projektach
  • 7. WADY • Helper’y zaśmiecają globalną przestrzeń • Przerośnięte modele • Skomplikowany kod kontrolerów • Łamanie SRP • Kod Spaghetti w przypadku bardziej skomplikowanej logiki biznesowej • Callback hell
  • 8. FAT MODEL, SKINNY CONTROLLER • Jeszcze bardziej rozdmuchane modele • Zgrabniejszy kod kontrolerów • Przeniesienie problemu w inne miejsce • No i dalej mamy kłopoty…
  • 10. OOP NA RATUNEK • SINGLE RESPONSIBILITY • OPEN-CLOSE • LISKOV SUBSTITUTION • INTERFACE SEGREGATION • DEPENDENCY INVERSION PRINCIPLE • LAW OF DEMETER • INHERITANCE • COMPOSITION • DELEGATION
  • 13.
  • 14. IDZIEMY NA DIETĘ… A NASZ CELTO: • Klasy modeli ActiveRecord i tak mają dużą odpowiedzialność - nie dokładajmy im dodaktowego ciężaru - potrzebna im dieta • Klasy kontrolerów ActionController powinny być zgrabne, by widoczny był przepływ informacji od żądania do odpowiedzi serwera - niekoniecznie wszystkie szczegóły logiki biznesowej • Szablony HTML, ERB, HAML - czyste, przejrzyste, bez zbędnej logiki zaciemniającej strukturę widoku • Helpery - w railsach i tak jest ich dużo, nie dokładajmy specyficznych zachowań do globalnej przestrzeni nazw
  • 15. DODATKOWE SKUTKI DIETY • Łatwiejsze testowanie aplikacji • Oprogramowanie bardziej odporne na zmiany • Kod rozdzielony na mniejsze i prostsze do ogarnięcia klasy o zawężonej odpowiedzialności (klasy PORO)
  • 16. CZEGO BĘDZIE WYMAGAĆ OD NAS DIETA? • Dyscypliny • Myślenia • Implementacji dodatkowych klas - w większości PORO
  • 17. DEKORATOR • Tak naprawdę od tego wszystko się zaczyna • Podstawa wielu innych rozwiązań • Rózni się tylko intencja programisty - jego zamiar wobec dekorowanego obiektu
  • 18. DEKORATOR • Z wykorzystaniem kompozycji dodajemy, zmieniamy lub rozszerzamy bieżące zachowanie obiektu z poszanowaniem zasady zamknięcia - dekorowany obiekt pozostaje nietknięty, a jednocześnie otwarty na rozszerzenie. • Proste w implementacji w Ruby ze względu na duck typing
  • 19. PRESENTER • Pozwalają uporządkować kod odpowiadający za prezentację obiektu • Odciążają klasy modelowe z metod związanych z prezentacją danych w określonych formatach • Mniej helperów i metod z przedrostkami w widokach
  • 20. PRESENTER - KLASA BAZOWA class BasePresenter attr_reader :object, :template alias_method :h, :template delegate :t, :current_locale, to: :h def initialize(object, template) @object = object @template = template end end
  • 21. PRESENTER - HELPER module ApplicationHelper def present(object, klass = nil) klass ||= "#{object.class}Presenter".safe_constantize return unless klass presenter = klass.new(object, self) yield presenter if block_given? presenter end end
  • 22.
  • 23. PRESENTER - JAKO MODUŁ module TaggablePresenter def tags_section return if object_tags.empty? h.content_tag(:section, tags, class: 'keywords') end alias_method :keywords_section, :tags_section def tags return if object_tags.empty? h.capture do h.content_tag(:span) do h.concat t('.tags') + ' ' h.concat comma_separated_linked_tags end end end alias_method :keywords, :tags private def object_tags object.tags_for_locale(current_locale) end def linked_tags object_tags.map do |tag| h.link_to(tag.name, h.search_path(q: tag.name)) end end def comma_separated_linked_tags separate_by_comma(linked_tags) end end
  • 24. PRESENTER - PRZYKŁADOWA KLASA class EventPresenter < BasePresenter include TaggablePresenter alias_method :event, :object delegate :event_type, :venue, :name, to: :event def summary to_safe_html event.summary end def start_date(date_format = :medium_datetime) if date_format.eql?(:date) h.l event.start_date.to_date else h.l event.start_date, format: date_format end end def description to_safe_html event.description end def event_type_logo_url h.image_url("/events/types/#{event_type_name_underscored}.png") end def event_type_name event_type.name end def event_type_name_underscored event_type_name.downcase.tr(' ', '_') end def organizer return 'USZANOWANKO!!!' if event.organised_by_up? event.organiser_name end def event_coverage if event.event_coverage.present? && event.event_coverage.published? event.event_coverage end end private def to_safe_html(text) text.to_s.html_safe end end
  • 25.
  • 26. PRESENTER - SZABLON HTML - present event do |presenter| .header = image_tag(presenter.event_type_logo_url, alt: presenter.event_type_name) %h3= link_to presenter.name, event %span.date= presenter.start_date .content %p= presenter.summary .details %p = t '.venue' %strong= presenter.venue %br = t '.organiser' %strong = presenter.organizer %span.more = link_to t('.details'), event
  • 27. PRESENTER - PODSUMOWANIE Zalety: • Jasne rozdzielenie logiki prezentacji od samej formy prezentacji(szablonu) • Przejrzysty szablony(erb, haml itd…) UWAGA! • Mieszanie odpowiedzialności - presenter nie powinien tworzyć skomplikowanej struktury HTML a jedynie formatować dane i przygotowywać do prezentacji w formie np. HTML
  • 28.
  • 29. SERIALIZER - KREWNIAK PRESENTER’A GEM: ACTIVE_MODEL_SERIALIZERS Cechy: • Obiektowe podeście do serializacji • Prezentuje obiekt w formacie JSON • Idea podobna, tylko inny efekt końcowy Zalety: • Odciążenie modeli oraz kontrolerów od odpowiedzialności za serializację obiektów do formatu JSON • Przeniesie tej odpowiedzialności do konkretnych klas serializerów, adekwatnych do przypadków użycia
  • 30. SERVICE OBJECT • Dedykowane klasy realizujące logikę biznesową • Wyciągamy logikę biznesową z kontrolerów i modeli i enkapsulujemy ją w postaci dedykowanych klas • Wykorzystanie kompozycji • Łatwe wykorzystanie klasy w innym kontekście np. w tasku rake’owym, workerze
  • 31. SERVICE OBJECT - PRZYKŁAD class NewsletterSubscription < ActiveRecord::Base belongs_to :user validates :email, presence: true, uniqueness: true, format: Devise.email_regexp validates :accept_terms, acceptance: { accept: true } end class UserSubscriber attr_accessor :user def initialize(user) @user = user end def call subscription = NewsletterSubscription.new subscription.user = @user subscription.email = @user.email subscription.subscribed = true subscription.accept_terms = true subscription.subscribe_date = Time.current subscription.save! end end
  • 32. SERVICE OBJECTS - PODSUMOWANIE • Pozbywamy się zbędnych callbacków z modeli • Zwiększamy czytelność kodu kontrolerów, dzięki wyodrębnieniu logiki biznesowej w osobne miejsce • Modele nie sprawiają niespodzianek np. w przypadku importu (wysyłanie maili w callbackach itp.)
  • 33.
  • 34. VALUE OBJECT • Dedykowany klasa, która enkapsuluje wartość oraz jej specyficzne zachowanie • Można powiedzieć, że taki wrapper na prymitywne wartości lub wartości kalkulowane dynamicznie • Nie zmieniają swojego wewnętrznego stanu • Identyfikowany przez wartość • Pozwala na porównywanie, sortowanie itp. • Przykład: Fixnum, Range, Money
  • 35. VALUE OBJECT - PRZYKŁAD class Ratio include Comparable extend Forwardable def_delegators :value, :zero? attr_reader :teachers, :students, :value def self.zero new(0, 0) end def initialize(teachers, students) @teachers = teachers.to_f @students = students.to_f if students == 0 @value = 0.0 else @value = @teachers/@students end end def <=>(other) value <=> other.value end def to_s "#{teachers.round}:#{students.round}" end end
  • 36. VALUE OBJECT - INNE PRZYKŁADY • NUMERTELEFONU - możliwość wyodrebnienia numeru kierunkowego, pełnego numeru w postaci łańcucha tekstowego • ADRES EMAIL - możliwość wyodrębnienia nazwy użytkownika, domeny lub pełnego w postaci łańcucha tekstowego
  • 37. VALUE OBJECT - PODSUMOWANIE • Zachowanie pewnej klasy obiektów w jednym miejscu - a nie rozsiane po całej aplikacji • Ewentualne zmiany, rozszerzenia wymagają zmian tylko i wyłącznie w jednej klasie • Operujemy jeden poziom wyżej - operowanie na prymitywach niesie za sobą zagrożenia i ograniczenia
  • 38.
  • 39. ZAGADKA? class Car < ActiveRecord::Base enum air_conditioning: { blank: 0, manual: 1, climatronic: 2 } end CO ZWRÓCI WYWOŁANIE: car = Car.new car.air_conditioning = 'climatronic' car.present?
  • 42. NA RATUNEK NULL OBJECT • Alernatywa dla: object.nil?, object.kind_of?, object.present? • Implementuje interfejs obiektu zastępowanego • Obiekt zastępczy, który udaje obiekt zastępowany, gdy ten nie istnieje(np. nie ma go w bazie/repozytorium)
  • 43. NULL OBJECT - PRZYKŁAD class SidebarPresenter < BasePresenter def render_items h.capture do sidebar_items.each do |sidebar_item| h.concat render_sidebar_item(sidebar_item) end end end def sidebar @sidebar ||= home? ? Sidebar.home : Sidebar.primary @sidebar ||= Domain::NullSidebar.new end private def sidebar_items sidebar.sidebar_items.includes(:sidebar_item_type) end def render_sidebar_item(item) presenter = SidebarItems::PresenterFactory.create(item, h) presenter.render_item end def home? h.controller_name.eql?('home') end end
  • 44. NULL OBJECT - PRZYKŁAD class NullSidebar < NullObject def sidebar_items SidebarItem.none end end class NullObject def method_missing(*args, &block) self end end najprostsza implementacja(ma kilka wad)
  • 45. NULL OBJECT - PODSUMOWANIE • Nigdy więcej undefined method nazwa_metody for nil:NilClass • Można skupić się na zadaniu, zamiast ciągłym sprawdzaniu wartości lub tożsamości obiektów UWAGA! • Należy uważać na trudne do wykrycia błędy, która na pierwszy rzut oka wyglądają jak normalne działanie programu
  • 46.
  • 48. FORM OBJECT Sposób na ogarnięcie skomplikowanych formularzy i rozprawienie się z accepts_nested_attributes_for.W skrócie klasa modelowa, ale nie dziedzicząca po ActiveRecord::Base(tak, takie klasy też istnieją i mogą być modelami), której obiekty trzymają stan obiektu formularza i enkapsulują np. możliwe opcje, walidacje w danym przypadku użycia
  • 49. FORM OBJECT • ActiveModel::Model • Virtus • Reform • …
  • 50. QUERY OBJECT Sposób na łańcuszek wywołań na relacjach ActiveRecord oraz na inne skomplikowane zapytania do bazy danych.
  • 51. QUERY OBJECT @news = News.published .with_translations(locale) .not_promoted .visible .by_position .with_tile .merge(Tile.with_translations(locale)) .limit(limit)
  • 52. QUERY OBJECT Zasada jest prosta - wyciągamy skomplikowane zapytanie do osobnej klasy PORO a wynik wywołania udostępniamy na zewnątrz
  • 54.
  • 56. FAT MODEL SKINNY CONTROLLER? NIE! KAŻDA KLASA POWINNA SIĘ ZDROWO ODŻYWIAĆ I BYĆ SKINNY przynajmniej w założeniu… ;)
  • 57. NIE BÓJMY SIĘ PROGRAMOWANIA OBIEKTOWEGO nie jest takie trudne jak się na pierwszy rzut oka wydaje
  • 58. POMYŚLMY O PROGRAMISTACH, KTÓRZY WEJDĄ PO NAS W NASZ KOD Zróbmy wszystko, aby liczba przekleństw dążyła do zera ;)
  • 59. WYKORZYSTAJMYTO CO W RAILSACH DOBRE ale nie ograniczajmy się tylko i wyłącznie do tego co oferują
  • 61. A POWSTANIE LEKKOSTRAWNE I SMACZNE DANIE* *zakładając że logika biznesowa projektu nie jest zagmatwana ;)