Strona główna > Inne > Poszukiwanie narzedzia

Poszukiwanie narzedzia

Na początku była potrzeba tworzenia dokumentacji, zostało to opisane tutaj. Miało to jednak dalszą kontynuacje.

Wraz z przejściem do projektu (trwał on już od jakiegoś czasu) stanąłem przed wyzwaniem zapoznania się z bazą danych (jedną z wielu). Dokładniej miałem do rozpoznania jej wycinek, aby przygotować kilka zapytania. I tu okazało się, że to co kiedyś stworzyłem w innym projekcie na potrzeby klienta/administratora może być teraz pomocne dla mnie. Było to sposób produkcji dokumentu przedstawiającego relacje pomiędzy tabelami w bazie. W zamierzeniu miała to być pomoc do zaznajomienia się z baza, w sam raz na początek, gdy obraz jej nie jest jeszcze utrwalony w głowie.

Generowanie dokumentu
Cały ten proces zaczyna się od wykonania zapytania zwracającego informacje o strukturze bazy, wynik zapisywany jest do pliku csv (zapytanie we wcześniejszym poście). Następnie dane te są przerabiane przez aplikacyjne(skrypt) do postacie dokumentu html.
I to wszystko … niby niewiele, a potrafi cieszyć.

Wnioski
Korzyści z użycia dokumentacji były widoczne już w tym projekcie – łatwiej było ogarnąć bazę (około 250 tabel). Możliwe jest jednak wykorzystanie tego przy innych, przyszłych projektach. Jest to dość uniwersalny proces: Na samym początku mamy pozyskiwanie informacji o strukturze bazy, który może być dostosowany do różnych dostawców (tutaj była tylko potrzeba dla Oracla). Później mamy tworzenie samej dokumentacji, która może przyjąć różne postacie (o czym trochę dalej).

Korzyścią dla mnie było to, że mogłem się bardziej zaznajomić z technologiami, których nie używam codziennie, tutaj był to głównie Python i JavaScript.

Ostatnie co było cenne to doprecyzowanie tego co właściwie chcę uzyskać. Okazało się, że w toku poszukiwania (próby tworzenia nowych dodatków do dokumentacji) wykrystalizowało się to co chciałem osiągnąć. Dzięki temu mogłem lepiej o to zapytać w wyszukiwarce. Co w tym przypadku poskutkowało znalezieniem narzędzia, które dało mi to co już z większym trudem (dłuższe i kłopotliwe w realizacji) mogłem zrobić sam (o tym też na samym końcu).

Techniczne szczegóły
Przykład skryptu do przetwarzania csv do html jest następujący:

#-*- coding: utf-8 -*-
import csv

table_dict = {}
table_relation_dict = {}
output_doc_lines = []

def process_row_table(doc_line, tab_name):
    doc_line.append('<b id="heading2'+tab_name+'">Tabela:</b>'+tab_name+'</br>')
    doc_line.append('<div style="font-size: 11px"><b>Relacja do:</b>'+get_relations(tab_name)+'</div></br>')
    doc_line.append(get_table(tab_name))

def get_table(tab_name):
    text = '<TABLE class="servicesT" cellspacing="0" ><TBODY><TR bgcolor=#afafaf><TD class="servHd"><B>Kolumna</B></TD><TD class="servHd"><B>Tabela w relacji</B></TD><TD class="servHd"><B>Kolumna w relacji</B></TD></TR>'
    for row in table_dict[tab_name]:
        text = text + '<TR><TD class="servBodL">'+row[1]+'</TD>'
        text = text + '<TD class="servBodL">'+get_href(row[4])+'</TD>'
        text = text + '<TD class="servBodL">'+row[5]+'</TD></TR>'
    text = text + '</TBODY></TABLE></br></br>'
    return text

def get_relations(tab_name):
    text = ''
    if (tab_name in table_relation_dict):
        for v in table_relation_dict[tab_name]:
            text = text + get_href(v) + ', '
    return text

def get_href(tab_name):
    if (tab_name <> ''):
        return '<a href="#heading2'+tab_name+'">'+tab_name+'</a>'
    return ''
    
def get_table_heading(tab_name):
    return '<b id="heading2'+tab_name+'">Tabela:</b>'+tab_name+'</br>'
    
def get_table_realation_info(tab_name):
    return '<div style="font-size: 11px"><b>Relacja do:</b>'+get_relations(tab_name)+'</div></br>'

def get_document_start():
    return '\n\
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Wykaz tabel</title>\n\
    <style type="text/css">\n\
    table.servicesT\n\
    { font-family: Verdana;\n\
    font-weight: normal;\n\
    font-size: 11px;\n\
    color: #404040;\n\
    width: 650px;\n\
    background-color: #fafafa;\n\
    border: 1px #6699CC solid;\n\
    border-collapse: collapse;\n\
    border-spacing: 0px;\n\
    margin-top: 0px;}\n\
    \n\
    \n\
    table.servicesT td.servHd\n\
    { border-bottom: 2px solid #6699CC;\n\
    background-color: #BEC8D1;\n\
    text-align: center;\n\
    font-family: Verdana;\n\
    font-weight: bold;\n\
    font-size: 11px;\n\
    color: #404040;}\n\
    \n\
    \n\
    table.servicesT td\n\
    { border-bottom: 1px dotted #6699CC;\n\
    font-family: Verdana, sans-serif, Arial;\n\
    font-weight: normal;\n\
    font-size: 11px;\n\
    color: #404040;\n\
    background-color: white;\n\
    text-align: left;\n\
    padding-left: 3px;}\n\
    \n\
    .servBodL { border-left: 1px dotted #CEDCEA; } \n\
    \n\
    </style>\n\
    </HEAD><BODY>\n\
    <h3>Wykaz tabel</h3></br>\n\
    <TABLE class="servicesT" cellspacing="0" ><TBODY>'

def get_document_end():
    return '</TBODY></TABLE></br></br>\n\
    </BODY></HTML>'


print "start ..."

csv_file = 'tabele.csv'

print "przetwarzanie danych ..."
csvReader = csv.reader(open(csv_file), delimiter=';', quotechar='|')
print "slownik tabel ..."
for row_table in csvReader:
    table_name = row_table[0]
    if(not table_dict.has_key(table_name)):
        table_dict[table_name] = []
    table_dict[table_name].append(row_table)

print "slownik relacji ..."
for k, v in table_dict.iteritems():
    for row_table in v:
        if (row_table[4] != ''):
            if(not table_relation_dict.has_key(row_table[4])):
                table_relation_dict[row_table[4]] = []
            table_relation_dict[row_table[4]].append(k)


print "tworzenie dokumentu ..."
output_doc_lines.append(get_document_start())

for tab_name in table_dict:
    output_doc_lines.append(get_table_heading(tab_name))
    output_doc_lines.append(get_table_realation_info(tab_name))
    output_doc_lines.append(get_table(tab_name))

output_doc_lines.append(get_document_end())


print "zapis dokumentu ..."
filehandler = open('tabele.html', 'w')
for item in output_doc_lines:
    filehandler.write(item+ '\n')
    print item
filehandler.close()

print "koniec"

przykład csv:

Table1;NUMBER1;Y;NUMBER(22);;
Table1;Table2_ID;Y;NUMBER(22);Table2;ID
Table1;DATE1;Y;DATE(7);;
Table1;ID;N;NUMBER(22);;
Table1;DATE2;Y;DATE(7);;
Table1;STRING1;Y;VARCHAR2(100);;
Table2;STRING1;Y;VARCHAR2(500);;
Table2;DATE1;Y;DATE(7);;
Table2;STRING2;N;VARCHAR2(9);;
Table2;ID;N;NUMBER(22);;
Table2;NUMBER1;Y;NUMBER(22);;
Table3;NUMBER1;Y;NUMBER(22);;
Table4;NUMBER1;Y;NUMBER(22);Table3;NUMBER1

Dalsze zabawy
Dokumentacja już na tym poziomie spełniała swoje zadania. Ale podbudowany początkowymi sukcesami chciałem dodać do tego coś jeszcze ekstra😉. Zamarzyło mi się wizualizacja tego w postaci grafów. Sprawiło to, że trafiłem na bibliotek do robienia tego w JavaScripcie. Jest to jsPlumb tu jest przykład co to może. Ten przykład skusił mnie jednak, aby skorzystać z tej biblioteki. Było to dokładnie to co chciałem zrobić, oraz pokazywało jak to zrobić;). Tylko wziąć i zaadaptować dla swych potrzeb, co też zrobiłem (po krótkich walkach z obfuscatorem, który był tu zastosowany :)).
Technicznie to działało, ale moje zapędy ostudziła wydajność. Przeglądarka po prostu nie wyrabiała aby pokazać graf składający się z 250 węzłów (tabel). Eksperymentując doszedłem do optymalnej liczby około 16 tabel🙂. Sama wizualizacja na tym poziomie też była bardziej gadżetem niż dawała rzeczywistą wartość. Wymagało to jeszcze sporo pracy.

Jak to wcześniej wspomniałem eksperymenty te doprowadziły jednak do uświadomienia sobie czego chcę. Poprzez prace nad narzędziem, dokonałem specyfikacji tego co chcę. Czasami w taki sposób trzeba, jeśli nie można przeprowadzić tego rozumowania w głowie😉. Kończąc ten wątek, znalazłem fajne narzędzie, które dokonuje z grubsza tego co chciałem. Jest to DbVisualizer.

Kategorie:Inne Tags: , , ,
  1. Brak komentarzy.
  1. No trackbacks yet.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d bloggers like this: