programmierBar

Dann finde ich das "All Rights Reserved" persönlich besser.

Das ist aber relativ unsagend ;) Welche Rechte hat man da reserviert? Der Copyright-Vermerk - besser im Deutschen das Urheberrecht, das ist was grundlegend anderes - ist Pflicht, wenn man auf seine Rechte verweisen möchte. Wenn man "All Rights Reserved" schreibt, muss noch ein Kopier- und Vervielfältigungs-Verbot vermerkt werden!
 
Und wie schreibe ich das mit dem Urheberrecht auf? Reicht da ein "(c)"?

@Alex: Was es nicht alles gibt …
 
Und wie schreibe ich das mit dem Urheberrecht auf? Reicht da ein "(c)"?

Das Urheberrecht kannst und brauchst du nicht aufschreiben. Das ist ein Recht das du nicht abtreten kannst! Du bist und bleibst der Urheber! Clicker dich mal durch Wikipedia, um ein grobes Verständnis von Copyright/Copyleft/Urheberrecht/Lizenzen zu erhalten.
 
plattformunabhängig vs. usability

Hallöle,

ich habe folgendes Problem:
Nächstes Semester werden wir in der FH mit Java/Swing einen Texteditor entwickeln. Nichts weltbewegendes, allerdings stelle ich mir dabei folgende Frage:
Korrigiert mich, wenn ich Blödsinn erzähle, aber Usability besagt doch (indirekt auch), dass man dem Benutzer eines Programms eine gewohnte Umgebung bieten sollte, damit er sich möglichst schnell zurechtfindet - andernfalls bräuchte man ja beispielsweise gar keine Human Interface Guidlines.
Das bedeutet, dass das Programm idealerweise im typischen Look&Feel des Betriebssystems kommen sollte (das war ja z.B. ein wichtiger Kritikpunkt an der ersten Windowsversion von Safari).

Nun setzt sich ja in der Windowswelt gerade die Ribbons-Oberfläche durch, während wir unter Mac die "unified Toolbar" (inkl. textured buttons etc.) haben und Linux die klassische Toolsbar nutzt (ohne textured buttons).

Mal abgesehen davon, dass Ribbons in Swing noch im Nebula-Projekt stecken: Wie soll man das denn nun plattformunabhängig programmieren? Wenn man jetzt anfängt, die drei Oberflächen einzeln zu programmieren, kann man sich die Plattformunabhängigkeit auch sparen und gleich Plattformspezifisch arbeiten (dann braucht man nicht mal mehr Java). Wenn man eine einheitliche Oberfläche macht, geht es aber auf Kosten der Usability, oder nicht?

Gruß, Micha
 
Tja, eine Kröte muss man schlucken. Entweder das Programm lässt sich unter "allen" Plattformen ausführen, unterstützt dafür nicht die neusten und tollsten Funktionen oder man muss für einzelne Plattformen Anpassungen im Code vornehmen. Für MacOS ist das übrigens nicht so kompliziert, das Menü in die Menüleiste zu bekommen.

Plattformübergreifend heißt für mich übrigens nicht, dass der gesamte Code auf allen Systemen funktioniert. Das Programm muss nur auf allen Systemen ausführbar sein. Abfragen, welches System gerade darunter Läuft und entsprechende Anpassungen zur Compile- oder Laufzeit sind erlaubt. Ein Programm besteht ja nicht nur aus der grafischen Oberfläche. Es soll doch nicht nur anzeigen, sondern dabei auch sinnvolles tun. Der Code dürfte sich nicht ändern.
 
Backend bleibt gleich, Frontend wäre dann ein anderes.

Wo kann ich mehr zu diesen verschiedenen Toolbars finden?
 
Ist bei mir schon eine weile her, aber im Endeffekt waren das glaub ich irgendwelche Properties, die man setzen musste. Dann wußte die Apple-VM damit umzugehen.
 
Die Einige entsprechenden Properties gibts in der Apple Dokumentation unter Java Runtime System Properties.

Zuständig für die Unified Toolbar wäre theoretisch die Property "apple.awt.brushMetalLook", die aber unter JDK6 Darstellungsprobleme macht (unter AWT könnte es funktionieren, als Swing Komponente funktioniert es definitiv nur bis JDK5, also mit entsprechenden Einstellungen bis Leopard, nicht im Snow Leopard!). Wenn dein Programm so richtig 100% Mac-typisch aussehen soll, musst du auf der Toolbar "Textured Buttons" benutzen (siehe z.B. im Finder). Der einzige Artikel, den ich gefunden habe, der überhaupt darauf eingeht, ist "Sexy Swing App - the unified Toolbar" (schon etwas älter, damals gabs noch kein JDK6).

