Konstrukcja systemów obiektowych i rozproszonych

18
© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 1 listopad 2004 Konstrukcja systemów obiektowych i rozproszonych Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa [email protected] Instytut Podstaw Informatyki PAN, Warszawa [email protected] Wykład 7: Mocna kontrola typów, cz.1

description

Konstrukcja systemów obiektowych i rozproszonych. Wykład 7: Mocna kontrola typów, cz.1. Wykładowca : Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa [email protected] Instytut Podstaw Informatyki PAN, Warszawa [email protected]. Po co są typy?. - PowerPoint PPT Presentation

Transcript of Konstrukcja systemów obiektowych i rozproszonych

Page 1: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 1 listopad 2004

Konstrukcja systemów obiektowych i rozproszonych

Wykładowca: Kazimierz Subieta

Polsko-Japońska Wyższa SzkołaTechnik Komputerowych, [email protected]

Instytut Podstaw Informatyki PAN, [email protected]

Wykład 7: Mocna kontrola typów,cz.1

Page 2: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 2 listopad 2004

Po co są typy?

Istotnym składnikiem języka programowania jest system kontroli typologicznej.

Chroni on programistów przed ich własnymi błędami, stąd jest kluczowym czynnikiem podwyższenia niezawodności oprogramowania. • Istnieją szacunki pokazujące, że system kontroli typologicznej jest w stanie

wykryć 80% błędów semantycznych i koncepcyjnych. Dało to podstawę do ukucia pojęcia bezpieczeństwo typologiczne (typing

safety) jako podstawowej zasady języków programowania. System typów ma również znaczenie dla modelowania pojęciowego, gdyż

typy pełnią rolę semantyczną w dziedzinie przedmiotowej. • Np. typ Student przypisany do obiektu zdradza nam jego intencję i biznesową

semantykę. Typy przenoszą także informację o metodzie reprezentacji danych

wewnątrz pamięci komputera (ważne dla standardów, np. CORBA). Języki bez mocnej kontroli typów są uważane za niebezpieczne,

prowadzące do niskiej jakości oprogramowania.

Page 3: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 3 listopad 2004

Dlaczego typy nie zawsze są doceniane? (1)

Jakość i niezawodność oprogramowania nie zawsze jest priorytetem działania firm komercyjnych.

Wprowadzenie typów do języka wymaga odpowiedniej kompetencji w tym zakresie, która często nie jest właściwa decydentom i twórcom języków wywodzącym się z tych kręgów. • Nieliczne uczelnie prowadzą w tym zakresie wykłady i ćwiczenia.

• Niektóre z nich traktują typy jako okazję do prezentowania (wyrafinowanych, lecz niepraktycznych) teorii matematycznych w zakresie typów, a nie do objaśniania rzeczywistych problemów i rozwiązań.

• Przełożenie tych teorii na efektywną implementację jest zwykle trudne lub niemożliwe, a najczęściej (z powodu ograniczeń teorii) bezsensowne.

Implementacja kontroli typologicznej jest dodatkowym obciążeniem dla twórców języka lub systemu, zwiększającym koszt i czas wytworzenia odpowiedniego oprogramowania.

Programy uwzględniające kontrolę typologiczną są dłuższe (chociaż zwykle bardziej czytelne, ze względu na modelowanie pojęciowe).

Page 4: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 4 listopad 2004

Dlaczego typy nie zawsze są doceniane? (2)

Język z mocną kontrolą typów traci część elastyczności. Zwykle oznacza bardziej sztywne struktury danych, co może być

nieakceptowalne dla rozluźnionych formatów, np. dla XML. • W Pascalu zbyt mocna kontrola typologiczna uniemożliwia m.in. napisanie

procedury mnożącej dwie macierze o dowolnych wymiarach. Język z mocną kontrolą typów bardzo utrudnia programowanie

generyczne, przy którym docelowy typ przetwarzanego obiektu nie jest znany w czasie kompilacji. • Programowanie generyczne wymaga odzyskania informacji o strukturze/typie

obiektu podczas wykonania programu i zastosowanie do niego przetwarzania.

Ten aspekt zaowocował rodziną języków programowania tzw. polimorficznych, których najwybitniejszym przykładem jest SML. • Ta linia języków programowania nie sprawdziła się jak dotąd

w powszechnym programowaniu. • Podstawową metodą programowania generycznego jest refleksja (znana m.in.

z dynamicznego SQL i DII CORBA), która w istocie bardzo utrudnia lub wręcz uniemożliwia mocną statyczną kontrolę typów.

Page 5: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 5 listopad 2004

Co to jest system typów?

Typ jest formalnym ograniczeniem narzuconym na budowę bytu programistycznego lub jest specyfikacją jego parametrów i wyniku.

Z drugiej strony, typ jest formalnym ograniczeniem kontekstu, w którym odwołanie do tego bytu może być użyte w programie.

System typów języka programowania polega na przypisywaniu wyrażeń oznaczających typy bytom występującym w programie (obiektom, funkcjom, procedurom, metodom itd.), oraz sprawdzanie zgodności użycia danego bytu w programie z jego zadeklarowanym typem.

Typów używa się także do dynamicznej kontroli poprawności budowy obiektów• Patrz np. DTD lub XMLSchema dla plików XML.

Jest to istotna, ale raczej drugorzędna rola systemu typów, która w klasycznych językach programowania i językach baz danych nie występuje.

Page 6: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 6 listopad 2004

Typy a schematy baz danych (1)

Tradycyjnie typy są własnością programów. W związku z niezależnością danych nastąpiło przesunięcie typów na

stronę danych. W ten sposób pojawiło się pojęcie schematu bazy danych. Schemat pełni dwie role.

• Informuje programistę o tym, co baza danych zawiera i jak jest zorganizowana.

• Jest wykorzystywany przez SZBD do kontroli danych zapamiętanych w bazie danych.

Schemat bazy danych zwalnia języki programowania z obowiązku trzymania informacji typologicznej.

Kompilator języka powinien odczytać typ ze schematu zapamiętanego w bazie danych.

Typy przyjmują postać niezależną od konkretnego języka programowania. • Patrz np. system typów standardu OMG CORBA oraz standardu ODMG. • W ramach platformy .NET powstaje zunifikowany system typów dla

wszystkich języków programowania.

Page 7: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 7 listopad 2004

Typy a schematy baz danych (2)

Często podkreśla się podobieństwo typów znanych z języków programowania do schematów znanych z baz danych.

Schematy bazy danych nie definiują jednak wyłącznie typów, gdyż ich podstawową funkcją jest modelowanie pojęciowe. • Schematy są tym, co w języku programowania nazywa się deklaracją. • Schematy łączą deklarowanie zmiennych, obiektów, tabel lub innych bytów

bazy danych z określaniem ich typu. • Przykładowo, możemy mieć następującą definicję typu TypPrac:

typedef TypPrac struct{NrPrac:int, Nazwisko:string, Zar:int};Tę definicję można wykorzystać do deklaracji zmiennej MójPrac:MójPrac : TypPrac;

W schematach baz danych konstrukcją semantycznie równoważną jest wyrażenie, w którym nazwę typu tekstowo zastąpiliśmy prawą stroną definicji typu:

MójPrac : struct{ NrPrac:int, Nazwisko:string, Zar:int}; W schemacie konstrukcje typedef mogą występować lub nie.

• Przykładowo, w schematach zapisanych w SQL-92 nie występują.

Page 8: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 8 listopad 2004

Strukturalna zgodność typów

Z powodu lepszego modelowania pojęciowego, krótszego kodu oraz zwiększenia potencjału dla ponownego użycia definicje typów określające ich nazwy (po lewej stronie) oraz wyrażenie definiujące (po prawej stronie) są cechą większości znanych języków i systemów.

O takich konstrukcjach mówi się niekiedy jako o typach definiowanych przez użytkownika (user-defined types).

