Serwisy – po co i do czego?

Ostatnio w modzie jest SoA czyli Service-Oriented Architecture. Zastanowimy się dziś czym są serwisy, dlaczego są dobre i jak ich używać.

Ale zacznijmy od historii. :)

Model czy kontroler?

W sieci od dawna toczy się dyskusja – gdzie upchnąć logikę biznesową. Ciężki model – lekki kontroler czy odwrotnie? Niektórzy wrzucają wszystko do kontrolerów. Kotroler puchnie w oczach. Inni zrzucają logikę na modele tak, jakby cała logika polegała na bazodanowości aplikacji. Najczęściej kończymy z misz-maszem gdzie logika jest rozrzucona w obu.

Odpowiedzią są serwisy. Ani model ani kontroler nie powinny zajmować się biznesem. Modele przechowują dane. Kontrolery udostępniają akcje. Między nimi mamy serwisy.

Porównując do rzeczywistego świata – kontroler jest jak kierownica w aucie. Modele jak opony. Serwisy są prawdziwym silnikiem aplikacji.

Czym są serwisy?

Serwis to klasa. Może być niezależny od frameworka. Serwis będzie miał akcję – punkt wejścia. Będzie też znał modele i inne serwisy aplikacji.

Najlepiej myśleć, że serwis udostępnia komendy. Np. dodaj użytkownika. To komenda, akcja, user story. Można ją wywołać przez WWW. Można przez REST API. Możemy ją wywołać z konsoli.

Serwis będzie miał metodę, np: dodajUsera($parametry);. Sam kontroler pobierze parametry z WWW lub z innego wywołania. Przygotuje je odpowiednio i wywoła komendę. Obsłuży jej wynik i zwróci przekierowanie. Kod będzie wyglądał tak (w przykładowym PHP nie związanym z żadnym frameworkiem):

class MyController {
   public function addUserAction() {
      // pobierz parametry wywołania
      $params = $this->params();

      // pobierz serwis
      $service = $this->get('UserService');
      try {
      	  $service->addUser($params);
      } catch (\Exception $e) {
          return Response()->error($e->getMessage);
      }
      return Redirect('userAddedRoute');
   }
}

Dla wywołania przez AJAX będziemy mieli podobnie. Zamiast pobierania parametrów będzie json_decode(). Zamiast zwracania response wyślemy odpowiedni kod HTTP. Sama logika dodawania użyszkodnika się nie zmieni.

Co będzie siedziało w takim serwisie? Np. taka funkcja:

public function addUser($params) {

   // walidujemy za pomocą innego serwisu
   	$validator = $this->get('userParamsValidator');
   	$validator->validate($params);

   	// tworzymy encję z użytkownikiem
   	$user = new User();
   	$user->setEmail($params['email']);
   	$user->setPassword($params['password']);

   	// wrzucamy usera do bazy
   	$persistence = $this->get('database_service');
   	$persistence->persist($user);
   	$persistence->flush();

   	// wysyłamy maila
   	$mailer = $this->get('mailer');
   	$mailer->send($user->getEmail,'Dziękujemy za rejestrację','...');

   	// logujemy
   	$logger = $this->get('logger');
   	$logger->info(sprintf('User %s has been registered',$user->getEmail()));
}

Widzimy, że serwisy intensywnie korzystają z innych serwisów. Zakładając, że $this->get() zwraca nam odpowiedni serwis możemy elegancko ułożyć strukturę naszej aplikacji. Jeśli wszystkie serwisy będą rzucać wyjątkami obsługa błędów też jest łatwa.

Taki kod jest niezależny od wywołania. Nic nie stoi na przeszkodzie aby dodać komunikację w XML, AJAX, MQTT czy w dowolny inny sposób. Nawet importer dużej liczby użytkowników nie będzie problemem – po prostu wywołamy komendę serwisu wiele razy.

Co do serwisu, co do kontrolera?

Kiedy więc mamy umieszczać kod w serwisie a kiedy w kontrolerze? Zróbmy małą ściągę:

  • Jeśli kod jest niezależny od sposobu wywołania – serwis
  • Jeśli kod ma bezpośredni kontakt z wejściem i wyjściem – kontroler
  • Jeśli musimy zrobić copy-paste kodu do innego kontrolera – raczej nadaje się do serwisu
  • Jeśli musimy pisać w serwisie wiele komend, które zasadniczo robią to samo a różnią się parametrami – do kontrolera
  • Jeśli mamy przechowywać sesję – kontroler
  • Jeśli wiele miejsc w aplikacji korzysta z tego wywołania – serwis
  • Jeśli mamy ochotę wywołać coś przez kontroler ale czasem „z palca” w linii komend – serwis
  • Jeśli kod jest tylko dla WWW, tylko dla AJAXa, tylko dla REST API – kontroler

W idealnej sytuacji – kontrolery są chude. Nic nie robią oprócz wywołania odpowiednich komend. Mogą jedynie czytać i dodawać nagłówki HTTP i parametry.

Przykłady

Kilka przykładowych problemów:

  • Zapis i obsługa bazy danych – serwis
  • Logowanie – serwis
  • Wysyłanie maili – serwis
  • Walidacja parametrów – serwis
  • Konwersja wyjścia na JSON – kontroler
  • Obsługa sesji – kontroler
  • Wypełnienie widoków – kontroler
  • Zebranie listy błędów do wyświetlenia – raczej kontroler
  • Logika biznesowa – serwis

Co dalej?

Warto przeczytać interesujący artykuł o serwisach. Ciekawe spojrzenie na architekturę daje też wykład Roberta Martina.

Wkrótce napiszę więcej o serwisach. Okazuje się, że serwis serwisowi nierówny. :)

6 myśli na temat “Serwisy – po co i do czego?”

  1. Dobra zajawka tematu. ” serwis serwisowi nierówny ” , no właśnie czym innym jest serwis w SOA a czym innym w architekturze MSA. Fajne poruszasz tematy, które związane są architekturami opartymi o serwisy: protokoły, REST, jabyś poruszył temat messagingu – technologii, które ułatwiają komunikację między serwisami – i byłaby GITara.

    Tak jeszcze dodam, że schemat MVC z art. Ben’a to najbardziej klarowne wytłumaczenie tego wzorca i świetnie wyjaśnia podstawy działania aplikacji webowych.

    1. O serwisach będę jeszcze pisał niebawem. Temat w przygotowaniu. Dzięki za podpowiedź z messagingiem, masz jakieś interesujące linki na ten temat?

  2. A mnie tylko w tym wszystkim denerwuje nazwa serwis – jako odpowiednik service, wydaje mi się że poprawniej było by to nazywać usługami.

    1. Jest w tym trochę racji. Tylko tłumacząc to lepiej mamy architekturę zorientowaną usługowo (AZU) co jest już bardzo dalekie od angielskieko SOA. :)

  3. Tak, bo pamiętaj, że to jest serwis a nie model. Przełóżmy to na życie, masz dwa przypadki:

    1. Szef firmy mówi do kadrowej „zatrudnijcie mi kuzyna mojej znajomej”
    2. Informatyk firmowy tworzy konto użytkownika „Kuzyn Znajomej”

    Obie akcje to utworzenie/zatrudnienie użytkownika w firmie ale na zupełnie innym poziomie. W pierwszym kadrowa jest serwisem, musi zadzwonić do kandydata, zwalidować, że jest dostępny, umówić na rozmowę, podpisać umowę, zlecić informatykowi założenie kont. W drugim dodajemy tylko rekord do bazy.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *