Welcome Guest Search | Active Topics | Members | Log In

Definicje interfejsów - po co jest "feature"? Options · View
habela
Posted: Wednesday, December 08, 2004 5:44:54 PM
Rank: Administration

Joined: 12/6/2004
Posts: 360
Points: 52
W nawiązaniu do dyskusji w poprzednim wątku - kilka słów wyjaśnienia oraz otwarte kwestie w sprawie użytego tam pojęcia structural feature.
Zacznijmy od tego, że nazwa mogłaby być w istocie mniej egzotyczna (attribute, member field, member czy podobnie) i jeśli tak się nie stało, to po części przypadkiem, a po części za sprawą kilku cech szczególnych:
- dążenie do "wyciągnięcia przed nawias" w metamodelu kilku cech wspólnych dla podobiektów oraz związków asocjacyjnych (wspólny termin structural feature) czy wręcz - także operacji (wspólny termin - feature)
- możliwość zagnieżdżania w obiekcie podobiektów złożonych (jakoś sztucznie tu brzmiał attribute);
- założenie, że na najwyższym poziomie bazy (lub jej modułu) można wstawiać nie dowolne obiekty, ale tylko te odpowiadające jawnie zadeklarowanym "zmiennym globalnym" (w tej roli również, podobnie jak w ramach definicji klasy wystąpiłby structural feature, stąd nie użyto terminu "member").
***
Z powyższego jak się wydaje wynika, że owa konstrukcja (z dokładnością do nazwy oraz do zakresu przykrywanych przezeń własności - o tym za chwilę) w takiej czy innej postaci jest potrzebna: Nawet, jeśli rezygnujemy z obowiązku deklarowania miejsc występowania obiektów na górnym poziomie (czyli, że można tam wrzucać obiekty dowolnej zdefiniowanej wcześniej klasy), to potrzebujemy deklaracji aby zdefiniować np. interfejs obiektu złożonego.
***
Pojęcie nabiera większego znaczenia, jeśli przyjmiemy, że obiekt może posiadać zarówno podobiekty konkretne jak i wirtualne (tj. dostarczane przez mechanizm perspektyw). Wygląda bowiem na to, że deklaracja własności strukturalnej jest dogodnym miejscem, aby zdefiniować albo przeciążyć operacje generyczne związane z dostępem do opisywanych przezeń podobiektów. Chodzi o to, aby przejście od zadeklarowania w definicji interfejsu, że np. podobiekt "płaca" pozwala na aktualizację, do opisania sposobu, jak taka implementacja jest zaimplementowana, nie zmuszały programisty do zmiany sposobu myślenia.
***
Ostatnia istotna kwestia, to określanie nazwy obiektów opisanych danym structura feature:
- praktycznie niezbędne dla obiektów prostych;
- przydatne dla obiektów złożonych, bo jak wywnioskowałem z dzisiejszych konsultacji, warto móc określać nazwę obiektu jako inwariant w typie obiektów złożonych, jednak nie oznacza to wymuszania zależności 1:1 nazwa instancji<->typ.
***
Reasumując - zapewne istnieją możliwości uproszczeń, ale całej konstrukcji nazwanej tu "struct feature" nie sposób zupełnie wyeliminować...
KK
Posted: Thursday, December 09, 2004 11:40:54 AM
Rank: Advanced Member

Joined: 12/7/2004
Posts: 226
Points: 30
To może bardziej konkretnie na przykładzie.
Mamy obiekt:
Code:

class Osoba
{
   Name : String;
   Friends : Osoba;
   Parents : Osoba;
}


To mamy tu trzy Structural Feature. Jak widać do obiektów zagnieżdżonych wygodnie jest dodawać nazwę inną niż nazwa klasy. Można generalnie zauważyć, że włożenie obiektu do innego obiektu związane jest z określeniem pewnych ograniczeń i własności, które w tym momencie się pojawiają. Chodzi o to, że instancja Osoba nazwana Friends istnieje w zakresie wewnętrznym dla obiektów Osoba i jako taka może mieć -- inną liczność (niż np Parents), -- inne prawa dostępu/aktualizacji itd. Dochodzimy do tego, że razem z zadeklarowaniem Feature pojawia się możliwość podania dowolnej liczby atrybutów, które wynikają z przyjętego metamodelu. Dobrze byłoby przyjąć składnię, która by nie ograniczała ich ilości. Jest tak np w XML gdzie atrybuty i ich wartości są wymieniane po nazwie obiektu (nie mylić z obiektami zagnieżdżonymi).
My moglibyśmy sobie wyobrazić coś takiego:
Code:

class Osoba
{
   Name : String;
   Friends [0-*, read=T, update=F, delete=T, public=T] : Osoba;
   Parents [0-2, read=T, update=T, delete=T, public=F]: Osoba;
}


Podsumowując pytanie o istnienie (być może tylko w naszej głowie) Feature jest takie: Czy nazwa obiektu jest inwariantem klasy czy instancji? Czyli inaczej, czy nazwa obiektów może (powinna) się zmienić gdy włożymy je do innego obiektu. My z Piotrem uważamy, że tak. Choćby dla uzyskania lepszej hermetyzacji, a co za tym idzie przenośności kodu.

Feature istnieje w każdym sensownym języku obiektowym. Dlaczego nie miałby istnieć w SBQL ?
habela
Posted: Thursday, December 09, 2004 5:24:29 PM
Rank: Administration

Joined: 12/6/2004
Posts: 360
Points: 52
Na początek uwaga natury formalnej: jeśli ten kod poniżem ma dotyczyć SBQL oraz np. Name oznacza nazwę podobiektu w obiekcie klasy Osoba, to wobec tego, niezależnie od tego jaka ma być licznośc tych friendów i rodziców, należałoby użyć również nazw w liczbie pojedynczej, tj. np.
Code:
Name : String;
Friend[0..*] : Osoba;
Parent[0..2] : Osoba;


Czy nazwa obiektu powinna być niezmiennikiem w klasie/typie? Osobiście nie podobało mi się założenie, że zawsze musi. Nie tylko dlatego, że powyższy przykład nie byłby dozwolony. Gorzej, że mógłby pójść za tym wymóg, że jeśli instance name w klasie Osoba jest "osoba", to w całej bazie danych żaden obiekt innej klasy nie może nosić tej nazwy.
Z kolei argumenty za stosowaniem tego niezmiennika, to zapewne uproszczenie deklaracji w schemacie. Ponadto Szef argumentował, że jeśli w klasie determinujemy nazwy pod-obiektów to dlaczego nie mielibyśmy zdeterminować również nazwy obiektu tej klasy. Że jest to sprzeczne z relatywizmem obiektów. Z kolei moja intuicja jest taka, że skoro mamy relatywizm i możemy korzystać z uprzednio zdefiniowanych klas, to każdemu poziomowi zagnieżdżenia odpowiada definicja jakiejś klasy czy typu, więc po co na jakimś poziomie fiksować nazwy wystąpień od razu dla dwóch poziomów. Ponadto relatywizm obiektów kojarzył mi się też z tym, że skoro string może mieć nazwę zadeklarowaną w danym miejscu użycia, to dlaczego nie np. Osoba.
Z wczorajszej rozmowy po seminarium wywnioskowałem jednak, że postulat jest taki, aby dla danego typu czy klasy nazwa obiektu mogła, a nie musiała być inwariantem.

Poza wskazał powyżej Krzysztof, poza określaniem nazwy przechowywanych wystąpień deklaracja featur może też określać liczności i szereg innych spraw. Wydaje mi się, że wobec tego założenie, że dla obiektów składowanych również na najwyższym poziomie powinny istnieć deklaracje stosownych structural features (jak zwał, tak zwał), estetycznie nam wszystko domyka.
P.S. Ten przykład z osobą jest może odrobinę sztuczny, bo skoro inna osoba jest przechowywana pod nazwą np. "Parent", niejako podporządkowuje użyciu w kontekście obiektu-właściciela (w praktyce projektant w tym wypadku by zapewne obiektó nie zagnieżdżał). Natomiast wierzę, że generalnie elastyczność w sensie nadawania nazw obiektom złożonym może być bardzo użyteczna.
stencel
Posted: Friday, December 10, 2004 4:42:32 PM

Rank: Advanced Member

Joined: 12/7/2004
Posts: 598
Points: 74
Location: Raszyn
W modelu M1 nazwa obiektu jest niezmiennikiem klasy i juz. To mi sie podoba.

Moglibysmy przyjac zasade, ze mozna zagniezdzac obiekty z wyjatkiem obiektow nalezacych do klas, ktorych to obiektow zagniezdzac nie mozna. Mozna natomiast wstawiac do obiektow referencje do obiektow klas.

Popatrzmy teraz na deklaracje:

Code:
class Osoba
{
   Name : String;
   Friends : Osoba;
   Parents : Osoba;
}


Pomieszane tu jest wszystko i poplatane. Szef w swojej ksiazce i w swoim umysle tez uwaza taka konstrukcje za chora, bo bezposrednio prowadzi do koniecznosci tworzenia skomplikowanych konstrukcji a la dziedziny Scotta.

Stad raczej powinno byc (a powyzszy kod powinien byc zabroniony):

Code:
class Osoba
{
   Name : String;
   Friends : ref to Osoba;
   Parents : ref to Osoba;
}


No i w koncu warto przypomniec, ze zagniezdzony obiekt w SBA nie dostaje nazwy poprzez zagniezdzenie gdzies, ale ma swoja wlasna nazwe, tak wiec ta klasa powinna wygladac tak:

Code:
simple object Name { String };

link object Friend { Osoba };

link object Parent { Osoba };

class Osoba
{
  Name[1..1];
  Friend[0..*];
  Parent[0..2];
}


Przypominam, ze nazwa obiektu jest definiowana wraz z tym obiektem, a nie wraz z jego zagniezdzeniem.

Oczywiscie moznaby zrobic tu cos ala XMLSchema, gdzie zamiast definiowac typ mozna wstawic jego definicje w miejsce uzycia. Wtedy wygladaloby to tak:

Code:
class Osoba
{
  simple object Name { String }[1..1];
  link object Friend { Osoba }[0..*];
  link object Parent { Osoba }[0..2];
}


Natomiast skladnia w rodzaju "Name : String;" powinna byc zarezerwowana dla binderow w srodowisku wykonawczym procedur/metod i nie mozna jej uzywac w definicjach obiektow skladu (zajrzyjcie do mojej wypowiedzi w watku o zagniezdzaniu obiektow). Bo wlasnie przez to ze uzywamy tej skladni tam, jest masa nieporozumien.
habela
Posted: Friday, December 10, 2004 8:02:51 PM
Rank: Administration

Joined: 12/6/2004
Posts: 360
Points: 52
Quote:
Pomieszane tu jest wszystko i poplatane. Szef w swojej ksiazce i w swoim umysle tez uwaza taka konstrukcje za chora, bo bezposrednio prowadzi do koniecznosci tworzenia skomplikowanych konstrukcji a la dziedziny Scotta.

Ten argument jest trochę tendencyjny - przykład z osobą nie jest, jak podkreślałem, zbyt szczęśliwy, ale nie widzę (pominięto tu liczności) tutaj koncepcyjnego problemu, który usnęłaby nazwa traktowana jako niezmiennik.

Quote:
No i w koncu warto przypomniec, ze zagniezdzony obiekt w SBA nie dostaje nazwy poprzez zagniezdzenie gdzies, ale ma swoja wlasna nazwe

To z kolei jest silny argument. Istotnie, chyba nie mamy w tej chwili w języku środków do zmiany nazwy zapisanej w obiekcie (?), gdybyśmy np. chcieli dostosować nazwę istniejącego obiektu na pasującą do określonej feature i następnie dokonać wstawienia. Bo as tworzy nam bindery. Czy tak? Ale zapewne jest to do zrobienia, jeśli okaże się przydatne.

BTW: Nie zaglądałem dość długo do raportu o typach, ale z tego co pamiętam, struktura metabazy jest przygotowana (przez istnienie określonych powiązań obiekt-nadrzędny-obiekt składowy) na przechowywanie informacji o wielu tak samo nazwanych obiektach różniących się typami?

Quote:
W modelu M1 nazwa obiektu jest niezmiennikiem klasy i juz. To mi sie podoba.

Ja ciągle podchodzę do tego z rezerwą z uwagi na drugi z argumentów wymienionych w poprzednim wątku:
2. Obawy budzi wynikły z tego założenia wymóg globalnej (w sensie całej bazy, a być może - federacji) unikalności nazw obiektów należących do różnych typów. Zwróćmy uwagę, że na gruncie XML-a (chyba można tu wysnuć taką analogię z niezmiennikami typ elementu XML -> nazwa elementu XML) wymusiło to wprowadzenie znanego i lubianego mechanizmu przestrzeni nazwowych...
michal
Posted: Friday, December 10, 2004 8:21:01 PM

Rank: Advanced Member

Joined: 12/6/2004
Posts: 332
Points: -61
Quote:
Ten argument jest trochę tendencyjny - przykład z osobą nie jest, jak podkreślałem, zbyt szczęśliwy, ale nie widzę (pominięto tu liczności) tutaj koncepcyjnego problemu, który usnęłaby nazwa traktowana jako niezmiennik.


zdaje sie ze Krzysiek wprowadzil tylko slowko ref dla zakcentowania, ze obiekt nie jest fizycznie zagniezdzony,
tylko jest referencja. oczywiscie chyba nikt z nas nie myslal ze osoba moze byc zagniezdzona w osobie -
brak ref byl tylko uproszczeniem skladniowym ...

Quote:
Obawy budzi wynikły z tego założenia wymóg globalnej (w sensie całej bazy, a być może - federacji) unikalności nazw obiektów należących do różnych typów. Zwróćmy uwagę, że na gruncie XML-a (chyba można tu wysnuć taką analogię z niezmiennikami typ elementu XML -> nazwa elementu XML) wymusiło to wprowadzenie znanego i lubianego mechanizmu przestrzeni nazwowych...


to chyba nie byloby problemem, bo mamy przeciez moduly ... mozna sobie utworzyc typ Employee
w module X i typ Employee w module Y, a ktora nazwa bedzie wykorzystana - to dopiero kwestia
modulu, ktory sobie zaimportujemy ...
habela
Posted: Friday, December 10, 2004 9:08:21 PM
Rank: Administration

Joined: 12/6/2004
Posts: 360
Points: 52
Quote:
to chyba nie byloby problemem, bo mamy przeciez moduly ... mozna sobie utworzyc typ Employee
w module X i typ Employee w module Y, a ktora nazwa bedzie wykorzystana - to dopiero kwestia
modulu, ktory sobie zaimportujemy ...

Brzmi obiecująco.
Trzeba sie upewnić, że:
- z punktu widzenia raportu Rafała i Krzyśka, takie "ulokalnienie" unikalności nazwy obiektów względem ich typów nie wnosi nadmiernych komplikacji;
- kod, który byłby zmuszony np. pracować równocześnie na obiektach o tej samej nazwie posiadających różne definicje, bo pochodzących z różnych modułów, posiada możliwość ich niezawodnego rozróżnienia;
... i można nanosić zmiany na szkic składni DDL. ;-)
Czekam na Wasze uwagi dotyczące takiego rozwiązania sprawy nazw-niezmienników!
michal
Posted: Friday, December 10, 2004 9:12:50 PM

Rank: Advanced Member

Joined: 12/6/2004
Posts: 332
Points: -61
Quote:
Brzmi obiecująco.


wcale nie ...

ja nadal jestem temu przeciwny, ale z innych powodow (inny watek) ...
habela
Posted: Saturday, December 11, 2004 2:16:50 PM
Rank: Administration

Joined: 12/6/2004
Posts: 360
Points: 52
Quote:
wcale nie ...
ja nadal jestem temu przeciwny, ale z innych powodow (inny watek) ...

Z komentarzem tam zawartym się zgadzam, ale trudno mi ocenić implikacje...
Może warto by powrócić tutaj do tej dyskusji.
stencel
Posted: Saturday, December 11, 2004 9:33:37 PM

Rank: Advanced Member

Joined: 12/7/2004
Posts: 598
Points: 74
Location: Raszyn
Rozwiazanie problemu tego, czy nazwa powinna jednoznacznie okreslac typ, nie jest proste. Moje zdanie jest pozytywne (TAK). To upraszcza definiowanie schematu bazy danych i w ogole poruszanie sie w bazie danych.

Wiem, ze jest to argument z innej polki, ale wydaje mi sie, ze Szef jest bardzo przywiazany do tej idei. Pisalem ten raport o typach i musialem dokladnie ksiazke przeczytac, wiec takie jest moje wrazenie. Moze warto go o to zapytac? Szkoda, ze nie wypowiada sie na forum, bo na podstawie przeszlosci wydaje mi sie, ze on bardzo dobrze czuje sie na forach.

Moze ktos naszkicuje jakis przyklad (dosc precyzyjnie) kiedy fakt jednoznacznosci typu dla nazwy jest szkodliwy? Na przykladzie bedzie latwiej dyskutowac. Bo na razie nie widze uzasadnienia dla odrzucenia tego zalozenia.

Code:
database Krakow
{
  root
  {
    Stud : Student;
    Absolw : Student;
  }
}


Ten przyklad (jesli ma byc uzyty) wymaga doprecyzowania np. jakims pseudokodem, ktorego nie da sie zapisac bez unikatowosci nazw.

Przeciez jesli Stud i Absolw nie roznia sie typem danych, to mozna to zrobic tak (bo chodzi tylko o kolekcje):

Code:
database Krakow
{
  root
  {
    complex object Stud { Student[0..*]};
    complex object Absolw { Student[0..*]};
  }
}


Czyli mamy dwie kolekcje studentow.

Jesli zas Stud i Absolw sie jakos od siebie roznia typem danych i chcemy to uwydatnic, to na Jowisza stworzmy odrebne podklasy Stud i Absolw.
michal
Posted: Sunday, December 12, 2004 1:52:02 AM

Rank: Advanced Member

Joined: 12/6/2004
Posts: 332
Points: -61
Bardzo prosze. Oto przyklad.

Zalozenie 1
Code:
SBQL> cos;

oznacza wykonanie instrukcji SBQL ad hoc (oczywiscie za pomoca shella odry, czyli OCLI ;)

Zalozenie 2
Cos jeszcze chyba krece z "ref Employee" i "Employee", ale to na szczescie nie
ma wiekszego wplywu na ten przyklad.

Sytuacja 1:
Procedura. Nazwa obiektu jako inwariant (proponuje nie pic tyle coli ;) klasy, np.:

Code:
class Employee invariant (Name = Emp) {
...
}


Czyli tak, jak chce Krzysiek (chyba?).

Code:
procedure blabla(p : ref Employee) {
  Prac<5..100> : Employee;
  Pracownik<1..*> : Employee;
}


jakis przykladowy sklad globalny (wypelniony wczesniej, nie wnikamy jak):
Code:
                            <i0, entry>
                                  |
-----------------------------------------------------------------------
|                      |                 |           |                |               |
<i1, Emp> <i2, Emp> <i3, Emp> <i4, Dept>  <i5, Dept>  <i6, blabla>


pomijam obiekt klasy Employee, ktory tez tutaj powinien byc widoczny

odpalamy sesje, robimy nested(i0) i dostajemy nastepujacy ENVS:

Code:
-------------------------------------------------------------------------------
Emp(i1), Emp(i2), Emp(i3), Dept(i4), Dept(i5), blabla(i6)
-------------------------------------------------------------------------------


teraz wywolujemy procedure blabla, podajac jako argument
pierwszego na liscie pracownikow (i1), czyli:

Code:
SBQL> blabla(Emp<1>);


otwieramy nowa sekcje, alokujemy sklad lokalny, bierzemy
nazwe parametru formalnego, parametr aktualny i robimy z tego binder, czyli mamy:

Code:
ENVS:
-------------------------------------------------------------------------------
p(i1)
-------------------------------------------------------------------------------
Emp(i1), Emp(i2), Emp(i3), Dept(i4), Dept(i5), blabla(i6)
-------------------------------------------------------------------------------


Sklad lokalny w blabla:
<i8, entry>

teraz mamy deklaracje Prac<5..100> : Employee;

poniewaz musimy miec minimalnie 5 obiektow identyfikowanych przez Prac,
wiec w lokalnym skladzie alokujemy 5 obiektow Employee
(konstruktor domyslny, czyli bezparametrowy), a na ENVS
wrzucamy bindery Prac do utworzonych obiektow. wiemy ze maja to byc nazwy
Prac, bo mamy je w kodzie procedury. nazwa obiektu nie ma znaczenia,
bo dostajemy sie do niego po binderze. mamy jednak inwariant wyznaczajacy
nazwe, wiec w skladzie obiekty nazywaja sie Emp

Sklad lokalny w blabla:

Code:
                          <i8, entry>
                                 |
---------------------------------------------------------------------------
|                    |               |                     |               |                 
<i9, Emp> <i10, Emp> <i11, Emp> <i12, Emp>  <i13, Emp>


ENVS w blabla:
Code:
--------------------------------------------------------------------
p(i1), Prac(i9), Prac(i10), Prac(i11), Prac(i12), Prac(i13)
--------------------------------------------------------------------
Emp(i1), Emp(i2), Emp(i3), Dept(i4), Dept(i5), blabla(i6)
--------------------------------------------------------------------


teraz mamy deklaracje Pracownik<1..*> : Employee, wiec
robimy to co wyzej:

Sklad lokalny w blabla:

Code:
                          <i8, entry>
                                 |
--------------------------------------------------------------------------
|                    |               |                     |           |                   |
<i9, Emp> <i10, Emp> <i11, Emp> <i12, Emp>  <i13, Emp>  <i14, Emp>



ENVS w blabla:
Code:
--------------------------------------------------------------------
p(i1), Prac(i9), Prac(i10), Prac(i11), Prac(i12),
Prac(i13), Pracownik(i14)
--------------------------------------------------------------------
Emp(i1), Emp(i2), Emp(i3), Dept(i4), Dept(i5), blabla(i6)
--------------------------------------------------------------------


jak widac wszystkie obiekty Employee maja nazwe Emp,
a jesli chcemy dostac sie po innej nazwie do konkretnego obiektu,
to mamy bindery.

wychodzimy z procedury, bindery znikaja, obiekty tez. zgadza sie?

Sytuacja 2:
Sklad globalny, trwaly albo i nie (nie ma to znaczenia), wazne
ze dostepny dla wszystkich uzytkownikow. Nazwa obiektu jako inwariant
(czyli tak, jak chce Krzysiek).

Sklad globalny (znowu dla uproszczenia bez klasy Employee):

Code:
<0, entry>


teraz tworzmy nowy modul:
Code:

SBQL> create module SuperAplikacja {
        p : Employee;
        Prac<5..100> : Employee;
        Pracownik<1..*> : Employee;
            };


sklad nam sie zmienia:

Code:
<i0, entry>
|
<i1, SuperAplikacja>
|
|--------------------------------------------------------------------------------------
|                       |                 |                |                |             |               |
<i2, Emp> <i3, Emp> <i4, Emp> <i5, Emp> <i6, Emp> <i7, Emp> <i8, Emp>


odpalamy sesje, robimy nested(i0) i mamy:

ENVS:
Code:
----------------------------
SuperAplikacja(i1)
----------------------------


Code:
SBQL> SuperAplikacja.Prac;


Po zrobieniu "SuperAplikacja." robimy nested(i1) i mamy:

ENVS:
Code:
-------------------------------------------------------------------------------------------
Emp(i2), Emp(i3), Emp(i4), Emp(i5), Emp(i6), Emp(i7), Emp(i8)
-------------------------------------------------------------------------------------------
SuperAplikacja(i1)
-------------------------------------------------------------------------------------------


zatem mozemy co najwyzej zrobic SuperAplikacja.Emp.

a gdzie p, Prac, Pracownik ? Nie ma, a ja chce ....
bo niby dlaczego moge lokalnie, a globalnie to juz nie ?

zwrocmy uwage, ze nie mozemy przy odpaleniu sesji za kazdym
razem tworzyc sobie obiektow w ramach modulu i generowac sobie bindery,
tak jak zmiennych lokalnych w przypadku procedury. dlatego napisalem,
ze mamy tutaj baze danych, a nie jezyk programowania.

Sytuacja 3:
Sklad globalny, trwaly albo i nie (nie ma to znaczenia), wazne
ze dostepny dla wszystkich uzytkownikow. Nazwa obiektu nie jest
inwariantem klasy, tylko jest wyznaczana przez deklaracje zmiennej (czyli tak jak chce ja).
Kazdy obiekt ma systemowo utrzymywana referencje do klasy z ktorej pochodzi
(niektore typy zlozone byc moze nie potrzebuja takiej referencji, bo mamy zgodnosc strukturalna)

Sklad globalny (znowu dla uproszczenia bez klasy Employee):

Code:
<0, entry>


teraz tworzymy nowy modul:

Code:
SBQL> create module SuperAplikacja {
        p : Employee;
        Prac<5..100> : Employee;
        Pracownik<1..*> : Employee;
            };


sklad nam sie zmienia:

Code:
<i0, entry>
|
<i1, SuperAplikacja>
|
|---------------------------------------------------------------------------------------------------------
|                       |                 |                |                |             |               |
<i2, p>    <i3, Prac>    <i4, Prac>   <i5, Prac>  <i6, Prac> <i7, Prac> <i8, Pracownik>


Code:
SBQL> SuperAplikacja.Prac;


ENVS:
Code:
-------------------------------------------------------------------------------------------
p(i2), Prac(i3), Prac(i4), Prac(i5), Prac(i6), Prac(i7), Pracownik(i8)
-------------------------------------------------------------------------------------------
SuperAplikacja(i1)
-------------------------------------------------------------------------------------------


wynik: i3, i4, i5, i6, i7, czyli taki jak chce ...

Sytuacja 4:

Procedura. Nazwa obiektu nie jest
inwariantem klasy, tylko jest wyznaczana przez deklaracje zmiennej
(czyli tak, jak chce ja)

Code:
procedure blabla(p : ref Employee) {
  Prac<5..100> : Employee;
  Pracownik<1..*> : Employee;
}


sklad globalny (ale tylko zakladajac, ze mamy deklaracje globalnych zmiennych Emp : Employee i Dept : Department):

Code:
                            <i0, entry>
                                  |
-------------------------------------------------------------------------------------
|                      |                 |           |                |               |
<i1, Emp> <i2, Emp> <i3, Emp> <i4, Dept>  <i5, Dept>  <i6, blabla>


znowu pomijam obiekt klasy Employee, ktory tez tutaj powinien byc widoczny

odpalamy sesje, robimy nested(i0) i dostajemy nastepujacy ENVS:

Code:
-------------------------------------------------------------------------------
Emp(i1), Emp(i2), Emp(i3), Dept(i4), Dept(i5), blabla(i6)
-------------------------------------------------------------------------------


teraz wywolujemy procedure blabla, podajac jako argument
pierwszego na liscie pracownikow (i1), czyli:

Code:
SBQL> blabla(Emp<1>);


otwieramy nowa sekcje, alokujemy sklad lokalny, bierzemy
nazwe parametru formalnego, parametr aktualny i robimy z tego binder, czyli mamy:

ENVS:
Code:
-------------------------------------------------------------------------------
p(i1)
-------------------------------------------------------------------------------
Emp(i1), Emp(i2), Emp(i3), Dept(i4), Dept(i5), blabla(i6)
-------------------------------------------------------------------------------


Sklad lokalny w blabla:
Code:
                                   <i8, entry>   


teraz mamy deklaracje Prac<5..100> : Employee;

poniewaz musimy miec minimalnie 5 obiektow identyfikowanych przez Prac,
wiec w lokalnym skladzie alokujemy 5 obiektow Employee, ale o nazwach Prac
(a nie takich jak wyznacza jakis inwariant w klasie Employee), a na ENVS
wrzucamy bindery Prac do utworzonych obiektow.

Sklad lokalny w blabla:

Code:
                          <i8, entry>
                                 |
-----------------------------------------------------------
|                    |               |                     |           |                 
<i9, Prac> <i10, Prac> <i11, Prac> <i12, Prac>  <i13, Prac>


ENVS w blabla:
Code:
--------------------------------------------------------------------
p(i1), Prac(i9), Prac(i10), Prac(i11), Prac(i12),
Prac(i13)
--------------------------------------------------------------------
Emp(i1), Emp(i2), Emp(i3), Dept(i4), Dept(i5), blabla(i6)
--------------------------------------------------------------------


teraz mamy deklaracje Pracownik<1..*> : Employee, wiec
robimy to co wyzej:

Sklad lokalny w blabla:

Code:
                          <i8, entry>
                                 |
------------------------------------------------------------------------------------------
|                    |               |                     |           |                   |
<i9, Prac> <i10, Prac> <i11, Prac> <i12, Prac>  <i13, Prac>  <i14, Pracownik>


ENVS w blabla:
Code:
--------------------------------------------------------------------
p(i1), Prac(i9), Prac(i10), Prac(i11), Prac(i12),
Prac(i13), Pracownik(i14)
--------------------------------------------------------------------
Emp(i1), Emp(i2), Emp(i3), Dept(i4), Dept(i5), blabla(i6)
--------------------------------------------------------------------


jak widac rowniez dziala. i osmielam sie stwierdzic, ze tez jest zgodne z SBA.


p.s.
prosze wiecej nie zmuszac mnie do pisania takich przykladow,
bo zajmuje to zbyt duzo czasu ....

stencel
Posted: Sunday, December 12, 2004 5:37:51 PM

Rank: Advanced Member

Joined: 12/7/2004
Posts: 598
Points: 74
Location: Raszyn
Code:
SBQL> create module SuperAplikacja {
        p : Employee;
        Prac<5..100> : Employee;
        Pracownik<1..*> : Employee;
            };


No to mnie przekonales. Rzeczywiscie nazwa obiektu nie musi byc niezmiennikiem klasy. Przekonales mnie tym przykladem z modulem, bo przeciez debilizmem byloby byloby inne traktowanie srodowiska modulu niz procedury. Mysle, ze mozemy przyjac, ze nazwa obiektow nie jest niezmiennikiem klasy.

To powoduje pewne problemy w modelu M1. Jesli byla klasa "OsobaKlasa" z niezmiennicza nazwa obiektow obiektow "Osoba" i dziedziczaca po niej klasa "PracownikKlasa" z niezmiennicza nazwa obiektow "Pracownik", to w momencie wiazania w zapytaniu nazwy "Osoba" na stos wynikow byly wkladane bindery "Osoba" do obiektow obu tych klas. Bylo to mozliwe dzieki niezmienniczym nazwom obiektow klas. Jak to teraz rozwiazac? Moze w modelu M2 nie ma juz tego problemu? Co o tym sadzicie?

Zasade przyjmijmy wiec taka, ze deklaracja

[code]a : b[\code]

powoduje utworzenie w skladzie obiektu typu/klasy b oraz nazwie a i wlozeniu na stos srodowisk (do rekordu aktywacji procedury/metody/modulu) bindera a wskazujacego na ten obiekt.

michal wrote:
wychodzimy z procedury, bindery znikaja, obiekty tez. zgadza sie?


Niezupelnie. Obiety moga pozostrac. Przyjmijmy, ze obiekty po prostru pozostaja w skladzie, ale skoro znikaja do nich wszelkie zewnetrzne odwolania (tutaj znikaja razem z rekordem aktywacji), to wkrotce garbage-collector je wychwyci i zniszczy.

michal wrote:
prosze wiecej nie zmuszac mnie do pisania takich przykladow, bo zajmuje to zbyt duzo czasu ....


Ale Michale dobrze zrobiles! O to chodzilo. Dobre przyklady sa niezbedne. Rozumiem, ze wg Ciebie straciles czas, ktory Ci jest potrzebny na kodowanie Odry, ale mysle, ze powinienss to juz porzucic. Nie jestes samotnym dlugodystansowcem. Kodowac maja studenci. Ty masz tym tylko kierowac.
michal
Posted: Sunday, December 12, 2004 6:09:59 PM

Rank: Advanced Member

Joined: 12/6/2004
Posts: 332
Points: -61
Quote:
To powoduje pewne problemy w modelu M1. Jesli byla klasa "OsobaKlasa" z niezmiennicza nazwa obiektow obiektow "Osoba" i dziedziczaca po niej klasa "PracownikKlasa" z niezmiennicza nazwa obiektow "Pracownik", to w momencie wiazania w zapytaniu nazwy "Osoba" na stos wynikow byly wkladane bindery "Osoba" do obiektow obu tych klas. Bylo to mozliwe dzieki niezmienniczym nazwom obiektow klas. Jak to teraz rozwiazac? Moze w modelu M2 nie ma juz tego problemu? Co o tym sadzicie?


to juz dziala. kiedys to opisze

Quote:
Niezupelnie. Obiety moga pozostrac. Przyjmijmy, ze obiekty po prostru pozostaja w skladzie, ale skoro znikaja do nich wszelkie zewnetrzne odwolania (tutaj znikaja razem z rekordem aktywacji), to wkrotce garbage-collector je wychwyci i zniszczy.


no tak, zgadzam sie. to byla uproszczona wersja, zakladajaca ze return moze zwracac tylko wartosci,
a nie referencje. tak bylo np. w loqisie o ile mi wiadomo

Quote:
Ale Michale dobrze zrobiles! O to chodzilo. Dobre przyklady sa niezbedne. Rozumiem, ze wg Ciebie straciles czas, ktory Ci jest potrzebny na kodowanie Odry, ale mysle, ze powinienss to juz porzucic. Nie jestes samotnym dlugodystansowcem. Kodowac maja studenci. Ty masz tym tylko kierowac.


gdybym tego wczesniej nie zaprogramowal, to nigdy nie wykrylibysmy tego problemu. a studenci niestety nie dadza sobie z tym rady ... mam z nimi cwiczenia, wiec wiem co ich interesuje, na co maja czas, i na co ich stac (no ok, moze ci z uw by sobie poradzili) ... musialbym im przygotowac jakis projekt calego systemu - specyfikacje jezyka, konkretne algorytmy, etc. a jak widac to dopiero sie rodzi i nie ma juz czasu (bo wkrotce koncza studia). poza tym po prostu pewnych rzeczy nie da sie wykryc nie implementujac tego samemu. ostatnio zreszta praktycznie nic nie programuje, tylko pisze specyfikacje sbqla. wkrotce ja tu wrzuce
habela
Posted: Sunday, December 12, 2004 7:22:24 PM
Rank: Administration

Joined: 12/6/2004
Posts: 360
Points: 52
Ja dodam tylko, że rozważałem to od innej strony (zakładając, że nazwa jest niezmiennikiem, ale aby się za bardzo nie uwiązać: 1. w innym module może być związana z innym typem; 2. w innym module można deklarować własność w oparciu o klasę zadeklarowaną w innym). Wyszło mi na to samo, w tym sensie, że w referencji obiektu tak czy owak musi być zawarta identyfikacja jego klasy. A skoro ponosimy już ten koszt, to warto przy okazji się zapytać: skoro nie musi być niezmiennika, to czy rezygnujemy zeń zupełnie, czy czynimy go opcjonalnym?
Co do "bindowania" instancji podklas pod nieobecność tego niezmiennika, to jeśli odpowiednie feature jest zadeklarowane - dysponujemy niezbędną informacją.
A odnośnie modelu M2, to moje wyobrażenie o rolach jest takie, że stanowczo nie wyeliminują one statycznego dziedziczenia - te dwa mechanizmy będą się uzupełniać.
KK
Posted: Tuesday, December 14, 2004 6:22:54 PM
Rank: Advanced Member

Joined: 12/7/2004
Posts: 226
Points: 30
No chłopaki, ale popisaliście się przez weekend. Niestety w domu zostałem odcięty od Forum... z jakiegoś powodu moja przeglądarka go nie wyświetla... jestem w trakcie badania problemu.

Co do poprzednich listów. Cieszę się że Krzysiek w końcu zaakceptował nasze ukochane Features :-).

Teraz chciałbym dodać jeszcze kilka słów na temat tego zagnieżdżania.

michal wrote:
Quote:
Ten argument jest trochę tendencyjny - przykład z osobą nie jest, jak podkreślałem, zbyt szczęśliwy, ale nie widzę (pominięto tu liczności) tutaj koncepcyjnego problemu, który usnęłaby nazwa traktowana jako niezmiennik.


zdaje sie ze Krzysiek wprowadzil tylko slowko ref dla zakcentowania, ze obiekt nie jest fizycznie zagniezdzony,
tylko jest referencja. oczywiscie chyba nikt z nas nie myslal ze osoba moze byc zagniezdzona w osobie -
brak ref byl tylko uproszczeniem skladniowym ...


A gdyby było tak:
Code:

class Osoba
{
   Name : String;
   Friends [0..*]: Osoba;
   Parents [0..2]: Osoba;
}

Struktura miałaby szansę się skończyć zanim skończyłoby się miejsce w pamięci.

Jednak zastanawia mnie co innego. Rozumiem, że pozwalamy by model nie był spłaszczony (czyli możemy wkładać całe obiekty zagnieżdżone, a nie tylko referencje do nich), ale tylko jeśli są to obiekty innego typu tak? Chcemy uniknąć zapętlania struktur tak?
A co powiecie na coś takiego?
Code:

class Osoba
{
   Imie : String;
   MieszkaW : Dom;
}

class Dom
{
   Nazwa : String;
   Mieszkańcy : Osoba;
}


Nigdy nie wiadomo jakiego rodzaju pętla powstanie. Ciągle jestem za tym by zrezygnować z wkładania struktur do struktur. Referencje w zupełności wystarczają. Nie tracimy nic z siły języka, ani z siły modelu danych.
KK
Posted: Tuesday, December 14, 2004 6:28:37 PM
Rank: Advanced Member

Joined: 12/7/2004
Posts: 226
Points: 30
stencel wrote:

Popatrzmy teraz na deklaracje:

Code:
class Osoba
{
   Name : String;
   Friends : Osoba;
   Parents : Osoba;
}


Pomieszane tu jest wszystko i poplatane. Szef w swojej ksiazce i w swoim umysle tez uwaza taka konstrukcje za chora, bo bezposrednio prowadzi do koniecznosci tworzenia skomplikowanych konstrukcji a la dziedziny Scotta.

Stad raczej powinno byc (a powyzszy kod powinien byc zabroniony):

Code:
class Osoba
{
   Name : String;
   Friends : ref to Osoba;
   Parents : ref to Osoba;
}


Ale jeśli Friends jest obowiązkowy (nie może być NULL) to jaka jest różnica. Jakoś jej nie dostrzegam. Chodzi o to, że wielkość struktury Osoba jest ograniczona i stała tak? Chodzi o kontrolę typów? Że nieby ref to Osoba nie jest kontrolowane strukturalnie tylko nazwowo... nie wiem. Nie rozumiem. Czy mógłbyś Krzyśku to wyjaśnić lepiej?

stencel
Posted: Wednesday, December 15, 2004 12:29:35 PM

Rank: Advanced Member

Joined: 12/7/2004
Posts: 598
Points: 74
Location: Raszyn
KK wrote:
Ale jeśli Friends jest obowiązkowy (nie może być NULL) to jaka jest różnica. Jakoś jej nie dostrzegam. Chodzi o to, że wielkość struktury Osoba jest ograniczona i stała tak? Chodzi o kontrolę typów? Że nieby ref to Osoba nie jest kontrolowane strukturalnie tylko nazwowo... nie wiem. Nie rozumiem. Czy mógłbyś Krzyśku to wyjaśnić lepiej?


Jak poczytasz dalej moj post, to zobaczysz ten sam przyklad, ktory jest juz z licznosciami i dopuszczone jest zero. To byla tylko przejsciowa forma.

KK wrote:
Code:

class Osoba
{
   Imie : String;
   MieszkaW : Dom;
}

class Dom
{
   Nazwa : String;
   Mieszkańcy : Osoba;
}


Nigdy nie wiadomo jakiego rodzaju pętla powstanie. Ciągle jestem za tym by zrezygnować z wkładania struktur do struktur. Referencje w zupełności wystarczają. Nie tracimy nic z siły języka, ani z siły modelu danych.


Uwazam, ze zagniezdzanie struktur jest potrzebne, ale problem istnieje. Moze tak:

1. Obiektow nalezacych do klas zagniezdzac nie wolno. Moga byc tylko referencje do nich.
2. Obiekty nie nalezace do zadnej klasy moga byc zagniezdzone.
3. Definicja klasy wskazuje niezmienniczy typ obiektow tej klasy.
4. Typedef jest makrem, ktore definiuje typy zmiennych innych niz klasowe.
5. Ref to uzywamy do definiowania pointerow zarowno przy klasach jak i przy obiektach spoza klas, zeby byla jedna skladnia.

Code:
typedef PreviousJobType = PreviousJob { company : string; years : int };
                                                  // definicja typu obiektow zlozonych
class Osoba {
   Name : String;
   Friends [0..*]: ref to Osoba;                  // zawsze pointery bo klasa
   Parents [0..2]: ref to Osoba;                  // zawsze pointery bo klasa
   PreviousJobType[0..*];                         // obiekt zagniezdzony
   joby[0..*] : ref to PreviousJobType;           // ALBO pointery
}


Po rozwinieciu makra:

Code:
class Osoba {
   Name : String;
   Friends [0..*]: ref to Osoba;                  // zawsze pointery bo klasa
   Parents [0..2]: ref to Osoba;                  // zawsze pointery bo klasa
   PreviousJob[0..*] : { company : string; years : int };
   joby[0..*] : ref to PreviousJob { company : string; years : int };
}



Gdyby sie zdarzyla wzajemna rekurencja typedefow jak u Ciebie Dom<->Osoba, to bylby blad kompilacji, bo preprocesor procesujacy makra wykrylby to zagniezdzenie.

Jakos jestem przywiazany do tego "ref to", bo wydaje mi sie, ze to duzo wyjasnia. I jak widac z przykladu jest to istotna roznica skladniowa (widac w przykladzie po rozwinieciu makr).
KK
Posted: Wednesday, December 15, 2004 12:47:04 PM
Rank: Advanced Member

Joined: 12/7/2004
Posts: 226
Points: 30
Czyli jednak to zagnieżdżanie nie jest takie łatwe i bezproblemowe? :-)

stencel wrote:

1. Obiektow nalezacych do klas zagniezdzac nie wolno. Moga byc tylko referencje do nich.
2. Obiekty nie nalezace do zadnej klasy moga byc zagniezdzone.
3. Definicja klasy wskazuje niezmienniczy typ obiektow tej klasy.
4. Typedef jest makrem, ktore definiuje typy zmiennych innych niz klasowe.
5. Ref to uzywamy do definiowania pointerow zarowno przy klasach jak i przy obiektach spoza klas, zeby byla jedna skladnia.


Uważam, że dla minimalizacji liczby pojęć lepiej byłoby (choć tracimy pewną cechę to nie tracimy mocy całości):

Code:
typedef PreviousJobType = PreviousJob { company : string; years : int };
                                                  // definicja typu obiektow zlozonych
class Osoba {
   Name : String;
   Friends [0..*]: ref to Osoba;                  // zawsze pointery bo klasa
   Parents [0..2]: ref to Osoba;                  // zawsze pointery bo klasa
   ref to PreviousJobType[0..*];                 // obiekt zagniezdzony
   joby[0..*] : ref to PreviousJobType;           // ALBO pointery
}


Po rozwinieciu makra:

Code:
class Osoba {
   Name : String;
   Friends [0..*]: ref to Osoba;                  // zawsze pointery bo klasa
   Parents [0..2]: ref to Osoba;                  // zawsze pointery bo klasa
   ref to PreviousJob[0..*] : { company : string; years : int };
   joby[0..*] : ref to PreviousJob { company : string; years : int };
}


Naprawdę nie widzę różnicy czy obiekt jest za referencją, czy bezpośrednio. Może jedyna różnica jest taka, że jak jest za rederencją to może być widoczy w kilku miejscach na raz, a jak jest włożony bezpośrednio, to tylko w jednym.

stencel wrote:

Gdyby sie zdarzyla wzajemna rekurencja typedefow jak u Ciebie Dom<->Osoba, to bylby blad kompilacji, bo preprocesor procesujacy makra wykrylby to zagniezdzenie.


Oj boję się że to jest poważny problem. Zastanawiam się co będzie w wynikach zapytań. W końcu tam też mogą pojawić się bardzo różne struktury. Nie znam się na sbql na tyle by podać przykład lub wyrokowac, że takiego przykładu nie ma.
stencel
Posted: Wednesday, December 15, 2004 2:40:24 PM

Rank: Advanced Member

Joined: 12/7/2004
Posts: 598
Points: 74
Location: Raszyn
Code:
class Osoba {
  ...
  ref to PreviousJobType[0..*];                 // obiekt zagniezdzony  (?????????????)
  ...
}


Code:
class Osoba {
   ...
   ref to PreviousJob[0..*] : { company : string; years : int };
   ...
}


To nie moze byc obiekt zagniezdzony (bo ref) i nie moze byc ref (bo nie ma nazwy). Moim zdaniem te napisy nie maja zadnego sensu.

KK wrote:
Uważam, że dla minimalizacji liczby pojęć lepiej byłoby (choć tracimy pewną cechę to nie tracimy mocy całości).


Ja tak nie uwazam. Nic tu nie minimalizujesz bo i tak masz zagniezdzanie obiektow, tylko ograniczone do obiektow prostych.
To wlasnie przy okazji takiego ograniczenia mozna stwiedzic, ze jest ono nieestetyczne, bo nieuzasadnione

Model M0 jest po prostu super i nie bede nigdy glosowal za jego zmiana. Jesli sie z tym godzimy, to zrobmy tak zeby nie walczyc z modelem M0.
michal
Posted: Thursday, December 16, 2004 3:28:15 AM

Rank: Advanced Member

Joined: 12/6/2004
Posts: 332
Points: -61
z mojego punktu widzenia (tz. programisty, a nie specjalisty z zakresu dziedzin scotta)
rozwiazanie problemu wstepnie wyglada nastepujaco:

1. Zagniezdzanie obiektow jest konieczne, chociazby znowu dlatego:

Code:
module SuperAplikacja {
  p : Employee;
  Prac : Employee;
  Emp<0..*> : Employee;
}


to oczywiscie oznacza, ze obiekt reprezentujacy modul SuperAplikacja
musi zawierac zagniezdzone obiekty. inaczej nie da sie tego
sensownie zadeklarowac. nie moze byc tylko referencji do obiektow,
bo te obiekty nie moga sobie wisiec w prozni, tak jak w javie.

oczywiscie mozemy sobie tez (a nie tylko) tutaj zadeklarowac
referencje do obiektow zagniezdzonych gdzie indziej,
np. w innym module, czyli:

Code:
module SuperAplikacja {
  p : ref Employee;
}


jezeli zatem w modulach obiekty maja byc zagniezdzone, to w innych
obiektach zlozonych tez musi byc taka mozliwosc.

2. Na czym polega problem z tymi referencjami
i dlaczego (imho) Profesor twierdzi, ze musi byc:

Code:
class Osoba {
  imie : string;
  dziecko : ref Osoba;
}


Wyobrazmy sobie metabaze dla nastepujacej klasy:

Code:
class Osoba {
  imie : string;
  dziecko<0..*> : Osoba;
}


zeby zbudowac taka metabaze, musimy porozwijac Osobe,
poniewaz chcemy dopuscic kazde zapytanie typu
os(.dziecko)*.imie. to oznacza, ze hierarchia w obiekcie
reprezentujacym w metabazie klase osoba,
musialaby byc nieskonczenie dluga, aby mozna bylo
statycznie wyewaluowac takie zapytanie. trzeba
by zatem zbudowac cos takiego, co oczywiscie nie jest mozliwe:

Code:
entry
+--Osoba
   +--imie
   +--dziecko
      +--imie
      +--dziecko
         +--imie
         +--dziecko
            ... itd.


natomiast jesli zrobimy sobie (w metabazie!) w obiekcie dziecko
referencje na osobe, to wszystko jest ok:

Code:
entry
+--Osoba
  +--imie
  +--dziecko -> Osoba


3. w metabazie zagniezdzania zatem nie ma, sa tylko referencje (czyli jest
tak jak chce KK), natomiast w bazie danych zagniezdzanie jest
(czyli tak jak chce KS). to oznacza, ze dopuszczalny jest np. taki obiekt:

Code:
+--Osoba
   +--imie="Jan"
   +--dziecko
      +--imie="Stefan"
      +--dziecko
         +--imie="Felek"


oczywiscie mozemy rownie dobrze tez tworzyc zagniezdzone referencje
na podobnej zasadzie.

podsumowujac, z punktu widzenia jezyka dobre jest zarowno:

Code:
class Osoba {
  imie : string;
  dziecko<0..*> : Osoba;
}


jak i:

Code:
class Osoba {
  imie : string;
  dziecko<0..*> : ref Osoba;
}


tylko obie definicje oznaczaja co innego.
pierwsza oznacza obiekt zagniezdzony, druga referencje do obiektu
zagniezdzonego gdzie indziej. od programisty zalezy
co chce otrzymac.

mam nadzieje, ze to zadowala obu adwersarzy
Users browsing this topic
Guest


Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Main Forum RSS : RSS

Powered by Yet Another Forum.net version 1.9.1.6 (NET v2.0) - 11/14/2007
Copyright © 2003-2006 Yet Another Forum.net. All rights reserved.
This page was generated in 0.272 seconds.