Z powodu semantycznej równoważności typy definiowane przez użytkownika nie są składnikiem formalnej semantyki schematu (abstrahującej od modelowania pojęciowego).

Nazwy typów występujące w deklaracjach są tekstowo rozwijane do pełnej postaci, z użyciem prawych stron definicji typów.

Takie podejście jest określane jako strukturalna zgodność typów. • W strukturalnej zgodności typów ich nazwy nie mają znaczenia.

• Liczy się tylko czy definiowane struktury danych są takie same.

Page 9: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 9 listopad 2004

Nazwowa zgodność typów

Większość języków programowania przyjmuje zgodność typów, określaną jako zgodność nazwową (często kombinowaną z elementami zgodności strukturalnej).

Przy zgodności nazwowej nazwa typu jest nośnikiem semantyki formalnej i nie może być zastąpiona przez prawą stronę definicji nazwy typu. • Przykładowo, jeżeli mamy dwie definicje typów:

typedef TypOsoba struct{ Imię : string, Wiek: int };

typedef TypPies struct{ Imię : string, Wiek: int };

to przy zgodności strukturalnej deklaracja zmiennej Florek:

Florek : TypOsoba;

jest dla kompilatora równoważna deklaracji

Florek : TypPies;

W niektórych sytuacjach przyjęcie zgodności strukturalnej może prowadzić do osłabienia kontroli typologicznej • Np. zmienna typu TypPies może być użyta w kontekstach, w których oczekiwana jest

zmienna typu TypOsoba.

Nazwowa zgodność typów rozróżnia deklaracje bytów programistycznych wykorzystując nazwy typów.

Page 10: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 10 listopad 2004

Statyczna i dynamiczna kontrola typologiczna

Statyczna kontrola typów zachodzi w trakcie kompilacji programu, zaś dynamiczna – w czasie jego wykonania.

Kontrola dynamiczna może także dotyczyć obiektów zapamiętanych w składzie. • Języki takie jak DTD i XML Schema służą głównie do dynamicznej kontroli

obiektów (plików) XML.

• Nie jest jasne, czy i jak mogą być zastosowane do statycznej kontroli typów zapytań lub programów.

Uważa się, że prawdziwa, mocna kontrola typów jest kontrolą statyczną. Kontrola dynamiczna jest również skuteczna, gdyż umożliwia wykrycie

błędu typologicznego podczas testowania programu. • Wadą kontroli dynamicznej jest dodatkowe obciążenie tą kontrolą czasów

wykonania.

• Kontrola ta może być również niepełna, gdyż niemożliwe jest przetestowanie programu na wszystkie przyszłe sytuacje, w których może on się znaleźć.

Page 11: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 11 listopad 2004

Dynamiczna kontrola obiektów

Często jest głoszony pogląd, że dobra, „szczelna” statyczna kontrola typologiczna eliminuje potrzebę dynamicznej kontroli typologicznej obiektów, gdyż przy szczelnym systemie typów nie jest możliwe wytworzenie obiektu typologicznie niepoprawnego.

Jest to prawda pod warunkiem, że obiekty są przetwarzane wyłącznie przez jeden język programowania. • W klasycznych językach programowania, takich jak C lub Pascal, obiekty (zmienne)

są upakowane oszczędnie, w postaci sekwencji bitów, zaś cała informacja o reprezentacji wartości jest składnikiem jego typu.

• Typ z kolei jest drugiej kategorii programistycznej, czyli jest niedostępny podczas czasu wykonania.

• Przy tym założeniu dynamiczna kontrola typu obiektu jest oczywiście niemożliwa. To założenie nie jest spełnione dla obiektów bazy danych, które z reguły są

obsługiwane przez wiele języków i interfejsów, zazwyczaj z odmiennymi systemami typologicznymi lub nie posiadające kontroli typologicznej.

Niektóre opcje w językach programowania (np. warianty, wartości zerowe, elipsy, automatyczne koercje) stwarzają nieszczelności w systemie typów,

W takiej sytuacji kontrola dynamiczna typów obiektów jest równie ważna jak typologiczna kontrola programów.

Page 12: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 12 listopad 2004

Typy w językach zapytań (1)

Teoria i praktyka typów jest w dużej mierze niezależna w stosunku do języków zapytań. • Na temat typów napisano tak wiele, że z pozoru wniesienie tu istotnego

wkładu jest zadaniem niemożliwym. • W takich sytuacjach pada najczęściej sugestia zaadaptowania jednego

z istniejących systemów typów spośród propozycji przedstawionych w rozlicznych językach, systemach, standardach lub literaturze.

Istnieją jednak cechy języka zapytań, które wprowadzają nowe problemy i potencjalnie nowe rozwiązania:• Nazwa obiektu jako jego inwariant.

• Obiekty w językach programowania nie mają przypisanej im nazwy. • Tymczasem jest to reguła dla obiektów zapamiętanych w bazie danych. • Nazwa jako inwariant obiektu powinna być sprawdzana typologicznie.

• Struktury, których składniki nie posiadają przypisanych im nazw. • Budowana konsekwentnie semantyka języka zapytań prowadzi do konieczności

wprowadzenia takich struktur. • Natomiast najbardziej znane systemy typologiczne zakładają, że w ramach

struktur każdy element musi mieć przypisaną mu nazwę.

Page 13: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 13 listopad 2004

Typy w językach zapytań (2) – dalsze odstępstwa

• W naszym przypadku (i w przypadku XML) pojęcie kolekcji nie zostało wprowadzone na poziomie składu obiektów, gdyż takie potraktowanie go prowadzi do złamania zasad obiektowości.

• Natomiast wprowadziliśmy kolekcje (bagi i sekwencje) na poziomie rezultatów zwracanych przez zapytanie.

• Automatyczne koercje i elipsy. W językach zapytań nabierają większego znaczenia.

• Nieregularności w danych. Dotychczasowe systemy statycznej kontroli typologicznej ustalały nie tylko sztywny format danych, ale również reprezentację danych.

• Dynamiczne role w modelu M2 stwarzają nieco inną sytuację dla mocnej kontroli typu.

• Konieczność uwzględnienia w systemie wnioskowania o typie całej sytuacji na stosie środowiskowym, tak jak ona została opisana w poprzednich rozdziałach. Przykładowo, zapytanieOsoba.(Dział where Nazwa = Nazwisko)ma sens koncepcyjny. Czy takie zapytanie będziemy uważać za typologicznie poprawne?

Page 14: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 14 listopad 2004

Wady istniejących systemów typologicznych

Poza wymienionymi osobliwościami baz danych i ich języków zapytań, mamy wiele zastrzeżeń do stosowanych w systemach obiektowych rozwiązań typologicznych i ich teorii. • Przykładowo, zarówno CORBA, jak i Java nie zajmują się asocjacjami, mają

też ograniczenia w zakresie definicji kolekcji.

Próbą stworzenia systemu typów dla obiektowych baz danych był Object Definition Language (ODL) standardu ODMG.• Jednakże przyjęty tam polimorfizm inkluzyjny jest krytykowany jako

niespójny.

• Alternatywą miał być pomysł teoretyczny określany jako F-bounded polymorphism.

• Ta koncepcja nie wydaje się jednak na tyle dojrzała, aby traktować ją jako implementowalną i skuteczną w praktycznych językach.

Polimorfizm parametryczny (parametric polymorphism), znany z SML i innych języków tzw. polimorficznych, pozostaje koncepcją akademicką nie znajdującą potwierdzenia w powszechnej praktyce.

Page 15: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 15 listopad 2004

Pojęcie typu

Istnieje sporo poglądów i nieporozumień dookoła pojęć takich jak:• typ, klasa, interfejs, • abstrakcyjny typ danych, • dziedziczenie, • dynamiczne role obiektów.• ...

Splątanie tych pojęć w literaturze języków programowania, mnogość definicji i różne wypowiedzi na temat ich wzajemnego stosunku spowodowały znaczny chaos.

Paradoksalnie, w opisie metod mocnej kontroli typu najtrudniejsze jest wyjaśnienie, co to jest „typ”. • Na ten temat napisano ogromną liczbę książek i artykułów. • Ich podmiotem jest pojęcie typu zdefiniowane jako matematyczna abstrakcja. • Sprowokowało ono teoretyków do potraktowanie typu jako pojęcia

matematycznego oraz kontroli typologicznej jako systemu formalnego działającego na bytach matematycznych.

• Efektem jest nie uporządkowanie pojęć, lecz jeszcze większy chaos.

Page 16: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 16 listopad 2004

Moje podejście do typów

Będę starać się objaśnić mocną kontrolę typologiczną na gruncie praktycznym, bez nawiązywania do niepraktycznych teorii. • Nie będę starać się definiować pojęcia typu „jako takiego”. • Pojęcie typu będzie więc wyjaśnione implicite, poprzez abstrakcyjną

implementację mechanizmu kontroli typologicznej. Nieadekwatność teorii typów polega na traktowaniu semantyki typu

jako zbioru wartości. W odróżnieniu przyjmiemy, że typy są tylko napisami

kwalifikującymi schemat bazy danych i inne byty. Kontrola typów polega na ustaleniu i zaimplementowaniu reguł

przekształcania specyfikacji (sygnatur) zawierających te napisy. Wyjaśnienie mocnej kontroli typologicznej sprowadza się do

wykorzystania funkcji static_type_check bardzo podobnej do wprowadzonej w poprzednich wykładach funkcji static_eval. • Zachowanie się funkcji static_type_check jest uzależnione od definicji funkcji

static_nested, konstrukcji metabazy, konstrukcji stosów S_ENVS i S_QRES oraz pewnych reguł i metareguł wnioskowania o typie.

Page 17: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 17 listopad 2004

Zewnętrzny i wewnętrzny system typów

Zewnętrzny system typów jest określony przez zbiór napisów, których intuicyjną semantyką jest wyróżnienie niezmienników budowy danego bytu programistycznego, np. bazy danych, obiektu lub modułu. • Przykładem jest napis integer przypisany do deklaracji pewnego obiektu.

Zewnętrzny system typów często jest uwikłany w definicje innych abstrakcji, np. w definicje interfejsów, klas, modułów, funkcji, metod itd. • Często, np. w języku Pascal lub C, typ przybiera postać samodzielnego

nazwanego fragmentu tekstu programu. Będziemy przyjmować (w odróżnieniu od większości systemów

typologicznych), że taki nazwany fragment tekstu nie ma samodzielnej formalnej semantyki. • Istnieje wyłącznie jako makrodefinicja, czyli pewien nazwany napis. • To wyklucza typy rekurencyjne, ale ich znaczenie w praktyce jest marginalne.

Dowolna nazwa typu (poza int, float, string, bool, date, itd.) jest tylko skrótem dla tego napisu, który ostatecznie powinien być tekstowo rozwinięty do pełnej postaci, w której występują tylko typy atomowe.

Page 18: Konstrukcja systemów obiektowych i rozproszonych

© K.Subieta. Konstrukcja systemów obiektowych i rozproszonych 7, Folia 18 listopad 2004

Reguły wnioskowania o typie

Nie będziemy także zajmować się semantyką napisów, takich jak int, float, string, bool, date itd. • Matematycy widzą w takich napisach oznaczenia pewnych zbiorów, ale będzie

to dla nas nieistotne. Istotna będzie dla nas „arytmetyka” operatorów działających na takich

napisach, np.• (int + int) int• (int + float) float• (int = int) bool• (int + string) błąd typu int• itd.

Są to tzw. monomorficzne reguły wnioskowania o typie. Lewa strona takiej reguły przedstawia pewną sytuację podczas działania

procedury static_type_check, natomiast prawa strona - wynik tego działania. Elementami tej arytmetyki są sygnatury (wprowadzone  poprzednio). Dla dowolnego operatora należy przypisać zestaw takich reguł.