Some of posts from this blog has been moved to dywicki.pl. You will be automatically redirected to new blog if you would submit comment.
New posts are published on dywicki.pl, this blog contains old content and it is not continued.

Niektóre posty z tego bloga zostały przeniesione do dywicki.pl. Zostaniesz automatycznie przekierowany jeśli bedzięsz chciał dodać komentarz.
Nowe posty sa publikowane na dywicki.pl, ten blog zawiera stare treści i nie jest kontynuowany.

Obiekty biznesowe w aplikacji.

Filed under MVC,PHP by

Pierwsze błędy

Pamiętam swoje pierwsze implementacje MVC, w czasach gdy słowo framework nie było jeszcze trendy a wiele osób, w tym i ja, nawet go nie używało. W owych pierwszych implementacjach MVC model był pewnego rodzaju fasadą, która zapewniała dostęp do danych.
Problem polegał na tym, że kod np klasy User wyglądał następująco:

<?php
class User extends Model {
    function User(DB $db) {
        parent::Model($db);
    }

    function getById($id) {
        $sql = 'SELECT * FROM user WHERE user_id = '. $id;
        return $db->query($sql);
    }
}
?>

Jak widać na powyższym listingu klasa jest odpowiedzialna za pobieranie danych. Problem takiej implementacji polega na tym, że wciąż operujemy na tablicach bądź na ResultSetach zwracanych przez obiekt odpowiedzialny za wykonywanie zapytań. Kod w takim wykonaniu jest mocno związany z bazą danych i jest ciężki do użycia w innych projektach. Co więcej w pierwszym podejściu nie korzystałem z wielu możliwości jakie daje programowanie obiektowe i po prostu odwołania do klasy nadrzędnej czy też metody abstrakcyjne były co najmniej sporadyczne. Także, każdy “model” miał swoją metodę getById, która miała swoje zapytanie. Jest to najprostsza implementacja, która zapewnia tylko jedno – wyłączenie zapytań do oddzielnych plików.

Wzorce

Znacznie lepszym krokiem byłoby wykorzystanie możliwości chociażby dziedziczenia i użyć nazwanego przez Martina Fowlera wzorca ActiveRecord, który zapewnia nam mapowanie pojedynczej encji do klasy.

Problem, jaki powstaje przy użyciu ActiveRecordu to niestety uzależnienie kodu od wybranej implementacji wzorca, co więcej kod będzie nieprzenośny, np nie da się go użyć bez zewnętrznych bibliotek. Zatem problem pozostaje taki jak był wcześniej – logika, która była związana z danymi (np przeliczanie wartości jednego pola w zależności od drugiego) została zawarta w modelu staje się bezużyteczna.

Problemy te można rozwiązać wyraźnie oddzielając obiekty z których korzysta aplikacja od warstwy dostępu do nich. Tutaj rodzi się pojęcie Domain Model czy też Domain Object. Przede wszystkim jest to kod, który jest niezależny od źródła danych np obiekt Invoice możemy pobrać zarówno z bazy jak i z zewnętrznego systemu powiedzmy przez usługę sieciową. Obiekt zawsze zachowa się w ten sam sposób i jego użycie nie będzie zależne od miejsca z którego je uzyskaliśmy. Idealnym przykładem implementacji Domain Modelu są np beany utrwalane przy pomocy Hibernate. Mamy kod, który jest przenośny, w którym nie ma żadnych jawnych odwołań do informacji zawartych poza “obiektami domenowymi”, jest ona po prostu autonomiczna.

Ciężko jest określić czym w pierwszej kolejności się zająć bazą czy obiektami biznesowymi? Wydaje mi się, że modelując najpierw bazę danych ciężko jest wychwycić dziedziczenia pomiędzy obiektami biznesowymi i najzwyczajniej w świecie zostaną one pominięte. Z drugiej strony tworząc najpierw obiekty biznesowe możemy natrafić na trudności z odwzorowaniem całej, nie raz, złożonej struktury do encji w bazie.

Data Access Objects

Dostęp warstwy z obiektami domenowymi realizujemy przez Data Access Objects. Jest to zespół klas, które zapewniają odczyt, usuwanie oraz zapisywanie obiektów (całość modyfikujemy przez dostępne w obiektach domenowych metody). DAO ma na celu zapewnienie jednolitego interfejsu dla dostępu do obiektów bez pojawiania się kodu specyficznego dla danego źródła danych, niezależnie czy to będzie baza danych czy usługa sieciowa.

Service Layer

Warstwa usług to miejsce przecięć różnych źródeł danych. Granica między DAO a Service Layer jest dość istotna – DAO obejmuje transakcje systemowe podczas gdy Service Layer transakcje biznesowe. Może słowo wyjaśnienia na temat tych dwóch rodzai transakcji – pierwsza jest zwykle kontrolowana przez bazę danych i zawiera ciąg poleceń SQL. Transakcja biznesowa obejmuje jedną konkretną operację np przelew bankowy – to logowanie, określenie kwoty i odbiorcy, weryfikacja kodu jednorazowego oraz zablokowanie środków. Powodzenie takiej operacji zależy od wielu czynników w tym od systemów zewnętrznych.
Warstwa usług jest bardzo przydatna w chwili gdy z tej samej logiki korzysta więcej niż jeden system. Niestety nie mam wielkiego doświadczenia z takimi sytuacjami i nie czuję się na siłach by o tym pisać, a to co tu przytoczyłem to głównie to co pamiętam z PoEAA.

20 responses so far

20 Responses to “Obiekty biznesowe w aplikacji.”

  1. Strzałek says:

    Ja poproszę o wyjaśnienie lamerowi o co biega w tych Beans’ach. Co to? Jak się używa? Po co :P ?

  2. Bean to zwykła klasa, która udostępnia metody dzięki którym możesz się dobierać do danych, które hermetyzuje. Np.
    [sourcecode lang=”php”]< ?php class Author { private $books = array(); public function addBook(Book $b) { $this->books[] = $b;
    }

    public function getBooks() {
    return $this->books;
    }
    }

    class Book {
    private $title;
    private $isbn;
    private $category;

    public function setCategory(Category $c) {
    $this->category = $c;
    }

    // etc …
    }

    class Category {
    private $name;

    public function setName($n) {
    $this->name = $n;
    }
    }
    ?>[/sourcecode]

  3. NuLL says:

    Czy jak dobrze zrozumialem fasolka ;) to kontener poprostu ze zdefiniowanymi setterami i getterami ? : )

  4. Dokładnie, czasami z niewielką ilością logiki..

  5. Andrew says:
    1. Może mój komentarz jest trochę spóźniony, ale myślę, że używanie pojęcia Bean (w tym przypadku powinno być raczej Entity Bean, w odróżnieniu od innych EJB) z framework’a Java Enterprise w PHP jest lekkim nadużyciem.
      Główną zaletą EJB (Enterprise Java Bean) jest to, że można je umieścić w kontenerze, który nimi zarządza (tranzakcje, persistence. Poza J2EE na klasy tego typu mówi się po prostu Encje.
    2. “Ciężko jest określić czym w pierwszej kolejności się zająć bazą czy obiektami biznesowymi?” – no to trochę dziwne pytanie. IMHO zawsze tworzy się najpierw model domenowy a na jego podstawie buduje się warstwę biznesową. A na podstawie warstwy biznesowej myśli się jak to upchnąć do bazy danych (opcjonalnie tworząc pewne uproszczenia). Kolejność jest ważna, bo to baza pełni usługę dla modelu domenowego, a nie odwrotnie.

    Uwaga – model domenowy, o którym mówię, to nie “Domain Model” w ujęciu Fowlera, tylko w ujęciu Unified Process.

  6. Andrew – pojęcie “bean” w Javie jest starsze niż samo EJB i wykorzystałem to pojęcie w tej wierze (bez jakichkolwiek aluzji do serwerów aplikacyjnych). Zgodnie z definicją Suna:
    JavaBean jest przenośnym, niezależnym od platformy komponentem napisanym w Javie. Specyfikacja JavaBeans umożliwia tworzenie komponentów, które będą używane wielokrotne – napisz raz, uruchamiaj wszędzie.
    Samo EJB w wersji 2.x nie ma nic wspólnego z tradycyjnymi beanami, dopiero od trójki można mówić o wykorzystaniu ‘fasolek’ jako takich (JPA).
    Pytanie odnośnie kolejności prac – projekt bazy czy “warstwy domenowej” – podyktowane jest trudną odpowiedzią na nie. Prawdę powiedziawszy obiekty, które będą funkcjonować w aplikacji można wskazać bez większych problemów, po prostu powstają one same na podstawie kolejnych zdań ze specyfikacji wymagań. Próbowałem kiedyś zaprojektować taką bazę aplikacji logistycznej – największym problemem było wyszukiwanie i optymalizacja tras a nie samo utrwalanie czy odwzorowanie obiektów. Mając tabelki mogłem spokojnie z nich powiedzieć jak będą wyglądały klasy i zależności między nimi. Fakt, że nie byłem w stanie powiedzieć jakie hierarchie klas będą występować.

  7. Andrew says:
    1. A, ostatnio siedzę najczęściej w aplikacjach Enterprise i słowo Bean kojarzy mi się jednoznacznie. Ale rzeczywiście, coś takiego jak JavaBeans też istnieje ale… też nijak nie pasuje mi ich definicja do twoich przykładów (np. klasy np Author ;)
    2. Tym klasom bliżej do pojęcia POJO (z tym, że tu bym “wymyślił” skrót PPO – Plain PHP Object ;)
    3. A co do kolejności prac: zaczynając od modelu obiektowego ma się więcej swobody i łatwiejszy sposób na modelowanie rzeczywistości niż gdy “myślimy” modelem relacyjnym, który jakby nie było jest dość ograniczony (głównie brakiem generalizacji). I to miałem na myśli :)
  8. Andew Dlaczego sądzisz, że definicja klasy Author nie pasuje do JavaBeans? Co według Ciebie jest nie tak z pozostałymi klasami?
    Co do POJO. Jest to zwykły JavaBean, POJO = JavaBean – chociaż były spory czy rzeczywiście mamy tutaj do czynienia z tożsamością to nic konstruktywnego z nich nie wynikło. Samo pojęcie zaczęło funkcjonować jakiś czas przed pojawieniem się Springa i jest to odwrócenie się od ciężkich rozwiązań takich jak EJB, gdzie większość komponentów musiała implementować interfejsy, których i tak się później nie wykorzystywało.
    Spróbuję podejść do projektu zgodnie z Twoimi radami, zobaczę co uda mi się uzyskać. :)

  9. Andrew says:
    1. Jakby POJO = JavaBean to nikt by nie wymyślił tego drugiego terminu, bo po co? ;) JavaBean to przede wszystkim komponent.
    2. JavaBean to nie jest zwykła klasa. Dlatego nie można tego pojęcia rzutować na inne języki tak bezpośrednio. Żeby klasę można było nazwać Bean to musi ona:
      – mieć możliwość korzystania z niej poprzez graficzne środowisko (np dopasowywanie przez panel właściwości);
      – obsługiwać zdarzenia;
      – obsługiwać właściwości (properties);
      – i inne;
      (http://java.sun.com/products/javabeans/faq/faq.general.html#Q2)
    3. Jak pisałem, powyższej klasie Author bliżej do encji, czy zwykłego DTO.
  10. POJO to marketing. Inna nazwa pojęcia, może nie zamiennik, ale z pewnością oznacza to samo. Za Wikipedią:
    The term has most likely gained widespread acceptance because of the need for a common and easily understood term that contrasts with complicated object frameworks. A JavaBean is a POJO that is serializable, has a no-argument constructor, and allows access to properties using getter and setter methods.

    JavaBean to zwykła klasa. Nie ma w niej żadnych cudów uniemożliwiających przeniesienia pojęcia do innych języków, konstrukcji czy zachowań specyficznych tylko dla Javy. W praktyce poprawny bean zaczyna się od metod get/set.

    Samo pojęcie “fasoli” ewoluowało i już dawno wykroczyło poza erę Swingowego GUI, czego przykładem może być chociażby POJO. Można bez problemów tworzyć beany znacznie prostsze. Jeśli nie korzystasz z WYSYWG-a to nie potrzebujesz PropertyDescriptora, PropertyChangeListener jest przeznaczony dla Ciebie i jeśli nie widzisz potrzeby nie musisz propagować informacji o wszystkich zmianach.
    Zwróć uwagę, że pojęcia JavaBean używa się głównie na płaszczyźnie par metod get+set. JSP i JSTL bazuje na tej specyfikacji, ale nie wymaga nic poza odpowiednimi metodami.
    DTO czy też encja również jest JavaBeanem.

  11. Andrew says:
    1. No wiesz, ja przytaczam dokumenty z Sun’a, a ty z Wikipedii ;) JavaBean to przede wszystkim technologia (http://java.sun.com/products/javabeans/) i nie chodzi tu tyle o budowę klasy co jej kontekst. Według tej definicji z Wikipedii Bean to praktycznie każda klasa, co by było bez sensu.
    2. Przenosząc to na szerszy grunt, nie można powiedzieć na klasę Author, że to jest DTO (nawet jak ma tylko akcesory i mutatory) dopóki nie będzie użyta w sposób, w jaki używa się DTO (czyli przenoszenia danych) (może trudno sobie wyobrazić taką klasę w innej roli, ale powiedzmy, że jest taka możliwość)
    3. Jeżeli przeniesiesz całą technologię JavaBeans do PHP to będziesz mógł używać tego czy innego terminu (np PHPBeans). I wtedy będzie miało to sens ;)
    1. Technologia czy też nie, ja bazuję na pojęciu beana. Jeśli chcesz mi udowodnić że się mylę ok – mylę się. Wiesz lepiej czym jest bean, bo przeczytałeś na tym na stronie Suna a ja tylko z tego korzystam i bazuję na definicji z wikipedii.
    2. Napisałem, że DTO i encja to JavaBean, zatem klasa Author, która według mnie jest beanem może być i DTO i encją.
    3. Widzisz, ja wychodzę z założenia, że beanem może być dowolna klasa niezależnie od języka, stąd nie muszę przenosić czegokolwiek do PHP by cokolwiek udowadniać. Fakt, że jeśli bym potrzebował propagowania zdarzeń to wówczas sobie zaimplementuję Mediatora na modłę PropertyChangeSupport, póki co nie widzę takiej potrzeby a tym bardziej sensu tworzenia kolejnego pojęcia z prefiksem PHP.

    Wszystkie pojęcia ewoluują. Pierwotnie specyfikacja JavaBeans (1997 rok) tyczyła się tworzenia graficznego interfejsu użytkownika z biegiem czasu, gdy pojawiło się większe grono technologii pojęcie beanów zaczęto stosować szerzej – gdzie nie ma konieczności tworzenia dodatkowych elementów, poza określoną konstrukcją klas. Jeśli nie możesz znieść stosowania takiego poglądu mów sobie na przykładowe klasy powiedzmy – fasole. Tworzone na bazie specyfikacji JavaBeans.

  12. Andrew says:
    1. “Wszystkie pojęcia ewoluują” – to się zgadza, ale specjalnie poszukałem w necie… tylko strona angielskiej wikipedii (nawet nie polskiej) jest tak liberalna co do pojęcia JavaBean. Nie wiem czemu tak się uparłeś żeby używać tego pojęcia. Bean miał być symbolem komponentu wewnątrz języka java. Komponentu, który miał przed sobą określone zadania. Wszystkie inne klasy (czy to encyjne czy biznesowe (i nie EJB)) to po prostu zwykłe klasy (POJO jak kto woli).
    2. Czy mógłbyś zaprezentować jakąś stronę czy książkę, która używa pojęcia Bean poza językiem Java?
    1. Dla mnie encja to bean, DTO to bean, POJO to też bean, bo bean to zwykła klasa.
    2. Ta strona używa pojęcia bean w oderwaniu od Javy. Nie znam innej i nie zamierzam takowej szukać. Po prostu odpowiada mi stosowanie tego pojęcia zamiast namolnego silenia się na podpinanie się pod specyfikacje i definicje bądź tworzenie własnych definicji pokroju PHPBeans.
  13. Andrew says:
    1. Aha, czyli pojęcie “klasa” jest dla ciebie mało fajne? Ok. Ale Strzałek pytał o wytłumaczenie mu pojęcia, a ty zamiast ogólnie przyjętego standardu wytłumaczyłeś mu to pojęcie na wzór “tylko tej strony/bloga”. Na innym forum już miałby problemy z komunikacją.
    2. Co do “bean to zwykła klasa” => NIE. Terminy (takie cuś językowe) będą spełniać swoją rolę informatywną tylko wtedy, gdy są tak samo rozumiane przez wszystkich lub daną grupę. Cały czas myślałem, że chcesz mnie przekonać, do tego, że pojęcie z języka Java można przenieść na inny grunt – myliłem się – ty chcesz zmienić znaczenie “fajnie brzmiącego terminu”. Nieładnie.
  14. Słuchaj Andrew, czepiłeś się tych beanów jak rzep psiego ogona. Mam tego serdecznie dosyć.
    Gwoli ścisłości – to Ty zacząłeś od pomylenia JavaBeana z EJB. Następnie dowiadujesz się że takie pojęcie istnieje i stwierdzasz, że moje przykłady są złe, po czym wędrujesz do specyfikacji z 1997 roku i mówisz mi, że beanem jest tyko to, co spełnia wymogi specyfikacji o której, nota bene, nawet nie wiedziałeś. I mimo wszystko dalej śmiesz mnie w tej kwestii pouczać?

    Nie zamierzam zmieniać znaczenia beana, ponieważ większość znanych mi programistów Javy tak właśnie to pojęcie rozumie. To po prostu klasa z metodami zgodnymi z konwencją i bezargumentowym konstruktorem, stąd tożsamość encji, POJO i DTO. I takie postrzeganie tego pojęcia jest przenośne na dowolny grunt. Bean nie musi mieć przecież żadnych dodatkowych elementów. Jeśli tego nie rozumiesz to potraktuj to co napisałem parę zdań wcześniej jako najmniejszy wspólny mianownik.

    Nie zamierzam zmieniać znaczenia, jak to określiłeś, “fanie brzmiącego terminu” ponieważ posługuję się synonimem utartym w branży a nie przestarzałym dokumentem, stąd moje wytłumaczenie pojęcia Strzałkowi, nawet jeśli nie pełne, na pewno nie odbyło się z krzywdą dla niego samego.

    Z mojej strony, nalegam na zakończenie tematu, ponieważ te wywody do niczego nie prowadzą.

  15. Andrew says:
    1. “stąd tożsamość encji, POJO i DTO.” – odsyłam do książki PoEAA, ta literatura ci się przyda, definiuje wszystkie te rzeczy, polecam. Pojęcie POJO powstało właśnie po to, żeby odróżnić czyste klasy od EJB to tworzenia klas warstwy logiki. Gdyby programiści Javy mogli wykorzystać do tego JavaBean to by to zrobili. Ale JB nie służy do budowy _logiki aplikacji_ ! Encje i DTO to prawie to samo, służą do komunikacji z warstwą danych (DTO nie tylko), i ani jedno ani drugi nie zawiera logiki. Dlatego nie mogą być tożsame z POJO. W czym jak w czym, ale w informatyce znaczenie terminów jest ważne, bo dzięki nim dokumentacja jest krótsza, ale nie może być źle rozumiana.
    2. “ponieważ posługuję się synonimem utartym w branży” – jasne, prosiłem żebyś poparł to jakimś linkiem, bo ja takowego nie widziałem. Jeżeli zaprezentujesz stronę o lepszej reputacji niż Wikipedia to się zgodzę.
    3. Masz racje, nie ma sensu tego ciągnąć.

    1. Nie pomyliłbym JavaBean z EJB, gdyby nie to, że klasa, którą zaprezentowałeś, nie jest ani jednym ani drugim.
    2. Nie czepiałbym się gdybyś _publicznie_ nie prezentował takich wymyślonych historii. Zasłyszałeś coś od programistów Javy, którzy zapewne dobrze używali tego pojęcia, a rozpowszechniasz w innym znaczeniu.
    3. PHP nie potrzebuje terminu Bean bo termin “klasa” jest wystarczający. Jak widzisz wprowadzenie nowego terminu, który nic nie wnosi tylko powoduje konflikty (przy commitowaniu go ;)
    4. Nie wiedziałem, że dokumentacja po paru latach jest nieważna i można zmieniać pojęcia w niej zawarte. (BTW: najnowsza jest z 2002 roku.) I czemu myślisz, że nie widziałem? To nie ja przekręcam pojęcia. Ty się posługujesz Wikipedią – to jest lepsze źródło? Zaraz mogę ją sprostować :P Nie jestem programistą Javy, ale nie jeden projekt na studiach musiałem w niej wykonać. Podstaw się nie zapomina :P BTW: wyśmiewasz dokumentację z “1997 roku” a w pierwszym poście do mojego sam się na nią powołałeś, w dodaktu na definicję, która jest sprzeczna z twoim użyciem (klasy Author przecier nie “uruchomisz”, a komponenty tak).

    *** Wszystko po “—” możesz usunąć żeby nie zaśmiecać ci bloga, nie chciałem ciebie obrazić, ani nic w tym sensie, tylko wyprostować pewne terminy.

  16. Andrew daruj sobie wycieczki osobiste, prosiłem o to by zakończyć tą dyskusję! Doszliśmy do porozumienia w kwestii kolejności podejmowania prac przy projektowaniu, co mnie bardzo cieszy. Niech spór tyczący się pojęcia “beana” pozostanie więc otwarty. Nie zamierzam prosić kolegów o to by opisywali w jaki sposób rozumieją “beany” ponieważ jest to irracjonalne i na pewno nie będzie dla Ciebie wiarygodne.

    Wszystko co miało sens zostało już powiedziane. Osoby, które trafią do tych komentarzy same będą musiały rozsądzić którą wersję pojęcia akceptują a którą odrzucają.

  17. Ace says:

    Czytam i czytam wasze komentarze. Myślę, że warto by było zakończyć tę dyskusję, bo powoli zaczyna zmierzać w złą stronę.

  18. Przypadkowo trafiłem na wpis na blogu innej osoby traktujący po części o JavaBeans..

Leave a Reply