Seite 1 von 1

Überprüfung in einer Klasse oder ausserhalb?

Verfasst: Montag 25. Dezember 2006, 21:54
von tischler
Servus,

ich hab eine Klasse die Bilder erstellt. Dazu werden im Konstruktor die Größenangaben übergeben, die ein paar Bedingungen erfüllen sollen.
1.) Integerwerte
2.) Positiv
3.) In einem Tupel

Soll ich diese Überprüfungen im Konstruktor durchführen, oder sollte ich mich darauf verlassen das die richtigen Parameter übergeben werden, also das sich der Aufrufer um die richtigen Werte kümmert?

Was wäre besserer Stil?

mfg
Tischler

Verfasst: Dienstag 26. Dezember 2006, 09:16
von sape
Hi und willkommen im Forum.

Hmm, gute Frage :?

Es gibt einige die vertreten die Meinung das man nicht _alles_ bis zu einem Meteoriteneinschlag überprüfen sollte, sondern darauf vertrauen dass der Programmierer, der die Klasse verwendet, weiß was er tut (Also, das er die Dokumentation gelesen hat, und weiß was die richtigen Parameter, etc sind!)
Joa, bis zu einem gewissen grad bin ich auch der Meinung! ->

Es gibt aber Situationen das bei falsch übergebene Parametern im Programmverlauf eigenartige Fehler passieren und so eigenartige Exceptions ausgelöst werden die nicht unbedingt das aussagen was man gerne hätte :roll: Oder noch schlimmer das die Klasse da einfach so hinnimmt und akzeptiert! 0__0 -> Das kann ich mir bei einer Bedingung wie "Zahl muss Positiv sein" sehr gut vorstellen das der Klasse das wenig juckt, wenn du das nicht vorher überprüfst und entsprechend darauf reagierst :D


Tja, ich bin ehrlich gesagt auch noch nicht in der Lage zu beurteilen wann es angebracht ist einen Parameter auf Datentype Gültigkeit hin zu überprüfen und bei ``False`` dann einen `TypeError` auszulösen :-[

Konnte dir zwar nicht wirklich helfen, daher sehe es als Gratispush vom Thread und als Thread-Abo von mir an, das ich mit diesem Post so eben Aboniert habe :p Mich interresiert nämlich auch wie das die anderen sehen.



Denoch meine Meinung dazu:
So vom Gefühl her (und würde ich bei mir auch machen!) würde ich eine Überprüfung machen und zwar aus folgenden gründen:
Weil die x und y angaben im `Tuple` Positive sein müssen! Genau das wird wohl ein grund sein wenn du negative Integerwerte angibst es trotzdem akzeptiert wird von deiner Klasse obwohl es nach _deinem_ Bedingungen nicht sein darf! Sehe ich das richtig?

Der nächste grund ist, das du im `Tuple`genau 2 werte von einem "einzigen" Datentype (int, long, oder eine Ableitung von eben genanten) voraussetzt! Da ist es mMn angebracht zu überprüfen...

Aber der wirklich ausschlaggebende Grund ist für mich das die Integerwerte Positiv sein müssen. So, was sollte man schon überprüfen, weil unter Umständen deine Klasse diesen "Fehler" Stil schweigend hinnehmen würde, anstatt mit einer Exception zu reagieren (Sehe ich das richtig, das deine Klasse bei einem Negativen Int ohne eine Exception darauf reagiert?)


Also konkreter: Wenn der Parameter Ein `Tuple` sein muss, dessen Inhalt alles mögliche sein kann oder besser gesagt nicht vom konkreten Datentype abhängig ist, würde ich mir eine Überprüfung sparen!

Wenn der Inhalt aber von einem Datentype sein muss (in deinem Fall vom Type `int`, `long` und dazu noch positiv!) würde ich immer eine Überprüfung machen und entsprechende mit einer Exception reagieren, unabhängig davon was mir die andere sagen! Das ist für mich der bessere Stil :)

Mein Vorschlag:
Wenn kein `Tuple` übergeben wurde -> `TypeError` mit einer schönen Fehlermeldung raisen.

Code: Alles auswählen

if not isinstance(tuple_, tuple):
    raise TypeError("deine Meldung")
Wenn die x, y werte im Tuple nicht vom Type int, long oder vom besagten abgeleitet sind -> `TypeError`

Code: Alles auswählen

if not isinstance(tuple_(0), int) or not isinstance(tuple_(1), int):
    raise TypeError("deine Meldung")
Wenn die Integerwerte im `tuple` negativ sind, dann auch eine Exception auslösen (muss du wahrscheinlich eine eigene Exception Klasse dafür definieren. Ich weiß nicht ob es für negative Werte schon eine vorgefertigete klasse gibt.)

my 2 cents

lg und schönen rutsch ins neue Jahr
sape

Verfasst: Dienstag 26. Dezember 2006, 13:24
von tischler
Servus und erstmal danke für die Antwort.
Ich benutze das PIL-Modul.
Hier mal ein bisschen Code:

Code: Alles auswählen

>>> from PIL import Image
>>> i = Image.new("RGB", (500, 500))
>>> i
<PIL.Image.Image instance at 0x009E4058>
>>> i = Image.new("RGB", (500.0, 500))
C:\Python24\lib\site-packages\PIL\Image.py:1710: DeprecationWarning: integer argument expected, got float
>>> i = Image.new("RGB", (-500, 500))
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "C:\Python24\Lib\site-packages\PIL\Image.py", line 1710, in new
    return Image()._new(core.fill(mode, size, color))
MemoryError
D.h. die Klasse raised eigentlich genug Exceptions...

In meine Klasse packe ich NUR die Programmlogik und nicht die Überprüfungen, weil ich MEINER Meinung nicht dafür verantwortlich bin...
Die zusätzlichen Überprüfungen blähen meinen Code doch nur auf.

Verfasst: Dienstag 26. Dezember 2006, 14:09
von BlackJack
Insbesondere ob es ein Tupel ist, würde ich *nicht* explizit prüfen. Wüsste nicht warum man ein Wertepaar nicht auch als Liste übergeben können sollte. Oder vielleicht als Objekt einer `Pair`-Klasse. Wenn man in der eigenen Klasse ein Tupel benötigt, zum Beispiel weil das Wertepaar Schlüssel in einem Dictionary sein soll, dann kann man sich so eines problemlos mit ``tuple(wertepaar)`` erzeugen, egal ob es nun ein Tupel, eine Liste oder irgendetwas anderes war, was auf ``wertepaar[0]`` und ``wertepaar[1]`` bzw. `iter()` entsprechend reagiert.

Positive Zahlen würde ich eventuell testen. IMHO muss man zwischen Tests auf Typen und Tests auf Werte unterscheiden. Typen testen geht erst einmal gegen die "Natur" von Python und man sollte sich das gut überlegen wann es etwas bringt und wann es das "duck typing" zu sehr beeinträchtigt. Aber Werte zu testen ist okay. Damit testet man letztendlich ob sich ein Objekt entsprechend verhält, also z.B. ob die Zahl-Ente, die man übergeben bekommen hat, nur im positiven Bereich quakt. ;-)

Verfasst: Dienstag 26. Dezember 2006, 15:52
von lunar
tischler hat geschrieben:Servus und erstmal danke für die Antwort.
Ich benutze das PIL-Modul.
Hier mal ein bisschen Code:

Code: Alles auswählen

>>> from PIL import Image
>>> i = Image.new("RGB", (500, 500))
>>> i
<PIL.Image.Image instance at 0x009E4058>
>>> i = Image.new("RGB", (500.0, 500))
C:\Python24\lib\site-packages\PIL\Image.py:1710: DeprecationWarning: integer argument expected, got float
>>> i = Image.new("RGB", (-500, 500))
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "C:\Python24\Lib\site-packages\PIL\Image.py", line 1710, in new
    return Image()._new(core.fill(mode, size, color))
MemoryError
D.h. die Klasse raised eigentlich genug Exceptions...

In meine Klasse packe ich NUR die Programmlogik und nicht die Überprüfungen, weil ich MEINER Meinung nicht dafür verantwortlich bin...
Die zusätzlichen Überprüfungen blähen meinen Code doch nur auf.
So wie ich das sehe (ich kenne PIL nicht), erzeugst du da doch ein neues Bild, indem du das Farbenformat und die Größe des Bildes angibst, oder?

Wenn dem so ist, würde ich auch auf die Überprüfung verzichten. Vielleicht bin ich egoistisch, aber ein Programmierer, der Bilder mit negativer Größe erzeugen will, ist selbst schuld wenn seine Anwendung nicht funktioniert. ;)

Außerdem ist das hier Python. Ungültige Argumente führen hier nicht wie in C gleich zu Segmentation faults. Es passiert nichts schlimmeres als eine Ausnahme, die man als Anwender deines Moduls auch prima abfangen kann.

Deswegen würde ich dir schon zustimmen, wenn du sagst, dass die Überprüfung nicht deine Sache ist. Dafür ist dann der verantwortlich, der dein Modul in eine GUI Anwendung einbettet oder sonst irgendwie verwendet.

Gruß
lunar

Edit: Radikale Vernichtung der Rechtschreibfehler...

Verfasst: Dienstag 26. Dezember 2006, 16:21
von sape
tischler hat geschrieben: D.h. die Klasse raised eigentlich genug Exceptions...
Sehe ich auch so, bei der ersten Exception. Dort wird ja schon gesagt das gefälligst Integer und nicht floats oder sonstiges übergeben werden soll ;) -> "DeprecationWarning: integer argument expected, got float"

Die Exception bei einem negativen Wert ist ehrlich richtig mist!! Da hat wohl einer geschlampt von den PIL Programmierern! -> "MemoryError" Ja ne ist kalr, aht auch viel damit zu tun das ein negativer Intergerwert übergeben wurde :roll: -> Hier eine Überprüfung auf negative Ints machen und dann ggf. eine schöne Exception auslössen die darauf hinweiste :)

BlackJack hat geschrieben:[...]
Positive Zahlen würde ich eventuell testen. IMHO muss man zwischen Tests auf Typen und Tests auf Werte unterscheiden. Typen testen geht erst einmal gegen die "Natur" von Python und man sollte sich das gut überlegen wann es etwas bringt und wann es das "duck typing" zu sehr beeinträchtigt.
Stimmt schon, bloß wan ist es berechtigt? Eine Frage die mir bisher keiner wirklich beantworten konnte. Ich bin mir nicht sicher ob es was bringt wenn ich euch z.B. jedesmal damit nerve ob es nun angebracht wäre ob wohl mir mein Gefühl sagt das es das ist :?

Ich stehe oft vor der Entscheidung bei übergebenen Parametern. Soll ich lieber eine schöne etwas konkretes sagende exception auslösen, oder lass ich lieber exceptions intern im code auslösen die nicht unbedingt dem Benutzer was sagendes gibt? Bestes Beispiel mit der oberen Exception: "MemoryError" <-- Finde ich nicht besonders gut, wenn man einen negativen int wert übergibt. Da würde ich z.B. direkt überprüfen ob es den Kriterien entspricht und ein eigene Exception auslösen die was aussagt und eben konkret auf das Problem hinweißt. Solche Situationen habe ich offt bei falsch übergebene Parametern...
BlackJack hat geschrieben: [...]
also z.B. ob die Zahl-Ente, die man übergeben bekommen hat, nur im positiven Bereich quakt. ;-)
Hehe ^^ xD

lg

Verfasst: Dienstag 26. Dezember 2006, 18:22
von BlackJack
sape hat geschrieben:
BlackJack hat geschrieben:[...]
Positive Zahlen würde ich eventuell testen. IMHO muss man zwischen Tests auf Typen und Tests auf Werte unterscheiden. Typen testen geht erst einmal gegen die "Natur" von Python und man sollte sich das gut überlegen wann es etwas bringt und wann es das "duck typing" zu sehr beeinträchtigt.
Stimmt schon, bloß wan ist es berechtigt? Eine Frage die mir bisher keiner wirklich beantworten konnte.
Die Frage lässt sich auch nicht pauschal beantworten. Wäre ja auch langweilig wenn's so einfach wäre. ;-)