programista w świecie RDF

O tym, że opis rzeczywistości funkcjonujący w Sieci Semantycznej może być w pewien szczególny sposób interesujący dla programisty już kiedyś wspominałem. Niestety zrobiłem to jak zwykle od środka i poza kontekstem, więc pewnie z czasem nawet ja sam zapomnę o co tam chodziło i dlaczego. Opublikowany stosunkowo niedawno tekst A Semantic Web Primer for Object-Oriented Software Developers natchnął mnie do zrewidowania sprawy i napisania bardziej uporządkowanej (no chociaż troszkę) notatki na temat porównania modelu obiektowego i modelu RDF.

ruszamy stępa — RDF

Opis zasobów (dowolnych) przy użyciu Resource Description Framework jest sam w sobie pomysłem tak prostym, że aż genialnym. Trójka {podmiot, predykat, obiekt} odzwierciedla naturalny dla człowieka sposób wypowiadania się o rzeczywistości.

  • „MiMaS stworzył tę stronę” — {http://mimas.ceti.pl/pub/mimas.rdf#mimas foaf:made http://mimas.ceti.pl/tarpit/}
  • „ta strona jest zatytułowana TheTarPit” — {http://mimas.ceti.pl/tarpit/ dc:title "TheTarPit"}
  • „strona jest opublikowana na licencji CC” — {http://mimas.ceti.pl/tarpit/ cc:licence http://creativecommons.org/licenses/by-nc-sa/2.5/}

I tak dalej, i tak dalej. Praktycznie wszystko o wszystkim można wyrazić w postaci trójki: {zasób, cecha, wartość}. A że używa się do tego URI oraz przestrzeni nazw i typów danych rodem z XML-a zamiast języka naturalnego — cóż, taka rzeczywistość dzisiejszej informatyki...

Jednak sam RDF nie daje wiele więcej niż ciekawy sposób opisania danych jakichkolwiek w sposób przetwarzalny maszynowo, a nie wymagający stworzenia formalnego DTD. Stanowi natomiast podstawę, na której można budować konstrukcje zaawansowane, a nawet faktycznie przydatne.[1]

kłus — RDFS

Sprawy interesujące z punktu widzenia programisty zaczynają się wyżej. Na RDF oparta jest specyfikacja RDF Schema (właściwie: RDF Vocabulary Description Language) wprowadzająca pojęcia klasy i własności oraz parę wariacji na ich temat. Pojęcia te wydają się znajome, jednak wbrew pozorom nie są tak całkiem podobne do analogicznych pojęć współczesnych języków obiektowych.[2] Wszystko rozbija się o fakt, że modele opisane przez RDF (i pochodne) muszą funkcjonować w Internecie, który jest środowiskiem otwartym tak bardzo, że bardziej już chyba nie można.

Podstawowa różnica między klasami w programowaniu (czy modelowaniu raczej) obiektowym, a klasami w RDF, może być albo prosta do zrozumienia, albo całkowicie niejasna, w zależności od tego czy rozumiesz pojęcie klasy na poziomie analityczno-projektowym, czy uważasz ją tylko za konstrukcje programistyczną. W modelowaniu obiektowym klasa definiuje zbiór cech i możliwych zachowań pewnego rodzaju obiektów, czyli określa typ instancji. Jeśli obiekt jest instancją jakiejś klasy, jakiegoś typu, to oznacza, że posiada określone cechy (własności, pola) i możliwe zachowania (metody). Czyli o cechach obiektu wnioskujemy na podstawie jego klasy. To się potem wprost przenosi na programowanie — programista opisuje konstrukcję klasy wyliczając jej pola i metody. Dalej mając instancje tej klasy (obiekty) wie z całą pewnością jakiego może po nich oczekiwać zachowania.

W modelu RDF podejście do pojęcia klasy jest zupełnie inne. Definicja klasy (rdfs:Class) i własności (rdf:Property) nie specyfikuje szczegółów typu instancji tylko podaje sposób opisania jakiegoś dowolnego istniejącego obiektu („zasobu” w nomenklaturze RDF). Co więcej własności w RDF nie są częścią składową definicji klasy, tak jak w modelowaniu obiektowym, lecz niezależnie zdefiniowanym bytem (rdf:Property jest instancją rdfs:Class). Każda klasa może być opisana jako podklasa jakiejś innej. Każda własność może (choć wcale nie musi!) wskazywać jakiej klasy dotyczy i jakie mogą być jej wartości, jak również może być opisana jako podwłasność innej własności. W efekcie daje to mechanizm całkowicie odwrotny w porównaniu z modelowaniem obiektowym — klasy i własności stanowią opis cech jakie musi spełniać obiekt by należeć do danej klasy. Jeżeli obiekt ich nie spełnia — nie należy do danej klasy, jeżeli spełnia wymagania kilku klas — należy do nich wszystkich równocześnie.

W efekcie takiego podejścia do definicji klasy zupełnie inaczej wygląda również praca z instancjami obiektów czyli zasobów. Nie możemy powiedzieć tak jak w programowaniu obiektowym, że jeśli zasób jest instancją jakiejś klasy to znaczy, że ma takie a nie inne cechy, czyli wiemy o nim wszystko. Wręcz przeciwnie — dowolny zasób może być równocześnie instancją nieskończonej liczby innych klas, o których możemy wiedzieć mało albo i nic wcale. Ba, te klasy mogą nawet powstać później niż sam zasób, a i tak może on do nich należeć. Możemy za to wnioskować w kierunku przeciwnym — jeżeli definicja własności podaje jakiej klasy ona dotyczy (rdfs:domain) to fakt, że zasób posiada jakąś własność oznacza, że należy on do tej klasy. Nie jak w programowaniu obiektowym — należy do klasy, to posiada określoną własność, tylko odwrotnie — posiada taką własność, to musi znaczyć, że należy do określonej klasy. Podobnie jeśli definicja własności podaje klasę wartości (rdfs:range) to fakt, ze jakiś zasób jest użyty jako wartość w wyrażeniu RDF, którego predykatem jest ta własność, oznacza, że zasób ten jest instancją danej klasy.

galop — OWL

Powyższe jest jeszcze całkiem proste — komplikuje się dopiero wtedy, gdy zaczynamy korzystać z dobrodziejstw języka OWL. Web Ontology Language wprowadza do całej zabawy całkiem zaawansowane mechanizmy logiki (description logic) i umożliwia opisywanie klas modelu RDF w taki sposób, by wystarczyło to do budowania ontologii z dowolnej dziedziny pojęciowej.

Z punktu widzenia rozpatrywanych różnic względem modelowania obiektowego, najistotniejszy jest fakt, że OWL umożliwia takie zdefiniowanie klasy, że przynależność do niej obiektu jest możliwa do ustalenia dopiero po jego zaistnieniu. W programowaniu obiektowym, gdzie klasa jest typem obiektu, nie może powstać instancja klasy nieznanej lub nieistniejącej. Natomiast w OWL naturalne są klasy „opisowe”, których definicja oparta jest na aktualnych cechach obiektów. Średnio inteligentne przykłady:

  • wszelkie możliwe rzeczy pochodzenia polskiego znajdujące się w moim pokoju

    <owl:Class rdf:ID="MyRoomPolishStuff">
    <rdfs:subClassOf>
    <owl:Restriction>
    <owl:onProperty rdf:resource="#hasOrigin" />
    <owl:hasValue rdf:resource="&country;Poland" />
    </owl:Restriction>
    <owl:Restriction>
    <owl:onProperty rdf:resource="#locatedIn" />
    <owl:hasValue rdf:resource="#MyRoom" />
    </owl:Restriction>
    </rdfs:subClassOf>
    </owl:Class>

    Po polsku: wszystko co spełnia takie ograniczenia, że dla własności hasOrigin ma wartość Poland (zdefiniowana w przestrzeni nazw wskazywanej przez jakąś tam encję &country;, mniejsza o szczegóły) oraz dla własności locatedIn ma wartość MyRoom. Wszystkie identyfikatory zaczynające się od # oznaczają klasy OWL zdefiniowane w tym samym pliku, mniejsza o to jak dokładnie zdefiniowane, pewnie w jakiś podobnie zakręcony sposób.

  • ... oprócz kotów

    <owl:Class>
    <owl:intersectionOf rdf:parseType="Collection">
    <owl:Class rdf:resource="#MyRoomPolishStuff" />
    <owl:Class>
    <owl:complementOf>
    <owl:Restriction>
    <owl:onProperty rdf:resource="#species" />
    <owl:hasValue rdf:resource="&pets;Cat" />
    </owl:Restriction>
    </owl:complementOf>
    </owl:Class>
    </owl:intersectionOf>
    </owl:Class>

    Po polsku: wszystko co należy równocześnie do zdefiniowanej wcześniej klasy MyRoomPolishStuff oraz do klasy rzeczy, które nie są takie, że dla cechy species mają wartość Cat (z jakiegoś tam &pets;). Całkiem uzasadnione jest spojrzenie na to jak na definicję zbioru: przekrój zbioru opisanego wcześniej jako MyRoomPolishStuff oraz dopełnienia zbioru rzeczy spełniających podane ograniczenie.

Bardzo trudno zdefiniować takie klasy w językach obiektowych, chociaż jak widać bardzo łatwo w OWL. Wynika to oczywiście z faktu, że OWL jest językiem zaprojektowanym do opisu ontologii i pojęć, nie obiektów jako takich. Zresztą dokładnie tak jak OWL działa nasze postrzeganie świata — np. klasa osób znajdujących się w tym pokoju: w tej chwili do niej należę, jak wyjdę to należeć przestanę. Z punktu widzenia modelowania obiektowego, obiekt mnie opisujący musiałby wtedy zmienić swój typ... dlatego w programowaniu obiektowym nie stosuje się takich klas mimo, że świetnie funkcjonują one w naszym życiu codziennym.

Z powyższego wynika również kilka mniej rzucających się w oczy (i może mniej istotnych) różnic w modelach obiektowych i RDF. Tabelkę przedstawiającą ich syntetyczne podsumowanie zawiera wspomniany test A Semantic Web Primer for Object-Oriented Software Developers. Polecam :-)

Na marginesie: fakt, że definicja klasy obiektu może być opisana na podstawie wartości jego cech, że mogą powstawać nowe klasy w czasie, oraz że obiekt może zmieniać klasę w zależności od okoliczności, wynika konieczność istnienia mechanizmów potrafiących zanalizować definicje klas OWL łącznie z ich zależnościami i hierarchiami, a następnie ustalić jak wg danej ontologii można aktualnie określić podany zasób. Narzędzia takie noszą nazwę reasoner i ... właściwie stanowią materiał na zupełnie inny wpis...

[1] Co wcale nie jest oczywiste — wiele całkiem udanych koncepcji nie ma żadnego zastosowania praktycznego, albo ich wykorzystanie w realnym świecie „nie wychodzi” tak elegancko jak to wyglądało w teorii. Zresztą cała inżynieria oprogramowania jest właściwie o tym jak mogłoby być fajnie, gdyby nie to, że wcale tak nie jest...

[2] Mówiąc o „współczesnych językach obiektowych” mam tak naprawdę na myśli języki wcale nie szczególnie obiektowe (raczej heterogeniczne) ani też nie za bardzo współczesne, tylko takie, jakie są powszechnie rozumiane pod tym hasłem — na dzisiaj jest to Java i C#, ewentualnie C++.

Komentarze

#1 | 2006.05.08 09:01 | gshegosh

W końcu udało Ci się mnie zaciekawić tematem :)

Czy na chwilę obecną istnieją jakieś używalne narzędzia, które zatwardziałemu ;) programiście pozwoliłyby pobawić się RDFem i OWLem w taki sposób, by zastąpić/uzupełnić w Javie czy C# standardowe klasy rodem z OOP?

