OOP und Datenkapselung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
arti73
User
Beiträge: 20
Registriert: Montag 12. September 2016, 12:20

Moin :)

kurze Frage bezüglich dem OO-Design. Man kann ja auf Attribute der Objekte direkt zugreifen. Sollte man dennoch getter und setter nutzen und entsprechende Methoden definieren?

So grundsätzlich mein ich :)

Danke und viele Grüße
Heiko
BlackJack

@arti73: Wenn Du triviale Getter und Setter für ein Attribut hast, dann ist es nicht wirklich gekapselt also machen die trivialen Getter und Setter nur unnötige Schreibarbeit. Wenn Du nicht-triviale Getter und Setter hast (oder zumindest einen von beiden), dann ist das eine Ermessensfrage ob man das über Properties oder Methoden regelt. Wobei ich mit Attributen hier jetzt immer ”Datenattribute” meine. Methoden sind ja auch Attribute. Für Methoden einer Klasse würde ich grundsätzlich eher keine Getter und Setter schreiben. ;-)
arti73
User
Beiträge: 20
Registriert: Montag 12. September 2016, 12:20

Ich meinte die Daten-Attribute, ja :)

In folgendem Beispiel wären das dann triviale, oder? Da würde ich mir das sparen.

Bei Datum hingegen macht es ggf. später Sinn abzufragen, ob das Datum in einem bestimmten Gültigkeits-Bereich liegt. Dann würd' ich da eine Setter-Methode später definieren. Oder sollte man das dann direkt für alle Attribute machen wegen einheitlichem Zugriff auf die Klasse.

Ich mag mir direkt ne vernünftige Linie angewöhnen...

Danke soweit :)

Code: Alles auswählen

class Patenkind():
    
    def __init__(self, vorname='', name='', geburt=datetime.date, nummer=0):
        self.vorname = vorname
        self.name = name
        self.geburt = geburt
        self.nummer = nummer
    
    def setVorname(self, vorname=''):
        self.vorname=vorname

    def setName(self, name=''):
        self.name = name
    
    def setGeburt(self, geburt=datetime.date):
        self.geburt = geburt
    
    def setNummer(self, nummer=0):
        self.nummer=nummer
        
[...]
Zuletzt geändert von Anonymous am Donnerstag 15. September 2016, 10:43, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@arti73: Die Frage ist ob das von Deinem Empfinden her eher ein Datenattribut ist oder etwas wofür das Objekt eine Tätigkeit ausführen muss. Für mich wäre es ein Datenattribut und zwar *immer*. Wenn da später doch noch mal etwas dazu kommt, zum Beispiel eine Bereichsprüfung, dann wird aus dem Attribut entweder ein Property oder es gibt eine zusätzliche Methode zum setzen mit Bereichsprüfung, falls die noch weitere Daten benötigt die vom Aufrufer kommen.

Die ganzen Defaultwerte machen keinen Sinn. Insbesondere bei den Settern und der Wert bei `geburt` ist falsch. Das ist kein Datum sondern ein Typ dessen Exemplare ein Datum repräsentieren.

Die Frage bei Defaultwerten ist immer ob es Sinn macht wenn sie verwendet werden. Ist ein Patenkind das durch ``Patenkind()`` entstanden ist, also gar kein Argument bekommen hat, tatsächlich ein sinnvoller Wert? Ich wage das zu bezweifeln.

Ich würde da einfach nur das hier schreiben:

Code: Alles auswählen

class Patenkind(object):
   
    def __init__(self, vorname, name, geburt, nummer):
        self.vorname = vorname
        self.name = name
        self.geburt = geburt
        self.nummer = nummer
Namen von allem, ausser Konstanten und Klassen, werden in Python übrigens `klein_mit_unterstrichen` geschrieben. Also wenn Setter, dann `set_vorname` statt `setVorname`. An der Stelle kann man dann auch gleich mal über den Sinn vom Mischen verschiedener (natürlicher) Sprachen bei den Namen nachdenken. Allgemein und auch innerhalb von einem Namen.
arti73
User
Beiträge: 20
Registriert: Montag 12. September 2016, 12:20

okay, das notier ich mir soweit :)

Edith sagt, dass ich gedacht habe, dass man bei der Übergabe den Datentyp festlegen muss. Aber ist wohl nicht notwendig.

Thx!
BlackJack

@arti73: Namen haben in Python keine Typen, Werte haben Typen.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Kapselung schaffst du in dynamischen Sprachen wie Python nicht durch Code sondern durch Dokumentation. Du dokumentierst welche Probleme sich wie mit deinem Code lösen lassen und verschweigst dabei die Module, Funktionen, Klassen, Methoden, Attribute usw. die ausschliesslich Teil der Implementation sind und nicht Teil der öffentlichen API.

Darüberhinaus kannst du langfristig rückwärtsinkompatible Änderungen ohnehin nicht vermeiden ohne dass es zur Lasten der Qualität geht. Es ist also viel wichtiger Wege zu finden mit solchen Änderungen umzugehen als Wege diese zu umgehen.
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Klassen, die rein für die Datenhaltung gedacht sind, lassen sich auch gut via collections.namedtuple() erstellen.
BlackJack

Und falls noch Methoden dazu kommen sollen, kann man von so einem mit `namedtuple()` erstellten Typ auch eine Klasse ableiten. Vorteil dabei ist, dass man schon eine `__init__()` hat, eine nette `repr()`-Darstellung, und die andern Eigenschaften eines Tupels, wie Hash und Vergleich über die Attribute, so dass man solche Objekte zum Beispiel als Schlüssel in Wörterbüchern verwenden kann.
arti73
User
Beiträge: 20
Registriert: Montag 12. September 2016, 12:20

Ich fühl mich etwas erschlagen, alles der Reihe nach :D
Antworten