window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster już istnieje') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() CZEŚĆ, JESTEM PORO - The Codest
The Codest
  • O nas
  • Nasze Usługi
    • Software Development
      • Frontend Development
      • Backend Development
    • Zespoły IT
      • Programiści frontendowi
      • Backend Dev
      • Inżynierowie danych
      • Inżynierowie rozwiązań chmurowych
      • Inżynierowie QA
      • Inne
    • Konsultacje IT
      • Audyt i doradztwo
  • Branże
    • Fintech i bankowość
    • E-commerce
    • Adtech
    • Healthtech
    • Produkcja
    • Logistyka
    • Motoryzacja
    • IOT
  • Wartość dla
    • CEO
    • CTO
    • Delivery Managera
  • Nasz zespół
  • Case Studies
  • Nasze Know How
    • Blog
    • Meetups
    • Webinary
    • Raporty
Kariera Skontaktuj się z nami
  • O nas
  • Nasze Usługi
    • Software Development
      • Frontend Development
      • Backend Development
    • Zespoły IT
      • Programiści frontendowi
      • Backend Dev
      • Inżynierowie danych
      • Inżynierowie rozwiązań chmurowych
      • Inżynierowie QA
      • Inne
    • Konsultacje IT
      • Audyt i doradztwo
  • Wartość dla
    • CEO
    • CTO
    • Delivery Managera
  • Nasz zespół
  • Case Studies
  • Nasze Know How
    • Blog
    • Meetups
    • Webinary
    • Raporty
Kariera Skontaktuj się z nami
Strzałka w tył WSTECZ
2018-01-03
Software Development

CZEŚĆ, JESTEM PORO

Katarzyna Jaruga

Wiele osób uczy się Rubiego zaczynając od frameworka Rails i niestety jest to najgorszy możliwy sposób nauki tego języka. Nie zrozum mnie źle: Railsy są świetne, pomagają budować aplikacje internetowe szybko i wydajnie bez konieczności zagłębiania się w wiele szczegółów technicznych.

Miło cię poznać!

Wiele osób uczy się Rubiego zaczynając od frameworka Rails i niestety jest to najgorszy możliwy sposób nauki tego języka. Nie zrozum mnie źle: Railsy są świetne, pomagają budować aplikacje internetowe szybko i wydajnie bez konieczności zagłębiania się w wiele szczegółów technicznych. Zapewnia wiele "magii Railsów", która sprawia, że rzeczy po prostu działają. Dla początkującego programisty jest to naprawdę świetne, ponieważ najprzyjemniejszym momentem procesu jest ten, w którym możesz powiedzieć "to żyje!" i zobaczyć, że wszystkie części pasują do siebie, a ludzie używają twojej aplikacji. Lubimy być "twórcami" 🙂 Ale jest jedna rzecz, która odróżnia dobrych programistów od przeciętnych: ci dobrzy rozumieją, jak działają narzędzia, których używają. I przez "zrozumienie narzędzi" nie mam na myśli znajomości wszystkich metod i modułów dostarczanych przez framework, ale zrozumienie, jak to działa, zrozumienie, jak dzieje się "magia Railsów". Tylko wtedy możesz czuć się komfortowo używając obiektów i programując w Railsach. Podstawą programowania obiektowego i tajną bronią, która sprawia, że skomplikowana aplikacja Railsowa staje się łatwiejsza, jest wspomniane już w tytule PORO, czyli Plain Old Ruby Object.

Co tak naprawdę kryje się pod tą nazwą? Czym jest ta wielka tajna broń? Jest to prosta klasa Ruby, która nie dziedziczy po niczym. Tak, tylko tyle i aż tyle.

class AwesomePoro
koniec

Jak mogę ci pomóc?

Nieustannie rozwijasz swoją aplikację i dodajesz nowe funkcjonalności wraz ze wzrostem liczby użytkowników i ich oczekiwań. Dochodzisz do punktu, w którym napotykasz coraz więcej ciemnych miejsc o wyjątkowo pokręconej logice, miejsc, których unikają jak zarazy nawet najodważniejsi deweloperzy. Im więcej takich miejsc, tym trudniej zarządzać i rozwijać aplikację. Standardowym przykładem jest akcja rejestracji nowego użytkownika, która wywołuje całą grupę innych akcji powiązanych z tym zdarzeniem:

  • sprawdzanie adresu IP w bazie danych spamu,
  • wysłanie wiadomości e-mail do nowego użytkownika,
  • dodanie bonusu do konta polecającego użytkownika,
  • tworzenie kont w powiązanych usługach,
  • i wiele innych...

Próbka kod odpowiedzialny za rejestrację użytkownika może wyglądać następująco:

class RegistrationController < ApplicationController
  def create
    user = User.new(registration_params)
    if user.valid? && ip_valid?(registration_ip)
      user.save!
      user.add_bonuses
      user.synchronize_related_accounts
      user.send_email
    end
  end
end

Okej, masz to zakodowane, wszystko działa, ale... czy cały ten kod jest naprawdę w porządku? Może moglibyśmy napisać go lepiej? Po pierwsze, łamie on podstawową zasadę programowania - Single Responsibility, więc z pewnością moglibyśmy napisać go lepiej. Ale jak? Tutaj z pomocą przychodzi wspomniane już PORO. Wystarczy wydzielić klasę RegistrationService, która będzie odpowiedzialna tylko za jedną rzecz: powiadamianie wszystkich powiązanych usług. Przez usługi będziemy rozumieć poszczególne akcje, które wyodrębniliśmy już powyżej. W tym samym kontrolerze wystarczy utworzyć obiekt RegistrationService i wywołać na nim metodę "fire!". Kod stał się o wiele bardziej przejrzysty, nasz kontroler zajmuje mniej miejsca, a każda z nowo utworzonych klas jest teraz odpowiedzialna tylko za jedną akcję, dzięki czemu możemy je łatwo zastąpić, jeśli zajdzie taka potrzeba.

class RegistrationService
  def fire!(params)
    user = User.new(params)
    if user.valid? && ip_validator.valid?(registration_ip)
      user.save!
      after_registered_events(user)
    end
    użytkownik
  end
  private
  def after_registered_events(user)
    BonusesCreator.new.fire!(user)
    AccountsSynchronizator.fire!(user)
    EmailSender.fire!(użytkownik)
  end
  def ip_validator
    @ip_validator ||= IpValidator.new
  end
end
class RegistrationController < ApplicationController
  def create
    user = RegistrationService.new.fire!(registration_params)
  end
end

Jednak Plain Old Ruby Object może okazać się przydatny nie tylko dla kontrolerów. Wyobraźmy sobie, że tworzona przez nas aplikacja korzysta z miesięcznego systemu rozliczeń. Dokładny dzień utworzenia takiego rozliczenia nie jest dla nas istotny, musimy jedynie wiedzieć, że dotyczy on konkretnego miesiąca i roku. Oczywiście możesz ustawić dzień na pierwszy dzień każdego miesiąca i przechowywać tę informację w obiekcie klasy "Date", ale ani nie jest to prawdziwa informacja, ani nie potrzebujesz jej w swojej aplikacji. Za pomocą PORO można utworzyć klasę "MonthOfYear", której obiekty będą przechowywać dokładnie te informacje, których potrzebujesz. Co więcej, po zastosowaniu w niej modułu "Comparable" możliwe będzie iterowanie i porównywanie jej obiektów, tak jak w przypadku korzystania z klasy Date.

class MonthOfYear
  include Comparable
  attr_reader :year, :month
  def initialize(month, year)
    raise ArgumentError unless month.between?(1, 12)
    @year, @month = rok, miesiąc
  end
  def (other)
    [year, month]  [other.year, other.month]
  end
end

Przedstaw mi Railsy.

W świecie Railsów jesteśmy przyzwyczajeni do tego, że każda klasa jest modelem, widokiem lub kontrolerem. Mają one również swoją dokładną lokalizację w strukturze katalogów, więc gdzie można umieścić naszą małą armię PORO? Rozważmy kilka opcji. Pierwsza myśl jaka przychodzi do głowy to: skoro tworzone klasy nie są ani modelami, ani widokami, ani kontrolerami, to powinniśmy je wszystkie umieścić w katalogu "/lib". Teoretycznie jest to dobry pomysł, jednak jeśli wszystkie pliki PORO wylądują w jednym katalogu, a aplikacja będzie duża, katalog ten szybko stanie się ciemnym miejscem, które strach będzie otworzyć. Dlatego bez wątpienia nie jest to dobry pomysł.

AwesomeProject
├──app
│ ├─kontrolery
│ ├─modele
│ └─widoki
│
└─lib
  └─services
      #all poro here

Możesz również nazwać niektóre ze swoich klas nie-ActiveRecord Models i umieścić je w katalogu "app/models", a te, które są odpowiedzialne za obsługę innych klas, nazwać usługami i umieścić je w katalogu "app/services". Jest to całkiem dobre rozwiązanie, ale ma jedną wadę: podczas tworzenia nowego PORO za każdym razem będziesz musiał zdecydować, czy jest to bardziej model czy usługa. W ten sposób może dojść do sytuacji, w której mamy dwa ciemne miejsca w aplikacji, tylko mniejsze. Jest jeszcze trzecie podejście, a mianowicie: używanie klas i modułów z przestrzenią nazw. Wystarczy utworzyć katalog o takiej samej nazwie jak kontroler lub model i umieścić w nim wszystkie pliki PORO używane przez dany kontroler lub model.

AwesomeProject
├──app
│ ├─kontrolery
│ │ ├─registration_controller
│ │ └─registration_service.rb
│ │ └─registration_controller.rb
│ ├─models
│ │ ├─settlement
│ │ │ └─month_of_year.rb
│ │ └─settlement.rb
│ └─views
│
└─lib

Dzięki takiemu rozwiązaniu nie trzeba poprzedzać nazwy klasy przestrzenią nazw. Zyskujesz krótszy kod i bardziej logicznie zorganizowaną strukturę katalogów.

Sprawdź mnie!

Miłą niespodzianką jest to, że podczas korzystania z PORO testy jednostkowe aplikacji są szybsze i łatwiejsze do napisania, a później bardziej zrozumiałe dla innych. Ponieważ każda klasa jest teraz odpowiedzialna tylko za jedną rzecz, można szybciej rozpoznać warunki brzegowe i łatwo dodać do nich odpowiednie scenariusze testowe.

describe MonthOfYear do
  subject { MonthOfYear.new(11, 2015) }
  it { should be_kind_of Comparable }
  describe "tworzenie nowej instancji" do
    it "inicjalizuje z poprawnym rokiem i miesiącem" do
      expect { described_class.new(10, 2015) }.to_not raise_error
    end
    it "zgłasza błąd, gdy podany miesiąc jest nieprawidłowy" do
      expect { described_class.new(0, 2015) }.to raise_error(ArgumentError)
      expect { described_class.new(13, 2015) }.to raise_error(ArgumentError)
    end
  end
end

Mam nadzieję, że jeszcze się spotkamy!

Zaprezentowane przez nas przykłady wyraźnie pokazują, że stosowanie PORO poprawia czytelność aplikacji i czyni je bardziej modułowymi, a w konsekwencji łatwiejszymi w zarządzaniu i rozbudowie. Przyjęcie zasady Single Responsibility ułatwia wymianę poszczególnych klas w razie potrzeby i to bez ingerencji w inne elementy. Sprawia również, że ich testowanie jest prostsze i szybsze. Co więcej, w ten sposób utrzymanie modeli i kontrolerów Rails jest znacznie łatwiejsze, a wszyscy wiemy, że mają one tendencję do niepotrzebnego powiększania się w procesie rozwoju.

Powiązane artykuły

Software Development

Tworzenie przyszłościowych aplikacji internetowych: spostrzeżenia zespołu ekspertów The Codest

Odkryj, w jaki sposób The Codest wyróżnia się w tworzeniu skalowalnych, interaktywnych aplikacji internetowych przy użyciu najnowocześniejszych technologii, zapewniając płynne doświadczenia użytkowników na wszystkich platformach. Dowiedz się, w jaki sposób nasza wiedza napędza transformację cyfrową i biznes...

THEECODEST
Software Development

10 najlepszych firm tworzących oprogramowanie na Łotwie

Dowiedz się więcej o najlepszych łotewskich firmach programistycznych i ich innowacyjnych rozwiązaniach w naszym najnowszym artykule. Odkryj, w jaki sposób ci liderzy technologiczni mogą pomóc w rozwoju Twojej firmy.

thecodest
Rozwiązania dla przedsiębiorstw i scaleupów

Podstawy tworzenia oprogramowania Java: Przewodnik po skutecznym outsourcingu

Zapoznaj się z tym niezbędnym przewodnikiem na temat skutecznego tworzenia oprogramowania Java outsourcing, aby zwiększyć wydajność, uzyskać dostęp do wiedzy specjalistycznej i osiągnąć sukces projektu z The Codest.

thecodest
Software Development

Kompletny przewodnik po outsourcingu w Polsce

Wzrost liczby outsourcing w Polsce jest napędzany przez postęp gospodarczy, edukacyjny i technologiczny, sprzyjający rozwojowi IT i przyjazny klimat dla biznesu.

TheCodest
Rozwiązania dla przedsiębiorstw i scaleupów

Kompletny przewodnik po narzędziach i technikach audytu IT

Audyty IT zapewniają bezpieczne, wydajne i zgodne z przepisami systemy. Dowiedz się więcej o ich znaczeniu, czytając cały artykuł.

The Codest
Jakub Jakubowicz CTO & Współzałożyciel

Subskrybuj naszą bazę wiedzy i bądź na bieżąco!

    O nas

    The Codest - Międzynarodowa firma programistyczna z centrami technologicznymi w Polsce.

    Wielka Brytania - siedziba główna

    • Office 303B, 182-184 High Street North E6 2JA
      Londyn, Anglia

    Polska - lokalne centra technologiczne

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Warszawa, Polska

      The Codest

    • Strona główna
    • O nas
    • Nasze Usługi
    • Case Studies
    • Nasze Know How
    • Kariera
    • Słownik

      Nasze Usługi

    • Konsultacje IT
    • Software Development
    • Backend Development
    • Frontend Development
    • Zespoły IT
    • Backend Dev
    • Inżynierowie rozwiązań chmurowych
    • Inżynierowie danych
    • Inne
    • Inżynierowie QA

      Raporty

    • Fakty i mity na temat współpracy z zewnętrznym partnerem programistycznym
    • Z USA do Europy: Dlaczego amerykańskie startupy decydują się na relokację do Europy?
    • Porównanie centrów rozwoju Tech Offshore: Tech Offshore Europa (Polska), ASEAN (Filipiny), Eurazja (Turcja)
    • Jakie są największe wyzwania CTO i CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Warunki korzystania z witryny

    Copyright © 2025 by The Codest. Wszelkie prawa zastrzeżone.

    pl_PLPolish
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek pl_PLPolish