- Zeichensätze und -kodierung – Anwendungsentwickler-Podcast #32
- HTML – Anwendungsentwickler-Podcast #33
- Java (Lernzielkontrolle) – Anwendungsentwickler-Podcast #36
- Allgemeine Fragen zur Programmierung (Lernzielkontrolle) – Anwendungsentwickler-Podcast #37
- Variablen und Operatoren (Lernzielkontrolle) – Anwendungsentwickler-Podcast #38
- Zahlen und Zeichen (Lernzielkontrolle) – Anwendungsentwickler-Podcast #39
- Algorithmen und Methoden (Lernzielkontrolle) – Anwendungsentwickler-Podcast #42
- Objektorientierung Teil 1 (Lernzielkontrolle) – Anwendungsentwickler-Podcast #43
- Objektorientierung Teil 2 (Lernzielkontrolle) – Anwendungsentwickler-Podcast #44
- Datenbankmodellierung (Lernzielkontrolle zum Entity-Relationship-Modell) – Anwendungsentwickler-Podcast #48
- Datenbankmodellierung (Lernzielkontrolle zum relationalen Tabellenmodell) – Anwendungsentwickler-Podcast #49
- Java EE 7 (Lernzielkontrolle) – Anwendungsentwickler-Podcast #54
- Fehlerbehandlung (Lernzielkontrolle zu Exceptions) – Anwendungsentwickler-Podcast #79
- Arrays und Listen (Lernzielkontrolle) – Anwendungsentwickler-Podcast #99
Mit den Themen Algorithmen und Methoden setze ich in der zweiundvierzigsten Episode des Anwendungsentwickler-Podcasts meine Reihe der Lernzielkontrollen zur Einführung in die Programmierung mit Java fort.
TL;DR
Mit meiner Lernzielkontrolle zu Algorithmen und Methoden kannst du dein Wissen als IT-Azubi prüfen. Ein Algorithmus beschreibt wiederholbar, wie du ein Problem löst; seine Grundbausteine sind Sequenzen, Verzweigungen und Wiederholungen. An Java-Beispielen geht es um Bedingungen und Schleifen sowie darum, wie du Code in Methoden wiederverwendest. Dazu gehören eindeutige Methodensignaturen und das Überladen von Methoden, außerdem Rückgabewerte, Parameter und der Aufruf von Instanzmethoden oder statischen Methoden.
Podcast: Play in new window | Download (Duration: 44:23 — 20.5MB)
Abonnieren: Apple Podcasts | Spotify | RSS
Kapitelmarken
- [00:00:20] Lernzielkontrolle zu Algorithmen und Methoden
- [00:01:31] Was ist ein Algorithmus?
- [00:02:14] Lösungswege zuerst auf Papier entwickeln
- [00:03:33] Grundbausteine eines Algorithmus
- [00:04:20] Sequenzen und Verzweigungen
- [00:05:17] Fallunterscheidungen mit switch und Polymorphie
- [00:06:27] Aufbau einer if-Abfrage
- [00:07:51] Kopfgesteuerte und fußgesteuerte Schleifen
- [00:09:22] Die for-Schleife und Endlosschleifen
- [00:11:13] Collections mit For-Each durchlaufen
- [00:13:29] Schleifen mit continue und break steuern
- [00:15:31] Aufbau und Ablauf einer for-Schleife
- [00:17:18] Code mit Methoden wiederverwenden
- [00:17:53] Funktionen und Prozeduren
- [00:19:45] Methoden mit Extract Method erzeugen
- [00:20:18] Methodenaufbau und Signatur
- [00:22:57] Parametertypen und eindeutige Signaturen
- [00:24:56] Checked Exceptions und Antworten in der Prüfung
- [00:26:23] Methoden überladen
- [00:27:30] Rückgabewerte mit return und void
- [00:29:02] Parameter mit Call by Value übergeben
- [00:31:08] Call by Reference und ref in C#
- [00:32:18] Objekte und kopierte Referenzen als Parameter
- [00:34:34] Änderungen über Rückgabewerte nachvollziehen
- [00:35:35] Instanzmethoden und Klassenmethoden aufrufen
- [00:37:21] Statische Methoden mit static definieren
- [00:38:14] Objekte mit new erzeugen
- [00:39:01] Shownotes und Quellen zum Lernen mit Java
- [00:40:42] Legacy Code testen und fremde Projektvorlagen verwenden
- [00:41:55] Feedback und Kontakt
- [00:42:33] Podcast abonnieren und Newsletter
- [00:43:30] Ausblick auf die Objektorientierung
Inhalt
Algorithmen
- Was ist ein Algorithmus?
- Die wiederholbare Beschreibung zur Lösung eines Problems.
- Welche drei grundlegenden Bestandteile kann eine Algorithmus haben?
- Sequenz, Verzweigung und Wiederholung.
- Aus welchen Teilen besteht ein
if-Statement?if (bool) { } else { }
- Welche Schleifen gibt es in Java?
while,do while,for, „foreach“.
- Was machen die Statements
continueundbreak?- Sie setzen die Schleife mit der nächsten Iteration fort bzw. beenden sie.
- Wie definiert man eine
for-Schleife in Java?for (Initialisierung; Prüfung; Aktion) { }
Methoden
- Wann und warum schreibt man Methoden?
- Um Algorithmen wiederverwenden zu können.
- Was macht die
return-Anweisung?- Beendet die Methode und gibt den angegebenen Wert zurück.
- Was bedeutet das Schlüsselwort
void?- Einen leeren Return-Wert.
- Was ist die Signatur einer Methode und welche Bestandteile hat sie?
- Die Signatur einer Methode besteht aus dem Namen der Methode und der Anzahl und den Datentypen ihrer Parameter. In Java zählen auch Checked Exceptions zur Signatur.
- Welche Teile der Methodensignatur müssen eindeutig sein?
- Name und Anzahl/Datentyp der Parameter.
- Was bedeutet das Überladen von Methoden?
- Gleicher Name, andere Parameter.
- Welche Auswirkung hat die Änderung des Wertes eines Methodenparameters für den Aufrufer?
- Keine. Parameter werden by value übergeben und sind nur innerhalb der Methode gültig.
- Was ist der Unterschied zwischen call by value und call by reference?
- Beim call by value werden die Werte der Parameter einer Methode kopiert und sind nur innerhalb der Methode verfügbar. Änderungen wirken sich nicht auf den Aufrufer aus. Beim call by reference wird eine Referenz auf Variablen als Parameter übergeben. Änderungen an diesen Variablen sind damit auch dem Aufruf bekannt.
- Wie ruft man eine Instanzmethode auf?
- Durch den
.-Operator an einem Objekt.
- Durch den
- Was macht das Schlüsselwort
static?- Definiert eine Klasse, Methode oder Variable als statisch. Dieses Element hängt damit nicht an einem Objekt, sondern an einer Klasse.
- Was macht das Schlüsselwort
new?- Instantiiert eine Klasse (erzeugt ein Objekt).
Literaturempfehlungen
- 13 Datenstrukturen und Algorithmen – Rheinwerk Computing :: Java ist auch eine Insel
- 2.8 Methoden einer Klasse – Rheinwerk Computing :: Java ist auch eine Insel
- The Java™ Tutorials
*
*
(direkt beim Rheinwerk-Verlag bestellen*)
(direkt beim Rheinwerk-Verlag bestellen*)
Links
- Permalink zu dieser Podcast-Episode
- RSS-Feed des Podcasts
- Referenzparameter – Wikipedia
- Signatur (Programmierung) – Wikipedia
Zusammenfassung
Algorithmen verstehen
Wenn du eine Aufgabe programmieren möchtest, brauchst du zuerst einen Lösungsweg, den du selbst nachvollziehen kannst. Ein Algorithmus ist eine wiederholbare Beschreibung, wie sich ein Problem lösen lässt. Du kannst ihn auch auf Papier ausführen.
In meiner Ausbildung lasse ich IT-Azubis ihre Lösung zunächst mit eigenen Worten beschreiben. Wenn du beim Programmieren festhängst, zeichne dir beispielsweise das Array auf, das du sortieren möchtest, und verschiebe die Elemente auf dem Papier. So kannst du die einzelnen Schritte durchgehen, bevor du sie in Code übersetzt.
Die Grundbausteine
Mit diesen Bausteinen lassen sich berechenbare Probleme abbilden:
- Sequenz: Befehle werden nacheinander ausgeführt. Bei
a = 1; b = 3; c = a + b;folgt jeder Schritt auf den vorherigen. - Verzweigung: Eine Bedingung bestimmt, welchen Weg das Programm einschlägt. Dafür gibt es beispielsweise
ifundswitch. - Wiederholung: Eine Schleife führt einen Codeblock wiederholt aus.
Bei Fallunterscheidungen mit switch besteht die Gefahr, dass sich dieselbe Logik an mehreren Stellen verteilt. Kommt ein Fall hinzu, musst du diese Stellen anpassen. Ich bevorzuge für solche Aufgaben in objektorientiertem Code eine Lösung über Polymorphie.
Bedingungen mit if
In Java steht die Bedingung in runden Klammern hinter if. Ist sie wahr, wird der zugehörige Block ausgeführt, dessen geschweifte Klammern den Code zusammenhalten. Ein optionaler else-Block legt fest, was bei einer falschen Bedingung passiert.
if ist in Java ein Statement ohne Rückgabewert. Andere Programmiersprachen kennen dafür auch Ausdrücke, die einen Wert liefern.
Schleifen
while
Bei einer kopfgesteuerten, auch abweisenden Schleife wird die Bedingung vor dem Schleifenrumpf geprüft. Eine while-Schleife führt ihren Block aus, solange die Bedingung wahr ist. Ist sie bereits beim ersten Prüfen falsch, gibt es null Durchläufe.
do-while
Die fußgesteuerte beziehungsweise akzeptierende Schleife prüft ihre Bedingung am Ende. In Java beginnt sie mit do, worauf der Codeblock folgt; anschließend steht while mit der Bedingung. Dadurch läuft der Block mindestens einmal.
for
Eine for-Schleife ist kopfgesteuert und fasst häufig benötigte Schritte im Schleifenkopf zusammen. Das Beispiel for (int i = 0; i < 10; i++) zählt von 0 bis 9.
Zuerst wird i einmalig angelegt und auf 0 gesetzt. Vor jedem Durchlauf prüft die Schleife i < 10. Nach dem Schleifenrumpf erhöht i++ den Zähler, bevor die Bedingung erneut geprüft wird. Die Bestandteile im Schleifenkopf sind durch Semikolons getrennt.
for und while lassen sich ineinander umformen. Auch leere Bestandteile sind bei for möglich: for (;;) ergibt eine Endlosschleife.
Achte bei deinen Schleifen darauf, dass das Abbruchkriterium erreicht werden kann. Bleibt die Bedingung dauerhaft wahr, läuft die Schleife weiter.
for-each
Wenn du jedes Element eines Arrays oder einer Collection bearbeiten möchtest, empfehle ich dir eine For-Each-Schleife. Sie übernimmt das Durchlaufen der Elemente, sodass du dich auf den jeweiligen Inhalt konzentrieren kannst. Fehler beim Verwalten eines Zählers oder bei den Arraygrenzen entfallen damit.
In Java verwendet auch diese Schleife das Schlüsselwort for, etwa in for (String s : strings). Jedes Element steht im Schleifenrumpf über die temporäre Variable s bereit. C# hat dafür das Schlüsselwort foreach; in Ruby gibt es die Methode each.
Wenn du zusätzlich den Index brauchst, etwa für die Ausgabe oder um auf ein benachbartes Element zuzugreifen, verwende ich eine klassische for-Schleife.
continue und break
- Mit
continueüberspringst du den restlichen Code des aktuellen Durchlaufs. Danach wird die Schleife fortgesetzt; bei einer klassischenfor-Schleife folgt zunächst die Aktion im Schleifenkopf. breakverlässt die Schleife vollständig. Das Programm setzt hinter ihr fort. Bei der Suche nach einem Wert kannst du damit nach einem Treffer die verbleibenden Durchläufe sparen.
In Natural heißen die entsprechenden Statements ESCAPE TOP und ESCAPE BOTTOM.
Code in Methoden wiederverwenden
Wenn du denselben Code mehrfach brauchst, fasse ich ihn als Methode zusammen. Sie gibt einem Codebereich einen Namen, über den du ihn an verschiedenen Stellen aufrufen kannst. Eine Methode zum Berechnen des Alters kann beispielsweise das Geburtsdatum und das aktuelle Datum erhalten und das Alter zurückgeben.
Doppelter Code führt dazu, dass du Änderungen an mehreren Stellen einpflegen musst. Wird dabei eine Stelle übersehen, können Fehler entstehen, die schwer zu finden sind. Meine Faustregel lautet deshalb: Sobald ich Code mehr als einmal brauche, mache ich daraus eine Methode. Eclipse unterstützt das über Refactor → Extract Method und erzeugt dabei auch passende Parameter und einen Rückgabewert.
In prozeduralen Sprachen bezeichnet eine Funktion einen benannten Codebereich mit Rückgabewert. Eine Prozedur hat keinen Rückgabewert. In Java heißen beide Varianten Methoden.
Aufbau und Signatur
Bei einer Methode steht der Rückgabetyp vor dem Namen. Dahinter folgen die Parameter in runden Klammern.
Die Signatur kennzeichnet eine Methode eindeutig. Für die allgemeine Antwort in einer Prüfung gehören dazu der Methodenname sowie die Anzahl und die Datentypen der Parameter.
Bei add(int a, int b) führen andere Parameternamen zu derselben Signatur: Auch add(int b, int c) erhält zwei Integer-Werte. Eine zusätzliche Variante add(double a, double b) lässt sich anhand der Datentypen unterscheiden. Beim Aufruf add(2, 3) werden Werte übergeben, aus denen die passende Methode bestimmt wird.
In Java bleibt der Rückgabetyp bei dieser Unterscheidung außen vor. Methoden mit gleichem Namen und gleichen Parametertypen lassen sich durch einen anderen Rückgabetyp allein nicht auseinanderhalten.
Java kennt außerdem Checked Exceptions, die mit throws an einer Methode angegeben werden. Der aufrufende Code muss diese behandeln, beispielsweise mit try-catch.
Für Prüfungsfragen empfehle ich dir eine allgemeine Antwort, die du mit Beispielen aus deiner Programmiersprache ergänzt. Konkrete Sprachdetails sind insbesondere dann relevant, wenn du die Sprache selbst verwendet hast, etwa im Abschlussprojekt.
Methoden überladen
Beim Überladen legst du mehrere Methoden mit demselben Namen an, deren Parameter sich in ihrer Anzahl oder ihren Datentypen unterscheiden. So kann add sowohl für Integer-Werte als auch für Double-Werte angeboten werden.
Werte zurückgeben
Mit return gibst du ein Ergebnis an den aufrufenden Code zurück, beispielsweise mit return alter;. Einige Sprachen geben auch den zuletzt ausgewerteten Ausdruck zurück.
Für eine Java-Methode ohne Rückgabewert steht void an der Stelle des Rückgabetyps.
Parameter übergeben
Call by Value
Bei Call by Value erhält die Methode eine Kopie des übergebenen Werts. Hat deine Variable i den Wert 5, bekommt der Methodenparameter diesen Wert beim Aufruf. Änderungen am Parameter betreffen die lokale Kopie. Die Variable i im aufrufenden Code behält ihren Wert.
Call by Reference
Bei Call by Reference erhält die Methode Zugriff auf die Variable des aufrufenden Codes. Ändert sie deren Wert, ist diese Änderung anschließend auch dort sichtbar. In C# wird das beispielsweise durch ref sowohl beim Parameter der Methode als auch beim Aufruf kenntlich gemacht.
Ich bevorzuge Rückgabewerte, weil sich Änderungen über Referenzparameter schwer nachvollziehen lassen können. Gerade beim Suchen nach Fehlern ist relevant, wo ein Wert verändert wurde.
Objekte als Parameter
Wenn du in Java ein Objekt übergibst, wird der Wert seiner Referenz kopiert. Die Methode und der aufrufende Code greifen damit auf dasselbe Objekt zu. Ändert die Methode beispielsweise den Namen einer Person, sieht der aufrufende Code den geänderten Namen ebenfalls.
Weist du dem lokalen Parameter innerhalb der Methode mit new Person(...) ein anderes Objekt zu, gilt diese neue Referenz innerhalb der Methode. Die Variable im aufrufenden Code verweist weiterhin auf das bisherige Objekt.
Instanzmethoden und statische Methoden
Eine Instanzmethode gehört zu einem konkreten Objekt. In Java rufst du sie mit dem Punktoperator auf, etwa als person.setName(...). Für den individuellen Namen einer Person brauchst du eine solche Instanz.
Mit new erzeugst du ein Objekt einer Klasse. Person p = new Person(); legt beispielsweise eine Variable vom Typ Person an und weist ihr ein neu erzeugtes Objekt zu.
Eine statische Methode, auch Klassenmethode genannt, gehört zur Klasse. In Java kennzeichnest du sie mit static und rufst sie über Klassenname.methodenname(...) auf. Dafür brauchst du kein zuvor erzeugtes Objekt. Ich verwende sie für Aufgaben, die unabhängig von den Attributen einer konkreten Instanz sind.
Quellen und ergänzende Themen
Unter anwendungsentwicklerpodcast.de/42 findest du meine Links zu den behandelten Themen. Dazu gehören "Java ist auch eine Insel" und eine Java-Einführung aus dem Rheinwerk-Verlag. Eine ältere Ausgabe der Java-Insel ist als kostenloses Openbook verfügbar; verlinkt sind unter anderem Kapitel zu Algorithmen und Methoden. Das Java-Tutorial von Oracle behandelt die Inhalte auf Englisch.
In meinem Blog verweise ich außerdem auf einen Artikel darüber, wie du vorhandenen Code testbar machen kannst, sowie auf "Working Effectively with Legacy Code" von Michael Feathers. Ein weiterer Beitrag behandelt fremde Vorlagen für die Projektdokumentation, darunter Fragen zum Zitieren und zu möglichen Punktabzügen.
Fragen oder Ergänzungen kannst du mir als Kommentar zur Episode schicken. Über den RSS-Feed lässt sich der Podcast abonnieren. Unter anwendungsentwicklerpodcast.de/newsletter bekommst du Zugang zu meinen Checklisten zur Projektarbeit. Als nächstes Thema der Lernzielkontrollen ist die Objektorientierung vorgesehen.
Transkription der gesamten Episode
Automatisch erzeugte Transkription der Episode
Herzlich Willkommen zum Anwendungsentwickler-Podcast, dem Podcast rund um die Ausbildung zum Fachinformatiker für Anwendungsentwicklung.
In dieser Episode gibt es eine Lernzielkontrolle rund um Algorithmen und Methoden. Viel Spaß dabei!
Hallo und herzlich Willkommen zur 42. Episode des Anwendungsentwickler-Podcasts.
Mein Name ist Stefan Macke und heute setze ich meine Reihe der Lernzielkontrollen fort, auf zahlreichen Wunsch.
Ich wollte ja erst noch ein paar andere Themen einschieben, aber die Nachfrage nach den Lernzielkontrollen war dann doch so groß, dass ich gesagt habe,
okay, ich mache nochmal zwei Episoden, so passend zu Weihnachten als kleines Vorabgeschenk, mache ich nochmal zwei Lernzielkontrollen rund um Java und Programmierung
und danach gucken wir dann mal, wie es weitergeht.
Es gibt wohl einige Azubis da draußen, die diesen Podcast hier nutzen, um ihren eigenen Lernerfolg so ein bisschen zu kontrollieren und zu gucken,
was andere denn so lernen in der Zeit, in der sie sich auch in die Programmierung einarbeiten.
Und von daher möchte ich euch gerne dabei unterstützen, keine Frage.
Deswegen machen wir jetzt nochmal die nächsten Lernzielkontrollen, die nach denen auch wirklich anstehen würden, die ich beim letzten Mal aufgenommen habe.
Und heute wären wir dann halt angekommen bei den Algorithmen und Methoden.
Das passt, glaube ich, auch ganz gut zusammen, wie ich finde, denn Methoden sind ja letztlich nichts anderes als wiederverwendbare Algorithmen.
Von daher fangen wir einfach mal mit dem Part über Algorithmen an und wechseln dann rüber zu den Methoden.
Und dabei frage ich mal so ein paar Sachen ab, die man da vielleicht wissen sollte oder auch beschreiben können sollte.
Gut, dann fangen wir gleich vorne an mit dem Algorithmus.
Was ist denn überhaupt ein Algorithmus?
Ich fange jetzt also nicht ganz vorne an, wie der Name zustande kam.
Und da gab es ja diesen berühmten arabischen Forscher oder Mathematiker, der dem Algorithmus seinen Namen gab.
Ich kann ihn selber nicht aussprechen, das ist ein ellenlanger Name.
Das ist für mich jetzt auch ein bisschen irrelevant, sage ich mal.
Wichtig ist, dass man beschreiben kann, was überhaupt ein Algorithmus ist und was das für uns als Programmierer bedeutet.
Ein Algorithmus, den würde ich erklären als eine wiederholbare Beschreibung zur Lösung eines Problems.
Und da ist auch noch nicht ein einziger IT-Begriff drin in dieser Definition, denn ein Algorithmus ist etwas, wofür man nicht unbedingt einen Computer braucht.
Es ist einfach nur eine Lösungsbeschreibung, um irgendein Problem eben zu lösen.
Und das kann auch etwas sein, was man auf dem Blatt Papier ausrechnet oder irgendwie in der realen Welt einfach umsetzt.
Und genau so fange ich mit meinen Azubis eigentlich auch immer an, wenn sie Programmieren lernen.
Die sollen mir die Sachen, die sie da programmieren sollen, erst mal so erklären, als wenn sie die selber lösen müssten.
Zum Beispiel eben mit Zettel und Papier.
Zettel und Papier ist doppelt, aber mit einem Stift.
Und das dann wirklich auf Papier lösen.
Also zum Beispiel, wie berechne ich denn die Wurzel einer Zahl?
Das kann man ja mathematisch lösen.
Und da muss ich erst mal beschreiben können, wie ich das grundsätzlich mache, bevor ich das einem Computer dann beibringen kann.
Der Computer macht auch nichts anderes als das, was ich ihm sage.
Und wenn ich selber gar nicht formulieren kann, wie ein Problem zu lösen ist, dann kann ich es auch nicht programmieren.
Und ich finde, das ist auch immer ein ganz guter Trick.
Wenn man mal etwas programmieren muss und man kommt einfach nicht weiter, man kommt nicht auf die Lösung,
dann macht einfach mal den Bildschirm aus oder schiebt die Tastatur weg und versucht mal, das Ding auf dem Papier zu lösen.
Mal dir mal ein bisschen was auf.
Zeichne dir mal das Array auf, mit dem du gerade einen Sortieralgorithmus implementieren willst.
Und versuch das mal auf dem Blatt Papier hin und her zu schieben.
Das mache ich mit meinen Studenten in der FH auch immer so.
Da wird das Ding dann mal an der Tafel gelöst.
Wie soll man denn auch etwas einem Computer beibringen, was man selber nicht verstanden hat?
Das geht nicht.
Von daher muss man erst mal offline versuchen, diese Aufgabe zu lösen.
Und das kann man wunderbar machen, indem man sich einfach mal ein Blatt Papier nimmt
oder einfach irgendwas zu schreiben nimmt und das dann versucht zu lösen.
Also Algorithmus, wiederholbare Beschreibungslösung eines Problems.
Und jetzt ist die Frage, was sind denn die Bestandteile eines Algorithmus?
Woraus besteht er denn jetzt?
Und da gibt es eigentlich drei grundlegende Bestandteile.
Das sind so ein bisschen die Bausteine von Algorithmen.
Daraus kann ich mir meine Algorithmen zusammenbauen.
Und wenn ich diese drei Bausteine habe, dann kann ich tatsächlich auch jedes lösbare Problem,
sofern es denn wirklich lösbar ist, es gibt ja auch nicht lösbare Probleme,
aber dann kann ich jedes lösbare Problem tatsächlich auch abbilden.
Mehr brauche ich dafür nicht.
Das meinen dann immer viele Prüflinge, dass man sagt,
ich brauche unbedingt Objektorientierung und Funktionale und Vererbung und weißt gar nicht was.
Brauchen wir im Prinzip eigentlich nicht.
Es reichen drei grundsätzliche Bestandteile, um jegliches Problem lösen zu können.
Und das sind die Sequenz, die Verzweigung und die Wiederholung.
Oder auf Englisch Sequence, Branching und Repetition oder Loop oder wie auch immer.
Und diese drei Teile gucken wir uns jetzt mal einmal im Detail an.
Eine Sequenz ist eigentlich das einfachste von allen.
Das bedeutet nämlich einfach nur eine Abfolge von Befehlen, die nacheinander ausgeführt werden.
Also wenn ich sowas sage wie a gleich 1, b gleich 3, c gleich a plus b, meinetwegen,
dann wären das drei Befehle hintereinander.
Und das ergibt halt eben eine Sequenz.
Dafür muss der Computer sorgen, dass die Teile, die ich da von oben nach unten eintippe,
auch von oben nach unten ausgeführt werden.
Dann habe ich eine Sequenz.
Jetzt kommt das nächst komplexere.
Das wäre dann die Verzweigung.
Die Verzweigung ist nicht einfach nur ein Ablauf von oben nach unten,
sondern hier geht es noch im Prinzip um eine Unterscheidung.
Soll ich links oder rechts lang?
Wenn ich mal so eine Straße langfahre zum Beispiel.
Sequenz bedeutet, ich fahre einfach immer geradeaus.
Und bei einer Verzweigung, da kann ich mich jetzt entscheiden, wo ich langfahre.
Links oder rechts.
Oder vielleicht gibt es sogar eine Kreuzung und ich habe drei Wege, die ich wählen kann.
Und diese Verzweigung ist klassischerweise umgesetzt im Poemiersprachen mit dem beliebten If-Statement.
Das ist dann auch gleich die Anschlussfrage, wie so ein If-Statement aussieht.
Aber das vertiefen wir jetzt erstmal noch nicht.
Und es gibt auch noch ein zweites, was es in vielen Poemiersprachen gibt.
Das ist nämlich das Switchcase.
Davon würde ich dann abraten, weil der Code dann teilweise sehr schwierig zu verstehen ist,
wenn ich mehrere verschiedene Verzweigungen habe.
Ifs und geschachtelte Ifs reichen meist schon aus, um den Code komplex genug zu machen.
Von daher würde ich persönlich auf ein Switchstatement verzichten.
Ich habe das in meinem JavaScript-Tutorial noch nicht mal eingebaut,
weil ich das so unsinnig oder unpraktikabel finde, weil der Code nachher einfach schwer zu verstehen ist.
Und man muss ihn sehr oft anpassen, denn was hat man in so einem Switchcase häufig?
Irgendeine Fallunterscheidung.
Und wenn dann ein weiterer Fall hinzukommt, darf ich alle die Stellen im Code anpassen,
wo eben diese Fallunterscheidung auftaucht.
Und wenn ich damit einmal anfange, dann ist es ganz häufig so, dass sich das wild durch den Code verteilt.
Und da muss ich an mehreren Stellen rumhantieren oder rumändern, nur weil ein neuer Fall hinzukommt.
Das würde ich in einer objektorientierten Programmiersprache heutzutage Polymorph lösen.
Polymorphie, da kommen wir doch in einer der nächsten DLC-Kontrollen dann drauf.
Also das Switchcase-Statement wäre für mich ein Statement, das ich gar nicht benutzen würde.
Da gibt es bessere Möglichkeiten, sowas zu lösen.
Und der letzte Teil der Algorithmen-Bausteine, das wäre dann die Wiederholung,
also die allseits bekannten Schleifen, die dann in der Programmiersprache diese Wiederholung umsetzen.
Und da gibt es verschiedene Schleifen, die gucken wir uns auch gleich nochmal im Detail an.
Aber wir gehen mal der Reihe nach, denn wir hatten gerade gesagt, die Verzweigung,
das ist ein ganz wichtiges Statement, nämlich das IF-Statement.
Und das sollte man auch kurz beschreiben können, wie das aussieht.
Ist im Prinzip recht einfach. Wer schon mal programmiert hat, hat das wahrscheinlich auch schon mal gesehen.
Es ist einfach das Statement IF.
Oder Statement, es kommt jetzt ganz darauf an, was für eine Programmiersprache ich habe.
Es kann teilweise auch ein Ausdruck sein, der einen Wert zurückgibt.
In vernünftigen Programmiersprachen ist das z.B. so.
Aber in Java z.B. ist es tatsächlich ein Statement, d.h. es gibt keinen Wert zurück.
Aber der Aufbau ist eigentlich immer gleich in allen Programmiersprachen.
Und dann habe ich eine Prüfung.
Und je nachdem, ob die Prüfung wahr oder falsch ist, wird der nach der Prüfung kommende Ast durchlaufen.
Das ist dann, wenn die Prüfung wahr ist.
Und wenn die Prüfung falsch ist, wird der zweite Ast durchlaufen.
Wobei ich in den meisten Programmiersprachen für den zweiten Ast noch ein ELS davor brauche.
D.h. der Aufbau wäre IF, Prüfung, dann Block quasi.
ELS, sonst Block.
So wäre der Aufbau in Java zumindest.
Blöcke werden ja mit geschweiften Klammern umschlossen.
Das kennen wir schon.
Und die Prüfung bei dem IF wird in normale Klammern eingefasst.
Das war es zum Thema IF.
Ach ja, ganz wichtig. So wichtig ist es auch nicht.
Aber der ELS-Block ist optional.
D.h. ich kann auch einfach nur eine IF-Abfrage haben mit einer Prüfung.
Und dann wird im Wahrheitsfall true etwas ausgeführt.
Und ansonsten passiert halt einfach nichts. Das geht auch.
Also ich brauche keinen ELS-Zweig.
Dann kommen wir zum etwas interessanteren Thema, nämlich den Schleifen.
Da gibt es nämlich einfach ein paar mehr von, die man auch auseinanderhalten sollte.
Deswegen fangen wir doch mal ganz vorne an mit der WHILE-Schleife.
Die WHILE-Schleife ist eine sogenannte kopfgesteuerte Schleife oder auch eine abweisende Schleife.
Das bedeutet, wenn ich die WHILE-Schleife programmiere und ich gebe die Bedingung an,
wie lange diese Schleife durchlaufen werden soll.
Das sagt schon das Wort WHILE.
Solange die Prüfung, die diese Schleife im Kopf macht, wahr ist, wird irgendwas getan.
D.h. wenn ich jetzt mir vorstelle im Code, ich schreibe irgendwo eine WHILE-Schleife,
die, wie gesagt, irgendwas prüft, z.B. x kleiner 18 meinetwegen,
dann kann es ja sein, dass das x schon größer 18 ist, bevor die Schleife überhaupt aufgerufen wird.
D.h. sie wird niemals durchlaufen.
Deswegen nennt man diese Schleife auch abweisend, weil sie potenziell auch einfach gar nicht ausgeführt werden kann,
weil die Bedingung eben nicht zutrifft.
Demgegenüber steht die sogenannte fußgesteuerte oder akzeptierende Schleife,
das wäre in Java und vielen anderen Promi-Sprachen auch, die sogenannte DO-WHILE-Schleife.
Da ist die Syntax dann ein bisschen anders.
Dann mache ich ein DO, dann kommt der Block, der ausgeführt wird,
und WHILE, die Prüfung, die kommt erst ganz am Ende.
D.h. diese Schleife wird immer mindestens einmal durchlaufen.
Es gibt also keinen Fall, wo diese Schleife gar nicht durchlaufen wird.
Deswegen heißt sie auch akzeptierende oder eben fußgesteuerte Schleife,
weil die Prüfung erst am Ende erfolgt.
Das ist im Prinzip der zentrale Unterschied zwischen diesen Schleifen,
kopf- und fußgesteuert,
und alle anderen Schleifen, die dann eventuell noch angeboten werden in einer Programmiersprache,
lassen sich auf diese beiden Schleifentypen zurückführen,
nämlich die allseits beliebte VOR-Schleife z.B.
Das ist auch nichts weiter als eine kopfgesteuerte Schleife,
die einfach nur ein bisschen nette Syntax hat,
weil ich z.B. bei einer WHILE-Schleife ganz häufig einen Zähler habe,
und dann wird am Ende des Schleifendurchlaufs irgendwas hochgezählt,
dann wird die Bedingung geprüft,
und vorher muss ich noch eine Variable initialisieren,
kann ich das Ganze auch ein bisschen kompakter machen,
wenn ich es mit einer VOR-Schleife mache.
Eine VOR-Schleife, und dann mache ich einfach VOR, Klammer auf,
und dann kommen da die drei Komponenten mit Semikolon getrennt,
nämlich einmal das, was durchgeführt wird, bevor die Schleife überhaupt losläuft,
da kann ich z.B. eine Deklaration machen, eine Initialisierung.
Als zweites kommt dann nämlich eben genau meine Prüfung,
solange diese Bedingung wahr ist, wird irgendwas gemacht,
und als letztes kommt in diesem Drei-Gespann, sage ich mal,
die Aktion, die am Ende eines Schleifendurchlaufs ausgeführt wird,
meistens wird da z.B. ein Zähler hochgezählt.
Das muss aber nicht so sein,
die VOR-Schleife kann auch einfach aus leeren Komponenten bestehen,
also kann ich machen VOR, Klammer auf, Semikolon, Semikolon, Klammer zu,
da steht dann einfach nichts drin,
da habe ich dann nichts weiter programmiert als eine Endlosschleife.
Es gibt keine Prüfung, d.h. sie läuft einfach ewig weiter im Prinzip.
Das muss ich überhaupt bei all diesen Schleifen berücksichtigen,
dass ich immer eine Endlosschleife programmieren kann,
d.h. eine Schleife, die nie beendet wird.
Und das bedeutet natürlich, wenn ich das Programm starte und es hört nie wieder auf,
ja, das wäre doof für den Benutzer, der möchte das ja vielleicht mal beenden.
Von daher muss ich immer sehr besonders darauf achten,
dass meine Abbruchbedingungen oder mein Abbruchkriterium auf jeden Fall auch zutreffen kann
und ich nicht etwas programmiere, was in der Bedingung z.B. niemals den Wert Falls ergibt,
denn das bedeutet, dass die Schleife eben unendlich weiterläuft.
Das wäre halt eben nicht so schön.
Aber letztlich ist die Vorschleife nur eine Abkürzung, sage ich mal, für eine While-Schleife.
Ich kann jede Vorschleife in eine While-Schleife umwandeln und übrigens auch umgekehrt.
Aber ich kann z.B. nie eine While-Schleife in eine Do-While-Schleife umwandeln,
weil die halt eben zwei völlig unterschiedliche Konzepte haben,
nämlich eben Kopf bzw. Fuß gesteuert.
Und es gibt in Java und in vielen anderen Promiesprachen auch noch eine schöne weitere Schleife,
nämlich die For-Each-Schleife.
Die wird in Java netterweise genauso geschrieben wie die Vorschleife.
Es gibt also kein extra Schlüsselwort, das For-Each heißt.
In C-Sharp heißt es z.B. For-Each.
In Ruby heißt es, na gut, da ist es keine Schleife, da ist es eine Methode,
aber die heißt Each auch dann tatsächlich.
Und dieses For-Each bedeutet immer, dass ich über irgendeine Collection drüber laufe
und mit jedem Element irgendetwas tue.
Z.B. jedes Element eines Arrays durchlaufen und damit irgendwas machen.
Und das könnte ich potenziell mit einer While- oder auch mit einer Vorschleife einfach programmieren.
Mit einer Vorschleife, ich fange mit einem i z.B. an, mit Index 0,
zähle das dann hoch und mache dann mit dem Element in meinem Array irgendwas.
Das würde wunderbar funktionieren.
Aber das ist ziemlich fehleranfällig.
Ich muss einen Zähler initialisieren, ich muss wissen, dass der bei 0 anfängt.
In einer anderen Programmiersprache fängt der vielleicht bei 1 an.
Da muss ich immer dran denken.
Dann muss ich den Zähler auch hochzählen.
Dann muss ich die Abbruchbedingungen vernünftig setzen.
Wenn ich das nicht tue, habe ich vielleicht eine Endplus-Schleife usw.
Das ist also ziemlich viel Aufwand und ziemlich fehleranfällig,
nur um so eine Standardaufgabe zu lösen, nämlich ein Array zu durchlaufen.
Von daher würde ich in meinem echten Code immer nur eine For-Each-Schleife für sowas benutzen,
denn die versteckt quasi vor mir diese Komplexität, die ich da programmieren muss.
Das sage ich dann in Java z.B. einfach vor meinetwegen String s in Strings,
in einem Array, wo Strings drinstehen, mache irgendwas.
Und dann sorgt Java dafür, dass jedes Element durchgelaufen wird,
in eine temporäre Variable gepackt wird, mit der ich dann arbeiten kann.
D.h. ich muss mich nicht um irgendwelche Indizes hochzählen usw. alles kümmern.
Das macht halt eben die Schleife für mich.
Von daher, wenn ich im Code irgendwie sowas sehe wie eine Vorschleife,
um durch ein Array zu laufen, da sage ich immer meiner Zobis,
stell das Umruf nur für eine For-Each-Schleife.
Die einzige Ausnahme ist, wenn ich zusätzlich zu dem Inhalt des Arrays auch noch den Index brauche.
D.h. wenn ich mit diesem Index selber irgendwas tun will,
weil ich z.B. den Index irgendwie brauche, um was auszugeben oder Zeilen durchzufärben
oder ich weiß nicht, was man noch Tolles damit machen kann.
Oder z.B. nehme ich den Index, um auf den nächsten, folgenden Index drauf zuzugreifen,
um z.B. eins hochzurechnen usw.
Dann brauche ich eine Vorschleife. Das geht dann nicht mehr mit einer For-Each-Schleife.
Aber ich sage mal, für 99% meiner Anwendungsfälle,
wenn ich einfach nur Collection durchlaufe und irgendwas mit den Elementen tue,
reicht eine For-Each-Schleife völlig aus.
Gut, dann haben wir noch zwei Statements, die ganz nett sind im Zusammenhang mit Schleifen.
Die gibt es nicht in allen Promiesprachen, aber in den meisten mir Bekannten gibt es die.
Und zwar heißen die Continue und Break.
Was machen die?
Continue, wenn ich das in eine Schleife packe, irgendwo in den Schleifenrumpf,
bedeutet das, die Schleife wird mit dem nächsten Wert fortgesetzt.
Wenn ich z.B. eine Vorschleife habe, die von 1 bis 3 zählt,
und ich mache irgendwo mitten in meinem Schleifenrumpf ein Continue,
dann würde der aktuelle Zähler einfach hochgesetzt und mit dem nächsten Element würde weitergemacht.
Bedeutet aber auch, dass in dieser Zeile, wo das Continue steht,
die Ausführung der Schleife tatsächlich abgebrochen wird quasi.
Alles, was hinter dem Continue noch kommt in der Schleife,
da könnte ja noch irgendwie ein bisschen Code drinstehen,
der wird übersprungen und dann wird wirklich von vorne mit dem nächsten Wert in der Vorschleife weitergemacht.
Break macht das Ganze im Prinzip genauso,
nur dass da nicht mit dem nächsten Wert weitergemacht wird,
sondern da wird die komplette Schleife verlassen.
Das heißt, ich springe wirklich ans Ende der Schleife
und dann wird der Code weiter ausgeführt, der hinter der Schleife kommt.
Mit Continue springe ich also einfach zum nächsten Wert
und die Schleife fängt quasi vorne wieder an mit diesem erhöhten Wert.
Und bei Break springe ich komplett aus der Schleife raus
und mache mit dem Code weiter, der dahinter steht.
Das gibt es tatsächlich sogar auch in der Programmiersprache,
die wir häufig benutzen, nämlich Natural.
Da heißen die beiden Statements völlig anders,
nämlich Escape Top und Escape Bottom.
Das finde ich auch sehr schön sprechend.
Das bedeutet nämlich einfach, dass man zum Top, also zum Kopf der Schleife,
quasi zurückspringt und mit dem nächsten Wert weitermacht.
Und Escape Bottom bedeutet halt eben, ich springe zum Ende der Schleife
und die gesamte Schleife wird eben verlassen.
Also diese beiden Statements sind auch häufig anzutreffen in der Praxis,
wenn ich zum Beispiel, meinetwegen in einem Array, einen bestimmten Wert suche
und es gibt da keine Funktion für,
dann könnte ich ja zum Beispiel mit einer Vorschleife da durchlaufen
und jeden Wert vergleichen.
Und wenn ich jetzt den Wert gefunden habe, warum muss ich dann zum Beispiel
noch die 1000 folgenden Elemente noch weiter durchlaufen?
Das wäre ja Quatsch.
Ich könnte also sagen, oh, Wert gefunden, Break.
Und dann gehe ich halt ans Ende der Schleife
und spare mir die restlichen Iterationen.
Gut, und letzte Frage zum Thema Algorithmus.
Da nämlich die große Frage der Vorschleife.
Die wird halt auch häufig in Prüfungen abgefragt,
gerne auch in Schriftlichen natürlich.
Wie sieht jetzt so eine Vorschleife aus?
Ich hatte es gerade schon mal kurz besprochen.
Ich nehme das Schlüsselwort vor und dann kommt in Klammern einmal die Initialisierung,
dann kommt ein Semikolon, dann kommt eine Prüfung,
dann kommt noch ein Semikolon und dann kommt die Aktion,
die am Ende jedes Schleifendurchlaufs durchlaufen wird.
Klassischerweise sieht also eine Vorschleife so aus wie vor, Klammer auf, int i gleich 0.
i nimmt man halt häufig als Variablename für den Iterator,
für die Iterationsvariable.
Dann kommt ein Semikolon, dann kommt die Prüfung,
zum Beispiel i kleiner 10 meinetwegen.
Ich möchte also von 0 bis 9 meinetwegen zählen.
Und dann kommt noch ein Semikolon, dann kommt die Aktion,
in diesem Fall meistens i++.
Das heißt, Zähler wird hochgezählt.
Und die Vorschleife wird jetzt so durchlaufen.
Einmalig wird die Initialisierung durchgeführt,
also die Deklaration von i in diesem Fall.
Dann kommt als allererstes auch die Prüfung,
denn die Vorschleife ist ja kopfgesteuert.
Kann ja sein, dass der Wert von i direkt am Anfang schon so groß oder klein ist,
dass die Schleife gar nicht mehr durchlaufen werden soll.
Und dann kommt erstmal der Schleifenrumpf,
also das, was in dem Block hinter der Vorschleife steht,
wird komplett abgearbeitet.
Ganz am Ende des Blocks kommt dann die Aktion,
das heißt, i wird hochgezählt.
Und dann kommen wir wieder zur Prüfung, Block, Aktion.
Prüfung, Block, Aktion und so weiter,
bis die Prüfung irgendwann mal falsch wird.
So wird dann die gesamte Vorschleife abgearbeitet.
So, dann haben wir jetzt quasi alles gelernt,
um richtig programmieren zu können.
Wir können eine Sequenz bilden,
indem wir einfach Befehle untereinander schreiben.
Wir können eine Verzweigung machen,
indem wir ein if-Statement benutzen.
Oder wir können eine Wiederholung machen,
indem wir kopf- oder fußgesteuerte Schleifen programmieren.
Mensch, super.
Damit können wir jetzt also jedes berechenbare Problem im Prinzip lösen,
mit diesen drei Grundbausteinen.
Und jetzt kommt als nächstes unser Bereich der Methoden,
denn wenn wir jetzt was Tolles programmiert haben,
dann sollten wir auch eine ganz wichtige Grundregel bei der Programmierung beherzigen,
nämlich Code nur einmal schreiben und wiederverwenden
und nicht copy-paste und alles doppelt und dreifach programmieren.
Und das können wir in den meisten Programmiersprachen in irgendeiner Form tun.
Wir können nämlich den Code, den wir programmiert haben,
in irgend so ein Ding reinquetschen,
das ich dann einfach nur noch aufrufen muss.
Und das wären dann in Java oder in anderen objektorientierten Programmiersprachen
auch die sogenannten Methoden.
Man kann sie aber auch Funktionen oder Prozeduren nennen.
Vielleicht einmal vorweg.
In Prozeduralen Programmiersprachen gibt es zwei Begriffe für solche aufrufbaren Codeteile.
Und zwar einmal die Funktion und einmal die Prozedur.
Eine Prozedur hat einfach keinen Rückgabewert und eine Funktion hat einen Rückgabewert.
Das ist eigentlich der zentrale Unterschied zwischen beiden.
Und beides, sowohl Funktion als auch Prozedur, ist einfach nur ein benannter Code-Bereich im Prinzip.
Dem kann ich einen Namen geben und dann rufe ich den auf.
Und das ist im Prinzip eine Möglichkeit, diesen Code wiederzuverwenden.
Ich kann also, wenn ich einen tollen Algorithmus programmiert habe,
meinetwegen um das Alter einer Person zu berechnen,
dann kann ich diesem Algorithmus einen schönen Namen geben,
zum Beispiel berechne Alter.
Und dem kann ich auch Parameter reingeben,
wie zum Beispiel Geburtstag und aktuelles Datum zum Beispiel.
Und dann gibt er mir irgendwas zurück, nämlich zum Beispiel das Alter der Person.
Und diese Dinge kann ich also wunderbar wiederverwenden.
Ich kann mich dann irgendwo in meinem Code einfach sagen,
anstatt diesen ganzen Code runterzuprogrammieren mit Schleife und Vergleich und hin und her,
sage ich einfach, berechne Alter, Datum 1, Datum 2.
Und dann habe ich sofort das Alter und muss diesen Code nicht doppelt und dreifach schreiben.
Kommt einem so vor wie, ja, das ist doch logisch, mache ich da ja schon immer so.
Aber das war halt nicht immer so.
Es gab auch früher Programmiersprachen, als es noch ganz in den Anfängen war, der Informatik,
da ging das eben nicht.
Da musste ich halt tatsächlich meinen Code doppelt und dreifach schreiben,
weil ich eben solche benannten Funktionen oder Prozeduren nicht erzeugen konnte.
Aber in heutigen Programmiersprachen ist das sicher anders.
Und da sollten wir auf jeden Fall auch Gebrauch davon machen,
nämlich um diese Redundanzen in unserem Code zu vermeiden.
Redundanzen sind nämlich so das Schlimmste, was man tun kann in seinem Code.
Denn das bedeutet, wenn ich Änderungen habe, muss ich an mehreren Stellen irgendwas anpassen.
Und dabei vergesse ich ganz häufig irgendwie eine Stelle
und dann habe ich komische Inkonsistenzen in meinem Code und Fehler im Programm,
die sehr schwer zu finden sind.
Also, wir machen am besten alles nur einmal.
Das ist genau die Frage, warum schreibt man Methoden, um Code wiederverwenden zu können
oder eben um Algorithmen wiederverwenden zu können.
Ich würde mir ganz einfach als Daumenregel mitnehmen,
immer wenn ich einen Code mehr als einmal benutze, mache ich auf jeden Fall eine Methode draus.
Das heißt, ich extrahiere das dann zum Beispiel, wenn ich in Java entwickle mit Eclipse,
kann ich einen Rechtsklick auf den Code machen und dann mache ich RefactorExtractMethod.
Das ist ein ganz häufig verwendetes Pad, Refactoring.
Und dann baut der mir von alleine eine Methode draus.
Erzeugt mir auch die Parameter, Rückgabewert und so alles automatisch.
Und ich muss eigentlich fast gar nichts mehr tun.
Und dann kann ich sofort diese Methode natürlich an anderer Stelle aufrufen.
Also perfekt, um Dinge wiederzuverwenden.
So, dann schauen wir uns aber mal den Aufbau so einer Methode an.
Hatte ich noch gar nicht gesagt, wie der Name zustande kommt.
Also ich habe gerade gesagt, es gibt Funktionen und Prozeduren in anderen Programmiersprachen
und in Java und anderen objektorientierten Sprachen haben diese Funktionen an den Objekten den Namen Methode.
Das ist einfach nur Namenskonvention, die heißen einfach so.
Daran kann man auch nicht ablesen, ob es eine Funktion oder eine Prozedur ist.
Es haben also beide Dinge, sowohl mit Rückgabewert als auch ohne, den Namen Methode.
Gut, dann gucken wir uns aber mal den Aufbau so einer Methode an.
Und fangen gleich mit einem wichtigen Fachbegriff an, nämlich mit der Signatur einer Methode.
Was ist diese Signatur und was gehört dazu?
Wenn wir uns den Aufbau einer Methode anschauen, dann sehen wir meist in den meisten Programmiersprachen,
insbesondere Java, C Sharp und so weiter.
Wenn wir von links nach rechts die Methode uns anschauen, dann fängt die immer an mit dem Rückgabewert.
Dann kommt der Name der Methode und hinter dem Namen steht dann meist in Klammern die Parameter der Methode.
Also Rückgabewert, Name, Parameter.
Diese drei Dinge, die hat eine Methode, beziehungsweise darüber definiert man eine Methode.
Jetzt ist die zentrale Frage, was ist jetzt diese Signatur?
Je nach Definition könnte man jetzt sagen, diese drei Bestandteile gehören zur Signatur.
In Java ist das allerdings nicht so, der Rückgabewert gehört nämlich nicht dazu.
Warum, da kommen wir gleich noch zu.
Im engeren Sinne ist die Signatur der Name und die Anzahl und der Datentyp der Parameter.
Was das genau bedeutet, da kommen wir gleich noch mal drauf.
Die Signatur einer Methode muss eindeutig sein.
Das heißt, ich kann nicht einfach eine Methode anlegen mit dem gleichen Namen und den gleichen Parametern.
Denn, ganz einfach gesagt, die Programmiersprache kann dann nicht entscheiden, welche ich denn jetzt aufrufen will.
Wenn der Name gleich ist und die Parameter auch.
Und ich habe zweimal eine Methode, die so definiert ist.
Woher soll jetzt zum Beispiel Java wissen, welche Methode er aufrufen soll?
Kann er nicht, denn die unterscheiden sich ja nicht.
Und deswegen muss die Signatur einer Methode eben eindeutig sein.
Und jetzt erklären wir vielleicht auch, warum der Rückgabewert dann nicht zur Signatur gehört.
Denn angenommen, ich hätte eine Methode mit zwei unterschiedlichen Return-Werten,
aber dem gleichen Namen und den gleichen Parametern.
Woher soll Java jetzt wissen, welche Methode aufgerufen wird?
Denn ich schreibe ja hin bei meinem Methodenaufruf später, meinetwegen alter a gleich berechneAlter Tag Tag2.
Ich gebe ja nur ein berechneAlter Tag und Tag2.
Aber ich kann in keiner Weise vorgeben, welchen Rückgabewert ich denn jetzt gerne hätte.
Ich kann also jetzt nicht sagen, von der Methode hätte ich aber jetzt gerne einen anderen Rückgabewert.
Das ist einfach syntaktisch nicht möglich in Java.
Und deswegen gehört der Rückgabetyp auch nicht zur Signatur dazu.
Der Name dürfte relativ eindeutig sein.
Wenn ich zwei Methoden anlege mit unterschiedlichem Namen, dann unterscheiden die sich logischerweise.
Das ist kein Problem für Java.
Was wir uns im Detail einmal anschauen sollten, wäre jetzt der Datentyp und die Anzahl der Parameter.
Ich habe bewusst nicht den Namen der Parameter erwähnt, denn der Name ist völlig irrelevant für Java oder auch andere Programmiersprachen.
Es wird sich nur interessiert für wirklich die Anzahl der Parameter und welchen Datentyp sie haben.
Als Beispiel, wenn wir eine Add-Methode anlegen, um zum Beispiel zwei Zahlen zu addieren,
und wir definieren die als add, Klammer auf, int a, Komma, int b, Klammer zu.
Dann bekommt sie zwei Integer-Parameter rein.
Wenn ich jetzt eine zweite Methode anlege mit dem Namen add und ich schreibe in Klammern int b, Komma, int c, Klammer zu,
dann heißen die Parameter zwar unterschiedlich, nämlich a und b, beziehungsweise b und c, aber die Datentypen sind halt identisch.
Und das würde eine Programmiersprache nicht erlauben.
Denn hier ist wieder das Problem beim Aufruf der Methode. Wie soll die Programmiersprache entscheiden, welche Methode aufrufen wird?
Ich gebe ja beim Aufrufen nicht die Namen der Parameter mit, sondern ich gebe nur die Werte mit.
Das heißt, die Methode würde ich aufrufen mit add, 2, 3, um zum Beispiel 2 und 3 zu addieren.
Da schreibe ich aber nicht rein, 2 und 3 sind a und b, beziehungsweise b und c, sondern ich gebe nur die Werte rein.
Also wie soll die Programmiersprache dann diese Werte, den Namen zuordnen? Das ist nicht möglich.
Und genau deswegen ist es auch nicht möglich, zwei Methoden anzulegen mit dem gleichen Namen und der gleichen Anzahl und den gleichen Datentypen an Parametern,
die unterschiedliche Namen haben. Das reicht nicht aus, sondern die Datentypen müssen wirklich unterschiedlich sein.
Was ich also durchaus machen könnte, wäre sowas wie eine zweite add-Methode mit double a, Komma, double b anzulegen.
Das wäre in Ordnung, denn int und double sind zwei unterschiedliche Datentypen und dann kann die Programmiersprache sehr wohl entscheiden,
wenn ich was aufrufe, add, 2, 3 oder add, 2, 0, 3, 0, dann kann natürlich die Programmiersprache entscheiden,
ah, das erste sind Integers, also nehme ich die eine Methode und das zweite sind Doubles, also nehme ich die andere Methode.
Das reicht dann aus, um die Methode eindeutig zu identifizieren.
Eine schöne Besonderheit übrigens noch in Java, da gibt es noch so tolle Dinger, die Checked Exceptions heißen.
Haben wir uns noch nicht im Detail angeguckt, aber es sind ja Exceptions, die ich hinter die Methode schreibe mit dem Schlüsselwort throws
und dann wird ausgesagt, dass diese Methode eine gewisse Exception werfen kann.
Und das bedeutet, der Aufrufer muss den auch behandeln, also z.B. einen Try-Catch drum machen.
Und dieses Throws und die Exceptions, die da geworfen werden können, gehören auch mit zur Methodensignatur in Java.
Es wird also relevant, wenn ich entscheide, welche Methode aufgerufen werden soll.
Aber für so eine Prüfungssituation, nochmal vielleicht ganz konkret der Tipp, in der Prüfung werde ich nicht auf eine konkrete Programmiersprache geprüft,
außer ich habe sie selber verwendet, z.B. in meinem Abschlussprojekt.
Aber ich würde wahrscheinlich keinen Prüfling nach der konkreten Implementierung in Java fragen,
weil einfach nicht jeder Prüfling in seiner Ausbildung irgendwann mal Java gemacht hat.
Das kann man nicht voraussetzen.
Und von daher sollte man eher allgemein antworten und vielleicht Beispiele aus seiner Lieblingsprogrammiersprache bringen,
aber immer versuchen, die Fragen der Prüfer möglichst allgemein zu beantworten.
Deswegen würde ich sagen, zur Signatur einer Methode gehören der Name und die Anzahl und die Datentypen der Parameter.
Den Rückgabewert lasse ich weg und auch diese Exception-Geschichte aus Java lasse ich weg.
Und wenn dann noch eine konkrete Nachfrage kommt, sowas wie, ja, aber Sie kennen doch vielleicht Java, wie ist es denn da und da?
Okay, dann kann man natürlich darauf antworten, aber erstmal versuchen, möglichst allgemeingültig für so viele Programmiersprachen wie möglich,
sage ich mal, eine korrekte Antwort zu liefern.
So, jetzt haben wir also kennengelernt, wenn wir eine Methode definieren, dann sagen wir Rückgabewert, Name und dann die Parameter dahinter.
Jetzt gibt es aber noch eine tolle Funktion in vielen Programmiersprachen, die Überladen heißt.
Was ist das jetzt? Das kann man jetzt relativ einfach erklären.
Wenn wir jetzt nämlich wissen, was die Signatur einer Methode ist, dann können wir einfach sagen,
das Überladen von Methoden ist, eine Methode anzulegen mit dem gleichen Namen wie dem einer Methode, die es schon gibt,
aber mit unterschiedlichen Parametern.
Wir könnten also, wie ich es gerade erklärt habe, mit meiner Add-Funktion, könnte ich eine zweite Add-Funktion anlegen,
die genauso heißt wie die erste, aber eben andere Parameter bekommt.
Und genau das heißt Überladen.
Das heißt, ich habe, wenn ich die Methoden aufrufe und anschaue, ich gebe ein Add, Klammer auf,
und dann habe ich halt die Möglichkeit, zwischen verschiedenen Implementierungen dieser Add-Funktion, äh, Methode zu wählen.
Und genau das ist das Überladen von Methoden.
Also im Prinzip, kurze Antwort, gleicher Name, andere Parameter.
Und der Rückgabewert, wie gesagt, ist dabei irrelevant.
Das heißt, ich kann eben gerade nicht eine Funktion angeben, die den gleichen Namen, die gleichen Parameter,
aber einen unterschiedlichen Rückgabewert hat. Das ist nicht möglich.
So, wenn wir jetzt schon beim Rückgabewert gerade mal waren, wie geben wir denn überhaupt etwas zurück aus einer Methode?
Also wie geben wir einen zum Beispiel berechneten Wert zurück an den Aufrufer?
Dafür gibt es in den meisten Poemiersprachen das Schlüsselwort return.
Einige coolere Poemiersprachen verzichten auch zum Beispiel auf das Schlüsselwort return.
Da wird einfach der zuletzt in der Methode aufgerufene Wert zurückgegeben.
Also könnte ich zum Beispiel einfach alter da hinschreiben, und dann wird halt der Inhalt der Variable in alter zurückgegeben.
Aber in vielen, sag ich mal, Mainstream-Poemiersprachen, Java, C Sharp und so weiter,
wird das return-Schlüsselwort benutzt, um etwas zurückzugeben.
Und das, was hinter dem return dann steht, zum Beispiel return alter, das wird dann zurückgegeben an den Aufrufer.
Es gibt allerdings auch Methoden, die gar nichts zurückgeben.
Das wäre dann quasi die Analogie zu unseren Prozeduren.
Das heißt, ich habe eine Methode, die hat keinen Rückgabewert.
Die hat einen Namen und Parameter, wunderbar, aber die gibt nichts zurück.
Aber ich muss halt, wenn ich die Methode definiere, einen Rückgabewert definieren.
Der steht da, und der muss da auch stehen.
Jetzt ist die Frage, was schreibe ich denn da hin, wenn gar kein Rückgabewert da ist?
Dafür gibt es ein weiteres Schlüsselwort, und das heißt void.
Kommt aus dem Englischen, heißt sowas wie leere, also zum Beispiel die Leere im Weltraum.
Und dieses void schreibe ich da hin, wenn ich keinen expliziten Rückgabewert habe.
Also zum Beispiel string oder int oder partner oder was auch immer ich da zurückgebe.
Das heißt, der Aufbau einer Methode ist wirklich immer gleich Rückgabewert, Name, Parameter.
Und wenn es eben keinen Rückgabewert tatsächlich gibt, muss ich eben das Schlüsselwort void benutzen, um das deutlich zu machen.
Und das wäre dann eben eine Methode ohne Rückgabewert, also quasi eine Prozedur.
So, eine ganz wichtige Sache bei den Methoden, das sehe ich auch immer ganz häufig, gerade bei Premiere-Anfängern,
dass das irgendwie nicht so richtig verstanden wird, ist, wie die Parameter, die ich da so reingebe, sich verhalten.
Und zwar insbesondere beim Aufrufer.
Viele Leute sind nämlich der Meinung, ich mache dann sowas wie berechne Alter,
und die Sachen, die ich dann da reingebe, die werden irgendwie geändert,
und dann sind die nachher bei meinem Aufrufer auch geändert.
Aber das ist gerade eben nicht der Fall.
Und hier müssen wir uns zwei Sachen einmal angucken, die man beim Methodenaufruf unterscheiden muss.
Und zwar die Parameter, die man da reingibt.
Die können entweder, wie man das auf Englisch sagt, by value übergeben werden oder by reference.
Und die beiden Sachen sind grundsätzlich unterschiedlich, und das muss man auch einmal verstanden haben.
Der Standard in fast allen Premiere-Sprachen, die ich kenne, ist immer by value.
Das heißt, es wird, wie der Name sagt, der Wert der Parameter übergeben.
Kann man sich so vorstellen, ich habe meinetwegen eine Variable, die nenne ich meinetwegen int i,
und die hat irgendeinen Wert, sagen wir mal 5.
Und ich rufe dann eine Methode auf, der ich das i übergebe.
Also meinetwegen berechne irgendwas in Klammern i.
Dann wird die Programmiersprache dafür sorgen, dass der Wert, den i zum Zeitpunkt des Methodenaufrufs hat,
an diese Methode übergeben wird.
Und wenn jetzt in dieser Methodendefinition sowas steht wie, was hatte ich gerade gesagt, berechne, glaube ich,
berechne und dann Klammer auf meinetwegen int a,
dann wird der Wert, den i beim Aufruf hat, in den Parameter a übergeben,
aber nur der Wert wird einmalig da rein kopiert, quasi, wenn man so will.
Und innerhalb dieser Methode ist er dann in der Variablen mit dem Namen des Parameters verfügbar,
also meinetwegen a.
Dann kann ich mit a natürlich auch alle Dinge machen, die ich sonst mit Variablen auch tun kann.
Ich kann da neue Werte zuweisen oder was hochrechnen, runterrechnen, keine Ahnung.
Alles mögliche kann ich damit tun.
Allerdings hat das keinerlei Auswirkungen auf den Aufrufer, also das i in meinem aufrufenden Code.
Wenn ich das berechne aufgerufen habe, hat das i immer noch den gleichen Wert wie vorher.
Der ist unverändert, denn nur der Wert, den i hatte, wird eben kopiert und an die Methode übergeben.
Aber das ist halt eben eine Kopie.
Das heißt, wenn sich diese Kopie ändert, hat das keinerlei Auswirkungen auf den originalen Wert und die originale Variable.
Demgegenüber steht der Call bei Reference.
Das bedeutet nämlich, ich gebe nicht den Wert an die Methode,
sondern eben eine Referenz auf eine Variable im Prinzip.
Das heißt, ich sage dann nicht der Methode, hier hast du den Wert 5,
sondern ich sage der Methode hier, hier hast du die Variable im Speicher,
da steht die 5 drin und mit dieser Variablen kannst du jetzt irgendwas tun.
Und wenn die Methode das dann tatsächlich auch tut und zum Beispiel diese Variable verändert und der einen neuen Wert gibt,
dann hat das auch eine Auswirkung auf den Aufrufer.
Das heißt, in unserem Beispiel wäre das i nachher verändert, nachdem die Methode aufgerufen wurde.
Aber wie gesagt, die meisten Programmiersprachen machen das bei Value zum Standard.
Das heißt, es wird immer eine Kopie übergeben und nie die Originalvariable verändert.
Wenn ich das anders haben will, dann bieten einige Programmiersprachen das durchaus an.
Zum Beispiel in C-Sharp, da gibt es das Schlüsselwort ref.
Das kann ich vor meine Variable beim Parameter, beim Methodenaufruf hinschreiben.
Muss ich aber auch in der Methodensignatur machen.
Also hätte ich sowas wie brechne ref int i.
Das bedeutet dann, ich gebe wirklich eine Referenz da rein
und wenn die Methode diesen Wert dann ändert, dann gilt es auch beim Aufrufer.
Da gibt es noch eine wichtige Sache, die man wissen muss.
Und zwar, wenn ich jetzt Objekte übergebe an eine Methode,
dann ist das grundsätzlich auch immer bei Value.
Das bedeutet aber nicht, dass die Werte, die das Objekt hat,
zum Beispiel in seinen Attributen, dass die festgeschrieben und kopiert werden,
sondern nur die Referenz auf das Objekt.
Die kann sich nicht ändern, aber das Objekt kann sich sehr wohl ändern.
Der Inhalt des Objekts ist nämlich weiteränderbar
und das hat auch eine Auswirkung dann auf den Aufrufer.
Kleines Beispiel, mein Aufrufer hat irgendwie eine Person erzeugt,
ein Objekt vom Typ Person und diese Person hat einen Namen.
Wenn ich jetzt meinetwegen beim Aufruf der Methode Druckepartner oder sowas
diese Person da rein gebe und dieses Druckepartner verändert jetzt den Namen der Person,
dann hat die Zugriff auf den gleichen Speicherbereich,
den auch der Aufrufer benutzt hat.
Das heißt, wenn die Person dann quasi zurückkommt aus der Methode,
dann ist die auch für den Aufrufer verändert.
Was ich bei diesem CallByValue bei Objekten nicht tun könnte,
wäre innerhalb meiner Methode der Variablen eine ganz neue Person zuzuweisen.
Wenn ich jetzt also zum Beispiel sage, in meiner Druckepartner-Methode
greife ich auf meinen Parameter zu und sage zum Beispiel
Parameter gleich new Person mit irgendwas,
dann würde ich ja wirklich das komplette Objekt ersetzen.
Und das führt dann dazu, dass beim Aufrufer nichts verändert wird,
weil diese Referenz auf das Objekt tatsächlich nur innerhalb der Methode dann gültig war
und sich nicht auf den Aufrufer durchschlägt.
Aber wenn ich das Objekt so übernehme, wie ich es bekomme
und an dem Objekt herum manipuliere, zum Beispiel mit Gettern und Zettern usw.,
dann hat das sehr wohl eine Auswirkung auf den Aufrufer.
Von daher könnte man meinen, dass der Aufruf mit Objekten als Parametern
ein CallByReference ist, ist er aber nicht.
Es ist auch ein CallByValue, aber ich kann halt eben die referenzierten Objekte ändern
und das hat dann auch eine Auswirkung auf den Aufrufer.
Ich merke gerade, dass das, glaube ich, ziemlich schwierig erklärt war,
was ich jetzt hier gerade erzählt habe.
Also wenn es dazu noch Fragen gibt, dann meldet euch gerne,
schreibt mir gerne einen Kommentar zur Episode,
dann versuche ich nochmal etwas Schönes rauszusuchen
oder erkläre das nochmal einmal mit anderen Worten vielleicht.
Aber ganz wichtig, merken, CallByValue ist Standard,
das heißt, es werden nicht die Variablen übergeben, sondern tatsächlich die Werte.
Und wenn ich die Werte verändere, dann interessiert das den Aufrufer hässlich wenig.
Das Einzige, was ich tun kann, um den Aufrufer einen Wert zurückzugeben,
ist eben ein Return zu machen, also wirklich einen Rückgabewert zurückzugeben.
Wenn ich die Parameter ändere, dann interessiert den Aufrufer eigentlich null.
Der kriegt davon gar nichts mit.
Und wenn ich halt ein ByReference mache, dann ist das sehr wohl der Fall,
dann kriegt er die Änderung mit, aber das ist nicht umsonst so.
Das Programmiersprachen darf das eigentlich von Haus aus heute nicht mehr machen.
Sagt sogar Microsoft zu C Sharp, wo das zum Beispiel möglich ist mit dem Ref,
bitte nicht benutzen, weil das dazu führt, dass es ganz schwierig wird,
nachzuvollziehen, wo denn irgendwelche Werte herkommen.
Denn ich habe einen Methodenaufruf, da gebe ich eine Variable rein
und ich kann da ja nicht reingucken manchmal in die Methoden
und dann weiß ich gar nicht, wieso jetzt auf einmal ein Wert verändert ist.
Und dann frage ich mich, wie kommt es jetzt zum Fehler in meinem Programm
und dann suche ich stundenlang nach dem Fehler.
Das wollen wir also eigentlich nicht.
Schöner ist es, wenn wir nur mit den Return-Werten arbeiten
und so Reference-Aufrufe uns am besten komplett sparen.
So, da habe ich noch eine ganz triviale Frage,
aber da denkt man vielleicht nicht unbedingt so dran.
Wenn ich jetzt eine Methode aufrufen möchte, wie mache ich denn das überhaupt?
Und da müsste man vielleicht einmal unterscheiden.
Es gibt eigentlich zwei Arten von Methoden in der Objektdenotierung,
nämlich einmal die sogenannten Instanzmethoden oder Objektmethoden
oder auch die statischen oder Klassenmethoden.
Und beide werden in Java zumindest mit dem gleichen Operator aufgerufen,
nämlich mit dem Punkt.
Wenn ich also ein Objekt habe, meinetwegen diese Person von eben,
die hat meinetwegen auch den Namen Person,
dann mache ich Person, Punkt und dann gib Person aus oder sowas.
Über den Punkt greife ich auf diese Methode zu.
Wenn ich stattdessen eine statische oder eine Klassenmethode habe,
dann mache ich das genauso, nämlich auch mit dem Punkt,
aber das rufe ich nicht an einem Objekt auf, sondern an der Klasse selber.
Da würde ich jetzt also sowas machen wie,
Person ist jetzt ein doofes Beispiel, weil die Klasse auch vielleicht Person heißt,
aber dann würde ich halt eben Person mit einem großen P schreiben
für die Klasse Person und dann Punkt gib Person aus.
Das heißt also, der Aufruf ist in beiden Fällen gleich,
nämlich der Punktoperator und dahinter dann der Name der Methode.
Aber bei Instanzmethoden steht ein Objekt vor dem Punkt
und bei Klassenmethoden steht der Klassenname vor dem Punkt.
So, dann ist gleich die nächste Frage, was ist denn jetzt der Unterschied zwischen beiden?
Instanzmethoden, wie der Name sagt, kann ich nur an einer Instanz aufrufen.
Das heißt, ich brauche auch eine Instanz.
Ich kann also zum Beispiel nicht an der Klasse Person sowas wie SetName aufrufen,
denn ein Name ist für eine konkrete Person individuell
und das ist also nicht für alle Personen auf der ganzen Welt identisch.
Und genau daran würde ich auch die Unterscheidung machen,
nämlich alles, was individuell für ein Objekt gültig ist,
ist über eine Instanzmethode aufzurufen
und alles, was zum Beispiel für alle Objekte dieser Klasse gleich sein muss,
kann man dann über eine Klassenmethode machen, also über eine statische Methode.
Und wie man jetzt so eine statische Methode definiert, ist eigentlich relativ simpel.
Ich nutze das Schlüsselwort Static
und Static schreibe ich einfach irgendwo vor die Methodensignatur,
also zum Beispiel sowas wie Public, Static, Void und so weiter.
Ja, dann geht's los.
Und das bedeutet dann, dass ich eben diese Methode auch aufrufen kann,
ohne mir ein Objekt zu erzeugen.
Sonst müsste ich halt in meinem Code sowas machen wie
new Person, also zum Beispiel Person p gleich new Person
und dann kann ich machen p Punkt gibt aus.
Wenn ich jetzt aber was aufrufe, was an der Klasse definiert ist,
brauche ich halt dieses ganze new Gedöns da nicht,
sondern ich kann einfach machen Person mit großem p Punkt
und dann irgendwas, was für alle Personen gleich ist,
wie zum Beispiel, ja, da fällt mir jetzt natürlich wieder nichts ein,
aber irgendetwas, was für alle Personen weltweit gleich wäre
und wo ich auch zum Beispiel gar nicht auf die Attribute einer konkreten Person zugreifen müsste,
das würde ich halt eben als statische Methode modellieren.
Und jetzt habe ich auch schon gleich wieder ein weiteres Schlüsselwort benutzt,
was wir in diesem Kontext brauchen, um das aufrufen zu können, ohne das zu erklären,
und zwar das Schlüsselwort new.
Was macht new?
New erzeugt einfach ein neues Objekt einer Klasse oder instanziiert eine Klasse.
Das sagt man auch dazu.
Genau wie ich es gerade im Beispiel gemacht habe,
Person p deklariert die Variable als Typ Person gleich new Person
und new, da wird halt eben dann ein neues Objekt der Klasse Person erzeugt.
Das werden wir in den nächsten Lernsekretoren sicherlich nochmal vertiefen,
wenn es um die Objektorientierung geht.
Für jetzt merken wir uns erstmal den Unterschied.
Es gibt eine Instanzmethode.
Dafür brauche ich ein Objekt und das erzeuge ich mit new.
Und es gibt statische Methoden.
Da nehme ich einfach direkt den Klassennamen.
Da muss ich überhaupt nichts instanziieren.
So, damit wäre ich jetzt mit meinen Themen für heute durch.
Ich hoffe, es war ein bisschen was Interessantes dabei.
Wenn ich noch was Wichtiges vergessen habe, was du unbedingt ergänzen würdest,
dann schreib mich doch einfach an.
Oder am besten schreib einen Kommentar zur Episode.
Dann sehen auch andere Leute das.
Das kannst du wie immer tun unter anwendungsentwicklerpodcast.de
slash 42, also die Zahl 4 2, für die heutige 42. Episode.
Da findest du die Shownotes zu der heutigen Episode mit einigen Links noch.
Zu weit dafür in der Literatur.
Unter anderem habe ich heute wieder mal verlinkt das allseits bekannte Buch
die Java-Insel oder auch die Java-Einführung.
Beide aus dem Rheinwerk-Verlag.
Das sind tolle Bücher, um mit Java loszulegen.
Wie gesagt, ich mache meine Letzigertreuen ja recht fokussiert auf Java,
weil ich das immer anhand von Java mache.
Aber grundsätzlich gilt das, was ich heute erzählt habe,
eigentlich auch in vielen anderen Programmiersprachen.
In C-Sharp kann man quasi sogar die Syntax fast 1 zu 1 übernehmen.
In der anderen Programmiersprache, meinetwegen in Ruby,
ist vielleicht dann nicht das New vor der Klasse, sondern hinter der Klasse.
Aber im Prinzip sind die Konzepte überall dieselben.
Nur die Syntax unterscheidet sich dann halt vielleicht mal ein bisschen.
Also grundsätzlich habe ich eigentlich bei allen meinen Letzigertreuen immer drunter geschrieben,
die Java-Insel ist eigentlich das perfekte Buch, um irgendwas mit Java zu lernen.
Über 1000 Seiten dick und da wird natürlich auch alles im Detail vorgestellt,
was ich heute erzählt habe.
Ich habe die wichtigsten Inhalte auch nochmal konkret auf das Openbook verlinkt.
Die Java-Insel ist ja glücklicherweise kostenfrei im Internet verfügbar,
in einer etwas älteren Version.
Und da habe ich genau die Sachen zur heutigen Episode,
nämlich Datenstrukturen, Algorithmen und auch Methoden einer Klasse verlinkt.
Da kannst du gerne mal reinschauen.
Auch das Java-Tutorial direkt von Oracle kann ich absolut empfehlen.
Kannst du auch mal reingucken, ist auch sehr gut geschrieben,
allerdings dann halt auf Englisch.
Das erklärt die ganzen Sachen, die ich heute hier erzählt habe,
natürlich auch nochmal einmal im Detail.
So, wenn du schon auf der Website bist und mir einen Kommentar gerade schreiben möchtest, dann
guck doch mal in den Blog. Da habe ich letzte Woche auch noch mal zwei ganz nette Sachen
veröffentlicht. Mein Link der Woche ging darüber, wie man jeden Code in jedem System testbar macht.
Wir haben ja noch nicht so viel über Unit-Tests gesprochen, aber es ist eines meiner Lieblingsthemen.
Da werde ich sicherlich auch noch mal in Zukunft eine Episode dazu machen. Und ich habe einen ganz
interessanten Artikel da verlinkt und auch ein super Buch, nämlich Working Effectively with
Legacy Code von Michael Feathers kann ich nur empfehlen, wenn man mit Alt-Software arbeiten
muss. Und der Artikel, den ich verlinkt habe, ist quasi so eine Kurzform, wie man auch, ich sage
mal, uralt Code, für den man noch keine Unit-Tests hat, testbar machen kann. Und zwar auch gefahrlos,
ohne in dem Prozess etwas kaputt zu machen. Und als Blog-Artikel habe ich letzte Woche etwas
umfangreich geschrieben zum Thema Verwendung von fremden Vorlagen in der Projektdokumentation.
Meine beliebteste Seite auf dem Blog ist ganz klar die Vorlage für die Projektdokumentation,
meine LaTeX-Vorlage. Und häufig erreichen mich dann auch Fragen von Prüflingen, darf ich das
überhaupt benutzen? Wie muss ich denn die Vorlage zitieren zum Beispiel? Oder gibt es vielleicht
Punktabzuche, wenn ich irgendwelche Sachen aus dem Internet benutze? Und meine Antwort dazu findest
du auf jeden Fall in einem ausführlichen Artikel auch auf der Website. Wenn du selber noch Empfehlungen
hast, vielleicht für coole Links, die du gelesen hast, dann immer her damit. Schick mir das gerne
rüber. Ich teile die Sachen gerne auch mit meinen Zuhörern und Lesern. Und natürlich erwähne ich
gerne auch deinen Namen und verlinke dich, wenn du irgendeinen Blog hast oder sowas. Also immer
her mit dem Content. Und ich freue mich auch über jegliches Feedback. Also wenn du mir eine Mail
schreiben willst oder mich am besten noch weiterempfehlen willst, mach das gerne unter
mail.anwendungsentwicklerpodcast.de kannst du mich jederzeit erreichen. Oder eben noch besser, schreib
einen Kommentar zu der Episode hier. Du kannst mich auch jederzeit anschreiben, wenn du irgendwelche
Fragen hast rund um die Ausbildung. Das nutze ich auch immer gerne, um zum Beispiel auf neue
Themenideen für die Episoden zu kommen. Also schreib mich da gerne an, wenn du möchtest. Und
ich empfehle natürlich auch noch, den Podcast zu abonnieren. Dann verpasst du keine neue Episode.
Du kannst direkt auf die Shownotes gehen und da findest du auch wie immer unter jeder Episode den
Link zum ESS-Feed, wo du den Podcast abonnieren kannst. Ansonsten, wenn du irgendwie mit mir in
Kontakt treten willst, ich fasse das Ganze jetzt mal kurz zusammen. Es geht wie immer unter
anwendungsentwicklerpodcast.de und dann ein entsprechendes Wort für das Social Network, wo
du mich dann erreichen kannst. Zum Beispiel iTunes, Stitcher, Facebook, Twitter, Xing. Die fünf Links
gibt es schon. Einfach hinter anwendungsentwicklerpodcast.de schreiben und dann landest du automatisch auf der Seite,
wo du mit mir in Kontakt treten kannst, wenn du das möchtest. Und wie immer gibt es auch zuletzt den
Hinweis auf mein Newsletter. Wenn du möchtest, trage dich gerne ein unter anwendungsentwicklerpodcast.de
slash Newsletter. Als kleines Dankeschön bekommst du gleich Zugriff auf meine Checklisten rund um
die Projektarbeit und du bekommst auch immer von mir regelmäßig Informationen rund um die
Neuigkeiten auf der Webseite. So verpasst du dann auch keine neuen Inhalte. Nächste Woche ist
die letzte Episode vor Weihnachten 2015 und da mache ich dann tatsächlich mal ganz langweilig
eine weitere Lernzielkontrolle. Und dann steigen wir, glaube ich, schon mal ein in die
Objektorientierung. Da wird es dann also durchaus etwas interessanter. Und dann überlege ich mir mal,
was ich für die Episode nach Weihnachten mir dann Tolles ausdenke. Da würde ich sagen,
machen wir mal wieder eine kleine Pause von den Lernzielkontrollen. Ansonsten,
wenn dir die Lernzielkontrollen was bringen oder wenn du noch weitere Inhalte hören willst oder
oder oder, dann melde dich einfach bei mir. Ich freue mich über jegliches Feedback und ich versuche
immer möglichst schnell auf alle möglichen Kontaktanfragen zu antworten. Also kontaktiere
mich gerne. Würde mich freuen. Ansonsten sage ich vielen, vielen Dank fürs Zuhören und bis zum
nächsten Mal. Tschüss.









Neueste Kommentare