# Wozu braucht man private Methoden oder Variablen (Datenkappselung)?



## port29 (19. März 2010)

Hallo Leute,

seitdem ich nun seit zwei Jahren mit Ruby bzw. mit RoR programmiere, frage ich mich, wozu private Methoden und Variablen in C* oder Java tatsächlich gut sind. 

Ich habe mir auch den Artikel zur Datenkappslung bei Wikipedia durchgelesen, konnte aber dort auch keine richtigen Vorteile finden, außer dass man vielleicht das Innenleben einer Klasse geheimhalten möchte. Für mich persönlich steht eins fest: Programmierer sind nicht dumm. Wieso sollte man ihnen deshalb den Zugriff auf Variablen untersagen? Und wenn sie den Zugriff brauchen? Dann wird die private Variable einfach schnell zur public bzw. get/set Funktionen werden einfach reingesetzt. Da kann man sich ja eigentlich gleich die Mühe sparen und von Vorne rein alles public deklarieren. 

Ich bin selbst seit 10 Jahren C++ bzw. seit 5 Jahren C# Programmierer. Die Datenkappslung habe ich bisher noch nie in Frage gestellt, bis jetzt. Denn momentan sehe ich keinen Grund dafür. Wie seht ihr das?


----------



## Parantatatam (19. März 2010)

Ich programmiere zwar hauptsächlich in PHP, aber auch da gibt es für die Datenkappslung die drei Methodenarten: *private*, *protected* und *public*. Der Punkt ist, dass man teilweise auch Sachen programmiert, die später ein anderer Entwickler (oder manchmal auch ein DAU) verwendet. Wenn der nun ausversehen eine mit *private* gekennzeichnete Methode aufruft, dann sollte das einen Fehler erzeugen und ihm somit signalisieren, dass das, was er gerade versucht, nicht möglich ist. Ansonsten kann es auch dem Programmierer selbst passieren, dass er irgendwann nach einer gewissen Zeit das Skript vor lauter Zeilen nicht mehr sieht und er dann vielleicht selber etwas versucht, was nicht sein soll. Ich meine, dass die Datenkappslung letztendlich nur eine Hilfe für den Programmierer ist.


----------



## port29 (19. März 2010)

einfach nur crack hat gesagt.:


> Ich programmiere zwar hauptsächlich in PHP, aber auch da gibt es für die Datenkappslung die drei Methodenarten: *private*, *protected* und *public*. Der Punkt ist, dass man teilweise auch Sachen programmiert, die später ein anderer Entwickler (oder manchmal auch ein DAU) verwendet. Wenn der nun ausversehen eine mit *private* gekennzeichnete Methode aufruft, dann sollte das einen Fehler erzeugen und ihm somit signalisieren, dass das, was er gerade versucht, nicht möglich ist.



Da stellen sich mir zwei Fragen: 
  - Wieso sollte das, was er vorhat, denn nicht möglich sein? Wenn es wirklich nicht möglich ist, wird schon eine andere Exception fliegen.
  - Was macht der (DAU) Programmierer, wenn eine Methode privat ist? Er geht in den Quelltext und deklariert die als public.


----------



## medieninf (19. März 2010)

Hallo,

Datenkapselung ist u.a. wichtig wenn du die interne Implemenation änderst, nach außen jedoch konsistent bleiben willst.

Bsp.

class Person {

      private String name = "Hans Wurst";

     public String getName() { return name; }
}

Jeder Nutzt nun die Methode getName. Dann fällt dir ein man sollte das in private String vorname ="Hans"; und private String nachname ="Wurst" aufteilen. Gibst du halt return vorname+nachname zurück. Der Code der deinen Code aufruftt ändert sich nicht. Kann weiter getName aufrufen. Hättest du im Code direkt auf Person.name zugegriffen würde das nicht mehr funktionieren, da ja dort nur noch der nachname steht


----------



## Parantatatam (19. März 2010)

Zu den privaten Methoden: ich verwende private Methoden beispielsweise, wenn ich einen Algorithmus in verschiedenen anderen Methoden dieser Klasse verwenden will, aber eben nicht jedes mal den Code kopieren will, was auch recht hirnrissig wäre. Da könnte ich auch andere Funktionen verwenden, sicherlich, aber wenn dieser Algorithmus nur in dieser Klasse verwendet wird, warum sollte ich es dann in eine Funktion schreiben, die sonst niemand verwenden kann? Und zu den DAUs: gut, da hast du recht, aber wenn man wirklich nur jemanden hat, der ein Framework verwendet, aber nichts genaueres darüber weiß, der wird dadurch erstmal zurückschrecken.


----------



## port29 (19. März 2010)

medieninf hat gesagt.:


> Jeder Nutzt nun die Methode getName. Dann fällt dir ein man sollte das in private String vorname ="Hans"; und private String nachname ="Wurst" aufteilen. Gibst du halt return vorname+nachname zurück. Der Code der deinen Code aufruftt ändert sich nicht. Kann weiter getName aufrufen. Hättest du im Code direkt auf Person.name zugegriffen würde das nicht mehr funktionieren, da ja dort nur noch der nachname steht



Das ist kein Argument dafür:


```
public virtual String Name {
            get { return Vorname + Nachname; }

        }

....

String bla = instanz.Name
```

Wie du siehst, habe ich hier aus einer Variable ein Attribut erstellt, bei dem ich den Ausgabestring dynamisch gestalten kann.


----------



## medieninf (19. März 2010)

Weiteres Argument:

du kannst durch getter/setter Methoden den Zugriff auf Attribute "kanalisieren" und bsp. bestimmte Dinge abfragen. Bsp. könnte man so verhindern einer Variablen einen negativen Wert zuzuweisen...

BTW: 

Das erste ist durchaus auch ein Argument. Dein "dynamisches" vorgehen lässt sich möglicherweise nicht in jeder Programmiersprache realisieren...


----------



## deepthroat (19. März 2010)

Hi.





port29 hat gesagt.:


> Das ist kein Argument dafür:


Doch, ist es. Zumindest in C++ und Java.


port29 hat gesagt.:


> - Was macht der (DAU) Programmierer, wenn eine Methode privat ist? Er geht in den Quelltext und deklariert die als public.


Und auch ein DAU kann nicht so einfach die Zugriffslevel modifizieren ohne ein Bibliothek neu zu erstellen. Und selbst wenn ein DAU dann soetwas macht kann man ihn wohl schlecht davon abhalten.


port29 hat gesagt.:


> - Wieso sollte das, was er vorhat, denn nicht möglich sein? Wenn es wirklich nicht möglich ist, wird schon eine andere Exception fliegen.


Kontrolle zur Kompilierzeit ist besser als zur Laufzeit.

Sinnvoll sind private / protected Attribute außerdem um read-only Attribute zu realisieren (wenn die Sprache keine read-only Properties unterstützt).

Manche Attribute werden auch nur intern in der Klasse verwendet (zum Caching o.ä.), diese sollten eben von aussen nicht zugreifbar sein. Warum sollte man (öffentlich) die Hosen runterlassen wenn es nicht notwendig ist? ^^

Außerdem schränken private / protected Attribute die Komplexität ein. Es gibt nicht unzählige Stellen wo auf die Attribute zugegriffen werden kann, was sich beim Debugging bezahlt macht.

Gruß


----------



## Vereth (19. März 2010)

Manche Attribute werden nur intern verwendet. Um die *Datenkonsistenz* (ganz wichtiges Prinzip!) zu wahren, sollte der Zugriff von außen verhindert werden.
Manchmal rufe ich innerhalb einer Methode wiederum Methoden desselben Objektes auf; dafür splitte ich die aufzurufende Methode auf in eine private-Methode ohne aufwändige Parametertests (denn ich mache keine Fehler 8) und eine public-Methode, die nur die Parameter überprüft und dann, wenn diese ok sind, die private-Methode aufruft (denn beim DAU sind Fehler an der Tagesordnung).
Manche Methoden deklariere ich als private, weil diese Funktionalitäten zur Verfügung stellen, die mit der eigentlichen Klasse nichts zu tun hat, aber nützliche Dienste/Vorarbeiten für andere Methoden leisten, eventuell sogar für mehrere.
Meine IDE soll mich beim Auto-Vervollständigen nicht mit Sachen zumüllen, die sowieso keiner braucht.


----------



## port29 (19. März 2010)

Ich weiß momentan irgendwie nicht, wieso wir uns über DAU Programmierer unterhalten. Ich gehe eigentlich davon aus, dass die Leute, die an einem Projekt arbeiten, schon eine gewisse Ahnung haben, was die machen. Ich will jetzt nicht sagen, dass private Methoden etwas falsches sind (denn schließlich habe auch ich 10 Jahre auf diese Art programmiert), aber momentan hinterfrage ich etwas das Konzept und würde es mit euch gerne diskutieren.



deepthroat hat gesagt.:


> Kontrolle zur Kompilierzeit ist besser als zur Laufzeit.



Da hast du natürlich recht. Sicherlich könnte man jetzt gegenargumentieren und sagen, dass mögliche Fehler mit dem Unit-Testing aufgedeckt werden. 



deepthroat hat gesagt.:


> Sinnvoll sind private / protected Attribute außerdem um read-only Attribute zu realisieren (wenn die Sprache keine read-only Properties unterstützt).



Das ist wieder so eine Sache... Wozu brauche ich in einem Programm read-only Attribute / Variablen? Wenn ich eh nicht darauf schreibend zugreife, dann brauche ich die Variable auch nicht read-only zu deklarieren. Ich bin ja der jenige, der beschlossen hat, dass ich nur lesend auf die Variable zugreife. Zur Not benenne ich die Variable mit "_ro" als Postfix, rein zur Erinnerung. 



deepthroat hat gesagt.:


> Manche Attribute werden auch nur intern in der Klasse verwendet (zum Caching o.ä.), diese sollten eben von aussen nicht zugreifbar sein. Warum sollte man (öffentlich) die Hosen runterlassen wenn es nicht notwendig ist? ^^



Das ist natürlich der "klassische" Grund, der auch mir eingetrichtert wurde. Was meinst du denn genau mit öffentlich? Ich glaube, wir sind uns darüber einig, dass ein Anwender (also die Öffentlichkeit) absolut nichts sieht, was im Quelltext geschrieben steht. Er kann auch nicht einfach mal eben private Methoden aufrufen. Und dann gibt es noch den / die Programmierer. Wieso sollten die denn nicht sehen dürfen, was in der Instanz einer Klasse vorsich geht?

@Vereth
Ich sehe in deinem Posting keinen Grund gegen die Deklarierung von Attributen als public. Und mal ganz ehrlich: Rails bzw. RoR Anwendungen entwickle ich mit Textmate. Ein simpler Editor, der kein Intellisense oder Verfollständigungen in der Art von Visual Studio bietet. Am Anfang war es auch für mich schwierig, aber wenn du diese Hilfestellung nicht hast, konzentrierst du dich wirklich auf die Quellcodes, die du schreibst. Ich hab es früher in C# / Java auch immer so gemacht, dass ich den Instanznamen mit einem Punkt am Ende hingeschrieben habe, dann etwas gewartet habe, bis sich das Vorschlagsmenü aufgerufen hat und dann das richtige Kommando zuende getippt habe. In Textmate tippe ich entweder alles bis zum Ende durch oder drücke die Escape Taste (verfollständigt die Zeichenkette)


----------



## deepthroat (20. März 2010)

Hi.





port29 hat gesagt.:


> Da hast du natürlich recht. Sicherlich könnte man jetzt gegenargumentieren und sagen, dass mögliche Fehler mit dem Unit-Testing aufgedeckt werden.


Welche Software hat 100% Unit-Test Abdeckung? ;-]


port29 hat gesagt.:


> Das ist wieder so eine Sache... Wozu brauche ich in einem Programm read-only Attribute / Variablen? Wenn ich eh nicht darauf schreibend zugreife, dann brauche ich die Variable auch nicht read-only zu deklarieren. Ich bin ja der jenige, der beschlossen hat, dass ich nur lesend auf die Variable zugreife. Zur Not benenne ich die Variable mit "_ro" als Postfix, rein zur Erinnerung.


Um (wie Vereth auch schon sagte) Inkonsistenzen im System zu unterbinden. Warum sollte ich es riskieren das ein Programmteil (auf den ich keinen Einfluss habe) den Wert eines Attributes ändert (_ro Suffix hin oder her)?


port29 hat gesagt.:


> Das ist natürlich der "klassische" Grund, der auch mir eingetrichtert wurde. Was meinst du denn genau mit öffentlich? Ich glaube, wir sind uns darüber einig, dass ein Anwender (also die Öffentlichkeit) absolut nichts sieht, was im Quelltext geschrieben steht. Er kann auch nicht einfach mal eben private Methoden aufrufen. Und dann gibt es noch den / die Programmierer. Wieso sollten die denn nicht sehen dürfen, was in der Instanz einer Klasse vorsich geht?


Es geht nicht darum etwas zu dürfen. Wie gesagt kann man wohl kaum verhindern das jemand irgendetwas im Quellcode herumpfuscht. Aber nicht öffentliche Attribute / Methoden brauchen einen anderen Programmierer nicht zu interessieren. Man bietet eine öffentliche Schnittstelle und fertig. Die öffentliche Schnittstelle sollte man nie ändern, da andere Programmteile natürlich davon abhängen (könnten). Wenn ich sauber gearbeitet habe kann ich den Typ der privaten Attribute jederzeit ändern. D.h. ich bin frei in der Entscheidung etwas an der internen Implementierung zu ändern ohne das 3 andere Entwickler mir auf's Dach steigen weil ihre Module nicht mehr kompilieren oder laufen.

Hast du denn eigentlich mal ausprobiert was passiert wenn du aus einem Attribut eine read-only Property machst so wie in Beitrag #6? Du änderst hier das ABI - d.h. das Modul ist nicht mehr kompatibel zur alten Version und jedes abhängige Modul bzw. Programm muss neu kompiliert werden. Nur weil es syntaktisch gleich aussieht, ist es dennoch ein ganz anderes paar Schuhe.

Gruß


----------



## Vereth (21. März 2010)

@port29: Solange du deinen Programmcode nur für dich schreibst und ihn nicht anderen zugänglich machen willst/brauchst, kannst du selbstverständlich ganz deinem persönlichen Stil frönen; Dali hat schließlich auch anders gemalt als Dürer. Sobald du jedoch deine Klassen/Programme anderen Leuten zur Verfügung stellen möchtest, solltest die dich der Befolgung gewisser stilistischer Konventionen befleißigen, um die Lesbarkeit zu erhöhen. Es gehört nicht zum guten Ton, die Nachvollziehbarkeit durch fehlende Strukturierung und spät zu erkennende Redundanzen künstlich zu erschweren.


----------



## Neither (23. März 2010)

port29 hat gesagt.:


> Hallo Leute,
> 
> seitdem ich nun seit zwei Jahren mit Ruby bzw. mit RoR programmiere, frage ich mich, wozu private Methoden und Variablen in C* oder Java tatsächlich gut sind.
> ...
> Ich bin selbst seit 10 Jahren C++ bzw. seit 5 Jahren C# Programmierer. Die Datenkappslung habe ich bisher noch nie in Frage gestellt, bis jetzt. Denn momentan sehe ich keinen Grund dafür. Wie seht ihr das?



Peter Lavin hat es in einem seiner Bücher sehr gut erläutert: Es geht nicht nur um die Konsistenz von Daten oder darum Code vor anderen zu verbergen, vielmehr ist die Deklaration mit private, public oder protected auch eine wichtige, aber dennoch einfache Art der Dokumentation - nicht nur bei der Arbeit innerhalb von Teams, sondern auch für den einzelnen Entwickler selbst, der sich nach Monaten der Abstinenz wieder einmal mit dem eigenen Programm auseinandersetzen "darf".

Natürlich kann ein DAU je nach System und Aufbau der Programme versuchen den Code trotzdem zu ändern. Wenn er aber nicht wirklich absolut dämlich ist (jaja...) wird er sich bei der Deklaration private oder protected zumindest denken können, dass er damit in der Gefahr ist eine interne Logik zu umgehen, die vielleicht sogar nicht erkennbare Abhängigkeiten verbirgt.

Ich denke die Hemmschwelle ist bei (Skript-)Sprachen wie PHP, Ruby oder Python auch geringer, als bei Sprachen die kompiliert werden und bei denen dann doch häufiger fremde Klassen, Bibliotheken oder dlls eingebunden werden. Oft ist dort der Umfang der fremden Komponenten dort auch wesentlich größer, als dass man mal eben im Quellcode "rumpfuscht".

Andererseits denke ich auch, dass man da nicht allzu päpstlich sein sollte


----------



## Ringelsocke (30. März 2010)

Mir war bisher nie bewusst, dass man dieses Konzept in Frage stellen kann...
Ein Klasse sollte nach AUSSEN immer nur die Properties und Funktionen zur Verfügung stellen, die ein Anwender der Klasse verwenden dürfen soll. Was das genau ist, dass muss man beim Entwurf/Planen der Klasse (was jeder gute Entwickler tun sollte) festlegen. Und zu diesem Entwurf gehört nun mal auch, dass man festlegt, was der Anwender NICHT tun darf. Um ein ganz minimales Beispiel zu nennen, du hast ne Klasse User mit Vorname und Nachname. Du könntest nun natürlich das ohne Properties machen und direkt drauf schreiben lassen. Aber wie stellst du dann sicher, dass der Anwender keinen Mist einträgt? Oder wenn du nur bestimmte Namen zulassen willst? Das geht nur, wenn du private Variablen erstellst und das Setzen über den Setter geschieht, der dann überprüft, ob der Name überhaupt gültig ist. Das ist aber nur ein ganz einfaches Beispiel.

Es gibt aber weitere Vorteile:

- Ist alles public, dann sieht der Anwender viel mehr Funktionen, die meisten davon wahrscheinlich Hilfsfunktionen die er nicht nutzen soll oder braucht, das verwirrt und macht die API unnötig kompliziert. Man will es dem Anwender ja möglichst einfach machen und ihm das Leben nicht unnötig schwer machen. Zudem könnte ein Anwender, wenn er ungünstig irgendwelche Funktionen aufruf, das Objekt irgdenwie in einen ungültigen Zustand bringen. Willst du das alles abfangen? Und vor allem wo, denn die Problem müssen sich ja nicht zwingend unmittelbar zeigen (wenn der Anwender zum Beispiel einfach eine Variable auf null setzen und viel später erst fliegt ne Exception) Ist doch viel einfacher für dich als Entwickler wenn du es gleich von vorne herein sperrst, so dass er die Funktionen die er nicht nutzen soll auch garnicht nutzen kann...oder trifft der nächste Punkt zu?

- Wie du gesagt hast, wenn er was macht was er nicht soll, dann fliegen halt Exceptions...damit machst du es dir sehr einfach, läuft was schief, dann willst du die Schuld von dir abwälzen und auf den Anwender abschieben, er hätte ja die Funktion nicht verwenden sollen. In einer guten Bibliothek kennzeichnen sich Funktionen, die der Anwender nie-nicht verwenden soll, dadurch, dass er sie von vorne herein garnicht aufrufen kann, weil sie eben private ist...und der nächste Punkt schließt sich gleich an:

- klar muss der Anwender nicht ein "DAU" sein...aber auch einem fähigen Anwender muss man doch das Leben nicht unnötig schwer machen in dem Sinne, dass er sich durch zig Dokumentationen und APIs (die dann DU schreiben musst) wälzen muss um zu wissen, welche Funktionen für ihn gedacht sind und welche nicht? Oder würdest du verlangen, dass sich ein Anwender durch deinen Quellcode wühlt, um zu begreifen, was er darf und was er besser lassen sollte? Abgesehen davon, dass unter diesen Umständen die meisten Leute, die nicht gerade Programmier-DAUs sind, deinen Code garnicht verwenden sondern lieber was eigenes schreiben, würde jeder der Ahnung von Softwarequalität hat diese Philosophie mit mangelhaft bewerten. Also zertifiziet bekommst du auf diese Art und Weise zu Recht null.

- Wenn du eine Klasse "PizzaBäcker" hast mit einer Liste Zutaten und der Funktion BackePizza(), dann soll vielleicht der Anwender garnicht wissen dürfen, was denn in der Zutaten-Liste ist, oder welche Unterschritte notwendig sind um die Pizza zu backen...er soll einfach nur das Ergebnis bekommen. Oder noch schlimmer, wenn du eine Art Shop hast mit einer Artikelverwaltung, stell dir mal vor, ein Anwender könnte den Preis eines Artikels einfach so ändern...

Des weiteren gehst du immer davon aus, dass andere den Quellcode editieren können...ich weiß nicht an welchen Projekten du gearbeitest hast, aber in den Projekten in denen ich arbeite hält man die abgeschlossenen Dlls möglichst klein (und wiederverwendbar), nach außen gibt es nur klar definierte Schnittstellen (müssen nicht mal unbedingt Interfaces sein). Und in Dlls kann niemand so einfach rumeditieren, die verwendet man nur in anderen Projekten. Das muss man auch garnicht, wenn man von vorne herein geplant hat, was ein Anwender mit einer Klasse machen darf.

gruß
Ringelsocke


----------

