Modul 2 von 6

Programmieren lernen

Programmieren ist keine Begabung, sondern eine Fertigkeit wie Autofahren: Am Anfang musst du über jeden Handgriff nachdenken, nach einiger Zeit machst du ihn nebenbei. Der einzige Weg dorthin führt über das Selbertippen. Jedes Beispiel auf dieser Seite kannst du sofort ausführen und verändern.

Fortschritt in diesem Modul 0 von 9 Lektionen
Warum hier JavaScript?

Im Studium wirst du wahrscheinlich mit Java anfangen, bei SAP später mit ABAP arbeiten. Hier lernst du mit JavaScript - aus einem praktischen Grund: Es läuft in jedem Browser, du musst nichts installieren und siehst das Ergebnis sofort.

Das ist kein Umweg. Variablen, Schleifen, Funktionen und Objekte funktionieren in allen drei Sprachen gleich - nur die Schreibweise unterscheidet sich. Zu jedem Thema findest du deshalb einen Vergleich mit Java und Python.

1. Was ist ein Programm?

Ein Programm ist eine Liste von Anweisungen, die von oben nach unten abgearbeitet werden. Mehr ist es im Kern nicht. Alles Weitere - Verzweigungen, Schleifen, Funktionen - sind nur Regeln, die diese Reihenfolge steuern.

Das Kochrezept

Ein Rezept sagt: Backofen vorheizen, Mehl abwiegen, Eier unterrühren, 40 Minuten backen. Ein Programm sagt: Wert einlesen, prüfen, umrechnen, ausgeben. Der Unterschied ist, dass ein Koch mitdenkt und der Computer nicht. Steht "40 Minuten" da, wartet er 40 Minuten - auch wenn der Kuchen schon schwarz ist.

Dein erstes Programm

console.log(...) gibt etwas aus. Drück auf Ausführen und schau, was passiert. Ändere danach den Text und führ es noch einmal aus.

Die häufigsten Anfängerfehler
  • Eine vergessene schließende Klammer oder ein fehlendes Anführungszeichen.
  • Groß- und Kleinschreibung: Console.log funktioniert nicht, console.log schon. Der Computer ist da gnadenlos.
  • Deutsche Anführungszeichen („…") statt gerader ("…"). Passiert oft beim Kopieren aus Word.
Fehlermeldungen sind Hilfe, keine Beschimpfung

Lösch versuchsweise ein Anführungszeichen im Beispiel oben und führ es aus. Du bekommst so etwas wie SyntaxError: Invalid or unexpected token. Der Computer sagt dir damit: "In dieser Zeile steht etwas, das ich nicht deuten kann." Gewöhn dir früh an, Fehlermeldungen zu lesen statt sie wegzuklicken - das ist der größte einzelne Unterschied zwischen Anfängern und Fortgeschrittenen.

2. Variablen und Datentypen

Eine Variable ist ein benannter Behälter für einen Wert. Du legst etwas hinein, holst es später wieder heraus und kannst den Inhalt austauschen.

Die beschriftete Schublade

Auf der Schublade steht kundenname, darin liegt der Zettel "Meier". Später kannst du den Zettel austauschen - die Beschriftung bleibt. Deshalb heißt es Variable: veränderlich.

let alter = 19;              // eine Zahl
const name = "Sarah";        // ein Text, unveränderlich
let istEingeschrieben = true; // ein Wahrheitswert
let oder const?

const für Werte, die sich nie ändern. let für alles andere. Nimm im Zweifel const - dann meckert der Computer, falls du den Wert versehentlich überschreibst, und du findest den Fehler sofort statt in drei Stunden. (Das alte var solltest du nicht mehr verwenden.)

Die wichtigsten Datentypen

TypWas drinstehtBeispielIn Java heißt es
Zahlganze und Kommazahlen42, 3.14int, double
Text (String)Zeichenketten in Anführungszeichen"Hallo"String
Wahrheitswertnur true oder falsetrueboolean
Arrayeine Liste von Werten[1, 2, 3]int[], List
ObjektWerte mit Namen{ name: "Meier" }eigene Klasse
nullausdrücklich kein Wertnullnull
Kommazahlen rechnen ungenau - überall

Führ das nächste Beispiel aus: 0.1 + 0.2 ergibt nicht 0.3, sondern 0.30000000000000004. Das ist kein Fehler dieser Sprache, sondern gilt in Java, Python und fast überall. Der Grund: 0,1 lässt sich im Binärsystem nicht exakt darstellen, genauso wenig wie 1/3 im Dezimalsystem. Deshalb rechnet man Geldbeträge nie mit Kommazahlen, sondern in Cent als ganze Zahlen oder mit speziellen Dezimaltypen. In Buchhaltungssystemen wie SAP ist das eine harte Regel.

3. Rechnen und Vergleichen

ZeichenBedeutungBeispielErgebnis
+ - * /Grundrechenarten7 / 23.5
%Rest der Division7 % 21
===ist gleich3 === 3true
!==ist ungleich3 !== 4true
< > <= >=Größenvergleich5 >= 5true
&&logisches UNDtrue && falsefalse
||logisches ODERtrue || falsetrue
!Verneinung!truefalse
Ein Gleichheitszeichen oder drei?

= weist zu: "schreib das da hinein".
=== vergleicht: "ist das dasselbe?"
Das zu verwechseln ist der Klassiker unter den Anfängerfehlern - und in manchen Sprachen ergibt if (x = 5) sogar ein gültiges, aber falsches Programm.

Der Modulo-Operator ist nützlicher, als er aussieht

% liefert den Rest. Damit prüfst du Teilbarkeit: zahl % 2 === 0 ist genau dann wahr, wenn die Zahl gerade ist. Mit % 3 teilst du Daten gleichmäßig auf drei Server auf. Dieselbe Idee steckt hinter Prüfziffern von IBAN und Barcodes.

4. Verzweigungen: if und else

Bis jetzt lief jedes Programm stur von oben nach unten. Mit if trifft es Entscheidungen.

if (bedingung) {
  // läuft nur, wenn die Bedingung wahr ist
} else {
  // läuft in allen anderen Fällen
}
Die Weiche

Ein Zug fährt auf eine Weiche zu. Die Bedingung entscheidet, welches Gleis er nimmt. Danach fährt er auf jeden Fall weiter - nur eben auf einem von zwei Wegen.

Mehrere Fälle hängt man mit else if aneinander. Wichtig: Die Prüfung läuft von oben nach unten und hört beim ersten Treffer auf. Die Reihenfolge ist deshalb nicht beliebig.

Warum die Reihenfolge entscheidend ist

Stünde umsatz >= 1000 ganz oben, bekäme jeder Kunde über 1000 Euro nur 5 Prozent - die späteren Zweige würden nie erreicht. Bei gestaffelten Bedingungen gilt: von der engsten zur weitesten prüfen. Vertausch im Beispiel oben testweise die Zweige und schau, was passiert.

5. Schleifen: Dinge wiederholen

Eine Schleife wiederholt einen Block, solange eine Bedingung gilt. Ohne Schleifen müsstest du für 5000 Rechnungspositionen 5000 Zeilen schreiben.

Die for-Schleife

for (let i = 0; i < 5; i++) {
  console.log(i);
}
//   ┬        ┬        ┬
//   │        │        └─ nach jedem Durchlauf: i um 1 erhöhen
//   │        └────────── solange das gilt, weiterlaufen
//   └─────────────────── Startwert
Warum bei 0 anfangen?

In fast allen Programmiersprachen wird ab 0 gezählt. Eine Liste mit 5 Einträgen hat die Positionen 0, 1, 2, 3, 4 - nicht 1 bis 5. Der letzte gültige Index ist also immer länge - 1. Fast jeder Anfängerfehler bei Schleifen ist ein Vertun um genau eins.

Die while-Schleife

for nimmt man, wenn die Anzahl der Durchläufe vorher feststeht, while, wenn nicht - etwa "solange noch Daten kommen".

Die Endlosschleife

Wenn die Abbruchbedingung nie eintritt, läuft die Schleife ewig. Auf dieser Seite wird der Code nach 4 Sekunden abgebrochen, es kann also nichts passieren - probier es ruhig aus. Im Studium ist eine hängende Endlosschleife eine Erfahrung, die jeder mindestens einmal macht.

Aufgabe: Summe berechnen

Schreib eine Schleife, die alle Zahlen von 1 bis 100 zusammenzählt, und leg das Ergebnis in summe ab. Der Prüfen-Knopf sagt dir, ob es stimmt.

Lösung anzeigen
let summe = 0;

for (let i = 1; i <= 100; i++) {
  summe = summe + i;   // kürzer: summe += i;
}

console.log("Summe:", summe);   // 5050

Übrigens: Der Mathematiker Gauß soll diese Aufgabe als Kind ohne Schleife gelöst haben. Es gibt eine Formel dafür: n · (n+1) / 2, also 100 · 101 / 2 = 5050. Eine Rechnung statt hundert - genau darum geht es in Modul 3.

6. Funktionen

Eine Funktion ist ein benannter Codeblock, den du beliebig oft aufrufen kannst. Sie nimmt Werte entgegen (Parameter) und gibt einen Wert zurück (Rückgabewert).

Die Kaffeemaschine

Du gibst Bohnen und Wasser hinein (Parameter), drückst den Knopf (Aufruf) und bekommst Kaffee heraus (Rückgabewert). Wie sie innen arbeitet, musst du nicht wissen. Genau das ist der Zweck: Komplexität hinter einem Namen verstecken.

function bruttoPreis(netto, steuersatz) {
  return netto * (1 + steuersatz / 100);
}

const preis = bruttoPreis(100, 19);   // 119
Warum Funktionen so wichtig sind
  • Nicht wiederholen: Ändert sich der Steuersatz, änderst du eine Stelle statt vierzig.
  • Namen erklären: bruttoPreis(100, 19) versteht man auch nach einem halben Jahr noch, 100 * 1.19 nicht.
  • Prüfbar: Eine Funktion mit klarer Ein- und Ausgabe kann man automatisch testen - genau das macht der Prüfen-Knopf hier.

Aufgabe: Rabattfunktion

Schreib eine Funktion rabattPreis(preis, prozent), die den Preis nach Abzug des Rabatts zurückgibt. Bei 100 Euro und 20 Prozent sollen 80 herauskommen.

Lösung anzeigen
function rabattPreis(preis, prozent) {
  return preis - (preis * prozent / 100);
}

// gleichwertig und etwas eleganter:
function rabattPreis(preis, prozent) {
  return preis * (1 - prozent / 100);
}

Das häufigste Missgeschick hier: das return vergessen. Ohne return gibt eine Funktion undefined zurück, auch wenn innen alles richtig gerechnet wurde.

7. Listen und Objekte

Einzelne Variablen reichen nicht weit. Echte Programme arbeiten mit Sammlungen.

Arrays: eine nummerierte Liste

const preise = [10, 25, 7, 42];

preise[0]        // 10   - das erste Element hat den Index 0
preise.length    // 4    - Anzahl der Elemente
preise[preise.length - 1]  // 42 - das letzte Element

Objekte: Werte mit Namen

Bei einem Kunden willst du nicht wissen, was an Position 2 steht, sondern was der ort ist. Dafür gibt es Objekte:

const kunde = {
  nummer: 4711,
  name:   "Meier GmbH",
  ort:    "Walldorf",
  umsatz: 125000,
};

kunde.name          // "Meier GmbH"
kunde.umsatz        // 125000
Array oder Objekt?

Array, wenn du mehrere gleichartige Dinge hast (alle Kunden).
Objekt, wenn ein Ding mehrere unterschiedliche Eigenschaften hat (ein Kunde).
In der Praxis kombiniert man beides: ein Array von Objekten. Genau so sieht eine Datenbanktabelle aus - und genau so kommen Daten aus einer Schnittstelle zurück.

Das kommt dir bald bekannt vor

filter, map und reduce sind genau das, was SQL mit WHERE, SELECT und SUM macht - nur im Programmcode statt in der Datenbank. Wenn du Modul 4 erreichst, wirst du das Muster wiedererkennen.

8. Objektorientierung

Bei größeren Programmen reicht es nicht, Daten und Funktionen lose nebeneinander zu legen. Die objektorientierte Programmierung (OOP) bündelt beides: Daten und die dazu passenden Funktionen wandern in eine Klasse.

Bauplan und Haus

Eine Klasse ist der Bauplan, ein Objekt das fertige Haus. Aus einem Bauplan kann man beliebig viele Häuser bauen - jedes mit eigener Adresse und eigener Wandfarbe, aber alle mit demselben Grundriss. Das Erzeugen eines Objekts aus einer Klasse heißt Instanziierung.

Die vier Grundprinzipien

Kapselung

Die Daten eines Objekts sind vor direktem Zugriff von außen geschützt. Änderungen laufen über Methoden, die prüfen können - so kann kein Konto einen negativen Bestand bekommen, nur weil jemand von außen hineingeschrieben hat.

Vererbung

Eine Klasse kann Eigenschaften einer anderen übernehmen. Firmenkunde erbt alles von Kunde und ergänzt die Handelsregisternummer, statt alles zu wiederholen.

Polymorphie

Verschiedene Klassen reagieren unterschiedlich auf denselben Aufruf. rabatt() rechnet beim Privatkunden anders als beim Firmenkunden - der aufrufende Code muss den Unterschied nicht kennen.

Abstraktion

Ein Modell bildet nur das ab, was für die Aufgabe zählt. Ein Kunde im Rechnungssystem hat eine Steuernummer, aber keine Augenfarbe.

Für dein Studium

Objektorientierung ist das beherrschende Modell in Java und auch in modernem ABAP (dort heißt es ABAP Objects). Die vier Prinzipien oben sind eine Standardfrage in mündlichen Prüfungen - lern sie mit je einem eigenen Beispiel, nicht mit der Definition.

9. Fehler finden und behandeln

Programmieren besteht zum größeren Teil aus Fehlersuche. Das ist kein Zeichen von Unfähigkeit, sondern der Normalzustand des Berufs. Es hilft, drei Fehlerarten zu unterscheiden:

ArtWann er auffälltBeispiel
Syntaxfehler sofort, das Programm startet gar nicht fehlende Klammer
Laufzeitfehler während der Ausführung, das Programm bricht ab Zugriff auf ein Element, das es nicht gibt
Logikfehler gar nicht - das Ergebnis ist einfach falsch < statt <= geschrieben
Der gefährlichste ist der dritte

Ein abgestürztes Programm merkt jeder. Eine Rechnung, die um einen Cent daneben liegt, fällt vielleicht erst nach Monaten auf - dann aber teuer. Deshalb schreibt man Tests.

Die Fehlersuche in vier Schritten

  1. Fehlermeldung lesen. Sie nennt Datei und Zeile. Das klingt banal, wird aber ständig übersprungen.
  2. Ausgaben einbauen. console.log vor und hinter der verdächtigen Stelle zeigt dir, welche Werte tatsächlich ankommen. Fast immer ist es nicht der, den du erwartet hast.
  3. Halbieren. Kommentier die Hälfte des Codes aus. Tritt der Fehler noch auf? So grenzt du die Stelle in wenigen Schritten ein.
  4. Laut erklären. Erklär den Code einer anderen Person - oder einer Gummiente auf dem Schreibtisch. Beim Formulieren fällt einem der Fehler auffallend oft selbst auf. Der Trick heißt tatsächlich "Rubber Duck Debugging".

Fehler abfangen mit try/catch

Manche Fehler kann man nicht verhindern - eine Netzwerkverbindung bricht ab, eine Datei fehlt. Damit das Programm dann nicht abstürzt, fängt man sie ab:

Dieselbe Sache in drei Sprachen

Damit dich der Wechsel im Studium nicht überrascht: Hier ist derselbe Gedanke - eine Funktion, die Werte aus einer Liste summiert - dreimal aufgeschrieben.

JavaScript
function summe(zahlen) {
  let s = 0;
  for (const z of zahlen) {
    s += z;
  }
  return s;
}
Java - Typen müssen angegeben werden
public static int summe(int[] zahlen) {
    int s = 0;
    for (int z : zahlen) {
        s += z;
    }
    return s;
}
Python - Einrückung statt geschweifter Klammern
def summe(zahlen):
    s = 0
    for z in zahlen:
        s += z
    return s
Was sich unterscheidet - und was nicht

Unterschiedlich sind Klammern, Semikolons und die Frage, ob Datentypen hingeschrieben werden müssen. Identisch ist der Gedanke: Startwert setzen, durchlaufen, aufsummieren, zurückgeben. Wenn du das Denken beherrschst, ist eine neue Sprache eine Sache von Tagen, nicht von Monaten.

Übungen

Aufgabe 1 · leicht

Schreib eine Funktion istGerade(zahl), die true zurückgibt, wenn die Zahl gerade ist.

Lösung anzeigen
function istGerade(zahl) {
  return zahl % 2 === 0;
}

Nicht nötig ist if (zahl % 2 === 0) { return true; } else { return false; } - der Vergleich liefert bereits true oder false.

Aufgabe 2 · mittel

Schreib groessterWert(zahlen), die den größten Wert einer Liste zurückgibt - ohne Math.max zu benutzen.

Lösung anzeigen
function groessterWert(zahlen) {
  let groesster = zahlen[0];
  for (const z of zahlen) {
    if (z > groesster) {
      groesster = z;
    }
  }
  return groesster;
}

Die entscheidende Stelle: Der Startwert muss das erste Element sein, nicht 0. Sonst liefert die Funktion bei lauter negativen Zahlen fälschlich 0 - genau deshalb ist der zweite Test in der Liste.

Aufgabe 3 · mittel

Schreib zaehleGrosskunden(kunden), die zählt, wie viele Kunden mehr als 100 000 Euro Umsatz haben.

Lösung anzeigen
function zaehleGrosskunden(kunden) {
  let anzahl = 0;
  for (const k of kunden) {
    if (k.umsatz > 100000) {
      anzahl++;
    }
  }
  return anzahl;
}

// kürzer:
function zaehleGrosskunden(kunden) {
  return kunden.filter(k => k.umsatz > 100000).length;
}

Der dritte Test prüft die Grenze: "mehr als 100 000" heißt >, nicht >=. Solche Grenzfälle sind in Klausuren und in echten Projekten die häufigste Fehlerquelle.

Aufgabe 4 · schwer

Schreib istPrimzahl(n). Eine Primzahl ist nur durch 1 und sich selbst teilbar. Achtung bei den Randfällen: 0 und 1 sind keine Primzahlen, 2 ist die kleinste.

Lösung anzeigen
function istPrimzahl(n) {
  if (n < 2) return false;

  for (let i = 2; i * i <= n; i++) {
    if (n % i === 0) return false;   // Teiler gefunden
  }
  return true;
}

Warum i * i <= n und nicht i < n? Hat eine Zahl einen Teiler, der größer als ihre Wurzel ist, dann gibt es dazu zwangsläufig einen zweiten, der kleiner ist - und den hätte die Schleife längst gefunden. Bei n = 1 000 000 sind das 1000 Durchläufe statt einer Million.

Das ist ein erster Vorgeschmack auf Modul 3: Dieselbe Aufgabe, hundertfach schneller, nur durch eine bessere Abbruchbedingung.

Selbsttest

Karteikarten zu diesem Modul

Wenn du tiefer einsteigen willst

  • "Java ist auch eine Insel" von Christian Ullenboom - kostenlos online lesbar und das gängigste deutschsprachige Java-Buch. Passend, wenn deine Vorlesung mit Java startet.
  • exercism.org oder Codewars - kleine Übungsaufgaben mit automatischer Prüfung. Zwei Aufgaben am Tag bringen mehr als ein Wochenende Videos.
  • "Clean Code" von Robert C. Martin - ab dem zweiten Semester interessant, wenn du merkst, dass funktionierender Code und guter Code zwei Dinge sind.