diff --git a/notebooks/seminar03extra.ipynb b/notebooks/seminar03extra.ipynb
index 5c32c2e5d81bd269894d18cf40e158f3b8b1e36a..4048d0c2319a14d5ec12538d35b75f3a3e065e69 100644
--- a/notebooks/seminar03extra.ipynb
+++ b/notebooks/seminar03extra.ipynb
@@ -154,6 +154,8 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
+    "### 3.3 Und weiter\n",
+    "\n",
     "Sie kennen jetzt eine Funktion, um reguläre Ausdrücke in Python anzuwenden und damit Texte zu durchsuchen. Weitere Funktionen ermöglichen die Extraktion und das Ersetzen von Teilzeichenketten in Texten. Bevor wir diese Funktionen kennenlernen, ist es praktisch, mit regulären Ausdrücken vertraut zu werden. Eine sehr gute interaktive Übungsseite dazu finden Sie hier: https://regexone.com/lesson/introduction_abcs. Arbeiten Sie diese Seite gemeinsam Schritt für Schritt durch. Schrecken Sie nicht vor dem englischen Text zurück - ich helfe Ihnen bei Fragen gerne weiter.\n",
     "\n",
     "Es gibt noch viele andere gute Tutorials zu regulären Ausdrücken, z.B. [hier](https://ryanstutorials.net/regular-expressions-tutorial/) oder [hier](https://www.python-kurs.eu/re.php). Sie können auch eine dieser Anleitungen durcharbeiten, wenn Sie damit besser zurechtkommen."
diff --git a/notebooks/seminar04.ipynb b/notebooks/seminar04.ipynb
index 5d6695bda0a4df0680d5358e40422a0551c5f057..de5a1147ebd56c50504fd3c6113862c61b26a81d 100644
--- a/notebooks/seminar04.ipynb
+++ b/notebooks/seminar04.ipynb
@@ -498,6 +498,150 @@
     "Hätten wir vorausschauend geplant, hätten wir vielleicht `polyline` zuerst geschrieben und diese Umstrukturierung vermieden. Oft wissen wir aber am Anfang eines Projektes noch nicht genug, um schon alle Schnittstellen entwerfen zu können. Sobald wir anfangen zu programmieren, verstehen wir das Problem besser. Manchmal ist Refactoring ein Anzeichen dafür, dass wir etwas gelernt haben.\n"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 4.8 Ein Entwicklungsplan\n",
+    "\n",
+    "Ein **Entwicklungsplan** ist ein Prozess zum Schreiben von Programmen. Der Prozess, den wir in dieser Fallstudie verwendet haben ist \"Verkapselung und Verallgemeinerung\". Die Schritte dieses Prozesses sind:\n",
+    "\n",
+    "1. Wir schreiben ein kleines Programm ohne Funktionsdefinitionen.\n",
+    "2. Sobald das Programm funktioniert, identifizieren wir ein schlüssiges und zusammengehöriges Stück Code, verkapseln es in einer Funktion und geben ihm einen Namen.\n",
+    "3. Wir verallgemeinern die Funktion durch Hinzufügen geeigneter Parameter.\n",
+    "4. Wir wiederholen die Schritte 1 bis 3 bis wir eine Menge funktionierender Funktionen haben. Dabei kopieren wir Code und fügen ihn an der richtigen Stelle ein, um nochmaliges Eintippen zu vermeiden (und das damit ggf. verbundene Debugging).\n",
+    "5. Wir suchen nach Möglichkeiten, das Programm durch Refactoring zu verbessern. Wenn wir beispielsweise ähnlichen Code an verschiedenen Stellen haben, können wir überlegen, ob wir ihn nicht besser in eine geeignete allgemeine Funktion \"faktorisieren\". \n",
+    "\n",
+    "Dieser Prozess hat einige Nachteile (wir schauen uns Alternativen später an), aber er ist praktisch, wenn wir nicht vorab wissen, wie wir das Programm in Funktionen aufteilen könnten. Dieser Ansatz ermöglicht uns den Entwurf des Programms während wir es schreiben.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 4.9 Docstring\n",
+    "\n",
+    "Ein **Docstring** ist eine Zeichenkette am Anfang einer Funktion die die Schnittstelle der Funktion erklärt (\"doc\" ist kurz für \"documentation\", also Dokumentation). Hier ist ein Beispiel:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def polyline(t, n, length, angle):\n",
+    "    \"\"\"Draws n line segments with the given length and\n",
+    "    angle (in degrees) between them.  t is a turtle.\n",
+    "    \"\"\"    \n",
+    "    for i in range(n):\n",
+    "        t.fd(length)\n",
+    "        t.lt(angle)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Es gilt die Konvention, dass Docstrings in dreifachen Anführungszeichen gesetzt werden. Mit Hilfe der dreifachen Anführungszeichen kann der Text über mehr als eine Zeile hinwegreichen.\n",
+    "\n",
+    "Der Docstring im Beispiel ist knapp, enthält aber die wesentlichen Informationen, die jemand benötigt, der die Funktion nutzen möchte. Es wird prägnant erklärt, was die Funktion tut (ohne groß zu beschreiben, wie sie das tut). Es wird auch erklärt, welche Auswirkung jeder Parameter auf das Verhalten der Funktion hat und von welchem Typ jeder Parameter sein sollte (falls es nicht offensichtlich ist). \n",
+    "\n",
+    "Das Schreiben dieser Art von Dokumentation ist ein wichtiger Teil des Schnittstellenentwurfs. Eine gut konzipierte Schnittstelle sollte einfach zu erklären sein. Falls es Ihnen schwerfällt, Ihre Funktionen zu erklären, dann könnte es vielleicht helfen, die Schnittstelle zu verbessern. \n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 4.10  Debugging\n",
+    "\n",
+    "Eine Schnittstelle ist wie ein Vertrag zwischen der Funktion und den Aufrufenden. Die Aufrufenden stimmen zu, bestimmte Parameter bereitzustellen und die Funktion stimmt zu, eine bestimmte Aufgabe zu erledigen.\n",
+    "\n",
+    "Beispielsweise benötigt die Funktion `polyline` vier Parameter:\n",
+    "- `t` muss eine Schildkröte (Typ `Turtle`) sein,\n",
+    "- `n` muss eine ganze Zahl sein,\n",
+    "- `length` muss eine positive Zahl sein,\n",
+    "- `angle` muss eine Zahl sein, die einen Winkel in Grad darstellt.\n",
+    "\n",
+    "Diese Anforderungen nennen wir auch **Vorbedingungen**, denn es wird vorausgesetzt, dass sie erfüllt sind, bevor die Funktion ausgeführt wird. Umgekehrt heißen Bedingungen am Ende einer Funktion **Nachbedingungen**. Nachbedingungen schließen die beabsichtigte Wirkung der Funktion (wie z.B. ein Linienstück zeichnen) und etwaige Seiteneffekte (wie z.B. die Schildkröte zu bewegen oder andere Änderungen vorzunehmen) ein.  \n",
+    "\n",
+    "Die Erfüllung der Vorbedingungen ist die Aufgabe der Aufrufenden. Wenn die Aufrufenden eine (ordentlich dokumentierte!) Vorbedingung verletzen und die Funktion arbeitet nicht richtig, dann liegt der Fehler bei den Aufrufenden, nicht bei der Funktion.\n",
+    "\n",
+    "Wenn die Vorbedingungen erfüllt sind und die Nachbedingungen sind es nicht, dann liegt der Fehler bei der Funktion. Wenn ihre Vor- und Nachbedingungen klar und deutlich sind, dann kann das sehr beim Debugging helfen.\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 4.11  Glossar\n",
+    "\n",
+    "Legen wir uns eine Liste mit den wichtigsten Begriffen an, die wir im Kapitel 4 gelernt haben:\n",
+    "\n",
+    "- Methode: Eine Funktion, die zu einem Objekt gehört und mit Hilfe der Punktnotation aufgerufen wird.\n",
+    "- Schleife: \n",
+    "- Verkapselung: \n",
+    "- Verallgemeinerung:\n",
+    "- Schlüsselwortargument:\n",
+    "- Schnittstelle:\n",
+    "- Refactoring: Der Prozess, ein funktionierendes Programm zu verändern, um die Schnittstellen der Funktionen und andere Aspekte des Codes zu verbessern.\n",
+    "- Entwicklungsplan:\n",
+    "- Docstring:\n",
+    "- Vorbedingung:\n",
+    "- Nachbedingung:\n",
+    "\n",
+    "Ergänzen Sie die Liste in eigenen Worten. Das ist eine gute Erinnerungs- und Übungsmöglichkeit."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 4.12 Ãœbung\n",
+    "\n",
+    "#### Aufgabe 1\n",
+    "\n",
+    "Laden Sie den Code für dieses Kapitel hier herunter: http://thinkpython2.com/code/polygon.py\n",
+    "\n",
+    "*Für die folgenden Aufgaben benötigen Sie einen Editor, um den Code zu bearbeiten und Sie sollten mit der Ausführung von Python-Code ausserhalb von Jupyter vertraut sein. Alternativ können Sie versuchen, den Python-Code in ein leeres Jupyter-Notebook einzufügen und die Aufgaben dort zu lösen.*\n",
+    "\n",
+    "1. Zeichnen Sie ein Stapeldiagramm, welches den Zustand des Programms zeigt, während die Anweisung `circle(bob, radius)` ausgeführt wid. Sie können das manuell herausfinden, oder `print`-Anweisungen zum Code hinzufügen.\n",
+    "2. Die Version der Funktion `arc` in [Abschnitt 4.7](#4.7-Refactoring) ist nicht besonders präzise, denn die lineare Näherung eines Kreises ist immer ausserhalb des wahren Kreises. Daher steht die Schildkröte am Ende immer ein paar Pixel vom richtigen Ziel entfernt. Die Lösung im Python-Code zeigt eine Möglichkeit, die Auswirkung dieses Fehlers zu reduzieren. Lesen Sie sich den Code durch und schauen Sie, ob das für Sie einen Sinn ergibt. Vielleicht hilft es Ihnen weiter, ein Diagramm zu zeichnen.\n",
+    "\n",
+    "#### Aufgabe 2\n",
+    "\n",
+    "[Schildkröten-Blumen](http://greenteapress.com/thinkpython2/html/thinkpython2003.png)\n",
+    "\n",
+    "Schreiben Sie eine möglichst allgemeine Menge an Funktionen zum Zeichnen von solchen Blumen.\n",
+    "\n",
+    "*(Die [Lösung](http://thinkpython2.com/code/flower.py) benötigt auch [polygon.py](http://thinkpython2.com/code/polygon.py).)*\n",
+    "\n",
+    "#### Aufgabe 3\n",
+    "\n",
+    "[Schildkröten-Kuchen](http://greenteapress.com/thinkpython2/html/thinkpython2004.png)\n",
+    "\n",
+    "Schreiben Sie eine möglichst allgemeine Menge an Funktionen zum Zeichnen von solchen Figuren.\n",
+    "\n",
+    "*([Lösung](http://thinkpython2.com/code/pie.py))*\n",
+    "\n",
+    "#### Aufgabe 4\n",
+    "\n",
+    "*(Hinweis: Dies ist eher eine Fleiß- und Zusatzaufgabe.)*\n",
+    "\n",
+    "Die Buchstaben des Alphabets sind aus ein paar grundlegenden Elementen zusammengesetzt, wie z.B. vertikalen und horizontalen Linien und einigen Kurven. Entwerfen Sie ein Alphabet, welches mit einer kleinen Anzahl einfacher Elemente gezeichnet werden kann und schreiben Sie dann Funktionen zum Zeichnen der Buchstaben. \n",
+    "\n",
+    "Sie sollten eine Funktion für jeden Buchstaben schreiben, die Sie `draw_a`, `draw_b`, etc. nennen und diese Funktionen in eine Datei namens `letters.py` packen. Sie können [hier](http://thinkpython2.com/code/typewriter.py) eine \"Schildkrötenschreibmaschine\" herunterladen und damit ihren Code testen.\n",
+    "\n",
+    "Sie finden eine Lösung für diese Aufgabe hier: http://thinkpython2.com/code/letters.py; Diese benötigt auch http://thinkpython2.com/code/polygon.py.\n",
+    "\n",
+    "#### Aufgabe 5\n",
+    "\n",
+    "Lesen Sie etwas zu Spiralen auf Wikipedia: https://de.wikipedia.org/wiki/Spirale. Schreiben Sie dann ein Programm, welches eine [Archimedische Spirale](https://de.wikipedia.org/wiki/Archimedische_Spirale) (oder eine andere) zeichnet.\n",
+    "\n",
+    "Eine Lösung finden Sie hier: http://thinkpython2.com/code/spiral.py. "
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {},