🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.java
8 messages
8 total messages Started by Jacek Czerwinski Sun, 16 Oct 2011 07:52
Mysli na granicy OOP i SQL
#152971
Author: Jacek Czerwinski
Date: Sun, 16 Oct 2011 07:52
30 lines
2117 bytes
taka refleksja mnie naszła: n/t ORM
jest w RAM jakaś kolekcja obiektów (dziedziczących z) klasy X. 
Przeglądam je sobie wg jakiejś idei.

W OOP mogę się przeiterować przez tę kolekcję, odpytując metodę 
wirtualną oceniającą spełnienie jakiegoś warunku pasowania do schematu
boolean isCosTam()
i tylko dla nich wykonać pewien algorytm.

Zależność boolean, regułę biznesową implementuje się w klasie, tam jest 
jej najlepsze miejsce. Nie patrzymy na dane, są hermetyczne, tylko 
metoda wirtualna.

Ilość metod (reguł biznesowych) nie jest duża, dwie-cztery i jest stała. 
Ilość klas w hierarchii X jest rozwojowa.

A teraz te obiekty (w ilości ciężkich tysięcy) są przeniesione do bazy 
(JPA2), chcę selektywnie wydobyć nieliczne pasujące i poddać je 
algorytmowi (a potem zapisać zmiany).

Nijak mi nie chce wyjść, żeby reguła biznesowa (de facto kwerenda, jako 
string lub criteria) nie musiała być wyniesiona poza klasę. Oczywiście 
pomijając brutal-force wczytanie wszystkiego.
Dodać te dwa-cztery składowe danych i wypełniać je przed zapisem, 
rozhermetyzować nieco?

na obecnym etapie nie chciałbym generować siostrzanych klas z metadanymi 
JPA2, chyba że jest to jedyna droga ... JPA mógłbym chyba zmienić np na 
Data Nucleus gdzie backendów nie-SQL jest większy wybór, ale nie wiem 
czy coś z tego wynika.
Re: Mysli na granicy OOP i SQL
#152972
Author: sielim
Date: Mon, 24 Oct 2011 14:09
82 lines
4768 bytes
W dniu 2011-10-16 09:52, Jacek Czerwinski pisze:
> taka refleksja mnie naszła: n/t ORM
> jest w RAM jakaś kolekcja obiektów (dziedziczących z) klasy X.
> Przeglądam je sobie wg jakiejś idei.
>
> W OOP mogę się przeiterować przez tę kolekcję, odpytując metodę
> wirtualną oceniającą spełnienie jakiegoś warunku pasowania do schematu
> boolean isCosTam()
> i tylko dla nich wykonać pewien algorytm.
>
> Zależność boolean, regułę biznesową implementuje się w klasie, tam jest
> jej najlepsze miejsce. Nie patrzymy na dane, są hermetyczne, tylko
> metoda wirtualna.
>
> Ilość metod (reguł biznesowych) nie jest duża, dwie-cztery i jest stała.
> Ilość klas w hierarchii X jest rozwojowa.
>
> A teraz te obiekty (w ilości ciężkich tysięcy) są przeniesione do bazy
> (JPA2), chcę selektywnie wydobyć nieliczne pasujące i poddać je
> algorytmowi (a potem zapisać zmiany).
>
> Nijak mi nie chce wyjść, żeby reguła biznesowa (de facto kwerenda, jako
> string lub criteria) nie musiała być wyniesiona poza klasę. Oczywiście
> pomijając brutal-force wczytanie wszystkiego.
> Dodać te dwa-cztery składowe danych i wypełniać je przed zapisem,
> rozhermetyzować nieco?
>
> na obecnym etapie nie chciałbym generować siostrzanych klas z metadanymi
> JPA2, chyba że jest to jedyna droga ... JPA mógłbym chyba zmienić np na
> Data Nucleus gdzie backendów nie-SQL jest większy wybór, ale nie wiem
> czy coś z tego wynika.

No jakby nie patrzeć: miejsce odpalenia kodu (można by powiedzieć:
fizyczny procesor) musi być bliskie danym, na których operuje :)
Więc jeśli masz bazę danych osobno i regułę biznesową java na serwerze
aplikacji osobno, to żeby wyjść na swoje musisz je do siebie
zbliżyć: albo rozhermetyzować i dociągnąć dane w pobliże procedury,
albo jakoś magicznie przenieść procedurę na procesor bazy danych.

W praktyce OOP typu Java/JPA/Hibernate, przy tak konkretnie postawionym
rozwiązaniu 'reguła biznesowa zaimplementowana w klasie bazowej 
isCosTam' to nie ma innej rady - trzeba na pałę załadować wszystko
i odpalać. Zresztą tak to chyba nawet da się zrobić z pomocą HQL'a
(da się ? nie pamiętam, czy to nie wymaga jakichś specjalnych zabiegów).

