Wie kommt man zu Klassen in Java? [] (Wie kommt man zu Klassen in Java?), Teilnehmerfrage, Seite 723069
https://www.purl.org/stefan_ram/pub/klassen_java (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
Java-Kurs

Wie kommt man zu Klassen in Java ?

Wie kommt man zu Klassen? 

Frage eines Kursteilnehmers  (2014-12)

(Die Frage ist so zu verstehen, daß gefragt wird, wie man ein Programm mit mehreren  Klassendeklarationen schreibt, und wie man dabei entscheidet, wie viele Klassendeklarationen dies sein sollen und wie sie deklariert werden sollen.)

Jeder Objekttyp wird durch eine Klasse festgelegt, entweder eine Klasse aus einer Bibliothek oder einer Klasse aus dem Programm. Man kommt zu Klassendeklarationen, wenn man Objekte eines bestimmten Typs  wünscht und es noch keine dafür passenden  Klasse in der Standardbibliothek oder anderen vertrauenswürdigen Bibliotheken gibt.

(Das Programm enthält dann mehr als eine Klassendeklaration, wenn man dann mehr als eine solche Klassendeklaration benötigt und schreibt.)

I prefer another approach when I do not have experience with a type of program: I start to write the program "procedurally".
One then sees that certain combinations of operations repeat, so these combinations become functions.
Next, one sees that some functions refer to a common state, so these functions then become methods of an object with this state. (Or I follow other patterns that suggest when to write a class, for example, as described in the book "Applying UML And Patterns" by Craig Larman.)

Es geht um objektorientierte Programmierung, nicht um klassenorientierte Programmierung!

Besser fragen: Wie kommt man zu Objekten?

Java  will ja die „objektorientierte Programmierung“ unterstützen und nicht die „klassenorientierte Programmierung“. Die Klassendeklarationen sind in einigen Sprache nur Hilfsmittel, um Objekte zu erzeugen, andere objektorientierte Sprachen kommen ganz ohne Klassendeklarationen aus!

In einem Programm spielen vielleicht zwei verschiedene Objekte mit ein und derselben Klasse eine wichtige Rolle. Wenn man nur an Klassendeklarationen denkt, kann man so etwas gar nicht richtig verstehen.

Objekte sind spezialisierte simulierte Mini-Maschinen, man legt also ein Objekt an, wenn man solch eine Maschine braucht. Wenn man mehrere Objekte braucht, dann verwendet man für sie eine vordefinierte Standardklasse, falls es eine passende gibt. Andernfalls schreibt man nur eine einzige Klassendeklaration für die Objekte, wenn alle Objekte gleichartig sind (gleichartige Felder und Methoden). Nur, wenn die Objekte unterschiedlichen Typ haben sollen (unterschiedliche Felder und Methoden) muß man mehrere Klassendeklarationen schreiben.

Man kommt also zu Klassendeklarationen, wenn man Objekte unterschiedlichen Typs  benötigt. Jeder Objekttyp wird dann durch eine Klassendeklaration festgelegt.

Von Prozeduren zu Objekten

Wenn man eine Prozedur aufruft, die mitzählen soll, wie oft sie aufgerufen wurde, dann ist dies mit einer klassischen Prozedure mit einer lokalen Variablen schwierig, weil die Variable nach dem Ende der Ausführung der Aufrufs wieder verschwindet. Man braucht also etwas wie eine Prozedure, dessen Variablen über den Aufruf hinaus erhalten bleiben: dies ermöglicht eine Objekt, das die Prozedur und eine Variable enthält.

Wenn man eine Prozedur aufrufen will, um eine Variable auf „1“ zu setzen, und eine andere, um dieselbe Variable wieder auf „0“ zu setzen, braucht man zwei Prozeduren, die einen gemeinsamen Zustand teilen: dies ermöglicht eine Objekt, das die beiden Prozeduren und eine Variable enthält.

Man könnte zwar zunächst denken, daß man die Anforderungen auch mit einer globalen Variablen erfüllen könnte, doch zum einen verschlechtern viele globale Variablen die Wartbarkeit eines Programmes und zum anderen lassen bei der Ausführung eines Programmes keine neuen globalen Variablen anlegen, wie bei Objekten. – Das Anlegen neuer Objekte zur Laufzeit wird aber oft benötigt.

Die Klassen sind nur Hilfmittel, um dann zur Laufzeit die benötigten Objekte anlegen zu können.

Gestaltungsfreiheit

Es ist nicht immer eindeutig, wie ein Programm auf mehrere Klassendeklarationen aufgeteilt wird, hierzu gehört auch eine gewisse Gestaltungsfreiheit.

Es gibt nicht immer eine eindeutige Lösung, sondern oft verschiedene Möglichkeiten.

(Bei den später erwähnte Entwurfsmuster und Entwurfsregeln, geht es auch weniger darum, sie alle zu befolgen, sondern eher darum, sie zu kennen, und dann zu wissen, wann es besser ist, sie zu befolgen, und wann nicht.)

Heute braucht man weniger Klassendeklarationen als früher

Gute objektorientierte Programmierung heißt nicht, möglichst viel Klassendeklarationen zu schreiben.

Heute kann man oft Methodenliterale oder -referenzen einsetzen, wo man früher Klassen schreiben mußte. Dann ist es manchmal besser, diese Methodenliterale oder -referenzen zu verwenden als Klassen.

Ältere Lehrbücher früherer Jahrzehnte geben diesen Aspekt noch nicht wieder. Daher ist es nicht verwunderlich, wenn sie mehr Klassendeklarationen in Programmen enthalten.

Wiederverwendung

Falls eine vordefinierte Standardklasse, wie »java.lang.String«, verwendet werden kann, dann keine neue Klassendeklaration schreiben, sondern die Standardklasse für die Objekte verwenden!

(Ausnahme: Man will Standardklassen zu Übungszwecken  nachprogrammieren.)

Lernen aus Quellen

In diesem Kurs wurden schon einige Klassen aus der Standardbibliothek vorgestellt, die als Beispiele dafür dienen können, wie Klassen gestaltet und wie Aufgaben auf mehrere Klassen aufgeteilt werden können.

Weiterlesen! In weiteren Lektionen dieses Kurses hier, wird noch zu der Frage „Wie kommt man zu Klassen?“ Hilfreiches behandelt.

Viele Übungen und Projekte bearbeiten

in Programmierforen lesen/schreiben

Machen Sie sich bewußt, daß Sie schon viele Beispiele von Klassen aus der Standardbibliothek kennen, wie beispielsweise »java.lang.String«, … und orientieren Sie sich beim Schreiben von Klassendeklarationen an diesen Vorbildern

Orientieren Sie sich auch an den Programmbeispielen aus diesem Kurs und aus anderen Quellen

Hilfreich auf diesem Gebiet ist Erfahrung, die man durch das Lösen von Programmieraufgaben gewinnen kann, sowie Lektüre der Literatur zu objektorientiertem Design und Softwarearchitektur

Orientieren an Beispielen: Standardklassen, Lehrbücher, Java-Programme, Quellcode der Standardbibliothek und -demos, Software-Entwurfsmuster aus Literatur (siehe unten, sowie Web)

Teilnahme an Treffen von Java-Benutzergruppen

„Eine Klassendeklaration schreiben“

Wichtig: Wenn eine Aufgabe verlangt, „eine Klassendeklaration zu schreiben“, dann wird damit NICHT ausgeschlossen, daß man zu dieser Klassendeklaration auch noch weitere Hilfsklassendeklarationen schreibt, oft ist diese sogar notwendig oder hilfreich. Es wird auch nicht ausgeschlossen, daß die Klassendeklaration nur klein ist und den größten Teil der Arbeit von einer anderen Klasse (Standardklasse) erledigen läßt, die es schon vorher gab (composition with library classes).

(Dies gilt auch für den Fall, daß man „eine Methodendeklaration schreiben“ soll.)

Dies gilt jedenfalls in diesem Kurs oder bei selbstgestellten Aufgaben. Sonst muß man (beispielsweise in einer Prüfung) gegebenenfalls nachfragen, ob weitere Hilfsklassen ausgeschlossen sind.

Klassen über ihre Felder finden

Falls eine einzelne lokale Blockvariable mit elementaren Typ ausreicht, dann kann man diese verwenden, ohne Objekte einführen zu müssen. Es sollte immer die einfachste  mögliche Lösung bevorzugt werden!

Objekte fassen oft mehrere zusammengehörige Felder zusammen oder werden verwendet, wenn eine Variable länger existieren soll, als der Block, in dem sie erzeugt wurd

Wenn Objekte mit benutzerdefinierten Klassen angelegt werden müssen, kann man zunächst erst einmal gedanklich für jedes Feld eine Klasse definieren.

Nun faßt man alle Felder in einer Klasse zusammen, die zusammengehören.

Nun fügt man Methoden, welche direkt mit diesen Feldern zu tun haben, zu der Klasse hinzu.

