ViviBook (oder auch: YAXA - Yet another xml adressbook)

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

ViviBook (oder auch: YAXA - Yet another xml adressbook)

Beitragvon BlackVivi » Sonntag 21. Oktober 2007, 12:08

Hab mich mal hingesetzt und'n Adressbuch programmiert, dass die Kontakte in der Beschreibungssprache XML speichert... Was auch den Vorteil hat, dass ich sie zum Beispiel im Browser mit einem entsprechenden Stylesheet anzeigen lassen könnte und sowas...

http://paste.pocoo.org/show/6955/

Sicherlich ist vielles nicht perfekt gelöst und die Docstrings fehler noch... Aber ich bezeichne das hier mal als Version 0.001 alpha. Editieren fehlt noch, weiß nocht nich genau wie ich das implementieren soll... Falls irgendwelche PEP8 Fehler sind, bitte weißt mich darauf hin. Bin ziemlich offen dafür. Mal ein Beispiel für die Benutzung...

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: UTF-8 -*-
from vivibook import ViviBook

foobar = ViviBook("foobar.xml")
foobar.add_contact("Marcell", "S.", "Foobarweg 12", "20.3.1337")
print foobar.get_contact(0)
foobar.add_contact("Vivi", "Orunita")
for i in foobar.get_all_contacts():
    print i
foobar.remove_contact(0)
print foobar.search_contacts("marcell")
print foobar.search_contacts("vivi")
for i in foobar.get_all_contacts():
    print i
foobar.save()


(Man könnte die dicts noch schöner printen lassen, aber dass überlass ich mal den Leuten die's programmieren... Das Ding steht übrigens unter der "MIR EGAL"-Lizenz, macht doch mit dem Quellcode was'r wollt... So toll is's eh nich :P)
BlackJack

Beitragvon BlackJack » Sonntag 21. Oktober 2007, 13:09

Also mir missfällt das eine externe Darstellung wie XML benutzt wird um intern die Daten zu verwalten. Das macht alles unnötig kompliziert und unflexibel. Zum Beispiel das lineare Suchen in einem `ElementTree` statt eines Dictionaries, dass IDs auf Adressen abbildet ist IMHO irgendwie daneben.

Ein besserer Entwurf wären Klassen zur Adressverwaltung, die die Adressen als Python-Objekte modellieren und Methoden oder Funktionen um diese Objekte als XML zu speichern und zu laden. Die Adressverarbeitung; erstellen, suchen, etc.; ist schliesslich unabhängig davon ob die Daten auf der Platte als XML, JSON, CSV oder in einer SQL-Datenbank liegen.

Den Wurzel-Tagnamen einer XML-Datei vom Dateinamen abhängig zu machen ist keine gute Idee. Die beiden Informationen sind eigentlich unabhängig, man sollte den Dateinamen ändern dürfen ohne das der Dateiinhalt dann inkonsistent wird und bei "variablen" Tagnamen kann man kein DTD oder Schema für das XML mehr angeben.

Was soll das Klassenattribut `attributes` eigentlich darstellen? Kann man überhaupt mehrere von diesen Objekten gleichzeitig benutzen ohne damit Probleme zu bekommen!?

In `add_contact` wird ``self.root.find("adresses")`` viel zu oft ausgeführt.

Die ganzen Attribut/Argumentnamen für eine Adresse werden viel zu oft im Quelltext ausgeschrieben. DRY ─ Don't Repeat Yourself ─ sonst muss man bei Änderungen auch alle Wiederholungen ändern und die Gefahr das man etwas vergisst oder nicht "synchron" ändert, steigt.

"Spezielle" Rückgabewerte sind keine gute Idee. Wenn ein Element nicht vorhanden ist, sollte man besser eine Ausnahme auslösen statt `False` zurückzugeben. Ausnahmen wurde ja gerade erfunden um diese hässlichen Sonderfälle loszuwerden. Bei der Suchmethode, die entweder eine Liste mit Ergebnissen oder `False` zurückgibt ist es noch unsinniger. Wenn kein Treffer vorhanden ist, gibt man einfach eine leere Liste zurück. Die ist im ``bool()``-Sinn auch `False` und man kann trotzdem über das Ergebnis iterieren ohne testen zu müssen ob es eine Liste oder `False` ist.

Bei einigen Methoden wird nach dem 'adresses'-Knoten gesucht, bei anderen einfach `self.root[0]` benutzt. Warum diese Unterscheidung?

`get_all_contacts()` ist übel. Die Methode geht linear durch die Knoten um dann den Knoten den sie gerade bearbeitet *nochmal* in `get_contact()` wieder linear von vorne zu suchen. Argh!

In `search_contacts()` wird ähnlich unsinnig mit der Laufzeit umgegangen. Ausserdem kann man sich den Test, ob die aktuelle Adresse schon im Ergebnis vorhanden ist, sparen wenn man bei einem Treffer abbricht und zum nächsten Datensatz geht, anstatt den, den man schon hinzugefügt hat, weiter zu untersuchen. Der ist ja schon drin, da macht es wenig Sinn zu prüfen ob noch mehr Felder zutreffen.
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Beitragvon BlackVivi » Montag 22. Oktober 2007, 10:45

Im ersten Moment war ich geschockt und doch ziemlich traurig, wie sehr BlackJack mein Beispiel heruntergeputzt hat ._. Aber im Endeffekt hat er Recht. Ich bin ja auch nicht böse oder eigenwillig, fand's nur schade das ich absolut gar nichts richtig gemacht habe.

Aber jetzt im Nachhinein versteh ich seine Anmerkungen viel besser. Die Laufzeit ist sehr doof und unüberlegt, viel ist quick and dirty. Ich hätte meine Struktur besser überlegen sollen, denn das zugrundeliegende Problem ist wohl, dass ich versuche die Daten mit ElementTree zu verwalten. Deswegen auch das Problem mit der "NR" und die doppelte Laufzeit, deswegen treten Befehle und Referenzierungen doppelt auf. Ich habs mir unglaublich schwierig gemacht. Ich sollte lieber die XML Datei beim __init__ einlesen und alles in eine Liste packen und während der Laufzeit alles mit der Liste organisieren. Anschließend kann ich ja bei der Methode "save" immernoch die Daten in die XML Datei zurückschreiben. Somit krieg ich wesentlich weniger Probleme, kann sogar meine "Nr" hinzufügen, ohne das es beim löschen Probleme mit Sprüngen gibt und sowas.

Die Sache mit den speziellen Rückgabewerten ärgert mich jetzt, ich hatte zuerst Exceptions und hatte es dann mit diesem, jetzt im Nachhinein, extrem unsinnigen return false ersetzt. Gott, manchmal fasst man sich an den Kopf und denkt: "Was zum Teufel..."

Danke BlackJack. Ich werde diese Woche mich nochmal hinsetzen und es überarbeiten. Ich werde die nächste Version natürlich auch hier reinstellen, damit du sie wieder zerpflücken und zerstören kannst :P (Nur Spaß..... Das Danke war ernst gemeint.)
BlackJack

Beitragvon BlackJack » Montag 22. Oktober 2007, 11:24

'Tschuldigung wegen dem Schock. Knappe, technische Kritik kommt oft etwas schroff und unfreundlich rüber, was aber wirklich nicht meine Absicht war.
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Beitragvon BlackVivi » Montag 22. Oktober 2007, 11:32

BlackJack hat geschrieben:'Tschuldigung wegen dem Schock. Knappe, technische Kritik kommt oft etwas schroff und unfreundlich rüber, was aber wirklich nicht meine Absicht war.
Absolut kein Problem, wie schon gesagt... Ich hab schon sehr viele Beiträge von dir gelesen und gemerkt, wie viele damit nicht klar kamen. Aber ich versuche es. Mein erster Schritt war eine erfolgreiche Implementierung hier zu zeigen, mein nächer ist es, sie zu verbessern. Das Forum hier und insbesondere eben dein Post hilft mir sehr. Ich denke, wenn man so eine Kritik nicht abkann, kommt man als Programmierer nicht weiter... Immerhin mach ich das noch nicht besonders lange.

Wenn ich weiter dran arbeite und deine Ratschläge befolge und es nochmal versuche, auf kleiner logischer Basis meines bestehenden Programmes, es zu programmieren... Dann komm' ich weiter. Immerhin haben alle mal klein angefangen, nicht wahr? Ich schaff' das schon. Nicht aufgeben...

Danke nochmal.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder