2    Pair Programming

»Pair Programming« (im Deutschen mitunter Paarprogrammierung oder Tandem-Programmierung) bedeutet, dass Sie den Code gemeinsam mit einem KI-Tool erstellen. Dabei ist es selten eine gute Idee, dem KI-Werkzeug mitzuteilen: »Meine Aufgabenstellung ist so und so, gib’ mir die Lösung!« Das funktioniert nur bei einfachen Problemen bzw. relativ kurzen Funktionen, die in sich abgeschlossen sind.

In den meisten Kapiteln dieses Buchs richten wir uns an Programmierer oder Entwicklerinnen, die ihr Handwerk bereits einigermaßen sicher beherrschen. Wir setzen also voraus, dass Sie zumindest in einer Programmiersprache versiert sind, sicher mit Funktionen, Methoden und Klassen umgehen können. Idealerweise verfügen Sie auch schon über etwas IT-Hintergrundwissen, können also z. B. mit Datenbanken oder mit Git umgehen.

In diesem Kapitel machen wir diesbezüglich eine Ausnahme: Hier wenden wir uns speziell an Leser oder Leserinnen, die gerade dabei sind, eine Programmiersprache zu lernen. In den Beispielen zeigen wir, wie KI-Tools Ihnen dabei helfen können.

Aber obwohl wir in diesem Kapitel den Lernprozess in den Vordergrund stellen, eignet sich Pair Programming selbstverständlich auch für Profis! Je größer Ihr Vorwissen, je komplexer Ihr Projekt, desto wichtiger ist es, dass Sie Schritt für Schritt vorgehen, die Struktur des Programms also vorgeben und mit KI-Hilfe ein Detail nach dem anderen lösen oder verbessern. Und somit liegt die Zielsetzung dieses Kapitels nicht darin, Ihnen zu zeigen, wie eine IBAN-Verifizierungsfunktion oder ein Sudoku-Solver funktionieren. Diese Beispielanwendungen dienen vielmehr dazu, Ihnen Beispiele für eine vernünftige Anwendung von KI-Werkzeugen zu geben. Wir wollen Ihnen also vermitteln, wie »Prompt-Engineering« in der Praxis aussieht.

Unsere Beispiele verwenden die weitverbreiteten Sprachen Python und Java. Wenn Sie eine andere Sprache lernen, macht das aber nichts! Die hier präsentierten Prompts funktionieren genauso gut in anderen Sprachen. So wie in den weiteren Kapiteln dieses Buchs geht es nicht primär um die Antworten des KI-Werkzeugs (die wir oft gar nicht oder nur sehr stark verkürzt dargestellt haben), sondern darum, wie Sie dem KI-Tool möglichst zielführend Fragen stellen.

Das optimale KI-System

Wir haben für die Beispiele in diesem Kapitel durchgängig ChatGPT mit GPT-4o verwendet. Sie können aber ebenso gut eines der konkurrierenden Chat-Systeme einsetzen. Besonders gute Erfahrungen haben wir bei den Arbeiten an diesem Buch mit Claude von Anthropic gemacht (https://claude.ai/chat). Zum Zeitpunkt unserer Tests Mitte 2024 lieferte Claude nicht nur qualitativ ausgezeichnete Antworten, sondern war etwas weniger redselig. Gerade mit einem erst bescheidenen Programmierwissen sind die kürzeren Antworten oft leichter verdaulich. Sie sehen schon: Auch wenn ChatGPT aktuell die größte Bekanntheit hat, gibt es durchaus spannende Alternativen, die – bei moderater Nutzung – ebenfalls kostenlos sind.

Wenn Sie programmieren lernen und nicht eine Aufgabe möglichst rasch erledigen wollen, dann raten wir vom Einsatz eines Coding-Assistenten wie GitHub Copilot dringend ab. Typische Übungsaufgaben wie »Schreiben Sie eine Funktion, die testet, ob der Parameter eine Primzahl ist« oder »Entwickeln Sie eine Klasse zur Abbildung eines Bankkontos« sind für Code-Assistenten trivial. Sie müssen nur einen plausiblen Funktionsnamen wie testIfPrime angeben, da spuckt der KI-Assistent auch schon den ganzen Code aus. Sie sind schnell fertig, aber lernen wenig.

Chat-basierte Systeme sind zum Lernen besser geeignet. Idealerweise geben Sie explizit im ersten Prompt eines Chat-Verlaufs an, dass Sie Einsteiger sind, sich Hilfe und Denkanstöße wünschen, aber keinen fertigen Code.

2.1    Code in Funktionen strukturieren

Auch wenn wir in diesem Kapitel keine jahrelange Coding-Praxis voraussetzen, beginnen wir doch nicht bei null. (Dazu gibt es andere Bücher.) Wir gehen davon aus, dass Sie bereits wissen, was Variablen, Verzweigungen, Schleifen usw. sind, und dass Sie mit diesen Sprachkonstrukten umgehen können.

Erfahrungsgemäß besteht bei diesem Wissensstand die nächste Hürde darin, längeren Code sinnvoll in Funktionen zu strukturieren. Das ist der Punkt, an dem wir hier starten.

Ein Ansatzpunkt besteht darin, dass Sie Ihrem KI-Chatpartner ganz einfach den von Ihnen verfassten (Spaghetti-)Code übergeben und ihn fragen, ob er eine Möglichkeit sieht, den Code über mehrere Funktionen aufzuteilen.

Prompt: I wrote this Python code to estimate the quality of a password. Can you help me break the code down into functions? Please explain why and how.

(50 lines of code …)

So viel können wir Ihnen verraten: Nahezu immer wird der Code danach ordentlicher aussehen! ChatGPT schlägt gleichzeitig sinnvolle Funktions- und Parameternamen vor und kümmert sich auch um die Dokumentation des Codes, sollten Sie diese vernachlässigt haben. Probieren Sie den obigen Prompt oder eine ähnliche Formulierung mit Ihrem eigenen Code aus! (Auf die Verbesserung vorhandenen Codes mit KI-Hilfe gehen wir übrigens im Kapitel 4, »Refactoring«, noch intensiver ein.)

Selbst Funktionen definieren

Anfänglich ist die vorhin skizzierte Vorgehensweise lehrreich, aber früher oder später sollten Sie in der Lage sein, Ihren Code selbst sinnvoll in Teilfunktionen zu gliedern. Solange Ihnen das schwerfällt, können Sie gezielt um Hilfe bitten.

Beachten Sie den Aufbau des Prompts: Er beginnt mit einer relativ detaillierten Zusammenfassung von Hintergrundinformationen: Welche Programmiersprache, welche Zielsetzung, welche Datenstrukturen? Außerdem versuchen Sie, Ihrem KI-Chat-Partner klar zu machen, dass dieser nicht gleich den fertigen Code ausspucken soll (was ihm leicht fällt), sondern dass Sie sich ganz explizit Unterstützung bei der Strukturierung des Codes wünschen.

Prompt: In my Python script I have a nested list of numbers. I need to test if this list is a »magic square« where the row, column, and diagonal sums are all equal. Please help me only to find a structure for the code. How should I define and use functions? Please also explain parameters. Don’t provide the code, I want to write it myself.

To structure the code for checking if a nested list of numbers is a magic square, you can break down the problem into several smaller functions. Here’s how you can define and use functions, along with an explanation of their parameters:

(more details …)

Die Antwort ist ein großartiger Startpunkt, um das Programm nun Stück für Stück in kleinen Schritten zu implementieren.

Definition von Funktionen und Parametern

Der Ausgangspunkt für das zweite Beispiel ist eine Übungsaufgabe. Sie sollen eine Funktion programmieren, die Duplikate aus einer Liste entfernt. Ihr erstes Problem ist weniger der Code an sich als vielmehr die Definition der Funktion und der resultierende Datenfluss. Offensichtlich werden Sie die zu verarbeitende Liste als Parameter an die Funktion übergeben. Aber wie soll die Funktion das Ergebnis zurückgeben?

Im Prompt fassen Sie wiederum die Aufgabenstellung zusammen und geben an, mit welcher Programmiersprache Sie arbeiten. Wichtig ist auch hier: Es geht Ihnen nicht um den Code, sondern um eine Hilfestellung für die Deklaration der Funktion und den Aufbau Ihres Codes.

Prompt: I need to write a Python function to remove duplicates from a list. How should I define the function? Don’t provide actual code for the function.

To define a function for removing duplicates from a list in Python, you can follow these steps to structure the function:

(detailed explanation with more details …)

Im Anschluss an die obige, bereits gekürzte Antwort kann ChatGPT der Versuchung nicht widerstehen, doch (fast) fertigen Code zu liefern. Davon abgesehen ist die Antwort aber wiederum eine gute Grundlage, um im Anschluss selbst Code zu verfassen. Besonders gut gefallen hat uns, dass das KI-Tool darauf hinweist, dass Ihre Funktion auch mit Sonderfällen (leere Listen) zurechtkommen muss.

Vielleicht haben Sie in der Vergangenheit schon mit anderen Programmiersprachen gearbeitet. Bei manchen Sprachen können Sie die im Parameter übergebenen Daten verändern. Das kann vor allem bei großen Datenmengen effizienter sein. Wie sieht das bei Python aus?

Prompt: Instead of returning the result, is it possible or even recommended to modify the data passed as a parameter to a function?

Yes, it is possible to modify the data passed as a parameter to a function in Python, especially if the data type is mutable, such as a list. However, whether it is recommended depends on the context and the specific use case. Here’s a detailed explanation.

(two pages of details …)

Die Antwort ist symptomatisch: ChatGPT generiert bereitwillig schier endlose Mengen von Text, um die Vor- und Nachteile verschiedener Varianten auszuloten. Das KI-Tool vermeidet aber in den meisten Fällen eine eindeutige Empfehlung. Im vorliegenden Fall spricht fast alles, insbesondere aber die Lesbarkeit des Codes, gegen eine direkte Veränderung der Daten. Stattdessen ist das einfache Schema zweckmäßig, bei dem die Parameter als Input verarbeitet werden und return das Ergebnis (den Output) liefert.

Je nachdem, welches Sprachmodell Sie verwenden, kann die Antwort auf dieselbe Frage auch ganz anders aussehen. Die folgenden Zeilen wurden vom freien Sprachmodell llama3 generiert, das wir lokal mit Ollama ausgeführt haben. Uns hat diese Antwort besser gefallen, sowohl inhaltlich als auch in ihrer Verbindlichkeit.

In Python, it’s generally not recommended to modify the original data structure.

(more details …)

So, while it’s technically possible to modify the input list, I would recommend against it.

Wir haben unser Glück auch mit dem KI-Chat-Tool »Claude« von Anthropic versucht. Dessen Antwort war ähnlich unverbindlich wie bei ChatGPT, enthielt aber einen neuen Aspekt: Claude weist darauf hin, dass es manchmal zweckmäßig ist, zwei Versionen einer Funktion zu entwickeln, eine zur In-Place-Verarbeitung der Daten, die zweite mit der Rückgabe von Ergebnissen.

(pros and cons of both approaches …)

Alternative approach: A common Python convention is to provide both versions:

Der objektorientierte Ansatz, also die Anwendung einer Methode auf eine Liste, richtet sich allerdings an schon einigermaßen fortgeschrittene Python-Fans.

Detailfragen zu Funktionen und Parametern

Beim Umgang mit Funktionen und Parametern gibt es eine Menge Sonderfälle, die stark je nach Programmiersprache variieren. Natürlich können Sie die Online-Dokumentation oder ein Python-Buch lesen – Sie können aber auch einfach ein KI-Tool fragen. Wenn Sie keine Lust auf seitenlange Exkurse haben, sollten Sie um eine prägnante Formulierung der Antwort bitten. Gerade ChatGPT weist die Tendenz auf, ausschweifend zu antworten und viel mehr Details zu liefern, als Sie gerade brauchen.

Vergessen Sie nicht, den Namen der von Ihnen eingesetzten Programmiersprache in den Prompt einzubauen. (Bei Folgefragen können Sie darauf verzichten, dann kennt das Sprachmodell bereits den richtigen Kontext.)

Die erste Frage bezieht sich auf das häufig auftretende Problem, dass eine Funktion ein mehrteiliges Ergebnis zurückgeben soll. Beachten Sie wieder den Prompt: Um dem KI-Tool klarzumachen, worum es uns geht, haben wir gleich ein einfaches Beispiel mitgeliefert.

Prompt: Can my Python functions return more than one data item (for example, a string and a number)?

Yes, your Python functions can return more than one data item, such as a string and a number, using several methods. Here are the most common ways:

# use a comma-separated list of values to create a tuple
def get_info():
return "Hello", 42
# return a list containing the values
def get_info():
return ["Hello", 42]

(three more variants: dictionary, namedtuple, custom object …)

Ebenso viele Fragen ergeben sich für Programmiereinsteiger rund um die Deklaration der Parameterliste von Funktionen. Sie können das KI-Tool Ihrer Wahl dazu wie eine Studienkollegin oder einen Nachhilfelehrer befragen.

Prompt: Using Python, how can I define a function to pass a variable number of parameters? And how can I process those parameters inside the function?

Prompt: I want to use optional parameters with default values. What’s the Python way to do this?

Prompt: How should I name functions and parameters?

Prompt: Within a Python function, can I access/change variables defined outside?

Prompt: What is the recommended order for a function with several parameters?

ChatGPT läuft bei derartigen Fragen zu Hochform auf und beschreibt seitenlang alle erdenklichen Varianten und Sonderfälle. Wenn Sie weder Lust noch Zeit haben, sich das durchzulesen, müssen Sie dem KI-Tool klarmachen, dass es Ihnen nur um die Basics geht, dass Sie beim Programmieren noch am Anfang stehen.

Prompt: Once again please. Be concise, drop special cases. I am a Python beginner.

Die besten Antworten erhalten Sie, wenn Sie nicht nur detailliert fragen, sondern auch gleich einen konkreten Anwendungsfall oder ein Beispiel angeben.

Prompt: OK. Now, consider only required parameters. What should come first? Suppose I want to write a function to find and replace items in a list. What’s better, replace(data, find, replace) or replace(find, replace, data)?

For functions with only required parameters, the general guideline is to order parameters from the most important or the most specific to the least important or the most general (more details …). For a function that replaces items in a list, it’s clearer and more intuitive to place the data last:

def replace(find, replace, data):
# Code to replace items
pass

Why This Order? (More details …)

Code-Optimierung

Möglicherweise haben Sie schon funktionierenden Code, den Sie nur noch optimieren möchten. ChatGPT kann Ihnen auch dabei helfen. Kontrollieren Sie aber unbedingt nach jedem Schritt, ob Ihr Programm danach noch wie beabsichtigt funktioniert!

In den ersten beiden Prompts geht es darum, vorhandenen Code an die üblichen Python-Regeln anzupassen. ChatGPT kennt die Konventionen wie beispielsweise korrekte Einrückungen, die Benennung von Variablen und Funktionen bereits. Auf diese Details müssen Sie also nur eingehen, wenn Sie Sonderwünsche haben. Liefern Sie dann idealerweise Vorlagen und konkrete Anweisungen mit.

Prompt: Please adapt this code to the Python naming conventions.

(100 lines of code …)

Prompt: Could you find better names for the variables and functions used in this code?

Good examples are: total_sales, current_temperature, user_input_calculcated.

Don’t use: TotalSales, CurrentTemperature, UserInputCalculated.

Viele Programmierer sind bei der Kommentierung von Code recht nachlässig. Diese ungeliebte Arbeit können auch KI-Tools übernehmen (siehe auch Kapitel 6, »Software dokumentieren«). Im einfachsten Fall reicht dazu ein Mini-Prompt wie im ersten Beispiel aus.

Prompt: Please add comments to this code.

Je nachdem, wer Ihren Code samt Kommentaren lesen soll, sollten Sie diese Zielgruppe angeben. Beachten Sie aber, dass das KI-Tool zwar meist Ihren Code nachvollziehen kann, aber nicht erraten kann, warum Sie sich für eine bestimmte Vorgehensweise entschieden haben. KI-Kommentare können eigene Kommentare also nur teilweise ersetzen.

Prompt: Add comments to this file to make the code understandable to a novice programmer.

Tipp

Die nachträgliche Kommentierung von Code kann auch helfen, wenn Sie Code von einer Kollegin, aus dem Internet oder aus einer anderen Quelle erhalten haben und nicht richtig verstehen.

Vielleicht funktioniert die von Ihnen entwickelte Funktion zwar, ist aber sehr langsam oder beansprucht viel Speicherplatz. Wenn Sie ein KI-Tool um eine Code-Optimierung bitten, sollten Sie möglichst konkret sagen, was optimiert werden soll (z. B. die Geschwindigkeit).

Prompt: This function is rather slow. Do you see any way to make the code more efficient?

Prompt: When processing large files, this function uses far too much memory. Is there a way to reduce the memory consumption of the code?

Code-Reuse

KI-Tools sollten nicht Ihr einziges Hilfsmittel beim Erlernen einer Programmiersprache sein! Wenn Sie bei der Suche nach Code im Netz auf für Sie unverständliche Konstruktionen stoßen, können Sie sich diese erklären lassen. (So wie Sie nie blind von der KI generierten Code übernehmen dürfen, solange Sie diesen nicht wirklich verstehen, gilt diese Regel auch für Code von Stack Overflow oder anderen renommierten Seiten: Gut möglich, dass der Code korrekt ist, aber für eine ganz andere Anwendung gedacht ist als die, die Sie im Auge haben.)

Der folgende Prompt zeigt, wie Sie die Stärken des universellen Ratgebers Internet mit denen der KI verbinden. Hier soll Ihnen das KI-Tool die Funktion linalg.norm erklären, die Ihnen bisher unbekannt war.

Prompt: This function apparently calculates the distance between some points. Can you explain what np.linalg.norm() does?

def get_distances(points_xy): 
l1 = np.linalg.norm(
points_xy[0, :] - points_xy[1, :])
l2 = np.linalg.norm(
points_xy[1, :] - points_xy[2, :])
return l1, l2

Vielleicht wechseln Sie gerade von einer Sprache zu einer anderen, oder Sie haben einen Lösungsansatz für Ihr Problem im Internet in einer anderen Sprache gefunden. Die meisten KI-Werkzeuge sind in der Lage, Ihren Code von einer Sprache in eine andere zu übersetzen.

Prompt: Last year I wrote a PowerShell script to download the image of a web page. How can I re-write this code using Python?

(20 lines of PowerShell code …)

Nach unseren Erfahrungen funktionieren solche Code-Umwandlungen nicht immer perfekt. Jede Programmiersprache, jede Bibliothek hat ihre Eigenheiten. Nehmen Sie sich Zeit, um den Code gründlich zu testen und seine Funktionen zu hinterfragen. Wenn Sie programmieren lernen wollen und nicht die schnelle Erledigung einer Aufgabe im Vordergrund steht, ist es noch besser, die vom KI-Bot vorgeschlagenen Module oder Bibliotheken als Startpunkt für eine eigene Recherche zu verwenden und den Code dann selbstständig neu zu entwickeln.

Code über mehrere Dateien aufteilen

Bei kleineren Programmen ist die Zerlegung in eigenständige Funktionen ausreichend, damit der Code lesbar, übersichtlich und wartbar bleibt. Bei komplexen Anwendungen kommt aber irgendwann der Punkt, wo es zweckmäßig ist, den Code über mehrere Dateien zu verteilen.

Im folgenden Prompt haben wir das KI-Tool gebeten, eine ca. 250 Zeilen lange Code-Datei in Teilfunktionen zu zerlegen. Dabei ist es uns nicht nur um die Erledigung der Arbeit an sich gegangen, wir wollten auch wissen, warum sich das KI-Tool für eine bestimmte Vorgehensweise entscheidet.

Prompt: I have written a long Python script, and I want to split the code in a logical way across more than one code file. Can you help? Please explain why and how.

(250 lines of code …)

To split your Python script logically across multiple files, we’ll use a modular approach. The goal is to organize your code into coherent units that make it easier to maintain, understand, and test. Here’s a step-by-step breakdown of how to do it:

Benefits of Modularization (more details …)

Bei dem von uns verwendeten Beispielcode hat ChatGPT tatsächlich einen sinnvollen Weg gefunden, den Code über mehrere Dateien zu verteilen, die jede für sich gut erweiterbar sind. Aber vielleicht ist Ihnen das Konzept von Python-Modulen noch gar nicht bekannt. Sie haben sicher schon fertige Module verwendet, aber noch keine eigenen definiert.

Prompt: Looks good. However, I am not yet familiar with creating modules. I have used Python modules before, but I have never written modules myself. Can you explain the basic concepts of how to create my own modules? Be concise!

Die Antwort lässt nichts zu wünschen übrig. Na ja, ChatGPT geht gleich auch auf Packages ein. Wenn Sie nicht wissen, was das ist (im Prinzip: mehrere Module in einem Verzeichnis), stellen Sie eine Folgefrage.

Prompt: What’s the difference between a module and a package?

Wenn Sie sich jetzt noch die Zeit nehmen, die von ChatGPT vorgeschlagenen Modul- und Package-Beispiele selbst auszuprobieren und vielleicht da und dort zu erweitern, sind Sie ein, zwei Stunden später mit dem Konzept vertraut. Großartig!

Tipps

Bei der Organisation von Code über mehrere Dateien gibt es große Unterschiede zwischen gängigen Programmiersprachen. Daher ein letztes Mal der Tipp: Geben Sie unbedingt an, in welcher Sprache Sie programmieren!

Beachten Sie außerdem, dass viele KI-Tools Probleme damit haben, sehr langen Code zu verarbeiten. Während die Aufteilung eines 250-zeiligen Codes über drei, vier Dateien wunderbar funktioniert, scheitern ChatGPT & Co häufig, wenn der Code-Umfang 500 oder 1000 Zeilen überschreitet. Warten Sie mit dem Zerlegen also nicht zu lange! Die Ursache für das Scheitern bei langen Code-Dateien sind Limits für die Größe des Kontextfensters und für die Länge der Antwort (siehe auch Tabelle 1.1 im Abschnitt 1.2, »Die Kunst des Prompting«).