Es werden ggf auch noch Felder für Hilfsobjekte, welche von diesen Methoden benötigt werden zur Klasse hinzugefügt und rechtzzeitig initialisiert.

Wann gehören Felder zusammen?

Dies ist etwas vage, weil der Programmier hier tatsächlich eine gewisse Freiheit der Interpretation und Gestaltung besitzt!

Ein Indiz dafür ist, daß Felder zusammengehören ist:

Wann werden Felder werden gemeinsam für eine bestimmte Aufgabe benötigt?

Beispiel (Refaktor)

f( a, x );

f( a, y );

f( a, z );

--->

o = new C( a );

o.f( x );

o.f( y );

o.f( z );

Klassen ohne Felder durch Zusammengehörigkeit von Methoden finden

Es kann auch mal Klassen ohne Felder geben, die zusammengehörige Methoden zusammenfassen.

Klassen durch Zerlegen finden

Bei Klassen mit sehr vielen Feldern und Methoden sollte geprüft werden, ob diese sinnvoll in mehrere kleine Klassen zerlegt werden können

Falls eine Klasse zu groß und dadurch inübersichtlich eird, versuchen in mehrere Klassen zu zerlegen,

Klassen möglichst so universell schreiben, daß sie in anderen Programmen wiederverwendet werden können

universelle Klassen wandern in Bibiliothek

Wenn eine Klasse etwas Universelles und etwas Spezielles enthält, dann möglichst in eine Klasse für das Universelle und eine für das Spezielle zerlegen.

Statische und Nicht-statische Methoden

Manchmal finden sich statische und nicht statische Einträge (Methoden und Felder) gemeinsam in einer Klasse, obwohl sie in manchen Einzelfällen wenig miteinander zu tun haben. Dann wird es manchmal aus übersichtlicher empfunden, solch eine Klasse in zwei Klassen aufzuteilen, deren eine nur die statischen Methoden und deren andere nur die nicht-statischen Methoden enthält.

Klassen als Erweiterung einer einzelnen Methoden

Wenn eine einzelne Methode so erweitert werden soll, daß sie sich bestimmte Informationen über mehrere Aufrufe hinweg merkt, dann kann sie in eine Klasse gepackt werden, deren Objekte im wesentlichen diese Methode repräsentieren (und die benötigten Felder enthalten). Geschichtlich kann man die Entstehung von Klassen in Simula so begreifen.

Klassen durch Anwendung von Software-Entwurfsmuster finden

Siehe Literatur (unten)!

Klassen durch Anwendung von Software-Entwurfsregeln finden

Lesen Sie einige der wichtigsten Regeln für den Entwurf von Software nach:

Treiber identifizeren

Das verallgemeinerter Treiberprinzip (encapsulate change, Protected Variations), rät dazu alles in eine Klasse (oder eine Gruppe von Klassen) auszulagern, was zu ein bestimmten Gerät oder einer Sprache oder einer Schnittstelle gehört, die sich einmal ändern könnte, beispielsweise: Drucker, GUI, natürliche Sprache (Deutsch/Englisch), formale Sprache (HTML, XHTML). Dies kann bei einer „GUI“ auch einmal das „Hauptprogramm“ sein.

Klassen durch monolithisch-prozedurale Programmierung und Refaktoren/Smells finden

Es soll eine Fähigkeit zu einem Programm hinzugefügt werden. Zuerst mit Aufruf vorhandener Methode probieren, falls das nicht geht, Methodendeklaration (einschließlich Hilfsmethodendeklarationen) probieren. Falls das nicht geht, oder zu unübersichtlich, probieren, ob Klassendeklaration hilft.

Eine andere Vorgehensweise, ist es, zunächst erst einmal das ganze Programm in eine Klasse und eine Methode schreiben. Wenn das Programm dann größer wird und der Autor schon einige Erfahrungen durch Lesen von Lehrbüchern und Programmen gesammelt hat, wird ein Punkt kommen, an dem es sich förmlich aufdrängt, bestimmte Teile aus diesem großen Block in eine separate Methode oder Klasse auszulagern, was dann durch Refaktorieren erreicht wird.

Man kann eine große Klassendeklaration durch Zerlegen in mehrere kleinere Klassendeklarationen oft übersichtlicher machen, aber hierfür ist es wichtig, wie genau  die Zerlegung durchgeführt wird! Dies wird in der Literatur zu Entwurfsmustern und Refaktoren erklärt.

Allerdings muß man hierzu eine Buch über Refactoring oder Smells gelesen haben.

Klassen durch reale Objekte finden

Aufgabenstellung Eine Methode soll Züge auf einem Schachbrett akzeptieren bis sie ein Schachmatt erkennt. Falls eine nicht-erlaubter Zug eingegeben wird, soll das Programm eine Fehlermeldung ausgeben und erneut zur Eingabe desselben Zugs auffordern.

Mögliche Gestaltung Bei einem realen Schachbrett gibt es als Objekte die Figuren und das Schachbrett selber. Diese realen Objekte können als Anregung für Objekte in dem Programm verwendet werden. Dabei könnten alle Figuren durch eine Klasse dargestellt werden. Es wäre aber auch möglich, für jeden Typ von Figur eine extra Klasse zu definieren. Bei einigen Klassen, die man auf diese Weise gewinnt, könnte es sich zeigen, daß sie im Programm gar nicht benötigt werden. Umgekehrt, kann es auch günstig sein, in einem Programm Objekte zu verwenden, zu denen es keine reale Entsprechung gibt.

Anmerkungen

Die Frage „Wie kommt man zu Klassen? “ ist gut! Aber warum eigentlich wurde nicht schon gefragt, wie man zu Methodendeklarationen kommt, als die eingeführt wurden? Dies nämlich mindestens ebenso wichtig und sollte vorher verstanden worden sein, da Klassendeklarationen auf Methodendeklarationen aufbauen! Daher wurden Methoden im Grundkurs auch so ausführlich behandelt! Bestimmte Methodenrefaktoren führen direkt zu Klassen! (Refaktoren wurden auch schon im Grundkurs behandelt!) Beispielsweise kann das Aufteilen einer Methode auf zwei kleinere Methode bedeuten, daß diese beiden kleineren Methoden nun besser gemeinsam in eine neue Klasse gepackt werden, welche dann auch einige der bisherigen Blockvariablen der Methode (die von den beiden neuen Methoden, und nur von diesen, geteilt  werden sollen) als Felder aufnimmt. Um zu verstehen, warum es günstig ist, diese Einträge alle in eine separate Klasse auszulagern, muß man aber auch das Prinzip des minimalen Gültigkeitsbereichs kennen, das ebenfalls schon im Grundkurs vermittelt wird.

Anfänger neigen dazu, alles in eine große Methode  zu schreiben anstatt Code sinnvoll auf mehrere Methoden zu verteilen. Dadurch sind ihnen viele elegante Lösungswege verbaut.

(Siehe das Programm „Rekursives Durchstreifen“)

Literatur

Zunächst

Ferner

Ferner

Software-Architektur und -Arbeit,

http://www.objectmentor.com/resources/articles/ocp.pdf

http://www.cs.cmu.edu/afs/cs/project/vit/ftp/pdf/intro_softarch.pdf

http://martinfowler.com/ieeeSoftware/whoNeedsArchitect.pdf

http://www.laputan.org/mud/

Structured Systems Analysis (DeMarco)

Object Oriented Software Engineering by Ivar Jacobson

Test-Driven Development by Kent Beck

The Pragmatic Programmer by Andrew Hunt

Domain Driven Design by Eric Evans

Working Effectively with Legacy Code by Michael Feathers

A Theory of Object-Oriented Design: The building-blocks of OOD and notations for representing them (with focus on design patterns.)

Martin Fowler. Analysis Patterns: Reusable Object Models. Addison-Wesley, 1997.

Brett McLaughlin, Gary Pollice, David West. Head First Object-Oriented Analysis and Design. O'Reilly, 2006.

An Object-Oriented Design Taxonomy, http://www.jonathanholloway.co.uk/thesis/MPhilThesis.pdf

Fundamentals of object oriented design and UML (Meilir Page-Jones)

Patterns oriented software architecture (Douglas Schmidt)

Software-Projekte

The Mythical Man-Month by Frederick Brooks

Code Complete, 2nd Ed. by Steve McConnell

Agile Principles, Patterns and Practices in C# (Robert C. Martin)

Siehe auch

http://foundationsof.com/FoundationsOfProgramming.pdf

Ein früher Artikel zur objektorientierten Programmierung:

Unter den »Klassikern« der objekt-orientierten Programmierung auf der Seite

http://e7l3.org/ref/classics.html

findet sich auch ein Text, an dessen Zustandkommen Stefan Ram etwas beteiligt war:

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723069 stefan_ram:723069 Wie kommt man zu Klassen in Java? Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723069, slrprddef723069, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/klassen_java