#2 | 2006.05.08 09:20 | MiMaS

Wspomiana publikacja zawiera dodatek, w którym są zawarte linki do stron różnych narzędzi. Podejrzewam, że jako programistę zainteresuje Cię głównie kategoria „APIs” i „Code generators”.
Dodatkowo warto rozejrzeć się po stronie Developers Guide to Semantic Web Toolkits for different Programming Languages.

#3 | 2006.05.10 01:33 | Michał Kwiatkowski

Tylko dlaczego to musi wyglądać tak XMLowato? Nie lepiej byłoby pójść w kierunku składni wyznaczonej przez języki pozwalające na programowanie logiczne? Czy ktoś pomyślał już o narzędziach, które pozwalałyby tłumaczyć kod milszy dla oka i umysłu na ten nieczytelny i trudny w modyfikacji format XMLowy? Idealnie gdyby podanego przez Ciebie OWLa można było zapisać następująco:

define MyRoomPolishStuff:
has self.hasOrigin, self.locatedIn
self.Origin is #Poland
self.locatedIn is #MyRoom

Nie trzeba by nawet opisu, bo składnia stanowi tłumaczenie samo w sobie. Piszę to nie znając stojących za tym standardów, chciałbym jednak dowiedzieć się jakie przesłanki stoją za użyciem XMLa. Czy chociażby dla OWLa nie można by uczynić pewnych rzeczy prostszymi i łatwiejszymy dla ludzi, którzy mają z tego korzystać? Naprawdę potrzebna jest niższa XMLowa wastwa?

#4 | 2006.05.10 08:36 | MiMaS

Tylko dlaczego to musi wyglądać tak XMLowato?

Nie musi. Powtarzam do znudzenia: RDF jest grafem, a RDF/XML to tylko jedna z możliwych serializacji tego grafu.

Zresztą RDF/XML jest okropny pod wieloma względami, przede wszystkim trudny do przetwarzania jako ... XML. Paradoks? Nie zupełnie — polecam np. taki eksperyment: graf składający się zaledwie z 3 trójek można zapisać w RDF/XML na 30 różnych sposobów! I wszystkie poprawne. Zresztą co to za dokument XML co nie ma żadnego DTD. Niemniej jednak jest to standard podany przez W3C i nim są zapisane wszystkie specyfikacje. Dlaczego? Nie wiem — może dlatego?

W praktyce jednak bardzo często stosuje się kilka innych sposbów zapisu, bardziej user friendlyN3 i Turtle są chyba najbardziej popularne.

 

Uwaga: Ze względu na bardzo intensywną działalność spambotów komentowanie zostało wyłączone po 60 dniach od opublikowania wpisu. Jeżeli faktycznie chcesz jeszcze skomentować skorzystaj ze strony kontaktowej.