Narzędzia CASE
Oracle Designer 10g

Ostatnio aktualizowano 13 maja 2008 r.

Oracle Designer to zintegrowane narzędzie CASE, wspierające szeroki zakres zadań na polu strategii, analizy, projektowania i generowania kodu. Narzędzie to pozwala użytkownikom zaprojektować cały system, oraz wygenerować w pełni funkcjonalne formularze i raporty na podstawie diagramów. Jak większość innych narzędzi CASE Oracle Designer zawiera repozytorium, w którym przechowywane są kolejne etapy projektowanych systemów.

Spis treści:
1. Wstęp.
2. Diagram Przepływu Danych.
3. Diagram Procesów.
4. Diagram Hierarchii Funkcji.
5. Ekport modelu do bazy danych.
6. Przydatne linki.

Wprowadzenie
Zaraz po uruchomieniu Oracle Designer łatwo zauważyć, że narzędzia zostały pogrupowane aby użytkownicy programu mogli wybrać odpowiednie w zależności od swoich potrzeb. Mamy do dyspozycji 4 grupy narzędzi:

* Modeling System Requirements - W tej grupie narzędzi mamy do dyspozycji: Process Modeler - służący do tworzenia diagramów procesów, Dataflow Diagrammer - służący do tworzenia diagramów przepływu danych (DFD), Entity Relationship Diagrammer - służący do tworzenia diagramów związków encji (ERD) oraz Function Hierarchy Diagrammer - pozwalający na tworzenie diagramów hierarchii funkcji (FHD). Wszystkie te narzędzia mają być pomocne dla projektanta podczas modelowania calego systemu, korzystanie z narzędzie pozwala na tworzenie przejrzystych diagramów opisujących system. Zapisywanie szczegółów procesów, ich wymagań oraz przechodzenie pomiędzy diagramami jest proste dzięki powiązaniu narzędzi.

* Transforming Preliminary Designs - Dwa narzędzia należące do tej grupy: Database Design Transformer oraz Application Design Transformer pozwalają na wygenerowanie wstepnych szkieletów projektów na podstawie wcześniej zdefiniowanych modeli.

* Designing and Generating - Do tej kategorii należy tylko jeden program: Design Editor - pozwala on generowanie komponentów strony serwera oraz aplikacji strony klienta na podstawie wszystkich definicji zapisanych w repozytorium.

* Repository Tools - Narzędzia należące do tej kategorii nie potrzebują szczegółowego opisu, albowiem służą one do wprowadzania i zamieniania informacji z Repozytorium, pokazują wszystkie zależności w repozytorium, generują raporty o zawartości repozytorium oraz umożliwiają administrowanie repozytoriami.

Przygotowanie środowiska pracy
Zakładam, że repozytorium zostało już utworzone i można przejść bezpośrednio do pracy z pakietem Designer. Na samym początku musimy zalogować się głównego ekranu Designera tzw.: launchpad. To właśnie z jego poziomu, możemy wykonywać wszelkie potrzebne operacje dotyczące projektowania systemu. Logujemy się na użytkownika: designer, podajemy hasło: oracle, do bazy danych: orcl. Jeden sposób na utworzenie repozytorium i kontenera był opisany na głównej stronie z materiałami, tutaj zostanie zapreznetowany sposób wykorzystujący narzędzie Repository Object Navigator. Aby je uruchomić wybieramy jego ikonę z głównego ekranu Designera lub z menu Tools>Repository Object Navigator.

Narzędzie uruchamia się bardzo powoli, ponieważ próbuje uruchomić usługę nasluchującą jednak nie jest ona niezbędna do poprawnego działania nawigatora. Jeżeli nie powiedzie się uruchamianie wspomnianej uługi Navigator wyświetli okno z informacją i załadauje pozostałe moduły. Po uruchomieniu pojawia sie okno z dwoma panelami. W jednym znajdziemy drzewo kontenerów znajdujących się w repozytorium, w drugim znajdują się właściwości repozytorium, kontenerów i innych katalogów związanych z przestrzenią roboczą.

Aby utowrzyć nowy kontener, klikamy prawym klawiszem myszy gdziekolwiek w panelu wyświetlającym drzewo przestrzeni roboczej i z menu wybieramy Create Child...(jeżeli mamy już jakiś kontener w przestrzeni roboczej, jak klikniemy go prawy przyciskiem myszy wyświetli się podobne menu) lub z menu Edit > Create Child..., w oknie które się pojawi wybieramy Aplication Systems, wystarczy nadać nazwę nowemu kontenerowi.

UWAGA! Niestety narzędzie ma problemy z odświeżaniem drzewa zawierającego elementy przestrzeni roboczej, wprowadzać w bład mogą nieistniejące (usunięte) kontenery, należy więc po usuwaniu uruchomić ponownie panel nawigatora zawierający drzewo.

Diagram Przepływu Danych
Oracle Designer pozwala na tworzenie rozbudowanych diagramów przepływu danych (DFD) zawierających funkcje globalne, lokalne, główne (global, local and frame functions), składnice danych, obiekty zewnętrzne oraz przepływy pomiędzy nimi. Diagram przepływu danych to obrazowe przedstawienie przemieszczania się danych pomiędzy zewnętrznymi obiektami a procesami i składnicami danych w systemie.

Przed przystąpieniem do modelowania, należy zdefiniować kilka pojęć oraz nazewnictwo stosowane przez Designer. Funkcja w kontekście Designera jest podobna w swym znaczeniu do "procesu" znanego z literatury traktującej o diagramach DFD. Najczęściej "proces" definiowany jest jako: "Praca lub akcje wykonane na danych tak, że są one przetworzone, przechowane lub przekazane dalej". Można powiedzieć, że w środowisku Oracle Designer funkcja jest synonimem kroku procesu.

Główne Funkcje (Frame Functions) - jak wskazuje nazwa jest to główna funkcja, która zawiera wszystkie funkcje należące do modelowanego systemu.
Lokalne Funkcje (Local Functions) - jest to funkcja znajdująca się w obrębie głównej funkcji, funkcje lokalne są przeciwieństwem Globalnych Funkcji (Global Functions), znajdujących się poza obszarem głównej funkcji.
Składnice Danych (Datastore) - jest to reprezentacja spójnego zbioru danych, innymi słowy składnice danych reporezentują dane fizycznie składowane w katalogach, plikach, bazie danych. Podczas tworzenia składnicy danych Designer pozwala na ustalenie typu składnicy, albowiem mamy do dyspozycji składnice: komputerowe (computer), ręczne np.: dokumenty papierowe (manual), przejściowe inne (transient).
Przepływy (Dataflows) - reprezentują przepływ danych pomiędzy składnicami a funkcjami i odwrotnie.
Obiekty Zewnętrzne (Externals) - są to jednostki organizacyjne, które mogą być źródłem lub celem przepływów.

Postaramy się przedstawić procesy zachodzące w fikcyjnym Systemie Rejestracji Studentów za pomocą DFD. Na samym początku przyjmijmy założenia, że udało nam sie zidentyfikować 4 główne procesy: zarządzanie danymi studentów, zarządzanie danymi kursów, zarządzanie przydziałem kursów i zarządzanie planami zajęć. Proces "zarządzanie danymi studentów" pobiera i akceptuje dane od studentów, wprowadza informacje do składnicy danych STUD. Proces ten będzie odpowiedzialny także za uzupełnianie i poprawianie wszelkich danych studenta (osobowych, teleadresowych itp.). Proces "zarządzanie danymi kursów" jest odpowiedzialny za pobieranie informacji o dostępnych kursach na wydziałach uczelni, kontrolowanie danych kursu, oraz wprowadzanie i uaktualnianie danych w składnicy CRSE. Jeżeli zaproponowany kurs jest niepoprawny, właściwy wydział zostaje poinformowany. Proces "zarządzanie przydziałem kursów" obsługuje przydzielanie studentów do danego kursu. Proces na początku sprawdza status studenta (studa dzienne lub wieczorowe) ze składnicy STUD. Następnie sprawdzana jest poprawność kursu (np.: czy kurs jest wogóle prowadzony) ze składnicy CRSE oraz sprawdzana jest dostępność kursu (czy są jeszcze wolne miejsca) ze składnicy ENROL. Jeżeli nic nie stoi na przeszkodzie student zapisywany jest na kurs co odnotowywane jest w składnicy ENROL, jeżeli student nie zostanie przyjęty na wybrany przez siebie kurs zostaje do niego wysłane powiadomienie. Proces "zarządzanie planami zajęć" na podstawie składnic STUD, CRSE,ENROL generuje plan zajęć wysyłany studnetom.

Aby utworzyć diagram DFD należy uruchomić DataFlow Diagrammer, można to zrobić z głównego ekranu Designera, z menu Tools>DataFlow Diagrammer lub z poziomu menu narzędzia Repository Object Navigator.

Po uruchomieniu DataFlow Diagrammer wybieramy z menu File>New. Następnie wybieramy kontener w którym zostanie utworzony diagram. W oknie, które się pojawi wybieramy przycisk Create Function pozowli nam to na stworzenie głównej funkcji (frame function), nazwiemy ja SRS (System Rejestracji Studentów) -- możemy także wybrać, który diagram DFD w obrębie naszego kontenera będziemy edytować. Po utworzeniu głównej funkcji możemy przystąpic do tworzenia pozostałych funkcji (nasze 4 funkcje, które określiliśmy sobie wcześniej). Dodanie lokalnej funkcji polega tylko i wyłącznie na wybraniu ikony tworzenia funkcji i kliknięcia w obrębie naszej głownej funkcji. Główną funkcję naszego diagramu przepływu danych przed utworzeniem funkcji lokalnych, można zobaczyć tutaj a całość tego etapu projektowania tutaj.

Po utworzeniu wszystkich funkcji, możemy przystąpić do tworzenia przepływów, składnic danych oraz obiektów zewnętrznych. Aby utworzyć składnicę danych należy wybrać ikonę składnicy danych, oraz kliknąć gdziekolwiek w obrębie głównej funkcji. W oknie, które się pojawi możemy wprowadzić podstawowe informacje dotyczące naszej składnicy. Według prostego projektu, który przedstawiliśmy na początku tego opisu powinniśmy utworzyc 3 składnice, STUD, CRSE oraz ENROL. Gdy już uporamy się ze wszystkimi składnicami musimy stworzyć przepływy pomiędzy funkcjami a składnicami. Tworzenie przepływu jest równie proste jak tworzenie dowolnego innego elementu diagramu, wystarczy przeciagnąć strzałkę z funkcji, składnicy lub obiektu zew. do innego elementu diagramu i określenie zawartości etykiety dla nowego przepływu. Nasz diagram po utworzeniu wszystkich przepływów a przed stworzeniem obiektów zewnętrznych powinien wyglądać następująco. Ostatnim elementem diagramu są obiekty zewnętrzne, po utworzeniu obiektów oraz przepływów pomiędzy nimi a pozostałymi elementami diagramu, możemy zapisać naszą pracę. Diagram w postaci finalnej wygląda nastepująco.

UWAGA! Czasami narzędzie Designer dziwnie reaguje na tworzenie nowych obiektów, rzuca wyjątkami związanymi z próba narysowania elementu diagramu na innym mimo, że taka próba nie wystąpiła, wystarczy wtedy przesunąć diagram i wszystko wraca do normy ;)

Można się łatwo domyślić, że projekt dużego systemu nie składa się z pojedynczego diagramu przepływu danych. Wiadomo, że jednopoziomowy diagram nie odpowie na wszytskie pytania dotyczące działania systemu, dlatego Oracle Designer umożliwia łatwy sposób tworzenia diagramów kolejnych poziomów. Poziom 0 to poziom najwyższy, aby modelować niższe poziomy klikamy w menu pozycje File>Open Down po zaznaczeniu funkcji, którą chcemy modelować na osobnym diaramie. Narzędzie Designer pomoże nam i utworzy podstawowy diagram zawierający wszystkie składnice i obiekty zewnętrze związane z modelowaną funkcją. Tworzenie nowych funkcji polega na tym samym jak w diagramie poziomu 0. Ostateczny wygląd przepływu dla modelowanej funkcji.

Diagram Procesów
Diagramy procesów są graficzną reprezentacją wszystkich procesów zachodzących w modelowanym systemie, w skład czego wchodzą przechowywanie, manipulacja i wymiana danych pomiędzy systemem a zewnętrznymi obiektami a także pomiędzy różnymi elementami systemu (modułami). Nie musimy traktować modelowania jako opisu jakiegoś systemu komputerowego, możemy opisywać procesy zachodzące w firmie, pomiędzy jej oddziałami i kontrahentami.

Przed przystąpieniem do modelowania, należy zdefiniować kilka pojęć oraz nazewnictwo stosowane przez Designer.
Jednostki Organizacyjne (Organizational Unit) - jednostka jest to element systemu odpowiedzialny za realizację danych procesów. Każdej jednostce przydzielana jest przestrzeń w której znajdują się procesy związane z daną jednostką. O tych przstrzeniach mówi sie czasami "tory pływackie". Oracle zawsze uwzględnia uogólnioną jednostkę organizacyjną nazwaną "Unspecified", jednostka ta odnosi się do procesów, które wykonuja pewne akcje ale znajdują się poza głównym obszarem zainteresowań systemu. Designer pozwala na tworzenie dowolnej ilości jednostek organizacyjnych i nazywanie w zupełnie dowolny sposób.
Pozostałe elementy diagramu procesów czyli: proces (funkcja), przepływ, składnica danych oraz obiekt zewnętrzny mają identyczne znaczenie jak w diagramie przepływu danych. To podobieństwo powoduje, że mówi się często o diagramie procesów jako następcy diagramu przepływu danych.

Na tym etapie projektowania wykonamy dekompozycje procesu "Zarządzanie Przydziałem Kursów", który stworzyliśmy podczas tworzenia diagramu przepływu danych. Taką dekompozycję moglibyśmy równie dobrze wykonać za pomoca Dataflow Diagrammer jednak chcemy pokazać, że jest to możliwe w innym narzędziu.

Zewnętrzny obiekt "Student" wysyła zapytanie o przydział na kurs ("studnet_zapytanie") do działu rejestracji ("Rejestracje"). Przyjmijmy, że przetwarzanie zapytania w biurze rejestracji składa się z następujących kroków:
1. Status studenta jest sprawdzany przy użyciu informacji o studencie pobranych ze składnicy danych STUD.
2. Następny krok to sprawdzenie poprawności kursu, wszystkie informacje dotyczące kursu są przechowywane w składnicy CRSE.
3. Następnie sprawdzane jest czy student spełnia wszystkie wstępne wymagania aby uczestniczyć w kursie.
4. Następnie sprawdzane jest czy są jeszcze wolne miejsca na kursie.
5. Ostatni krok, to uaktualnienie składnicy ENROL jeżeli student zostanie zapisany na kurs oraz wysłanie powiadomienia z informacją o powodzeniu rejestracji.

Process Modeler może byc uruchomiony z poziomu Designer launchpad, z menu Tools>Process Modeler narzędzia Repository Object Navigator lub z menu Tools>Process Modeler z Designer launchpad. Po uruchomieniu narzędzie wygląda następująco.

Aby utworzyć nowy diagram wybieramy z menu File>New. Po wyborze kontenera pojawi się okno pozwalające na utworzenie nowego diagramu lub edycję projektu znajdującego się w kontenerze. Główny projekt został już przez nas utworzony więc będzie na liście projektów. Po odznaczeniu opcji "Root Process only" pojawią się wszystkie funkcje należące do naszej głównej funkcji stworzonej w diagramie przepływu danych. Na tym etapie będziemy dekomponować proces "Zarządzanie Przydziałem Kursów" (SRS3) więc musimy go zaznaczyć na liście i wybrać OK. Naszym oczom powinien ukazać się podstawowy widok edytora, zawierający tylko jedną jednostkę organizacyjną "Unspecified".

Na początku tworzymy wszystkie niezbędne jednostki organizacyjne. Aby to zrobić wybieramy ikonę jednostki organizacyjnej i klikamy diagram, w oknie, które się pojawi wprowadzamy dane jednostki. Po zatwierdzeniu, pojawi się na diagramie nowa jednostka, jej położenie w stosunku do "Unspecified" zależy od nazwy, ponieważ są one ustawiane alfabetycznie. W ten sposób tworzymy jednostki: PRZYJECIA oraz REJESTRACJE, pozostawiamy jednostkę "Unspecified" bez zmian. Po ich utworzeniu diagram powinien wyglądać następująco.

Jedyny obiekt zewnętrzny jaki będzie występowal na wykresie to obiekt STUDENT, stworzymy go w jednostce "Unspecified". Obiekty zewnętrzne tworzy się podobnie jak procesy, składnicze czy jednostki org., jednak z listy rozwijanej type musimy wybrać External. Krotkie nazwy obiektów oraz etykiety powinny być takie same jak na diagramie przepływu danych.

Po utworzeniu obiektu zewnętrznego musimy utworzyć procesy: "Sprawdź Status Studenta", "Sprawdź Szczegóły Kursu" oraz "Uaktualnij Przyjęcia". Pierwszy z nich związany jest z kontrolą danych studenta, drugi ze sprawdzeniem czy kurs jest dostępny a ostatni w przypadku powodzenia rejestracji na kurs zapisuje odpowiednie dane w składnicy. Okno tworzenia procesu pozwala na wprowadzenie podstawowych danych.

Pozostaje utworzyć składnice danych oraz przepływy. Tworzymy składnie STUD, ENROL i CRSE, jeżeli podczas nadawania tych samych nazw co na diagramie przepływ danych pojawi się okno z opisem błędu, nie należy się tym przejmowac i nadać składnicom nazwy DBSTUD, DBENROL oraz DBCRSE. Przykład dodania składnicy, można zobaczyć tutaj. Po utworzeniu składnic należy stworzyć przepływy zgodne z wcześniejszym opisem. Aby stowrzyć przepływ klikamy ikonę przepływu danych, klikamy elementy diagramu pomiędzy którymi ma powstać przepływ i w oknie które się pojawi określamy informacje go dotyczące. Domyślnie Designer nie wyświetla etykiet przepływów na diagramie, należy kliknąć przepływ którego etykiete chcemy wyświetlić i z menu wybrać Properties. Pojawi się okno na ramce Display zaznaczamy opcję Name, należy wziąć pod uwagę, że nie są to globalne ustawienia i musimy wykonać tą samą operację dla każdego przepływu. Po dodaniu etykiety diagram powinien wyglądać następująco.

Po dodaniu wszystkich przepływów diagram wygląda następująco. Możemy go wyświetlić w trybie iconic, gdzie "pudełka" zastępowane są ślicznymi ikonami.

Diagram Hierarchii Funkcji
Diagram hierarchii funkcji pokazuje w sposób hierarchiczny wszystkie funkcje, które składają się na modelowany system. W przeciwieństwie do digarmów przepływu danych i procesów nie pokazuje zewnętrznych obiektów, składnic oraz przepływów między nimi. Diagram FHD wskazuje jedynie funkcję "rodzica" i wszystkie funkcje "dzieci", każda z przedstawianych na diagramie funkcji może zostać pokazana na diagramie jako rodzić, a jej funkcje składowe jako "dzieci". Jako, że mamy już stworzony diagram przepływu danych oraz diagram procesów, Oracle Designer utworzy diagram hierarchii funkcji w sposób automatyczny.

Function Hierarchy Diagrammer można uruchomić z poziomu launchapd, z menu Tools>Function Hierarchy Diagremmer lub z poziomu tego samego menu narzędzia Repository Object Navigator. Po uruchomieniu narzędzia, wygląda ono następująco. Aby stworzyć nowy diagram, wybieramy z menu File>New, musimy wybrać kontener w którym będziemy pracować. Aby Designer wygenerował nam podstawowy diagram musimy wybrać na podstawie jakiego modelu ma to zrobić. Wybieramy na liście nasz system SRS.

Szybkość generowania diagramu zależy od poziomu komplikacji projektu naszego systemu, dla naszego prostego systemu SRS po wygenerowaniu diagram wygląda następująco. Wygenerowanie diagramu nie oznacza, że nie możemy dodać kolejnych elementów. Dlatego utworzymy 3 dodatkowe funkcje związane z zarządzaniem danymi studentów. Aby utworzyć funkcje "dzieci" dla danej funkcji, zaznaczamy ją i klikamy ikonę tworzenia funkcji, w oknie które się pojawi, ustalamy dane nowej funkcji. Finalna postać diagramu znajduje się tutaj.

Diagram Związków Encji
Diagram związków encji jest logiczną reprezentacją danych przetwarzanych przez system. Diagram ERD zawiera encje, związki pomiędzy encjami oraz atrubty encji. Potrzebujemy zdefiniować kilka pojęć:

Encja (Entity) - jest to osoba, miejsce, obiekt na temat którego system musi przechowywać dane. (np.: STUDENT)
Atrybut (Attribute) - jest to konkretna właściwość encji, która jest istotna dla modelu systemu. (np.: Student_ID)
Związek (Relationship) - jest to powiązanie pomiędzy zbiorem encji. (np.: Student bierze udział w Kursie, gdzie Student i Kurs to encje a "BIERZE" to związek pomiędzy nimi)
Stopień związku (Degree of Relationship) - jest to liczba typów encji biorących udział w związku. W przykładzie powyżej stopień związku to dwa (lub popularnie nazywany binarny). Należy mieć świadomość, że Oracle Designer pozwala tylko na tworzenie związków unarnych i binarnych.
Liczność związku (Cardinality of Relationship) - w przypadku rozpatrywania od encji A do encji B jest to liczba instancji encji B, które mogą być powiązane z każdą encją A.

Aby uruchomić narzędzie E-R Diagrammer, wybieramy pozycje z menu Tools>Entity Relationship Diagrammer launchpad, lub korzystamy z Repository Object Navigator. Po uruchomieniu narzędzia, wybieramy z pozycje z menu File>New, po wyborze kontenera możemy rozpocząć pracę nad diagramem E-R.

Na tym etapie projektowania zrobimy diagram przedstawiający jedynie zależność dwóch encji, encji STUDENT oraz encji KURS. Aby stworzyć te encje wystarczy wybrać ikonę tworzenia nowej encji i kliknąć w dowolnym obszarze diagramu, w nowym oknie które się pojawi możemy ustalić podstawowe informacje dotyczące tworzonej encji. Musimy ustalić także atrybuty naszych encji, robimy to poprzez otworzenie okna Properties i przejścia do zakładki atrybuty. Ustalmy jakie atrybuty będą posiadały encje:

STUDENT
STUDID - VARCHAR2 - klucz główny
STUDNAME - VARCHAR2
STATUS - VARCHAR2
KIERUNEK - VARCHAR2
PLEC - VARCHAR2
START_SEM - VARCHAR2
START_ROK - NUMBER
Przykład ustawionych atrybutów.

KURS
KURSID - VARCHAR2 - klucz główny
KURSNAZWA - VARCHAR2
PLAN - VARCHAR2
MAX_UCZESTNIKOW - NUMBER

Przykład ustawionych atrybutów.

Pozostało jedynie utworzyć odpowiednie związki, aby to zrobić klikamy odpowiednią ikonę związku i przeciągamy kursorem pomiędzy encjami, które chcemy połączyć. Tworzenie związku jest równie proste jak tworzenie encji. Finalna postać diagramy.

Ekport modelu do bazy danych
Kiedy cały projekt jest juz gotowy możemy wyeksportować diagram E-R do bazy danych. Robimy to za pomocą narzędzia Database Design Transformer, możemy je wywołać z poziomu menu Tools>Database Design Transformer lub z launchpad. Po załadowaniu pojawi się następujący ekran. Wybieramy najbardziej satysfakcjonujące nas opcje (zdecydowac sie nalezy pomiedzy automatyczna generacja a manualnym wyborem tabel). Praca czarodzieja wygląda następująco. Po wygenerowani odpowiednich tabel przechodzimy do Design Editor, za jego pomocą wygenerujemy odpowiednie skrypty SQL oraz diagram dla utworzonych tabel i relacji między nimi.

Przydatne linki
* http://pl.wikipedia.org/wiki/CASE
* http://www.eioba.pl/a74308/narzedzia_case
* http://www.cs.put.poznan.pl/bbebel/pi/01_PI_wprowadzenie.pdf
* http://www.cs.put.poznan.pl/bbebel/pi/02_PI_modelowanie_procesow.pdf
* http://www.cs.put.poznan.pl/bbebel/pi/03_PI_modelowanie_ER.pdf
* http://www.cs.put.poznan.pl/bbebel/pi/04_PI_modelowanie_przeplywow_danych.pdf
* http://www.cs.put.poznan.pl/bbebel/pi/05_PI_modelowanie_hierarchii_funkcji.pdf
* http://www.cs.put.poznan.pl/bbebel/pi/06_PI_generowanie_bazy_danych.pdf

Wiedza tylko wtedy jest wiedzą, kiedy zdobyta została wysiłkiem własnej myśli, a nie wyłącznie dzięki pamięci.

Poprawny XHTML 1.0! Poprawny styl CSS!hacker emblem open source emblem