🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.objects
13 messages
13 total messages Started by Adam Przybylek Wed, 11 Jul 2007 18:54
Composition Filters
#17243
Author: Adam Przybylek
Date: Wed, 11 Jul 2007 18:54
10 lines
1189 bytes
Czy ktos z Was moze wyjasnic dlaczego CFs nie zyskaly popularnosci 
chocby takiej jak AOP (chocby na poziomie akademickim). Przeczytalem 
kilka papierow i wydaje mi sie, ze koncepcyjnie CFs w elegancki sposob 
rozszerza model obiektowy i rozwiazuje czesc problemow zwiazanych z 
klasycznym OO. Jesli w CFs jest jakis haczyk ktorego nie widze to bede 
wdzieczny za nakierowanie. Gdyby ktos chcial sie zainteresowac podaje linka:
http://trese.cs.utwente.nl/oldhtml/composition_filters/

Pozdrawiam,
Adam
Re: Composition Filters
#17244
Author: A.L.
Date: Sun, 15 Jul 2007 04:22
16 lines
1365 bytes
On Wed, 11 Jul 2007 20:54:29 +0200, Adam Przybylek <adampap1@vp.pl>
wrote:

>Czy ktos z Was moze wyjasnic dlaczego CFs nie zyskaly popularnosci 
>chocby takiej jak AOP (chocby na poziomie akademickim). Przeczytalem 
>kilka papierow i wydaje mi sie, ze koncepcyjnie CFs w elegancki sposob 
>rozszerza model obiektowy i rozwiazuje czesc problemow zwiazanych z 
>klasycznym OO. Jesli w CFs jest jakis haczyk ktorego nie widze to bede 
>wdzieczny za nakierowanie. Gdyby ktos chcial sie zainteresowac podaje linka:
>http://trese.cs.utwente.nl/oldhtml/composition_filters/
>

Dlatego, jak sadze, ze podobnie jak w przypadku Aspect Programming,
odpowiada na pytanie ktorego nikt nie zadal.

A.L.
Re: Composition Filters
#17245
Author: Kamil Janiszewski
Date: Thu, 02 Aug 2007 22:45
36 lines
2988 bytes
On 15 Lip, 06:22, A.L. <f...@2005.com> wrote:
> On Wed, 11 Jul 2007 20:54:29 +0200, Adam Przybylek <adamp...@vp.pl>
> wrote:
>
> >Czy ktos z Was moze wyjasnic dlaczego CFs nie zyskaly popularnosci
> >chocby takiej jak AOP (chocby na poziomie akademickim). Przeczytalem
> >kilka papierow i wydaje mi sie, ze koncepcyjnie CFs w elegancki sposob
> >rozszerza model obiektowy i rozwiazuje czesc problemow zwiazanych z
> >klasycznym OO. Jesli w CFs jest jakis haczyk ktorego nie widze to bede
> >wdzieczny za nakierowanie. Gdyby ktos chcial sie zainteresowac podaje linka:
> >http://trese.cs.utwente.nl/oldhtml/composition_filters/
>
> Dlatego, jak sadze, ze podobnie jak w przypadku Aspect Programming,
> odpowiada na pytanie ktorego nikt nie zadal.
>
> A.L.

Moim zdaniem problem separacji zagadnie  jest istotny w codziennym
 yciu programistów i architektów. AOP jest kolejnym krokiem na
nieko cz cej si  drodze ku rozwi zaniu tego problemu.
Uwa am,  e programowanie aspektowe zdecydowanie zdoby o/zdobywa sobie
popularno  , zacz  o od  wiata Javy, w którym  wietnymi przyk adami s 
zastosowania tej metodyki w Springu, JBossie i GlassBoxie. Po
stronie .Netu równie  co  si  ruszy o: w sk ad Enterprise Library (od
wersji 3.0) wchodzi Policy Injection Block, który jest czym  na
kszta t AOP.

Z tego co wiem, to AOP czerpie z CF, programowania adaptacyjnego, i
meta-poziomowego. Mam nadziej ,  e czerpie z nich to co najlepsze :)

Ponadto AOP z jakiego  powodu jest bardzo dobrze umocowane
politycznie, Gregor Kiczales, by y pracownik Xerox PARC (tam pracowa 
w a nie nad AOP), jest do   wp ywowy, od 1999 roku zarz dza dzia em
wytwarzania oprogramowania w Xerox Canada/Sierra Systems/Natural
Sciences and Engineering Research Council of Canada/ University of
British Columbia.
Re: Composition Filters
#17246
Author: A.L.
Date: Thu, 02 Aug 2007 23:31
15 lines
1389 bytes
On Thu, 02 Aug 2007 22:45:04 -0000, Kamil Janiszewski
<zedzik@googlemail.com> wrote:
 
>Ponadto AOP z jakiego  powodu jest bardzo dobrze umocowane
>politycznie, Gregor Kiczales, by y pracownik Xerox PARC (tam pracowa 
>w a nie nad AOP), jest do   wp ywowy, od 1999 roku zarz dza dzia em
>wytwarzania oprogramowania w Xerox Canada/Sierra Systems/Natural
>Sciences and Engineering Research Council of Canada/ University of
>British Columbia.


To ma byc argument na co?... Taki argument ze "Teoria Lysenki musi byc
prawdziwa bo Lusenko to Uczony Radziecki"?...

A.L.
Re: Composition Filters
#17251
Author: Adam Przybylek
Date: Fri, 03 Aug 2007 10:45
19 lines
1623 bytes
Kamil Janiszewski napisał(a):
> [...] 
> Z tego co wiem, to AOP czerpie z CF, programowania adaptacyjnego, i
> meta-poziomowego. Mam nadziej ,  e czerpie z nich to co najlepsze :)
> 

W papierach pisza, ze CFs byly prekursorem AOP, ale podobienstwa miedzy 
nimi to za bardzo nie widze. Jedyne co je laczy to cel - lepsza 
separacja zagadnien niz w klasycznym modelu OO.
Mnie jednak ciekawilo co innego: dlaczego AOP pomimo, ze narusza pewne 
praktyki wypracowane przez OO rozwija sie dynamicznie, natomiast CFs 
praktycznie nie istnieja, choc w elegancki i naturalny sposob 
rozszerzaja OO.
Ale juz chyba czesciowo znalazlem odpowiedz. Za kilka dni jak bede mial 
wiecej czasu pokaze przyklad.


Pozdrawiam,
Adam
Re: Composition Filters
#17247
Author: Kamil Janiszewski
Date: Fri, 03 Aug 2007 13:26
24 lines
2331 bytes
On 3 Sie, 01:31, A.L. <f...@2005.com> wrote:
> On Thu, 02 Aug 2007 22:45:04 -0000, Kamil Janiszewski
>
> <zed...@googlemail.com> wrote:
> >Ponadto AOP z jakiego  powodu jest bardzo dobrze umocowane
> >politycznie, Gregor Kiczales, by y pracownik Xerox PARC (tam pracowa
> >w a nie nad AOP), jest do   wp ywowy, od 1999 roku zarz dza dzia em
> >wytwarzania oprogramowania w Xerox Canada/Sierra Systems/Natural
> >Sciences and Engineering Research Council of Canada/ University of
> >British Columbia.
>
> To ma byc argument na co?... Taki argument ze "Teoria Lysenki musi byc
> prawdziwa bo Lusenko to Uczony Radziecki"?...
>
> A.L.

Moim zdaniem o popularno ci AOP przes dzi a wp ywowo   pana Kiczalesa,
ten kawa ek tekstu mia  j  potwierdza .

Prosz  zerkn   na: http://media.xerox.ca/news/default.asp?articleID=153
, mo e to b dzie mocniejsza poszlaka.

Zobaczymy jakie nowo ci przyniesie przysz a wypowied  Pana Adama
Przybyleka.
Re: Composition Filters
#17248
Author: A.L.
Date: Fri, 03 Aug 2007 13:32
26 lines
1985 bytes
On Fri, 03 Aug 2007 06:26:09 -0700, Kamil Janiszewski
<zedzik@googlemail.com> wrote:

>On 3 Sie, 01:31, A.L. <f...@2005.com> wrote:
>> On Thu, 02 Aug 2007 22:45:04 -0000, Kamil Janiszewski
>>
>> <zed...@googlemail.com> wrote:
>> >Ponadto AOP z jakiego  powodu jest bardzo dobrze umocowane
>> >politycznie, Gregor Kiczales, by y pracownik Xerox PARC (tam pracowa
>> >w a nie nad AOP), jest do   wp ywowy, od 1999 roku zarz dza dzia em
>> >wytwarzania oprogramowania w Xerox Canada/Sierra Systems/Natural
>> >Sciences and Engineering Research Council of Canada/ University of
>> >British Columbia.
>>
>> To ma byc argument na co?... Taki argument ze "Teoria Lysenki musi byc
>> prawdziwa bo Lusenko to Uczony Radziecki"?...
>>
>> A.L.
>
>Moim zdaniem o popularno ci AOP przes dzi a wp ywowo   pana Kiczalesa,
>ten kawa ek tekstu mia  j  potwierdza .

"Popularmosc" AOP jest dokladnie zerowa, neizaleznei od tego co Pan
Kiczales twierdzi.

A.L.
Re: Composition Filters
#17252
Author: A.L.
Date: Fri, 03 Aug 2007 13:33
19 lines
1571 bytes
On Fri, 03 Aug 2007 12:45:09 +0200, Adam Przybylek <adampap1@vp.pl>
wrote:

>Kamil Janiszewski napisał(a):
>> [...] 
>> Z tego co wiem, to AOP czerpie z CF, programowania adaptacyjnego, i
>> meta-poziomowego. Mam nadziej ,  e czerpie z nich to co najlepsze :)
>> 
>
>W papierach pisza, ze CFs byly prekursorem AOP, ale podobienstwa miedzy 
>nimi to za bardzo nie widze. Jedyne co je laczy to cel - lepsza 
>separacja zagadnien niz w klasycznym modelu OO.
>Mnie jednak ciekawilo co innego: dlaczego AOP pomimo, ze narusza pewne 
>praktyki wypracowane przez OO rozwija sie dynamicznie, 

Ze jak sie rozwija?... Moze i dymamicznie sie rozwija, ino nikt go nie
uzywa.

A.L.
Re: Composition Filters
#17253
Author: Adam Przybylek
Date: Fri, 03 Aug 2007 16:04
11 lines
1189 bytes
A.L. napisał(a):
> 
> Ze jak sie rozwija?... Moze i dymamicznie sie rozwija, ino nikt go nie
> uzywa.
> 

Tzn. ja oceniam AOP z perspektywy zainteresowania na konferencjach 
naukowych, a nie w przemysle.

Pozdrawiam,
Adam
Re: Composition Filters [uwaga dlugie]
#17249
Author: Adam Przybylek
Date: Thu, 16 Aug 2007 16:28
418 lines
12432 bytes
Kamil Janiszewski napisa?(a):
> Zobaczymy jakie nowosci przyniesie przyszla wypowiedz Pana Adama
> Przybylka.

No wie;c skoro obieca?em to pisze;. W poprzednim pos'cie mówi?em, z.e 
znalaz?em cze;s'ciowo odpowiedz' na pytanie dlaczego CFs sie; nie 
upowszechni?y. Otóz. celem CFs by?o dostarczenie mechanizmu 
umoz.liwiaja;cego lepsza; separacje; zagadnien' (SoC - Separation of 
Concerns) niz. w paradygmacie obiektowym. Moje zdanie jest takie, z.e 
wykorzystuja;c CFs dla niektórych przypadków moz.na osia;gna;c' lepsza; SoC, 
ale nie ma ona wie;kszego wp?ywu na poprawe; evolvability i reusability.
Poniz.ej przyk?ad na problemy jakie powstaja; przy implementacji w Javie 
oraz próba (bezowocna) rozwia;zania ich przy pomocy dodania do Javy 
filtrów input (hipotetyczna sk?adnia).

Za?óz.my, z.e tworza;c nowy modu? chcemy w jak najwie;kszym stopniu 
wykorzystac' istnieja;ce modu?y. Ponadto na kaz.dym etapie chcemy zrobic' 
dobra; implementacje; pod aktualne wymagania, a nie pod ewentualne 
przysz?e, o których nic nie wiemy. Zapominamy o istnieniu gotowych 
pakietów Javy. Za?óz.my takz.e, z.e posiadamy w repozytorium naste;puja;ca; 
implementacje; kolejki:

public class Queue {
   protected Object[] buf;
   protected int numItems;
   protected int nextToRemove;

   public Queue(int capacity) {
     buf = new Object[capacity];
   }

   public boolean isFull() {
     return (numItems==buf.length);
   }

   public boolean isEmpty() {
     return (numItems==0);
   }

   public int size() {
     return numItems;
   }

   public boolean put(Object x) {
     if ( isFull() ) return false;
     buf[(nextToRemove+numItems) % buf.length] = x;
     numItems++;
     return true;
   }

   public Object get() {
     Object tmp=null;
     if ( !isEmpty() ) {
       tmp = buf[nextToRemove];
       numItems--;
       nextToRemove = (nextToRemove+1) % buf.length;
     }
     return tmp;
   }
}

Etap 1. Nalez.y zaimplementowac' klase; Buffer pod klasyczny problem 
producenta-konsumenta.
a) rozwia;zanie Java
public class Buffer extends Queue {

   public Buffer(int capacity) {
     super(capacity);
   }

   public synchronized boolean put(Object x) {
     while ( isFull() ) try {
       wait();
     } catch (InterruptedException e) {}
     super.put(x);
     notifyAll();
     return true;
   }

   public synchronized Object get() {
     while ( isEmpty() ) try {
       wait();
     } catch (InterruptedException e) {}
     Object tmp = super.get();
     notifyAll();
     return tmp;
   }
}

Nalez.y zauwaz.yc', z.e zagadnienie synchronizacji (zagadnienie 
przecinaja;ce) jest splecione z zagadnieniem odk?adania i pobierania 
danych (zagadnienie podstawowe).

b) rozwia;zanie CFs
public class BufferCF {
   private Queue delegate;

   filter Wait {
     delegate.isFull() => put(Object),
     delegate.isEmpty() => get()
   };
   filter Dispatch { true => delegate.* };
}
Dzia?a to w ten sposób, z.e kaz.dy komunikat przychodza;cy z zewna;trz do 
obiektu przechodzi najpierw przez filtr Wait, a naste;pnie przez filtr 
Dispatch. Pierwszy wpis w filtrze Wait mówi, aby us'pic' wa;tek wykonuja;cy 
put(Object) na pe?nym buforze, a drugi, aby us'pic' wa;tek wykonuja;cy get() 
na pustym buforze.
Na?oz.enie na metode; filtru Wait sprawia, z.e staje sie; ona synchroniczna. 
Ponadto sprawdzenie warunku (równiez. synchroniczne) i ewentualne 
rozpocze;cie metody jest atomowe.
Z kolei zastosowany filtr Dispatch mówi, aby kaz.dy komunikat (*) 
bezwarunkowo (true) przekazac' do obs?uz.enia obiektowi delegate. Gdyby 
filtr Dispatch zawiera? wie;cej wpisów rozpatrywane by by?y od lewej do 
prawej tak d?ugo az. skojarzony z któryms' warunek be;dzie spe?niony. Jes'li 
z.aden warunek nie zostanie spe?niony to rzucany jest run-time error.

Etap 2. Przychodzi nowe wymaganie - dla kaz.dego elementu wk?adanego do 
bufora nalez.y pamie;tac' date; kiedy zosta? on w?oz.ony. Ponadto umoz.liwic' 
pobranie elementu razem z ta; data;.
a) rozwia;zanie Java
public class HistoryBuffer extends Buffer {
   protected Queue delegateDates;

   public HistoryBuffer(int capacity) {
     super(capacity);
     delegateDates = new Queue(capacity);
   }

   public synchronized boolean put(Object x) {
     while ( isFull() ) try {
       wait();
     } catch (InterruptedException e) {}
     super.put(x);
     delegateDates.put( new Date() );
     notifyAll();
     return true;
   }

   public synchronized Object get() {
     while ( isEmpty() ) try {
       wait();
     } catch (InterruptedException e) {}
     Object tmp = super.get();
     delegateDates.get();
     notifyAll();
     return tmp;
   }

   public synchronized Pair getWithDate() {
     while ( isEmpty() ) try {
       wait();
     } catch (InterruptedException e) {}
     Pair tmp = new Pair( super.get(), delegateDates.get() );
     notifyAll();
     return tmp;
   }
}

b) rozwiazanie CFs
public class HistoryBufferCF {
   private Queue delegateObjects;
   private Queue delegateDates;

   public HistoryBufferCF(int capacity) {
     delegateObjects = new Queue(capacity);
     delegateDates = new Queue(capacity);
   }

   public void put(Object x) {
     delegateObjects.put(x);
     delegateDates.put(new Date());
   }

   public Object get() {
     delegateDates.get();
     return delegateObjects.get();
   }

   public Pair getWithDate() {
     return new Pair(delegateObjects.get(),delegateDates.get());
   }

   filter Wait {
     delegateObjects.isFull() => put(Object),
     delegateObjects.isEmpty() => { get(), getWithDate() }
   };
   filter Dispatch { true => this.*, true => delegateObjects.* };
}

Etap 3. Na potrzeby monitoringu nalez.y logowac' informacje o stanie 
bufora po kaz.dej transakcji.
a) rozwia;zanie Java
public class LogHistoryBuffer extends HistoryBuffer {

   public LogHistoryBuffer(int capacity) {
     super(capacity);
   }

   protected void log() {
     System.out.println("stan bufora: "+size());
   }

   public synchronized boolean put(Object x) {
     super.put(x);
     log();
     return true;
   }

   public synchronized Object get() {
     Object tmp = super.get();
     log();
     return tmp;
   }

   public synchronized Pair getWithDate() {
     Pair tmp = super.getWithDate();
     log();
     return tmp;
   }
}

b) rozwia;zanie CFs
public class LogHistoryBufferCF {
   private HistoryBufferCF delegate;

   private void log() {
     System.out.println("stan bufora: "+delegate.size());
   }

   public void put(Object x) {
     delegate.put(x);
     log();
   }

   public Object get() {
     Object tmp = delegate.get();
     log();
     return tmp;
   }

   public Pair getWithDate() {
     Pair tmp = delegate.getWithDate();
     log();
     return tmp;
   }

   filter Wait {
     delegate.isFull() => put(Object),
     delegate.isEmpty() => { get(), getWithDate() }
   };
   filter Dispatch { true => this.*, true => delegate.* };
}

W obu implementacjach zagadnienie logowania (zagadnienie przecinaja;ce) 
przeplatane jest z zagadnieniem podstawowym.

Etap 4. Stworzyc' moz.liwos'c' pobrania n kolejnych elementów w postaci 
tablicy. Pobieranie rozpocza;c' jes'li istnieje w buforze przynajmniej 
jeden element. Logowanie ma byc' pojedyncze dla kaz.dej transakcji 
(pobranie tablicy n elementów be;dzie logowane tylko raz).

a) rozwia;zanie Java
public class EnhancedLogHistoryBuffer extends HistoryBuffer {

   protected boolean lock;

   public EnhancedLogHistoryBuffer(int capacity) {
     super(capacity);
   }

   protected void lock(boolean b) {
     lock = b;
   }

   protected boolean isLock() {
     return lock;
   }

   protected void log() {
     System.out.println("stan bufora: "+size());
   }

   public synchronized boolean put(Object x) {
     super.put(x);
     log();
     return true;
   }

   public synchronized Object get() {
     while ( isEmpty()||isLock() ) try {
       wait();
     } catch (InterruptedException e) {}
     Object tmp = super.get();
     log();
     return tmp;
   }

   public synchronized Pair getWithDate() {
     while ( isEmpty()||isLock() ) try {
       wait();
     } catch (InterruptedException e) {}
     Pair tmp = super.getWithDate();
     log();
     return tmp;
   }

   public synchronized Object[] get(int n) {
     while ( isEmpty()||isLock() ) try {
       wait();
     } catch (InterruptedException e) {}
     lock(true);
     Object[] tmp = new Object[n];
     for(int i=0; i<n; i++) {
       tmp[i] = super.get();
       dates.get();
     }
     lock(false);
     log();
     return tmp;
   }

   public synchronized Pair[] getWithDate(int n) {
     while ( isEmpty()||isLock() ) try {
       wait();
     } catch (InterruptedException e) {}
     lock(true);
     Pair[] tmp = new Pair[n];
     for(int i=0; i<n; i++) tmp[i] = super.getWithDate();
     lock(false);
     log();
     return tmp;
   }
}
Implementuja;c operacje get(int) i getWithDate(int) nie moz.na wykorzystac' 
implementacji get() i getWithDate() z klasy LogHistoryBuffer poniewaz. sa; 
one splecione z zagadnieniem logowania. Poniewaz. w Javie nie ma 
moz.liwos'ci, aby niepolimorficznie wywo?ac' metode; zdefiniowana; w 
okres'lonej nadklasie, nalez.y ponownie za punkt wyjs'cia przyja;c' klase; 
HistoryBuffer. Takie rozwia;zanie wymaga ponownego zaimplementowania 
metody log.

b) rozwia;zanie CFs
public class EnhancedLogHistoryBufferCF {
   private HistoryBufferCF delegate;
   private boolean lock;

   public EnhancedLogHistoryBufferCF(int capacity) {
     delegate = new HistoryBufferCF(capacity);
   }

   public void lock(boolean b) {
     lock = b;
   }

   public boolean isLock() {
     return lock;
   }

   private void log() {
     System.out.println("stan bufora: "+delegate.size());
   }

   public void put(Object x) {
     delegate.put(x);
     log();
   }

   public Object get() {
     Object tmp = delegate.get();
     log();
     return tmp;
   }

   public Pair getWithDate() {
     Pair tmp = delegate.getWithDate();
     log();
     return tmp;
   }

   public Object[] get(int n) {
     lock(true);
     Object[] tmp = new Object[n];
     for(int i=0; i<n; i++) tmp[i] = delegate.get();
     lock(false);
     log();
     return tmp;
   }

   public Pair[] getWithDate(int n) {
     lock(true);
     Pair[] tmp = new Pair[n];
     for(int i=0; i<n; i++) tmp[i] = delegate.getWithDate();
     lock(false);
     log();
     return tmp;
   }

   filter Wait {
     delegate.isFull() => put(Object),
     delegate.isEmpty() || isLock() => { get(), getWithDate(), get(int), 
getWithDate(int) }
   };
   filter Dispatch { true => this.*, true => delegate.* };
}

Podobnie jak w przypadku rozwia;zania w Javie, trzeba ponownie 
zaimplementowac' zagadnienie logowania. Ponadto zagadnienie 
synchronizacji poprzez metode; lock zosta?o splecione z zagadnieniem 
podstawowym.

***
Wszystkie przedstawione problemy zwia;zane z przeplataniem zagadnien' 
moz.na rozwia;zac' za pomoca; AspectJ, a cze;s'c' z nich w klasycznym je;zyku OO 
umoz.liwiaja;cym niepolimorficzne wo?anie metody.

Pozdrawiam,
Adam
Re: Composition Filters [uwaga dlugie]
#17250
Author: Adam Przybylek
Date: Thu, 16 Aug 2007 16:35
417 lines
12506 bytes
Jeszcze raz to samo tylko poprawiłem kodowanie na polskie.

W poprzednim poście napisałem, że znalazłem częściowo odpowiedź na 
pytanie dlaczego CFs się nie upowszechniły. Otóż celem CFs było 
dostarczenie mechanizmu umożliwiającego lepszą separację zagadnień (SoC 
- Separation of Concerns) niż w paradygmacie obiektowym. Moje zdanie 
jest takie, że wykorzystując CFs dla niektórych przypadków można 
osiągnąć lepszą SoC, ale nie ma ona większego wpływu na poprawę 
evolvability i reusability.
Poniżej przykład na problemy jakie powstają przy implementacji w Javie 
oraz próba (bezowocna) rozwiązania ich przy pomocy dodania do Javy 
filtrów input (hipotetyczna składnia).

Załóżmy, że tworząc nowy moduł chcemy w jak największym stopniu 
wykorzystać istniejące moduły. Ponadto na każdym etapie chcemy zrobić 
dobrą implementację pod aktualne wymagania, a nie pod ewentualne 
przyszłe, o których nic nie wiemy. Zapominamy o istnieniu gotowych 
pakietów Javy. Załóżmy także, że posiadamy w repozytorium następującą 
implementację kolejki:

public class Queue {
   protected Object[] buf;
   protected int numItems;
   protected int nextToRemove;

   public Queue(int capacity) {
     buf = new Object[capacity];
   }

   public boolean isFull() {
     return (numItems==buf.length);
   }

   public boolean isEmpty() {
     return (numItems==0);
   }

   public int size() {
     return numItems;
   }

   public boolean put(Object x) {
     if ( isFull() ) return false;
     buf[(nextToRemove+numItems) % buf.length] = x;
     numItems++;
     return true;
   }

   public Object get() {
     Object tmp=null;
     if ( !isEmpty() ) {
       tmp = buf[nextToRemove];
       numItems--;
       nextToRemove = (nextToRemove+1) % buf.length;
     }
     return tmp;
   }
}

Etap 1. Należy zaimplementować klasę Buffer pod klasyczny problem 
producenta-konsumenta.
a) rozwiązanie Java
public class Buffer extends Queue {

   public Buffer(int capacity) {
     super(capacity);
   }

   public synchronized boolean put(Object x) {
     while ( isFull() ) try {
       wait();
     } catch (InterruptedException e) {}
     super.put(x);
     notifyAll();
     return true;
   }

   public synchronized Object get() {
     while ( isEmpty() ) try {
       wait();
     } catch (InterruptedException e) {}
     Object tmp = super.get();
     notifyAll();
     return tmp;
   }
}

Należy zauważyć, że zagadnienie synchronizacji (zagadnienie 
przecinające) jest splecione z zagadnieniem odkładania i pobierania 
danych (zagadnienie podstawowe).

b) rozwiązanie CFs
public class BufferCF {
   private Queue delegate;

   filter Wait {
     delegate.isFull() => put(Object),
     delegate.isEmpty() => get()
   };
   filter Dispatch { true => delegate.* };
}
Działa to w ten sposób, że każdy komunikat przychodzący z zewnątrz do 
obiektu przechodzi najpierw przez filtr Wait, a następnie przez filtr 
Dispatch. Pierwszy wpis w filtrze Wait mówi, aby uśpić wątek wykonujący 
put(Object) na pełnym buforze, a drugi, aby uśpić wątek wykonujący get() 
na pustym buforze.
Nałożenie na metodę filtru Wait sprawia, że staje się ona synchroniczna. 
Ponadto sprawdzenie warunku (również synchroniczne) i ewentualne 
rozpoczęcie metody jest atomowe.
Z kolei zastosowany filtr Dispatch mówi, aby każdy komunikat (*) 
bezwarunkowo (true) przekazać do obsłużenia obiektowi delegate. Gdyby 
filtr Dispatch zawierał więcej wpisów rozpatrywane by były od lewej do 
prawej tak długo aż skojarzony z którymś warunek będzie spełniony. Jeśli 
żaden warunek nie zostanie spełniony to rzucany jest run-time error.

Etap 2. Przychodzi nowe wymaganie - dla każdego elementu wkładanego do 
bufora należy pamiętać datę kiedy został on włożony. Ponadto umożliwić 
pobranie elementu razem z tą datą.
a) rozwiązanie Java
public class HistoryBuffer extends Buffer {
   protected Queue delegateDates;

   public HistoryBuffer(int capacity) {
     super(capacity);
     delegateDates = new Queue(capacity);
   }

   public synchronized boolean put(Object x) {
     while ( isFull() ) try {
       wait();
     } catch (InterruptedException e) {}
     super.put(x);
     delegateDates.put( new Date() );
     notifyAll();
     return true;
   }

   public synchronized Object get() {
     while ( isEmpty() ) try {
       wait();
     } catch (InterruptedException e) {}
     Object tmp = super.get();
     delegateDates.get();
     notifyAll();
     return tmp;
   }

   public synchronized Pair getWithDate() {
     while ( isEmpty() ) try {
       wait();
     } catch (InterruptedException e) {}
     Pair tmp = new Pair( super.get(), delegateDates.get() );
     notifyAll();
     return tmp;
   }
}

b) rozwiazanie CFs
public class HistoryBufferCF {
   private Queue delegateObjects;
   private Queue delegateDates;

   public HistoryBufferCF(int capacity) {
     delegateObjects = new Queue(capacity);
     delegateDates = new Queue(capacity);
   }

   public void put(Object x) {
     delegateObjects.put(x);
     delegateDates.put(new Date());
   }

   public Object get() {
     delegateDates.get();
     return delegateObjects.get();
   }

   public Pair getWithDate() {
     return new Pair(delegateObjects.get(),delegateDates.get());
   }

   filter Wait {
     delegateObjects.isFull() => put(Object),
     delegateObjects.isEmpty() => { get(), getWithDate() }
   };
   filter Dispatch { true => this.*, true => delegateObjects.* };
}

Etap 3. Na potrzeby monitoringu należy logować informacje o stanie 
bufora po każdej transakcji.
a) rozwiązanie Java
public class LogHistoryBuffer extends HistoryBuffer {

   public LogHistoryBuffer(int capacity) {
     super(capacity);
   }

   protected void log() {
     System.out.println("stan bufora: "+size());
   }

   public synchronized boolean put(Object x) {
     super.put(x);
     log();
     return true;
   }

   public synchronized Object get() {
     Object tmp = super.get();
     log();
     return tmp;
   }

   public synchronized Pair getWithDate() {
     Pair tmp = super.getWithDate();
     log();
     return tmp;
   }
}

b) rozwiązanie CFs
public class LogHistoryBufferCF {
   private HistoryBufferCF delegate;

   private void log() {
     System.out.println("stan bufora: "+delegate.size());
   }

   public void put(Object x) {
     delegate.put(x);
     log();
   }

   public Object get() {
     Object tmp = delegate.get();
     log();
     return tmp;
   }

   public Pair getWithDate() {
     Pair tmp = delegate.getWithDate();
     log();
     return tmp;
   }

   filter Wait {
     delegate.isFull() => put(Object),
     delegate.isEmpty() => { get(), getWithDate() }
   };
   filter Dispatch { true => this.*, true => delegate.* };
}

W obu implementacjach zagadnienie logowania (zagadnienie przecinające) 
przeplatane jest z zagadnieniem podstawowym.

Etap 4. Stworzyć możliwość pobrania n kolejnych elementów w postaci 
tablicy. Pobieranie rozpocząć jeśli istnieje w buforze przynajmniej 
jeden element. Logowanie ma być pojedyncze dla każdej transakcji 
(pobranie tablicy n elementów będzie logowane tylko raz).

a) rozwiązanie Java
public class EnhancedLogHistoryBuffer extends HistoryBuffer {

   protected boolean lock;

   public EnhancedLogHistoryBuffer(int capacity) {
     super(capacity);
   }

   protected void lock(boolean b) {
     lock = b;
   }

   protected boolean isLock() {
     return lock;
   }

   protected void log() {
     System.out.println("stan bufora: "+size());
   }

   public synchronized boolean put(Object x) {
     super.put(x);
     log();
     return true;
   }

   public synchronized Object get() {
     while ( isEmpty()||isLock() ) try {
       wait();
     } catch (InterruptedException e) {}
     Object tmp = super.get();
     log();
     return tmp;
   }

   public synchronized Pair getWithDate() {
     while ( isEmpty()||isLock() ) try {
       wait();
     } catch (InterruptedException e) {}
     Pair tmp = super.getWithDate();
     log();
     return tmp;
   }

   public synchronized Object[] get(int n) {
     while ( isEmpty()||isLock() ) try {
       wait();
     } catch (InterruptedException e) {}
     lock(true);
     Object[] tmp = new Object[n];
     for(int i=0; i<n; i++) {
       tmp[i] = super.get();
       dates.get();
     }
     lock(false);
     log();
     return tmp;
   }

   public synchronized Pair[] getWithDate(int n) {
     while ( isEmpty()||isLock() ) try {
       wait();
     } catch (InterruptedException e) {}
     lock(true);
     Pair[] tmp = new Pair[n];
     for(int i=0; i<n; i++) tmp[i] = super.getWithDate();
     lock(false);
     log();
     return tmp;
   }
}
Implementując operacje get(int) i getWithDate(int) nie można wykorzystać 
implementacji get() i getWithDate() z klasy LogHistoryBuffer ponieważ są 
one splecione z zagadnieniem logowania. Ponieważ w Javie nie ma 
możliwości, aby niepolimorficznie wywołać metodę zdefiniowaną w 
określonej nadklasie, należy ponownie za punkt wyjścia przyjąć klasę 
HistoryBuffer. Takie rozwiązanie wymaga ponownego zaimplementowania 
metody log.

Alternatywne rozwiązanie polega na rozszerzeniu klasy LogHistoryBuffer i 
"od zera" napisanie implementacji get(int) i getWithDate(int).

b) rozwiązanie CFs
public class EnhancedLogHistoryBufferCF {
   private HistoryBufferCF delegate;
   private boolean lock;

   public EnhancedLogHistoryBufferCF(int capacity) {
     delegate = new HistoryBufferCF(capacity);
   }

   public void lock(boolean b) {
     lock = b;
   }

   public boolean isLock() {
     return lock;
   }

   private void log() {
     System.out.println("stan bufora: "+delegate.size());
   }

   public void put(Object x) {
     delegate.put(x);
     log();
   }

   public Object get() {
     Object tmp = delegate.get();
     log();
     return tmp;
   }

   public Pair getWithDate() {
     Pair tmp = delegate.getWithDate();
     log();
     return tmp;
   }

   public Object[] get(int n) {
     lock(true);
     Object[] tmp = new Object[n];
     for(int i=0; i<n; i++) tmp[i] = delegate.get();
     lock(false);
     log();
     return tmp;
   }

   public Pair[] getWithDate(int n) {
     lock(true);
     Pair[] tmp = new Pair[n];
     for(int i=0; i<n; i++) tmp[i] = delegate.getWithDate();
     lock(false);
     log();
     return tmp;
   }

   filter Wait {
     delegate.isFull() => put(Object),
     delegate.isEmpty() || isLock() => {
       get(), getWithDate(), get(int), getWithDate(int)
     }
   };
   filter Dispatch { true => this.*, true => delegate.* };
}

Podobnie jak w przypadku rozwiązania w Javie, trzeba ponownie 
zaimplementować zagadnienie logowania. Ponadto zagadnienie 
synchronizacji poprzez metodę lock zostało splecione z zagadnieniem 
podstawowym.

***
Wszystkie przedstawione problemy związane z przeplataniem zagadnień 
można rozwiązać za pomocą AspectJ, a część z nich w klasycznym języku OO 
umożliwiającym niepolimorficzne wołanie metody.
Re: Composition Filters
#17254
Author: Jarek
Date: Thu, 30 Aug 2007 09:57
12 lines
1522 bytes
>
> Ze jak sie rozwija?... Moze i dymamicznie sie rozwija, ino nikt go nie
> uzywa.
>
A już wymieniony przez kogoś Spring to nikt? Przecież to jeden z 
najpopularniejszych frameworków.
JBoss też wewnętrznie używa AOP do implementacji paru rzeczy.
Kolega twierdzi, że w firmie (dość dużej), w której pracuje też używają AOP, 
o ile się nie mylę, do zarządzania transakcjami.

Pozdrawiam
Jarek
Re: Composition Filters
#17255
Author: Kamil Janiszewski
Date: Wed, 05 Sep 2007 17:20
76 lines
5024 bytes
On 30 Sie, 11:57, "Jarek" <nie...@takiego.numeru> wrote:
> > Ze jak sie rozwija?... Moze i dymamicznie sie rozwija, ino nikt go nie
> > uzywa.
>
> A ju  wymieniony przez kogo  Spring to nikt? Przecie  to jeden z
> najpopularniejszych frameworków.
> JBoss te  wewn trznie u ywa AOP do implementacji paru rzeczy.
> Kolega twierdzi,  e w firmie (do   du ej), w której pracuje te  u ywaj  AOP,
> o ile si  nie myl , do zarz dzania transakcjami.
>
> Pozdrawiam
> Jarek

On 30 Sie, 11:57, "Jarek" <nie...@takiego.numeru> wrote:
> > Ze jak sie rozwija?... Moze i dymamicznie sie rozwija, ino nikt go nie
> > uzywa.
>
> A ju  wymieniony przez kogo  Spring to nikt? Przecie  to jeden z
> najpopularniejszych frameworków.
> JBoss te  wewn trznie u ywa AOP do implementacji paru rzeczy.
> Kolega twierdzi,  e w firmie (do   du ej), w której pracuje te  u ywaj  AOP,
> o ile si  nie myl , do zarz dzania transakcjami.
>
> Pozdrawiam
> Jarek

Wycinek z mojej, mam nadziej , przysz ej pracy magisterskiej:

                        AOP a  wiat, kto korzysta z AOP

Wydawa oby si ,  e niewielu informatyków s ysza o o programowaniu
aspektowym. Dlatego nikt nie spodziewa si ,  e AOP jest wykorzystywane
w powa nych projektach. Tymczasem rzeczywisto   mo e zaskoczy  wielu z
nas.
Programowanie aspektowe jest u ywane w kilku wielkich projektach:
ˇ	Deutsche Post World Net - aplikacja stanowi ca rozwi zanie problemów
zarz dzania, transportu, przesy ania informacji i p atno ci dla grupy
firm: Deutsche Post, DHL i Postbank (.NET),
ˇ	Philips - wiele projektów informatycznych firmy stworzonych na bazie
autorskiego rozwi zania Koala. (inne),
ˇ	Spring Framework - bardzo popularny szkielet wytwarzania aplikacji
(Java),
ˇ	JBoss - równie popularny serwer aplikacji (Java),
ˇ	Glassbox - agent pomagaj cy rozwi zywa  cz sto wyst puj ce problemy
programistyczne (Java).
Inne zastosowania AOP to np.:
ˇ	Tapestry - szkielet dla dynamicznych,  atwo skalowalnych aplikacji
rozproszonych (Java),
ˇ	Contract4J - narz dzie wspieraj ce programowanie kontraktowe (Design
by Contract - DBC),
ˇ	Jakarta Cactus - szkielet testowy do przeprowadzania testów
jednostkowych kodu po stronie serwera (Java),
ˇ	Objectweb Cooperative Open Workflow - silnik przep ywów pracy
(Java),
ˇ	Objectweb Java Open Transaction Manager - zarz dca transakcji (na
przyk ad bazodanowych) (Java),
ˇ	GridSphere portal framework - szkielet portalu internetowego (Java),
ˇ	MySQL Connector/J - natywny sterownik bazy danych dla JDBC (Java).
Po przeczytaniu tej listy projektów nazuwa si  spostrze enie,  e
korzystanie z AOP jest znacznie bardziej popularne w  wiecie Javy, ni 
na platformie .NET, czy w C++. Powodem jest znaczna przewaga w rozwoju
narz dzi i j zyków programowania aspektowego w Javie oraz cz sto
otwarty charakter projektów pisanych w Javie.  Realnie programowanie
aspektowe do niedawna mia o tylko jednego prawdziwego (dopracowanego i
popularnego) przedstawiciela i by  to AspectJ. Jest to rozszerzenie do
Javy stworzone w s ynnym laboratorium Xerox PARC pod kierownictwem
Gregora Kiczalesa. Pierwsza publiczna wersja AspectJ ujrza a  wiat o
dzienne w roku 2001.
Nie ma popularnych implementacji AOP poza AspectJ, aczkolwiek mo na
spodziewa  si  znacznego zainteresowania bibliotek  Policy Injection
Block wchodz c  w sk ad Enterprise Library od wersji 3.0 (kwiecie 
2007) dla platformy .NET. Pury ci AOP mog  zwraca  uwag , na to,  e
Policy Injection Block nie jest do ko ca zgodny z wszystkim
za o eniami AOP (nie planowano tego), mimo to ja uwa am,  e jest
w a nie tym, co spopularyzuje podej cie do programowania znanego z AOP
w pot  nym  rodowisku programistów .NET.
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