FAQs – Programmieren lernen

FAQs – Programmieren lernen

Wie kann ich Fehler in meinem Programm finden und beheben?

Zum Finden von Fehlern gibt es verschiedene Möglichkeiten.

Zielführend kann beispielsweise ein Schreibtischtest sein. Solch ein Test hilft, den geschriebenen Code besser nachvollziehen zu können.

Eine weitere Möglichkeit bietet die Verwendung von Testausgaben. Werte von Variablen und Zwischenergebnisse von Berechnungen werden auf die Konsole zur Kontrolle ausgegeben. Dabei sollte man Überlegungen bezüglich geeigneter Testdaten anstellen. Will man beispielsweise einen Sortieralgorithmus implementieren, ist es hilfreich, in der Entwicklungsphase mit einem kleinen, repräsentativen Datensatz zu arbeiten. Nur so sind die Kontrollausgaben leicht nachvollziehbar.

Verwendet man eine geeignete Entwicklungsumgebung, kann man auf einen Debugger zurückgreifen. Mit dem Debugger kann ein Programm an bestimmten Stellen (Breakpoint) angehalten oder zeilenweise ausgeführt werden. Immer wenn das Programm anhält, werden die Inhalte der Variablen angezeigt.

Wie kann ich meinen Code gut strukturieren?

Zur Strukturierung von Code kann man Methoden, Klassen, Pakete sowie Schnittstellenbeschreibungen in Form von Interfaces verwenden.

Methoden haben verschiedene Aufgaben. Sie fassen öfter benötigte Funktionalitäten zusammen um Redundanzen zu vermeiden. Solche Funktionalitäten können Zugriffe auf Zustände eines Objektes, das Erzeugen eines Objektes, mathematische Funktionen, … sein. Beim Schreiben von Methoden ist es wichtig, die richtige Granularität zu finden. Wird zu viel Funktionalität in einer Methode zusammengefasst, besteht die Gefahr, dass die Methode zu speziell für die Wiederverwendung ist. Außerdem wird das Testen erschwert. Wird Funktionalität in zu viele Methoden aufgeteilt, kann sich das Nachteilig auf die Lesbarkeit und Wartbarkeit des Codes auswirken.

Klassen werden verwendet, um zusammengehörende Funktionalitäten zu sammeln und Abhängigkeiten zwischen Klassen zu modellieren. Dabei spielen Vererbungshierarchien und Interfaces eine zentrale Rolle. Konstruktive Anregungen für die Entwicklung von Klassenstrukturen liefern Design-Pattern.

Eine zusätzliche Strukturierungsmöglichkeit bieten inhaltlich zusammengehörende Klassen, die in Paketen gebündelt werden.

Gute Code-Strukturierung lernt man nicht von heute auf morgen. Erst aus Erfahrung mit vielen kleineren und mehreren größeren Projekten lernt man, wie man Interfaces, Vererbung, Abhängigkeiten, … richtig einsetzt.

Wie wird man ein guter Programmierer / eine gute Programmiererin? Was macht einen guten Programmierer / eine gute Programmiererin aus?

Das wird man, indem man algorithmisches und lösungsorientiertes Denken trainiert. Mehr dazu findest du in unserer FAQ hier.

Was ist ein Schreibtischtest?

Schreibtischtests tragen zu einem besseren Verständnis von Algorithmen bei. Sie werden üblicherweise mit Papier und Bleistift durchgeführt. Mit Hilfe eines Schreibtischtests kann man jeden terminierenden Algorithmus schrittweise nachvollziehen, indem man in jedem Schritt die Werte der Variablen in einer Tabelle notiert.

Beispiele findet man unter anderem auf den Folien 11 – 13 in Grundlagen der Programmierung, Mössenböck.

Wie schreibe ich Code, so dass er einfach und leserlich für andere ist?

Ein zentraler Punkt in diesem Zusammenhang ist die Strukturierung des Codes in Klassen und Pakete, die das Problem abbilden (Design-Pattern). Darüber hinaus ist es sinnvoll, nach Möglichkeit die Algorithmen und Datenstrukturen aus der Klassenbibliothek zu verwenden, da deren Funktionsweise bekannt, dokumentiert und getestet ist.

In den Klassen ist zur Gewährleistung der Lesbarkeit auf eine sinnvolle Aufteilung des Codes in Methoden zu achten. Die Sichtbarkeit (public, private, …) von Attributen und Methoden schafft Übersichtlichkeit.

Außerdem ist es sehr wichtig, passende Namen für Pakete, Klassen, Methoden und Variablen zu wählen.

Bei der Erstellung von Code gilt es Konventionen einzuhalten. In Java beginnen Methodennamen mit einem Kleinbuchstaben, Klassennamen mit einem Großbuchstaben, … . Weiters sind bei Methodennamen gewisse Präfixe konventionell: getX, setX, isX, …

Dokumentationen (javadoc) und Kommentare an den richtigen Stellen können zur Verständlichkeit des Codes beitragen.

Wie viel Zeit sollte ich jeden Tag für die Programmierung aufwenden?

Wie viel Zeit man täglich für die Programmierung aufwenden soll oder will, hängt von verschiedenen Faktoren ab.

Zum einen spielen die persönlichen Umstände wie sonstiges Arbeitspensum, persönliche Lebenssituation, … eine wichtige Rolle.
Zum anderen wird die eigene Persönlichkeit und die Herangehensweise von Bedeutung sein. Ist man beispielsweise recht experimentierfreudig und probiert gerne Sachen aus, wird man unter Umständen mehr Zeit investieren können und wollen, wie jemand der sehr zielstrebig und lösungsorientiert an der Umsetzung von Aufgaben arbeitet.

Grundsätzlich sollte man darauf achten, dass man sich nicht überfordert und eine Abneigung gegen das Programmieren entwickelt. Freilich sollte man sich auch nicht unterfordern, sodass der Lernerfolg ausbleibt.

Ist es schlecht zuerst im Internet nach Lösungen zu suchen?

Um lösungsorientiertes und algorithmisches Denken zu trainieren, ist es grundsätzlich sinnvoll, Lösungen selbständig zu erarbeiten. Freilich kann man auch Lernfortschritte erzielen, indem man sich mit Lösungen aus dem Internet beschäftigt. Um die Lösungen zu verstehen, muss man auf alle Fälle Source-Code lesen. Das kann ungemein bilden. Man wird auch entdecken, dass unterschiedliche Herangehensweisen zur Lösung eines Problems existieren. Dadurch kann man seinen eigenen Horizont erweitern.

Ein Risiko für den Lernfortschritt bergen allerdings unreflektiert übernommene Lösungen. Außerdem wird man bei der Beschäftigung mit Code-Beispielen aus dem Internet schnell bemerken, dass manche Lösungen unvollständig, fehlerhaft und unbeholfen umgesetzt sind.

Wie kann ich den bereits gelernten Stoff am besten trainieren?

Das Lösen von Programmieraufgaben trainiert man am besten, indem man immer wieder neue Übungen macht, für bereits gefundene Lösungen neue Lösungsansätze sucht und Übungen ausbaut.

Neben der Erarbeitung von eigenständigen Lösungen kann es auch sehr hilfreich sein, Source-Code aus verschiedenen Quellen zu lesen. Auf diesem Weg kann man Lösungswege entdecken, die man selbst nie in Betracht gezogen hätte.

Was sind die meist vorkommenden Fehler der “Erstis”, die man beachten sollte?

Einer der häufigsten Fehler bei Personen mit wenig Erfahrung in der Programmierung ist, dass versucht wird, ein Problem als Ganzes zu lösen. Bei dieser Arbeitsweise ist die Komplexität der Lösung hoch und führt deswegen – gerade bei unerfahrenen Entwicklern und Entwicklerinnen – oft zum Scheitern.

Eine allgemeine Vorgehensweise beim Umsetzen von Programmen ist, dass man Aufgaben in Teilaufgaben zerlegt, um die Komplexität zu vermindern. Man sollte auch nicht vergessen, die gefundenen Lösungen für ein Teilproblem gründlich zu testen, bevor man damit weiter arbeitet.

Da Syntax oft recht schwer zu erlernen ist, kann die Verwendung einer geeigneten Entwicklungsumgebung hilfreich sein, da man sich besser auf die eigentliche Funktionalität des Programms konzentrieren kann.

Man sollte allerdings nicht den Fehler machen, das Erlernen der Syntax zu stark zu vernachlässigen. Ähnlich wie bei natürlichen Sprachen erleichtert und verbessert der routinierte Umgang mit den verschiedenen Sprachelementen die Ausdrucksweise.

Wie starte ich am besten zu Beginn eines Programms?

Am besten unterteilt man die Aufgabe zuerst in Teilaufgaben und versucht folgende Fragen zu beantworten:

  • Was will ich letztendlich berechnen, ausgeben, etc.?
  • Was benötige ich, um meine Berechnungen und Ausgaben umzusetzen?
    • Welche Eingabedaten werden benötigt? Wie kann ich darauf zugreifen?
    • Welche Variablen und Datentypen brauche ich?
    • Wo muss ich eigene Methoden schreiben?
    • Wo kann ich auf Methoden aus der Java-Bibliothek zurückgreifen?
  • Welche Aufgabe setze ich zuerst um?
  • In welcher Reihenfolge setze ich Teilaufgaben um?
  • Wie kann ich die umgesetzten und getesteten Teilaufgaben zielführend zusammenbauen?
  • Wie kann ich mein Programm sinnvoll in Klassen und Methoden strukturieren?

Siehe auch hier in unserer FAQ.

Wäre es sinnvoll gleich zu Beginn parallel eine andere Programmiersprache zu lernen?

Beginnt man mit dem Programmieren, spielt das Erlernen von algorithmischem und lösungsorientiertem Denken eine zentrale Rolle. Grundlegende Konzepte wie Zuweisungen, Verzweigungen, Schleifen, Rekursionen, Methoden, … müssen verstanden werden. In dieser Phase wird es für viele einfacher sein, Umsetzungen in nur einer Sprache formulieren zu müssen. Die Beschäftigung mit der Syntax muss auf alle Fälle in einem vernünftigen Verhältnis zur Beschäftigung mit den Algorithmen stehen.

Hat man Erfahrungen mit algorithmischem Denken und grundlegenden Konzepten gesammelt, ist das Erlernen weiterer prozeduraler oder objektorientierter Sprachen relativ leicht möglich.

Ist es für einen Anfänger / eine Anfängerin notwendig Effizienzüberlegungen zu machen?

Nein.

In einem ersten Schritt steht die Formulierung einer korrekten und gut verständlichen Lösung im Vordergrund. In einem weiteren Schritt, kann versucht werden, alternative Lösungen zur Steigerung der Effizienz zu finden.

Für den Lernfortschritt ist die Erarbeitung alternativer Lösungen ein konstruktiver und zielführender Ansatz. Freilich kann das Ziel der alternativen Umsetzung eine Steigerung der Effizienz sein.

In der Praxis steht oft die effiziente Arbeitsweise im Vordergrund. Hier werden Optimierungen in Bezug auf die Ausführungsgeschwindigkeit oft nur dann vorgenommen, wenn sie zur Behebung eines Problems notwendig sind.

Welche Tipps gibt es für AHS Absolventen / Absolventinnen, die noch kaum bzw. gar keine Programmiererfahrung haben?

Für Personen mit wenig Programmiererfahrung ist es wichtig, die Komplexität eines Problems zu verringern, indem die Lösung schrittweise erarbeitet und das Problem in Teilprobleme zerlegt wird.

Schrittweises Erarbeiten der Lösung
  • In einem ersten Schritt kann versucht werden, das Problem in Textform oder grafisch (Flussdiagramm, Nassi-Shneiderman-Diagramm) zu beschreiben.
  • In einem zweiten Schritt wird diese Beschreibung in Pseudocode übersetzt. Pseudocode ist eine programmiersprachenunabhängige Beschreibung von Algorithmen. Er ist an eine natürliche Sprache angelehnt, enthält aber formale Elemente und Elemente aus der Mathematik.
  • Im letzten Schritt wird der Pseudocode in die korrekte Syntax der Programmiersprache übertragen.

Beispiel:

Aufgabenstellung: Finde das Minimum von 2 Zahlen.
Ein Lösungsansatz für dieses Problem könnte wie folgt ausschauen:

  1. Textuelle oder grafische Beschreibung:

Textuell: Gegeben sind 2 Zahlen a und b. Wenn a kleiner b ist, dann gib aus a, sonst b.

Grafisch: Zur Umsetzung der grafischen Beschreibung wird ein Nassi-Shneiderman-Diagramm (Struktogramm) verwendet

Nassi-Shneiderman-Diagramm

2. Pseudocode:

wenn a kleiner b:
    ergebnis ist a
sonst:
    ergebnis ist b

3. Java-Code:

if(a < b) {
    result = a;
} else {
    result = b;
}
Zerlegung in Teilprobleme

Eine weitere wichtige Strategie beim Entwickeln von Software besteht darin, das Problem in kleinere Einheiten zu zerlegen. Diese Einheiten (Codesequenzen, Methoden) werden separat getestet und zu größeren Einheiten zusammengebaut.

Wie kann man lernen, wie ein Informatiker / eine Informatikerin zu denken?

Man kann lernen wie ein Informatiker / eine Informatikerin zu denken, indem man algorithmisches und lösungsorientiertes Denken trainiert.

Eine gute Übung dafür ist die Erarbeitung eigenständiger Lösungen für Probleme. Dabei kann es zielführend sein, ein gegebenes Problem in Teilprobleme zu zerlegen und Strukturen – beispielsweise durch Flussdiagramme oder Nassi-Shneiderman-Diagramme – sichtbar zu machen. Im Laufe der Zeit wird der Bestand an gefundenen Lösungen größer. Somit gibt es immer mehr Möglichkeiten ein Problem auf ein bereits gelöstes Problem abzubilden.

Eine weitere gute Übung kann die Beschäftigung mit Algorithmen und Mustern aus der Literatur sein.

Literatur:

Wie trainiert man algorithmisches bzw. lösungsorientiertes Denken am besten?

Algorithmisches und lösungsorientiertes Denken kann man trainieren, indem man versucht, eigenständige Lösungen für Probleme zu finden. Dafür kann man ein gegebenes Problem in Teilprobleme zerlegen oder Strukturen – beispielsweise durch Flussdiagramme oder Nassi-Shneiderman-Diagramme – sichtbar machen. Im Laufe der Zeit wird der Bestand an gefundenen Lösungen größer. Somit gibt es immer mehr Möglichkeiten ein Problem auf ein bereits gelöstes Problem abzubilden.

Eine weitere gute Übung kann die Beschäftigung mit Algorithmen und Mustern aus der Literatur sein.

Literatur: