Wie beschreibe ich Funktionsargumente elegant genauer?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Henning_als_Gast

Dienstag 27. September 2005, 11:44

Moin!
Folgendes Problemchen:
"Umgebung" des Problems:
Ich arbeite mit mod_python und cheetah, das ganze Ding ist relativ gut modularisiert, und natürlich auch objektorientiert.
Der grobe Aufbau ist der, dass jedes Modul eine Klasse gleichen Namens enthält, von der mein handler ein Objekt erzeugt und je nach übergebenen GET- oder POST-Parametern sich eine Funktion davon raussucht, und diese aufruft.
Danach wird novh eine Funtion namens body von dem Objekt aufgerufen, die bis dahin (meist von der vorher aufgerufenen Funktion) definiert sein sollte.

Auf diese Weise kann ich schön mit nem cheetah-template
von der Klasse ableiten, mit cheetah alle möglichen Ausgabe-Funktionen definieren, und in den Funktionen, die was tun, schreibe ich dann ein self.body = self.ausgabefunktion hin, und alle sin glücklich.

Diesen 2-Schritt mache ich bewusst um Datenvorbereitung (also SQL-Abfragen etc...) und ihre Prsäsentation getrennt zu halten.
So kann man leicht neue Templates für das Ding schreiben.

Nähere Umgebung des Problems:
Jetzt bin ich auf den Trichter gekommen, dass es blöd ist, wenn sich jede Funktion dauern selbst die Parameter aus dem field-objekt pulen und vor allem selbst auf Korrektheit testen muss.

Darum hab ich mir für Paramterabfrage und -entgegennahme auch wieder Klassen geschrieben, die folgendes leisten:
- Eine "Abfragefunktion" (gibt also z.B. <input name="$name" ...> aus)
- Eine Ausgabefunktion (gibt den Wert als lesbaren string aus)
- Eine Funktion, die zunächst alles aus dem field-objekt holt, was zu dem Parameter passt
- Eine Validierungsfunktion, die guckt, ob die übergebenen Werte Sinn machen und sie in ein nützliches Format umwandelt (z.B. datetime.date für ein Datum)

Problem:
soweit, so gut.
Jetzt hätte ich aber gerne, dass ich irgendwo Objekte von meinen Klassen erzeuge, so dass mein handler die Funktionen gleich schön elgant mit "echten" argumenten aufrufen kann.
Also bis jetzt würde ich das so machen:

Code: Alles auswählen

class Modul(Modulbasis):
  def __init__(self):
      register_function(self.callme, PText("surname", "Nachname", maxlen=20), PTime("dinner", "Abendessen"))

  def callme(self, surname, dinner):
     # do something with already clean surname and dinner
Das gefällt mir aber deswegen nicht, weil meine Module u.U. auch mal ein bisschen länger werden können, ich hätte
das gerne in der Nähe der Methodendefinition.
Diese lustigen @-dinger (wie heissen die gleich, deskriptoren?) kann ich leider nicht verwenden, in meinem mod_python ist ein 2.3.5 verbaut, selbst ein neues compilen kommt nicht in die Tüte :-/

Ich hatte auch schon sowas überlegt:

Code: Alles auswählen

class Modul(ModulBase):
   register_function(callme, ...)
   def callme(self, surname, dinner):
       # ...
Da finde ich aber auch nicht so richtig gefallen dran, weil ich wie im obigen Beispiel den Umstand gar nicht ausnutze, dass ich schon vor aufruf des Moduls weiß, welche Funktion aufgerufen werden soll.
Wenn ichs so wie hier mache lege ich ja ne ganze Menge Parameter-Parse-Objekte sinnlos an :-/

Halbwegs sympatisch ist mir noch die Variante:

Code: Alles auswählen

class Modul(ModulBase):
   # ...
   def callme(self, surname, dinner):
   """ Das hier ist die callme-Funktion.
        Sie tut eigentlich gar nichts.
        | surname = PText("Nachname", maxlen=20)
        | dinner = PTime("Abendessen")
   """
      # ....
...sprich, die Argumentdeklarationen im docsting vornehmen und vor dem Aufrufen den docstring der entspr. Funktion ausparsen.
(Ist nicht sonderlich schwer, eine regex drüberjagen und das ganze nach ein bisschen kosmetik in ein eval() stecken).

Aber im Endeffekt kommt mir nichts von alledem wirklich elegant vor.
Hat jemand eventuell ne "schönere" Idee? (Beautiful is better than ugly)
Kann jemand von euch abschätzen, wie sich welche Lösung auf die Performance auswirkt? (Performance ist kein Problem, aber ich mag den Gedanken einfach nicht, bei jedem request zu viel unnötige Arbeit zu tun)

Danke schonmal!
Henning
Antworten