Als (umständliche) Alternative bietet Apple noch irgendwelche Geschichten über das JNI an, aber so fit bin ich glaub ich noch nicht.

Für MacOS ist das übrigens nicht so kompliziert, das Menü in die Menüleiste zu bekommen.
Schwieriger wird es da schon beim Verhalten des Programms, wenn alle sichtbaren Fenster geschlossen sind. Und richtig Aufwändig wird die systemabhängige Unterscheidung zwischen Ribbons und Toolbar... mag sein, dass das Programm dadurch immer noch plattformübergreifend ist, aber wenn ich an den Programmieraufwand denke... eine Arbeitserleichterung gegenüber C++ Code sieht da anders aus.
Bei Ribbons erscheint es noch nicht schlimm, weil die unter Windows noch in den Kinderschuhen stecken, aber findest du z.B. Programme unter Mac mit nicht-unified Toolbar nicht irgendwie etwas befremdlich (z.B. OpenOffice)? Verknüpft mit der teils schrecklichen Bedienungsführung ist OpenOffice für mich ein klassisches Beispiel für schlecht-plattformunabhängige Software... Mh, ich war halt noch nie ein Fan von "Form-follows-function" ;) Lieber intuitiv, gut durchdacht und ansprechend gestaltet^^

Plattformunabhängigkeit bekommt man halt leider auch nicht umsonst...
 
Bei Java ging es doch nie darum, dass alles auf allen Plattformen korrekt angepasst aussieht. Das ist ein hoffnungsloses Unterfangen. Vielmehr ging es darum, dass der Bytecode auf allen Systemen ausführbar ist.

Plattformunabhängig ist für mich übrigens nicht dass das Compilat auf mehreren Plattformen ausführbar ist, sondern dass ich den geschriebenen Code auf mehreren Plattformen zum Laufen bekomme, ohne ihn verändern zu müssen. Das betrifft also auch C/C++ und andere Sprachen, deren Quellen in nativen Maschinencode übersetzt werden.
 
Wenn ich mich nicht irre, bist du mehr oder minder Java Entwickler (oder programmierst zumindest viel mit Java). Was ist deiner Meinung denn der Hauptvorteil von Java gegenüber C++? Warum entwickelst du in Java und nicht in C++? (hoffentlich kommt jetzt nicht "weil der Arbeitgeber das will" ;-) )
(edit: ich werde keinen Flame anfangen, keine Angst. Will nur mal deine Meinung als "Profi" hören)
 
Zuletzt bearbeitet:
Oh du irrst dich. ;) Derzeit programmiere ich viel in Python, davor in Java, C++, C, PHP alles etwa in gleichen Teilen.

Java war der Wunsch des Arbeitgebers im letzten Projekt. Das hat mich aber relativ wenig gestört. Zu der Zeit als das Projekt angefangen wurde, war Java eine der fortschrittlicheren Sprachen. Das Produkt was wir damals entwickelt haben, hat auch erzwungen, dass eigener Code zur Laufzeit erzeugt und in die Applikation eingebunden werden konnte. Mit C/C++ war das nicht möglich und die meisten anderen Sprachen, waren zu langsam weil Interpretersprachen. Zur Erklärung: Das war ein verteilter Application-Container, basierend auf einem selbstentwickelten Komponentenframework. Man hat also Komponenten der Anwendung beschrieben, die Verbindungen untereinander beschrieben (modelliert), implementiert und dann dem Container vorgeworfen. Der hat den Gluecode erzeugt, welcher die Komponenten miteinander auf Codebasis verbindent, die Komponenten miteinander verlinkt und auf den Knoten gestartet. Und wieso jetzt in gleichen Teilen auch C/C++, PHP, Delphi/Pascal... ? Ja weil die aus den Komponenten generierte Anwendung auch als einfache (lokale) Anwendung verknüpft werden konnte und dann ohne den ganzen Container-Klimbim lief. Das ging mit den anderen Sprachen sehr gut. Es wurde nur Gluecode erzeugt und dann statisch mit den Bibliotheken und dem Businesscode der Komponenten verknüpft.

Lange Rede, kurzer Sinn: Es gibt nicht "die Sprache", wie es für einen Schlosser nicht "das Werkzeug" gibt. Eine Programmiersprache ist nur ein Tool. Jede Sprache hat ihren Charme und ihre Vorteile, aber auch Nachteile. Man sollte bei einem Projekt, das man anfängt abwägen, welche Sprache sich am Besten eignet. Man sollte sich aber nicht der Illusion hergeben, dass man für ein Projekt extra eine Sprache lernt, wenn man noch nicht allzu viel Erfahrung mit mehreren verschiedenen Sprachen hat. Dann ist man weniger mit dem Projekt als mehr mit der Sprache beschäftigt und macht unter Garantie größere Fehler.

Ich hoffe, das war nicht allzu verwirrend. Da Oben sind viele Buzzwords gefallen.

Edit: Begriff Komponente: logisch abgeschlossene Einheit mit mindestens einer Schnittstelle nach Außen (Interface). Implementierungsdetails werden (für gewöhnlich) nach Außen hin versteckt.
 
Oop != oop?

@_ebm_
Hui, das klingt echt spannend. Verstehe ich das richtig, dass der Container den Gluecode selbst generiert hat? D.h. doch, dass die Verbindungen zwischen den Komponenten vom Container generiert wurden, also kann man quasi einfach die nötigen Verbindungen vorgeben und bekommt ein fertiges Programm erzeugt!? Der Gluecode wird also in Java erzeugt und dann mit Hilfe von anderen Sprachen (C/C++ etc.) als unabhängiges Programm "ausgegeben"? krass... :eek:

wieder @all: OOP != OOP?
Bzgl. der Sprachenvielfalt hätte ich dann auch noch eine Frage, die mir auf der Zunge liegt: Ich lerne ja wie gesagt Java/Swing in der FH. Früher in der Schule hatte ich auch C++ und weil mich C++ sehr interessiert, schnuppere ich trotz Zeitmangel immer mal wieder rein. Objective-C/Cocoa hab ich auch mal angekratzt... Das sind drei objektorientierte Sprachen, und irgendwie werde ich das Gefühl nicht los, dass diese Sprachen nicht nur hier und da ein paar Schönheits-OPs bekommen haben, sondern ziemlich grundlegend anders sind - fast, als wenn OOP != OOP.

Das fängt mit C++ an: Mehrfachvererbung, C++ killed the get & set accessors, seitenlange Diskussionen in C++ Foren darüber, dass Klassen-Attribute public sind (?? aus Java und ObjC kenne ich nur private Attribute!) und und und...

Objective-C bringt schon wieder vollkommen neue Muster ins Spiel, z.B. die scheinbar systematische Ignoranz von Polymorphie: In Obj-C schreibt man lieber drei komplett unterschiedliche Methoden (setPointToX:Y:, setPointToCenterOf:, setPointToOrigin: ) statt einfach eine, die überladen wird, wie in Java (setPoint(int x, int y), setPoint(obj centerOf), setPoint()) [Die Beispiele sind an den Haaren herbeigezogen, aber ich glaube, es ist verständlich was ich meine...]

Gibt es ein gutes Buch/Tutorial/etc., dass solche Unterschiede wenigstens zwischen Java und C++ mal behandelt? Vielleicht ein Buch über C++ für Java-Entwickler oder sowas?
Es geht mir hier eben auch darum, mal den "Programmierstil" von C++ zu lernen, statt ein Buch zu haben, was schon wieder bei if-else und while anfängt und zum 100. mal den Anfängerkram durchrührt....

Wäre toll, wenn jmd. so etwas kennt.

Danke, Micha
 
Naja, im Verteilungsfall waren theorethisch mehrere Sprachen vorgesehen. Sprich der eine Container wäre für C++-Komponenten gewesen, ein anderer für Java. Die hätten sich dann über ein Remoting Framework wie CORBA, SOAP oder REST unterhalten.

Nochmal zur Klärung. 1. Schritt war der architekturelle Entwurf der Anwendung. Man hat fachlich Bereiche (Komponenten) identifiziert, die sich einzeln und in sich abgeschlossen entwickeln lassen. Diese Komponenten bieten Schnittstellen für andere Komponenten an (zeigen also Facetten ihrer Fähigkeiten nach außen). Andere Komponenten docken sich dort an. Bekannt sind nur diese Facetten. Implementiert wurde hier noch nicht. Wenn das Strukturgerüst der Anwendung fertig ist, wird implementiert. Dabei sinkt die Komplexität bei der Entwicklung, da nur einzelne einfachere Bereiche betrachtet werden. So lassen sich eben ziemlich große komplexe Systeme beschreiben und umsetzen, ohne dass alles aus dem Ruder läuft.
Nachdem die Komponenten implementiert wurden, werden sie zusammen mit ihren Metadaten (Schnittstellenbeschreibung, Bibliotheksabhängigkeiten, Verknüpfungsdaten, Ressourcen,...) einem Codegenerator vorgeworfen und der übersetzt die Komponenten in die fertige Anwendung. Das kann verteilt in mehreren Containern passieren.
Dann wird Gluecode erzeugt, welcher die Verknüpfung übers Remoting realisiert, das kann aber - ohne die Implementierung der Komponente zu ändern - auch eine lokale Bindung erzeugen. Die Komponentenimplementierungen können zu dem Zeitpunkt sogar schon in Binärform vorliegen. Es gab da nämlich mal die wahnwitzige Idee, einen Markt für Komponenten zu eröffnen. Leider fand und findet die Industrie das nicht sonderlich sexy. Übrig geblieben ist im Endeffekt nur das Herunterbrechen der Komplexität einer großen Anwendung in ihre Teilprobleme.

OOP != OOP. Ja, richtig. Aber aus der reinen Lehre heraus vermischst du da was. OOP bedeutet ja Obect Oriented Programming. Da ist noch keine Aussage zu der Sprache getroffen. In dem oben erwähnten Projekt haben wir auch in MISRA-C (einem sehr stark eingeschränkten C89-Dialekt für die Automobilindustrie) objektorientiert programmiert. Das war zwar etwas aufwändiger, geht aber.

Dass es jetzt verschiedene Sprachen gibt, die auch unterschiedliche Ansätze bzw Paradigmen der OOP in ihrer Syntax unterstützen, ist eine andere Sache. C++ und Java sind sich da bis auf die Mehrfachvererbung sicherlich noch sehr ähnlich. Sie sind beide statisch typisiert. Anders sieht es mit Objective-C oder Python aus. Die Sprachen stammen von ihrer Idee her von Smalltalk ab, einer dynamisch typisierten Sprache. Wo ist der Unterschied? statisch typisierte Sprachen prüfen zur Compile-Zeit ob ein Objekt eine bestimmte Schnittstelle unterstützt. Tut sie das nicht, bricht der Vorgang ab. Dynamischen Sprachen reicht es, dass ein Objekt eine bestimmte Funktion mit einer festgelegten Signatur unterstützt. Die Überprüfung findet auch zur Laufzeit statt. Das nennt man auch etwas lakonisch Duck-Typing ("It walks like a duck, it quaks like a duck, so it is a duck").

Zur Diskussion der Getter und Setter. Die kamen in Java auch nur bei den Beans zum Einsatz. Ich bin strikter Verfechter des Grundsatzes, dass Getter evil sind und Setter faktisch unnötig, und das in jeder Sprache!. Warum? Wenn ich ein Feld an einem Objekt setzen will, setze ich das Feld. Wenn ich beim Setzen noch mehr mache, als das Feld zu setzen, ist es kein Setter mehr, ergo: unnötig. Getter wiederum zeigen, dass ich außerhalb des Objektes ein Implementierungsdetail benötige. Das zeigt mir aber, dass mein Design schlecht ist. Was interessiert mich außerhalb eines Objektes ein bestimmtes Feld, dass dort verwendung findet? Besser ist es doch, den die gewünschte Arbeit machen zu lassen, der davon ahnung hat, in diesem Fall das Objekt mit dem Feld, anstatt es außerhalb zu manipulieren. Das fällt einem spätestens dann auf die Füße, wenn die Implementierung des Objektes mit dem Feld nicht von einer Manipulation von Außen ausgeht. ("Der Getter sollte ja nur den Status zurückgeben, ein Programmierer verändert aber jetzt das Feld -> call by reference -> das Objekt verändert sich") Und dann knallt es weil es zu Seiteneffekten kommt.

Phoo, harter Tobak am Morgen.

Bücher? Tutorials? Hm.. Ich hau mal mit der großen Keule drauf. Lerne die Fähigkeiten der benötigten Sprache und siehe zu, wo du Design Pattern und Clean Code (autsch , ja wirklich!) anwenden kannst. Eigentlich sollte beides immer gehen.
 
Danke schön für die Erklärungen, ich muss meine Antwort gerade kurz halten, deshalb kann ich nur auf das wichtigste eingehen und evtl. später was nachschieben.

Ich bin strikter Verfechter des Grundsatzes, dass Getter evil sind und Setter faktisch unnötig, und das in jeder Sprache!. Warum? Wenn ich ein Feld an einem Objekt setzen will, setze ich das Feld. Wenn ich beim Setzen noch mehr mache, als das Feld zu setzen, ist es kein Setter mehr, ergo: unnötig.
Das ist genau das Hauptargument gegen Setter. Was ich mich dabei immer frage: Wer sagt, dass man in Settern nicht mehr machen darf? Wer hat das denn so definiert? Beispielsweise ein Setter, der zunächst überprüft, ob die übergebene Variable im Wertebereich liegt und zur Not einen Fehler auslöst - warum ist dies kein Setter?

Getter wiederum zeigen, dass ich außerhalb des Objektes ein Implementierungsdetail benötige. Das zeigt mir aber, dass mein Design schlecht ist.
Einfaches Gegenbeispiel: Ich habe zwei Klassen, eine "Stundent", eine "Vorlesung". Der Student hat eine Matrikelnummer, das ist eine Eigenschaft von Student, für die Student verantwortlich ist, sie muss also in Student stehen. Die Vorlesung speichert nun die Studenten, die sie besuchen, da dies eine Eigenschaft von der Vorlesung ist (1:n Beziehung, oder wenn du magst, kannst du auch eine n:m Beziehung daraus machen). Nun sollen sich natürlich nur Studenten zur Vorlesung eintragen können, die auch dazu berechtigt sind, also braucht die Vorlesung die Matrikelnummer.... klarer Fall für einen Getter (sofern die Attribute privat sind.) Deinem Argument nach wäre das Design schlecht, da die Vorlesung ein Implementierungsdetail, nämlich die Matrikelnummer, braucht. Wie würdest du diese (zugegebenermaßen etwas gestellte) Aufgabe lösen? Mit public Attributen? Warum trifft dein Argument nun auf deine public-Attribute nicht zu?

Was interessiert mich außerhalb eines Objektes ein bestimmtes Feld, dass dort verwendung findet? Besser ist es doch, den die gewünschte Arbeit machen zu lassen, der davon ahnung hat, in diesem Fall das Objekt mit dem Feld, anstatt es außerhalb zu manipulieren. Das fällt einem spätestens dann auf die Füße, wenn die Implementierung des Objektes mit dem Feld nicht von einer Manipulation von Außen ausgeht. ("Der Getter sollte ja nur den Status zurückgeben, ein Programmierer verändert aber jetzt das Feld -> call by reference -> das Objekt verändert sich") Und dann knallt es weil es zu Seiteneffekten kommt.
Ist das nicht gerade der Vorteil von Gettern? Bei public-Attributen (die einzige mir bekannte Alternative zu Gettern) kannst du das "Feld" erst recht ändern!? Dazu gibt es ja dann das immutable Pattern, oder?
 
Danke schön für die Erklärungen, ich muss meine Antwort gerade kurz halten, deshalb kann ich nur auf das wichtigste eingehen und evtl. später was nachschieben.

Kein Problem, geht mir ähnlich ;) Also auch nur in aller Kürze..


Das ist genau das Hauptargument gegen Setter. Was ich mich dabei immer frage: Wer sagt, dass man in Settern nicht mehr machen darf? Wer hat das denn so definiert? Beispielsweise ein Setter, der zunächst überprüft, ob die übergebene Variable im Wertebereich liegt und zur Not einen Fehler auslöst - warum ist dies kein Setter?

Validation gehört bei mir grundsätzlich zum guten Ton, es bleibt also ein Setter ;) Trotzdem kannst du dadurch Nebeneffekte provozieren. Beschränkung auf Wertebereich reicht eben nicht, auch ob derjenige das überhaupt darf, zählt.

Einfaches Gegenbeispiel: Ich habe zwei Klassen, eine "Stundent", eine "Vorlesung". Der Student hat eine Matrikelnummer, das ist eine Eigenschaft von Student, für die Student verantwortlich ist, sie muss also in Student stehen. Die Vorlesung speichert nun die Studenten, die sie besuchen, da dies eine Eigenschaft von der Vorlesung ist (1:n Beziehung, oder wenn du magst, kannst du auch eine n:m Beziehung daraus machen). Nun sollen sich natürlich nur Studenten zur Vorlesung eintragen können, die auch dazu berechtigt sind, also braucht die Vorlesung die Matrikelnummer.... klarer Fall für einen Getter (sofern die Attribute privat sind.) Deinem Argument nach wäre das Design schlecht, da die Vorlesung ein Implementierungsdetail, nämlich die Matrikelnummer, braucht. Wie würdest du diese (zugegebenermaßen etwas gestellte) Aufgabe lösen? Mit public Attributen? Warum trifft dein Argument nun auf deine public-Attribute nicht zu?

Ganz Einfach. Dein Beispiel ist schlecht! Der Student ist ein Value Object, nenne es meinetwegen auch C-Struct. Außerdem willst du nicht von außen die Liste der immatrikulierten Studenten modifizieren. Das wird kein Prof mögen. Du möchstest, dass ein Student sich in der Vorlesung einschreibt. Ob er damit mit Blut, seinem Namen oder seiner Imma-Nummer unterschreibt, ist der Vorlesung egal.

Code:
struct Student {
  string firstname;
  string lastname;
  string imma_nr;
};

interface Vorlesung {

  ...

  void einschreiben(Student student) raises EinschreibenFehlgeschlagenException;

  ...

};

Auf diese Art interessiert dich beider Implementierungsdetail nicht und du hast keinen Setter benutzt, Getter auch nicht! Wie die Vorlesung jetzt die Studenten führt, ist belanglos, genauso ob die Vorlesung noch sonstige Validierungen vornimmt!

Ist das nicht gerade der Vorteil von Gettern? Bei public-Attributen (die einzige mir bekannte Alternative zu Gettern) kannst du das "Feld" erst recht ändern!? Dazu gibt es ja dann das immutable Pattern, oder?

Dann willst du es aber auch ändern. Wenn du anfängst Funktionale Klassen mit Value-Objekten zu mischen, machst du was falsch. Dann vermischst du Verantwortlichkeiten!

Gruß Carsten
 
Objective-C bringt schon wieder vollkommen neue Muster ins Spiel, z.B. die scheinbar systematische Ignoranz von Polymorphie: In Obj-C schreibt man lieber drei komplett unterschiedliche Methoden (setPointToX:Y:, setPointToCenterOf:, setPointToOrigin: ) statt einfach eine, die überladen wird, wie in Java (setPoint(int x, int y), setPoint(obj centerOf), setPoint()) [Die Beispiele sind an den Haaren herbeigezogen, aber ich glaube, es ist verständlich was ich meine...]
Das ist keine Ignoranz, das geht einfach nicht anders, da ObjC dynamisch Typisiert ist und es deswegen für den Compiler unmöglich ist, die richtige Methode auszuwählen. Was du machen kannst ist dir eine setPoint:-Methode zu basteln und dann dort abfragen, was für einen Typ dein Objekt hat. Das ist aber hässlich und sollte vermieden werden. Da ist es eleganter verschiedene Methoden zu implementieren, die sich nur nach dem Verhalten eines Objektes richten und nicht nach dem Typ.



Zur Diskussion der Getter und Setter. Die kamen in Java auch nur bei den Beans zum Einsatz. Ich bin strikter Verfechter des Grundsatzes, dass Getter evil sind und Setter faktisch unnötig, und das in jeder Sprache!. Warum? Wenn ich ein Feld an einem Objekt setzen will, setze ich das Feld. Wenn ich beim Setzen noch mehr mache, als das Feld zu setzen, ist es kein Setter mehr, ergo: unnötig.
Das muss ich mal heftigst widersprechen. Gerade Getter und Setter sorgen dafür, dass man eben keine Implementierungsdetails benötigt. Ohne Getter und Setter kannst du die interne Struktur deines Objektes nicht ändern ohne die Schnittstelle nach außen zu ändern.

Getter wiederum zeigen, dass ich außerhalb des Objektes ein Implementierungsdetail benötige. Das zeigt mir aber, dass mein Design schlecht ist. Was interessiert mich außerhalb eines Objektes ein bestimmtes Feld, dass dort verwendung findet?
Dummes Beispiel: Ich habe ein Benutzer-Objekt und will an die E-Mail-Adresse. Das Benutzer-Objekt ist ein guter-Ort die Mailadresse aufzubewahren. Das Benutzer-Objekt sollte aber nicht dafür zuständig sein Emails zu verschicken, einen mailto-Link zu zeichen. Oder sonst sämmtliche Aktionen durchzuführen für die man die Mail-Adresse braucht. Ergo: Ich brauche das Feld außerhalb des Objektes. Also brauche ich einen Getter.

Und nein, das Benutzer-Objekt ist nicht zwingend ein „Value-Objekt“ genausowenig wie das Student-Objekt in Kümmelkorns Beispiel ein „Value-Objekt“ sein muss (was auch immer ein „Value-Objekt“ sein soll, ich vermute du meinst damit Objekte die nur Werte Speichern und sonst zu nichts gut sind).

Code:
interface Vorlesung {

  ...

  void einschreiben(Student student) raises EinschreibenFehlgeschlagenException;

  ...

};
Wie kommst du da jetzt ohne Getter an eine Liste der Studenten ran?

Die einzige Sprache bei der man wirklich keine Getter und Setter braucht ist Python. Aber das liegt daran, dass dort der Attributzugriff sowieso nicht direkt erfolgt und immer eine weitere Ebene der Indirektion zulässt.

Andere Sprachen wie Smalltalk oder Scala benötigen sowieso zwingend Getter und Setter weil dort Felder immer private sind.

Dann willst du es aber auch ändern. Wenn du anfängst Funktionale Klassen mit Value-Objekten zu mischen, machst du was falsch. Dann vermischst du Verantwortlichkeiten!
Dann hast du OOP nicht verstanden. Objekte haben einen inneren Zustand und ein Verhalten. Da macht man nichts falsch wenn man das „vermischt“.
 
Zuletzt bearbeitet:
Das muss ich mal heftigst widersprechen. Gerade Getter und Setter sorgen dafür, dass man eben keine Implementierungsdetails benötigt. Ohne Getter und Setter kannst du die interne Struktur deines Objektes nicht ändern ohne die Schnittstelle nach außen zu ändern.

Nochmal: Was interessiert dich der innere Zustand eines Objektes außerhalb? Die Felder sind dazu da, damit das Objekt eben seinen eigenen Zustand verwalten kann! Wozu benötigst du denn den inneren Zustand? Das Objekt weiß darüber viel besser bescheid, wie es diesen verwalten soll!

Dummes Beispiel: Ich habe ein Benutzer-Objekt und will an die E-Mail-Adresse. Das Benutzer-Objekt ist ein guter-Ort die Mailadresse aufzubewahren. Das Benutzer-Objekt sollte aber nicht dafür zuständig sein Emails zu verschicken, einen mailto-Link zu zeichen. Oder sonst sämmtliche Aktionen durchzuführen für die man die Mail-Adresse braucht. Ergo: Ich brauche das Feld außerhalb des Objektes. Also brauche ich einen Getter.

Richtig, Der Nutzer ist eine Entität (das meinte ich mit Value Object). Er hält nur Daten vor. Ein Email-Service bekommt also das Nutzer-Objekt und greift sich das Email-Feld des Nutzers. Wie er das dann auswertet ist seine Sache. So kann der Service dann meinetwegen auch noch den Namen davor setzen oder eben nicht. Das interessiert von außen nicht.

Und nein, das Benutzer-Objekt ist nicht zwingend ein „Value-Objekt“ genausowenig wie das Student-Objekt in Kümmelkorns Beispiel ein „Value-Objekt“ sein muss (was auch immer ein „Value-Objekt“ sein soll, ich vermute du meinst damit Objekte die nur Werte Speichern und sonst zu nichts gut sind).

Dann hast du OOP nicht verstanden. Objekte haben einen inneren Zustand und ein Verhalten. Da macht man nichts falsch wenn man das „vermischt“.

Doch und genau das meinte ich. Ich habe Objekten nie abgestritten, dass sie einen Zustand haben. Der gehört aber dem Objekt. Spätestens wenn du eine Komponente hast, an die mehrere andere Komponenten andockst, möchstest du nicht, dass die andockenden Komponenten für die Konsistenz der "Service"-Komponente verantwortlich sind. Das ist einzig und allein diese Komponente!

Getter sind doch dafür da, einen Teil des Zustandes eines Objektes nach außen hin zu reichen. Dieser ist dann frei veränderbar (abgesehen von immutable, was eher eine Krücke ist um schlechten Programmierstil zu verschleiern). Wenn du möchtest, dass dieses Feld für was auch immer verwendet wird, lass es das Objekt machen, das dieses Feld gehört. Es weiß am besten damit umzugehen! Und du musst dich nicht darauf verlassen, dass die Implementierung dieses Objektes dieses Feld für immer und alle Zeit besitzt. Wenn dem nicht mehr so sein sollte, widerspiegelt der Getter nicht mehr das, was er mal versprochen hat. Die Methode tut etwas anderes als der Name verspricht!

Ja und zu den Settern genau das Gleiche. Warum willst du den Zustand eines Objektes von außen manipulieren? Wenn das in einer multi-threaded-Umgebung mehrere Objekte in verschiedenen Threads tun, knallt es sehr schnell.. Und jetzt bitte nicht sagen, das macht man doch eh nicht. Anwendungen wachsen. Anforderungen ändern sich..

Nachtrag: Teilen sich Objekte einen State, ist dieser Bestandteil eines solchen VO wie ich erwähnt hatte. Er ist Mediator zwischen den Objekten und stellt die Konsistenz sicher.

Noch etwas: Ich habe OOP verstanden. Und ich habe defensive Programmierung verstanden... Danke der Nachfrage..
 
Zuletzt bearbeitet:
Nochmal: Was interessiert dich der innere Zustand eines Objektes außerhalb? Die Felder sind dazu da, damit das Objekt eben seinen eigenen Zustand verwalten kann! Wozu benötigst du denn den inneren Zustand?
Nochmal: Mich interessiert der innere Zustand nicht. Deswegen Getter. Damit bekomme ich Informationen aus dem Objekt raus, ohne den internen Zustand kennen zu müssen. Beispiel:

Code:
class Benutzer {
     public string VollständigerName() {
          if(spitzname) return name + " '" + spitzname +  "' " + nachname;
          return name + " "  + nachname;
     }
}
Es wäre nicht Aufgabe der Mailklasse den vollständigen Namen des Benutzers zusammenzustückeln.

Was ist dein
Code:
void einschreiben(Student student) raises EinschreibenFehlgeschlagenException;
denn anderes als ein Setter?

Wieso willst du da ran?
Willst du etwa dass die Vorlesung für sämtliche Aktionen zuständig ist, die mit der Liste der Studenten möglich ist? Also drucken, als HTML ausgeben, als PDF ausgeben, per Mail an den Dozenten verschicken? Dann muss man für jede neue Aktion das Objekt verändern. *DAS* ist schlechtes Design. Da landen wir beim gleichen Problem wie beim Benutzer-Objekt. Willst du jetzt die Vorlesung auch zu einer Entität degradieren und die Logik wieder an eine anderes Klasse delegieren? Da dreht man sich nur wieder aufs neue im Kreis.

Ja und zu den Settern genau das Gleiche. Warum willst du den Zustand eines Objektes von außen manipulieren? Wenn das in einer multi-threaded-Umgebung mehrere Objekte in verschiedenen Threads tun, knallt es sehr schnell.. Und jetzt bitte nicht sagen, das macht man doch eh nicht. Anwendungen wachsen. Anforderungen ändern sich..
Wenn du den Zustand eines Objektes von außen nicht manipulieren willst, dann darf keine einzige Methode deiner Klasse Parameter erwarten, denn jede könnte den Zustand deines Objektes ändern. Nein du darfst noch nicht einmal Methoden ohne Parameter aufrufen, denn die können auch den internen Zustand eines Objektes verändern und da knallt es auch mit Threads.

Ich verstehe dich da nicht, es geht fast immer da drum den internen Zustand eines Objektes zu manipulieren. Wie willst du zu einer Liste ein neues Objekt hinzufügen wenn du den Zustand nicht verändern darfst?

Edit: Irgendwie hab ich das Gefühl wir meinen verschiedene Sachen, aber ich habe nicht die geringste Vorstellung was du meinst.
 
Zuletzt bearbeitet:
Zurück
Oben Unten