W drugą stronę, czyli 'szybciutko skompilować kod metody java do postaci 
przyswajalnej przez serwer SQL (jaki ?) to się, póki co,
nie da :)

Ale ... Rozluźnijmy trochę. Po pierwsze: może niech metoda
w obiekcie, owa reguła biznesowa, będzie zapisana w postaci
HQL'a ? czyli nie
public boolean isCosTam(),
ale coś w rodzaju
public static String getIsCosTamCondition()
... i gdzieś tam dynamiczne sklejanie zapytania z wykorzystaniem
powyższego.
Nie rozwiązuje to problemu hermetyzacji dostępu do danych, a jedynie
może taką hermetyzację nieco 'udaje', być może jednak ktoś uzna
to za postęp - ze względu na organizację kodu - czyli jeśli priorytetem
jest trzymanie reguły biznesowej(warunku filtrującego) blisko klasy
danych.
Powstają jednak dwa pytania:

1. Może lepiej od razu zrobić po prostu NamedQuery w klasie
(jak się da) ?

2. Zaraz, ale dlaczego uparliśmy się na trzymanie filtrujących
reguł biznesowych w klasach danych ?
Może robimy tu jakiś błąd ? Idee OOP są cool, ale chyba jeszcze
bardziej cool są wzorce projektowe. A wzorce projektowe
w niektórych przypadkach dość drastycznie rozmiękczyły
ideę ścisłej hermetyzacji.
Weźmy wzorce/pojęcia: Data Access Object, TransferData,
albo jeszcze lepiej BusinessObject i do tego
Anemic Domain Model .
I wychodzi na to, że hermetyzacja poszła w krzaki :)
Business Object nic sam nie potrafi, a więc musi się
na wszystkich otworzyć. Finito ...

http://en.wikipedia.org/wiki/Business_object
http://en.wikipedia.org/wiki/Anemic_Domain_Model
Re: Mysli na granicy OOP i SQL
#152974
Author: Konrad Garus
Date: Tue, 25 Oct 2011 12:04
17 lines
1972 bytes
A może by tak pociągnąć troszkę bardziej od strony pokazanego w DDD
podejścia z repozytorium i specyfikacją? W modelu OO masz
repozytorium, z którego wyciągasz dane mniej-więcej tak:

MyObjectRepository repo;
// ...
MyObjectSpecification spec = ... // cokolwiek, co repozytorium
zrozumie
repo.getMyObjects(spec);

Specyfikacja może odpytywać obiekty o ich pola, albo implementować
bardziej interesującą logikę. Z drugiej strony, można by
zaimplementować to API w ten sposób, żeby repozytorium używało
Hibernate, a specyfikacja potrafiła się przetłumaczyć na HQL. Od
strony użytkownika masz model obiektowy (repo+spec), obiekty domeny
nie muszą nic o bazie wiedzieć, a wszystkim zajmują się repo i
specyfikacja "pod maską".
Re: Mysli na granicy OOP i SQL
#152975
Author: Jacek Czerwinski
Date: Wed, 26 Oct 2011 04:54
18 lines
1681 bytes
W dniu 2011-10-25 14:04, Konrad Garus pisze:
> A może by tak pociągnąć troszkę bardziej od strony pokazanego w DDD
> podejścia z repozytorium i specyfikacją? W modelu OO masz
> repozytorium, z którego wyciągasz dane mniej-więcej tak:
>
> MyObjectRepository repo;
> // ...
> MyObjectSpecification spec = ... // cokolwiek, co repozytorium
> zrozumie
> repo.getMyObjects(spec);

Ciekawa myśl, w sumie to uprawiam czasem podobnie, jakieś MyCriteria 
kilka razy robiłem. Jakoś DAO z wielością metod pobierania na każdy 
sposób zawsze mnie raziło, a takie mi się podobają bardziej.

Przemyślę jeden szczegół, w C++ bym jakieś friendy porobił, w Javie 
trzymanie w pakiecie klas danych i repo troche nie ten-tego, ale 
pomyslimy ...
Re: Mysli na granicy OOP i SQL
#152973
Author: Jacek Czerwinski
Date: Wed, 26 Oct 2011 04:54
14 lines
1360 bytes
W dniu 2011-10-24 16:09, sielim pisze:
> W dniu 2011-10-16 09:52, Jacek Czerwinski pisze:
>> taka refleksja mnie naszła: n/t ORM


> Może robimy tu jakiś błąd ? Idee OOP są cool, ale chyba jeszcze
> bardziej cool są wzorce projektowe. A wzorce projektowe
> w niektórych przypadkach dość drastycznie rozmiękczyły
> ideę ścisłej hermetyzacji.

Cenne spostrzeżenie, warto spojrzeć przez takie okulary.

Może nie ścisła hermetyzacja w sensie uniwersyteckim, ale "trzymanie 
blisko klasy" ?
Re: Mysli na granicy OOP i SQL
#152976
Author: Michal Kleczek
Date: Wed, 26 Oct 2011 11:42
28 lines
1856 bytes
On 2011-10-16 09:52, Jacek Czerwinski wrote:
> taka refleksja mnie naszła: n/t ORM
> jest w RAM jakaś kolekcja obiektów (dziedziczących z) klasy X.
> Przeglądam je sobie wg jakiejś idei.
>
> W OOP mogę się przeiterować przez tę kolekcję, odpytując metodę
> wirtualną oceniającą spełnienie jakiegoś warunku pasowania do schematu
> boolean isCosTam()
> i tylko dla nich wykonać pewien algorytm.
>

Tak oczywiscie mozna zrobic, ale znacznie lepiej od razu miec kolekcje 
zawierajaca tylko te obiekty, ktore chcesz przetwarzac. Wtedy to 
isCosTam() po prostu nie jest potrzebne.

>
> Nijak mi nie chce wyjść, żeby reguła biznesowa (de facto kwerenda, jako
> string lub criteria) nie musiała być wyniesiona poza klasę. Oczywiście
> pomijając brutal-force wczytanie wszystkiego.
> Dodać te dwa-cztery składowe danych i wypełniać je przed zapisem,
> rozhermetyzować nieco?
>

Patrz wyzej: po prostu swoje obiekty inicjuj tymi danymi, ktore sa 
potrzebne do przetwarzania.

-- 
Michal
Re: Mysli na granicy OOP i SQL
#152977
Author: Jacek Czerwinski
Date: Wed, 26 Oct 2011 12:09
15 lines
1400 bytes
W dniu 2011-10-26 13:42, Michal Kleczek pisze:
> On 2011-10-16 09:52, Jacek Czerwinski wrote:


> Patrz wyzej: po prostu swoje obiekty inicjuj tymi danymi, ktore sa
> potrzebne do przetwarzania.
>

Na chłopski rozum ok, ale jednak chciało by się aby klasa główna nie 
miała tej wiedzy o implementacji. Padło w tym wątku kilka myśli o różnym 
stopniu podporządkowania się klasycznym zasadom OOP, tu jednak metoda 
wirtualna BARDZO mi się podoba, to swoje boolean wypracowuje w klasach 
potomnych z bardzo różnych danych.

Przmyślę to sobie
Re: Mysli na granicy OOP i SQL
#152978
Author: Michal Kleczek
Date: Wed, 26 Oct 2011 12:36
71 lines
2878 bytes
On 2011-10-26 14:09, Jacek Czerwinski wrote:
> W dniu 2011-10-26 13:42, Michal Kleczek pisze:
>> On 2011-10-16 09:52, Jacek Czerwinski wrote:
>
>
>> Patrz wyzej: po prostu swoje obiekty inicjuj tymi danymi, ktore sa
>> potrzebne do przetwarzania.
>>
>
> Na chłopski rozum ok, ale jednak chciało by się aby klasa główna nie
> miała tej wiedzy o implementacji.

Nie rozumiem - mamy taka sytuacje:


interface Rzecz {
   boolean isCosTam();
   ...
}

class Algorytm {
   private Iterable<? extends Rzecz> rzeczy;

   public void run() {
     for (final Rzecz rzecz : rzeczy) {
       if (rzecz.isCosTam()) {
         przetworz(rzecz);
       }
     }
   }

   private void przetworz(Rzecz rzecz) {...}
}

class Main {
   public static void main(String[] args) {
     MyORMTool orm = ...;

     Collection<Rzecz> rzeczy = orm.find("moje zapytanie");
     new Algorytm(rzeczy).run();
   }
}

ja tylko mowie, zeby wyrzucil "isCosTam()" i zmienil "moje zapytanie" na 
"inne zapytanie". W szczegolnosci to "inne zapytanie" moze byc po prostu 
parametrem.

Jeszcze lepiej, jak ORM wspiera tworzenie niepersystentnych obiektow lub 
klasa Algorytm jest zwyczajnie persystentna.

wtedy w main masz po prostu:

orm.<Algorytm>load("well_known_id").run()

zas "inne zapytanie" laduje gdzies w konfiguracji ORM.

> Padło w tym wątku kilka myśli o różnym
> stopniu podporządkowania się klasycznym zasadom OOP, tu jednak metoda
> wirtualna BARDZO mi się podoba, to swoje boolean wypracowuje w klasach
> potomnych z bardzo różnych danych.

Tak czy inaczej te dane sa persystentne.
Wiec nic nie stoi na przeszkodzie zaimplementowac ich wyszukiwanie tam, 
gdzie jest tego miejsce - w bazie danych.
Zauwaz, ze nie ma zadnej duplikacji (bo usuwasz filtrowanie/wyszukiwanie 
z aplikacji). Nie ma tez zadnego "rozhermetyzowania", bo dane tak czy 
inaczej sa publicznie dostepne (w koncu sa w bazie danych, ktora je 
udostepnia).

-- 
Michal
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads