Teil 1: Grundlagen der Programmierung

Systematisch von Anfang an

Systematisch von Anfang an

Teil 1: Grundlagen der Programmierung

Systematisch von Anfang an


Dem Anfänger fällt es oft schwer, den Einstieg in die Programmierung oder besser in den gesamten Prozess der Softwareentwicklung zu finden. Fragen nach der Wahl der richtigen Programmiersprache oder welche Entwicklungsumgebung am besten geeignet ist, sind zu beantworten. In einer mehrteiligen Serie präsentieren wir einen umfassenden Einführungskurs in die Softwareentwicklung und legen dabei den Schwerpunkt auf die eigentliche Programmierung, also die Implementierung.

Aller Anfang ist schwer! In der Tat gilt diese Aussage auch bedingt für den Einstieg in die professionelle Softwareentwicklung. In einer umfassenden Artikelserie (siehe Kasten „Artikelserie“) präsentieren wir einen Einstieg in die Softwareentwicklung für den anspruchsvollen Leser. Wir richten uns damit explizit an Anfänger, die noch keine umfassenden Kenntnisse in der Programmierung (Implementierung) von Software gesammelt haben. Zu unserer Zielgruppe gehören also zum Beispiel Studierende der Informatik am Anfang ihres Studiums oder angrenzender Disziplinen, die praktische Kenntnisse in der Programmentwicklung erwerben möchten. Auch der interessierte Autodidakt findet hier einen kompakten Einstieg. Der Fokus der Abhandlungen liegt eindeutig auf der Implementierung. Bei der Betrachtung dieser technischen Disziplin wird dabei nicht vernachlässigt, dass die eigentliche Programmierung lediglich einen Teilschritt des gesamten Entwicklungszyklus (Abb. 1) darstellt. Wir werden an den geeigneten Stellen darauf hinweisen und Quellen zum tieferen Einstieg nennen.

krypczyk1.tif_fmt1.jpgAbb. 1: Der Entwicklungszyklus einer Software umfasst mehrere Phasen; unser Fokus ist die Implementierung

Programmierung

Das Ziel eines jeden Softwareentwicklungsprozesses ist die Bereitstellung von Programmen. Dabei spielt es vom Grundsatz zunächst keine Rolle, auf welchem System ein solches Computerprogramm laufen soll. Neben den klassischen Programmen für den Desktop spielen heute Anwendungen für die so genannten mobilen Endgeräte (Smartphone, Tablet) zunehmend eine Rolle. Zur Entwicklung von Computerprogrammen bedient man sich einer Programmiersprache. Ausgangspunkt ist stets ein Problem der realen Welt. Beispielsweise sollen Berechnungen durchgeführt werden, oder die Daten der Kunden sind systematisch zu verwalten. Auch Computerspiele fallen in diese Kategorie. Das Problem muss analysiert und damit einer Lösung zugänglich gemacht werden. Dafür werden Algorithmen verwendet. Ein Algorithmus wird wie folgt definiert [1]: „Ein Algorithmus ist eine detaillierte und explizite Vorschrift zur schrittweisen Lösung des Problems“. Es gelten folgende Eigenschaften:

  • Die Ausführung des Algorithmus erfolgt in einzelnen Schritten

  • Jeder Schritt umfasst lediglich eine einfache Grundaktion

  • Zu jedem Zeitpunkt muss klar sein, welcher Schritt als Nächstes auszuführen ist

Danach wird die Problemstellung in einer Programmiersprache verfasst. Man spricht auch vom Quellcode (Quellprogramm, Sourcecode). Programmiersprachen sind mehr oder weniger an den Bedürfnissen der Problemstellung ausgerichtet und erlauben damit eine problemorientierte Formulierung der Lösung. Von der Technik des Computers wird weitgehend abstrahiert. Der Computer selbst versteht lediglich die Maschinensprache (eine Folge von 0 und 1). Zwischen Quellprogramm und Maschinenprogramm findet die Übersetzung statt. Dieser Vorgang wird durch den Compiler erledigt. Letztendlich kann der gesamte Vorgang des Programmierens auch in Analogie zum Kommunikationsprozess zwischen Menschen aufgefasst werden. Beispielsweise erklärt man als Erwachsener eine recht komplexe Situation der realen Welt kindgerecht, lediglich unter Zuhilfenahme des kindlichen Wortschatzes (Abb. 2).

krypczyk2.tif_fmt1.jpgAbb. 2: Mensch-Maschine-Kommunikation über eine Programmiersprache [2]

Der Übersetzer (Compiler) bestimmt also, für welche Zielsysteme (Hard- und Software) das Programm erstellt wird. Er ist dabei u. a. auf das Betriebssystem und den Prozessor abgestimmt (Abb. 3).

krypczyk3.tif_fmt1.jpgAbb. 3: Prinzip der Übersetzung von Programmen [2]

Welche Sprache?

Diese Frage kann man nur bedingt beantworten. Gleich vorweg: Es gibt keine ideale – für alle Zwecke geeignete – Programmiersprache. Grundsätzlich können die einzelnen Sprachen bezüglich der von ihnen unterstützten Konzepte eingeordnet werden. Je nach Problemstellung eignet sich die eine oder andere Sprache besser, sie wird durch das gewählte Betriebssystem umfassender unterstützt, oder die dafür verfügbaren Werkzeuge (Entwicklungsumgebungen) sind besonders leistungsfähig. Auch die historische Entwicklung der Programmiersprachen spielt bis heute eine große Rolle. Einige Sprachen haben sich universell etabliert und weisen eine breite Palette an Konzepten auf, andere Sprachen haben auf neueste Entwicklungen reagiert und damit bewusst mit „Altlasten“ gebrochen. Eine (nicht vollständige) Übersicht bekannter und zugleich historischer Programmiersprachen zeigt Tabelle 1.

Name der Sprache

Entstanden

Sprachkategorie

Anwendungsgebiet

Bemerkungen

Fortran (Formula Translation)

1954–1957

Prozedural

Mathematisch-technische Probleme

Erste problemorientierte Sprache; Weiterentwicklung Fortran 77, Fortran 90

Algol 60 (Algorithmic language)

1958–1960

Prozedural

Mathematisch-wissenschaftliche Probleme

Anlehnung an mathematische Formeltradition; knappe einheitliche und geschlossene Defini­tion der Sprache. Weiterentwicklung: Agol 68

Cobol (Common Business Oriented Language)

1959–1960

Prozedural (objektorientiert)

Kaufmännische Probleme, fürtechnisch-naturwissen­schaft­liche Probleme ungeeignet

Keine klare Definition, unsystematischer Auf­­bau, ei­ne der am weitesten verbreiteten Sprachen; 1997 erweitert zu OO-Cobol mit objektorientierter Konzeption

Lisp (List Processing)

1959–1962

Funktional

Symbolmanipulation

Unterscheidet sich wesentlich von Fortran, Agol oder Cobol, besonderes in den Datenstrukturen

Basic (Beginner’s All Purpose Symbolic Instruction Code)

1963–1965

Prozedural

Kleinere mathematisch-technische Probleme

Dialogorientiert, Sprachumfang nicht einheitlich festgelegt; Weiterentwicklung: Visual Basic

PL/1 (Programming Language 1)

1964–1967

Prozedural

Mathematisch-technische und kaufmännische Probleme

Sehr umfangreich; mangelnde Systematik und Überblickbarkeit

Simula 67

1965–1967

Prozedural

Mathematisch-wissenschaftlich-technische Probleme und Simulation

Erweiterung von Agol 60; enthielt wichtige Konzepte für die objektorientierte Programmierung

Pascal (nach Blaise Pascal)

1971

Prozedural

Mathematisch-technische und kaufmännische Probleme

Weiterentwicklung von Agol 60; Berücksichtigung von didaktischen Gesichtspunkten

C

1974

Prozedural

Systemnahe Programmierung

Als Nebenprodukt zum Betriebssystem Unix entstanden; sehr verbreitet

Modula-2

1976

Prozedural (objektorientiert)

Mathematisch-technische und kaufmännische Probleme

Weiterentwicklung von Pascal, Modulkonzept, Modula-3 objektorientiert

Prolog

1977

Prädikativ

Anwendung mit symbolischen Formeln

Einsatz bei Expertensystemen

Ada

1979

Prozedural (objektorientiert)

Echtzeitanwendung

Weiterentwicklung von Pascal, Ada-95 um Objektorientierung erweitert

SQL

1970–1980

Deklarativ

Datenbankanwendung

1983 genormt

Smalltalk-80

1970–1980

Objektorientiert

Anwendungs- und Softwaresysteme

Objektorientierte Programmierung, erste objektorientierte Sprache

C++

1980–1983

Prozedural (und objektorientiert)

Anwendungs- und Softwaresysteme

Obermenge von C, erweitert im ANSI-Standard 1998

Eiffel

1986–1988

Objektorientiert

Umfangreiche Softwaresysteme

Konstruktion zuverlässiger, erweiterbarer und wiederverwendbarer Software; enthält Zusicherungen

Oberon

1988

Objektorientiert

Bildung (Universitäten)

Weiterentwicklung von Modula-2

Java

1990–1997

Objektorientiert

Anwendungen in vernetzten und heterogenen Umgebungen

Berücksichtigt C++- und Smalltalk-80-Konzepte; inzwischen breiter Anwendungsbereich

C#

2000–2002

Objektorientiert

Anwendung auf Microsoft-Plattformen

Große Ähnlichkeit mit Java; zugeschnitten auf die .NET-Plattform

Tabelle 1: Überblick über einige Programmiersprachen [2]

Und welche Sprache wählen wir jetzt? Egal ... naja nicht ganz! Um den Einstieg in der Programmentwicklung so einfach wie möglich zu gestalten, sollte man eine universelle Sprache mit guter Werkzeugunterstützung, einer Vielzahl von Anwendungsmöglichkeiten und ausreichender Verbreitung wählen. Auch moderne Konzepte sollten unterstützt werden. Hat man erst einmal die Grundlagen einer Sprache verstanden, so fällt es relativ leicht, eine zweite oder dritte Programmiersprache zu lernen. Es gibt stets viele Gemeinsamkeiten. Mit der Zeit wird man die Unterschiede als Chance sehen, für die aktuelle Problemstellung seinen Favoriten auszuwählen. Letztendlich bleibt es aber auch eine Frage des Geschmacks. Wir haben uns für C# entschieden. Dafür sprechen die folgenden Gründe:

  • Es ist eine moderne Sprache, mit Potenzial für die unterschiedlichsten Anwendungstypen (Desktop, App, Web)

  • Sie basiert auf dem leistungsfähigen .NET-Framework, das heute als Standard für die Entwicklung von Windows-Applikationen gilt

  • Die Sprache ist relativ einfach zu erlernen, die Komplexität von C und C++ ist außen vor geblieben

  • Sie bietet bestmögliche Unterstützung durch die integrierte Entwicklungsumgebung Visual Studio

  • Verfügbarkeit von vielfältigen Informationen (Fachbücher, Internet, Community)

  • Compiler und Werkzeuge für den Einstieg sind frei verfügbar

Handwerkszeug

Die Effizienz der Programmerstellung wird maßgeblich durch die Qualität der zur Verfügung stehenden Entwicklungsumgebung definiert. Für .NET-Anwendungen und C# wird Visual Studio verwendet. Für den durchaus professionellen Einstieg steht Visual Studio Community – aktuell in Version 2013 – zur Verfügung. Der Download erfolgt von [3], die Installation unterscheidet sich nicht von einem herkömmlichen Anwendungsprogramm.

Ein erstes Programm

Beginnen wir mit einem ersten Test. Wir erstellen eine Windows-Applikation. Sie werden sehen, es ist recht einfach. Motivierend dürfte wirken, dass mithilfe der integrierten Entwicklungsumgebung Visual Studio mit wenigen Handgriffen der Rahmencode für eine komplette Anwendung erstellt ist. Starten wir sogleich:

  • Start von Visual Studio 2013.

  • Wir rufen den Assistenten für ein neues Projekt über den Menüpunkt Datei | Neues Projekt auf (Abb. 4).

  • Aus den angebotenen Vorlagen wählen wir Visual C# | Windows-Desktop und unmittelbar den ersten Eintrag Windows-Forms-Anwendung.

  • Im unteren Teil des Dialogfelds sind der Name des Projekts und der Speicherort anzugeben. Sinnvoll ist es auf jeden Fall, einen eigenen Ordner anzulegen.

  • Mit Klick auf den Button OK wird das Projekt erstellt. Nach wenigen Augenblicken ist dieser Vorgang abgeschlossen, und man landet direkt im Entwurfsmodus des einzigen Formulars der künftigen Anwendung (Abb. 5).

  • Einem ersten Start steht nun nicht mehr im Wege. Klicken Sie dazu direkt in der Symbolleiste von Vi­sual Studio auf Starten. Die Anwendung wird darauf unmittelbar ausgeführt. Natürlich wird nur ein leeres Fenster angezeigt, das jedoch bereits alle typischen Eigenschaften einer Windows-Applikation erfüllt: Man kann das Fenster verschieben, minimieren, maximieren oder schließen. Auch das Systemmenü ist vorhanden.

krypczyk4.tif_fmt1.jpgAbb. 4: Auswahl eines neuen Projekts in Visual Studio
krypczyk5.tif_fmt1.jpgAbb. 5: Formular der Anwendung – automatisch von Visual Studio erzeugt

Nun wollen wir unsere erste Anwendung erweitern. Zur Demonstration grundlegender Aspekte werden wir einige Textfelder zur Oberfläche hinzufügen. In diese Textfelder können später Zahlen erfasst werden, mit denen wir einfache Berechnungen durchführen und das Ergebnis an ein anderes Textfeld zurückgeben. Folgende Schritte sind dazu notwendig:

  • Ziehen Sie aus dem Werkzeugkasten (Ansicht | Werkzeugkasten) drei TextBox-Steuerelemente und einen Button auf das Formular.

  • Zur Beschriftung der Textfelder ergänzen wir drei weitere Elemente vom Typ Label.

  • Über den Eigenschafteneditor (Ansicht | Eigenschaftenfenster bzw. die Taste F4) können zu jedem Steuerelement die Eigenschaften wunschgemäß angepasst werden. Zu den im Formular platzierten Steuerelementen nehmen wir dazu die Einstellung gemäß Tabelle 2 vor.

  • Beim Klick auf den Button sollen die in den Textboxen Zahl 1 und Zahl 2 erfassten Zahlenwerte addiert werden und das Ergebnis ist in der Textbox auszugeben. Dazu ist Code zu schreiben. Unterhalb des Menüpunkts Ansicht dienen die Einträge Code und Designer dem Umschalten zwischen dem grafischen Editor für das Formular und dem Quelltexteditor. Damit beim Klick auf den Button eine Aktion ausgelöst wird, muss ihm ein Ereignis zugeordnet werden. Dazu wählt man den Button aus und klickt im Eigenschafteneditor auf das Symbol für die Ereignisse. Man wählt das Ereignis Click, indem man mit der linken Maustaste doppelt neben das Wort „Click“ in das leere Feld klickt. Es öffnet sich automatisch der Quelltexteditor.

  • Es muss der Code zur Berechnung in der so genannten Ereignisbehandlungsmethode hinterlegt werden. In unserem Beispiel heißt die Ereignisbehandlungsmethode button1_Click(…). Erfassen Sie dazu den Code gemäß Listing 1. Sie müssen jetzt noch nicht alle Anweisungen verstehen. Einige Erläuterungen erfolgen noch im nächsten Textabschnitt, der vollständige Zusammenhang wird erst im Laufe der weiteren Beiträge klar.

  • Wenn Sie den Quelltext richtig erfasst haben (keine Hervorhebungen für Fehlerhinweise), können Sie danach die Anwendung neu starten und ausprobieren. Sie können jetzt zwei ganze Zahlen addieren und das Ergebnis wird nach Klick auf Berechnen angezeigt.

Listing 1

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace WindowsFormsApplication1
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }
 
    private void button1_Click(object sender, EventArgs e)
    {
      int Zahl1;
      int Zahl2;
      int Ergebnis;
      Zahl1 = int.Parse(textBoxZahl1.Text);
      Zahl2 = int.Parse(textBoxZahl2.Text);
      Ergebnis = Zahl1 + Zahl2;
      textBoxErgebnis.Text = Ergebnis.ToString();
    }
  }
}

Eigenschaft

Wert

TextBox 1

Name

textBoxZahl1

TextBox 2

Name

textBoxZahl2

TextBox 3

Name

textBoxErgebnis

Label 1

Text

Zahl 1

Label

Text

Zahl 2

Label 3

Text

Ergebnis

Button

Text

Berechnen

Tabelle 2: Anzupassende Eigenschaften der Steuerelementen im Formular

Eine erste Analyse

In diesem Abschnitt erfolgt eine knappe Analyse des Quelltexts aus Listing 1:

  • Die Zeilen 1 bis 9 enthalten using-Anweisungen (z. B. using System). Damit werden Bibliotheken geladen, die bei der Programmierung benötigt werden. Standardmäßig hat Visual Studio bereits ein paar sinnvolle Vorschläge gemacht. Zunächst sind hier keine weiteren Anpassungen notwendig.

  • Jede Anweisung muss mit einem Semikolon abgeschlossen werden.

  • Zeile 11: Jeder Programmcode muss einem Bereich zugeordnet werden. Diese Bereiche werden als namespace bezeichnet. Wenn die Projekte umfangreicher werden, dienen die Namespaces der späteren Strukturierung des Quellcodes. Auch hier macht Visual Studio bereits einen Vorschlag. Solche Bereiche werden in geschweiften Klammern (Zeile 12 und Zeile 32) eingefügt.

  • Auch andere zusammenhängende Bereiche müssen in geschweifte Klammern gesetzt werden. Dabei sind Bereiche ineinander zu schachteln.

  • Zeile 13: C# ist eine objektorientierte Sprache, d. h. alle Anweisungen müssen innerhalb von Klassen erfolgen (das Klassenkonzept wird ausführlich in Teil 3 dargestellt). Grundsätzlich ist das Formular auch eine Klasse mit den Namen Form1. Alle Klassen gehören einem bestimmten Typ an (hier vom Typ Form).

  • Zur Klasse Form1 gehört u. a. die Ereignisbehandlungsmethode button_Click(…) (Zeile 20 bis Zeile 30). Von Bedeutung sind jetzt die Zeilen 22 bis 28)

  • Zeile 22: Definition einer Variablen (dient der Speicherung von Werten eines bestimmten Typs) mit dem Namen Zahl1. Der Typ ist int (integer = Ganzzahl).

  • Zeile 23: Definition einer Variablen mit dem Namen Zahl2. Der Typ ist wieder int.

  • Zeile 24: Definition einer Variablen mit dem Namen Ergebnis. Der Typ ist wieder int.

  • Zeile 25: Zuweisung des Wertes aus der Textbox (textBoxZahl1) in die Variable Zahl1. Der eingegebene Wert steht in der Text-Eigenschaft der Textbox, und es handelt sich um eine Zeichenkette. Diese Zeichenkette muss in eine Zahl gewandelt werden. Das erfolgt mittels der Methode int.Parse(…).

  • Zeile 26: Wie Zeile 25 für die Variable Zahl2.

  • Zeile 27: Durchführung der Addition und Zuweisung des Ergebnisses an die Variable Ergebnis.

  • Zeile 28: Das Rechenergebnis aus der Variable Ergebnis wird in der Textbox (textBoxErgebnis) angezeigt. Dazu muss es von einer Zahl (Typ int) nunmehr in eine Zeichenkette gewandelt werden. Dies erledigt die Methode ToString().

Umfassende Erläuterungen zu Klassen, deren Bestandteilen und Datentypen erfolgen in den kommenden Beiträgen der Artikelserie.

Unsere Basis: .NET

Windows-Applikationen werden meist auf der Basis des so genannten .NET-Frameworks entwickelt. Der oben beschriebene allgemeine Vorgang der Programmerstellung (Quellcode => Kompilieren => Maschinecode) wird bei Verwendung einer .NET-Programmiersprache noch etwas abgeändert. Der Programmcode wird beim Kompilieren in eine Zwischensprache, den so genannten MSIL-Code (Microsoft Intermediate Language Code), übersetzt. Dieser Zwischencode ist für alle verwendeten Programmiersprachen gleich. Erst bei der Ausführung des Programms wird aus dem MSIL-Code mittels des Just-in-time-(JIT-)Compilers in Maschinencode übersetzt (Abb. 6).

krypczyk6.tif_fmt1.jpgAbb. 6: Grundkonzept JIT-Compiler [4]

Damit eine .NET-Anwendung auf dem Rechner ausgeführt werden kann, ist es erforderlich, dass die .NET-Laufzeitumgebung (in der aktuellen Version) auf dem Zielrechner vorhanden ist. Dies ist bei allen aktuellen Windows-Versionen automatisch der Fall. Das .NET-Framework ist eine Entwurfs- und Laufzeitumgebung. Die Hauptkomponenten sind [4]:

  • Common Language Specification (CLS): .NET-Anwendungen können in unterschiedlichen Sprachen (Visual Basic .Net, C#, F# …) entwickelt werden. Um aus diesen unterschiedlichen Ansätzen einen einheitlichen Zwischencode (MSIL) zu erzeugen, sind Richtlinien und Standards zu definieren, die eine .NET-Sprache einhalten muss. Damit wird sichergestellt, dass innerhalb eines Projekts mehrere Sprachen verwendet werden können.

  • Common Language Runtime (CLR): Die Laufzeitumgebung – sie ist die Basis dafür, dass .NET-Programme auf dem Zielrechner ausgeführt werden können.

  • .NET-Klassenbibliothek: Es wird eine Vielzahl von Klassen (mit jeder Version ist die Zahl der Klassen gestiegen) zur Verfügung gestellt, die in den Programmen verwendet werden können. Für fast jeden Anwendungszweck gibt es vorbereitete Klassen, die eine effektive Programmerstellung unterstützen.

  • Compiler für die diversen Programmiersprachen, z. B. für C#, VB.NET, F# usw.

Die Details der .NET-Klassenbibliothek (Funktionsweise, Aufbau) werden einem im Laufe der Programmierung schnell vertraut.

krypczyk7.tif_fmt1.jpgAbb. 7: Handskizze des UI zur Beispielaufgabe

Fazit, Hausaufgabe und Ausblick

Sie haben etwas über Programmierung, Programmiersprachen und die Programmentwicklung allgemein erfahren. Auch ein erstes Testprogramm – gewissermaßen zur Motivation – haben wir erstellt. Im kommenden Teil der Artikelserie werden wir uns mit den Kernelementen der Programmentwicklung auseinandersetzen. Wir betrachten die wichtigsten Elemente eines Algorithmus. Beginnend bei Datentypen und Variablen werden wir uns danach mit den Ablaufstrukturen eines Computerprogramms auseinandersetzen. Viele dieser Dinge sind seit den Anfängen der Programmierung nahezu unverändert. Aber auch neue technische Entwicklungen finden sich wieder. Bis dahin möchten wir Sie ermuntern, neugierig zu stöbern und sich interessiert mit den Inhalten dieses ersten einführenden Teils auseinanderzusetzen. Damit Sie Ihren Wissenstand gut kontrollieren können, finden Sie im Textkasten („Hausaufgabe“) eine kleine Übung. Die Lösung steht unter [6] zur Verfügung.

krypczyk_veikko_sw.tif_fmt1.jpgDr. Veikko Krypczyk studierte und promovierte in Betriebswirtschaftslehre mit dem Schwerpunkt Wirtschaftsinformatik. Er ist Fachautor und begeisterter Entwickler.

bochkor_olena_sw.tif_fmt1.jpgOlena Bochkor studierte Betriebswirtschaftslehre u. a. mit dem Schwerpunkt Wirtschaftsinformatik. Weitere Informationen zu diesen und anderen Themen der IT finden Sie unter http://it-fachartikel.de.

Elena Bochkor

Elena Bochkor arbeitet am Entwurf und Design mobiler Anwendungen und Webseiten.

Veikko Krypczyk

Dr. Veikko Krypczyk ist begeisterter Entwickler und Fachautor. Er ist stets auf der Suche nach neuen innovativen Lösungen und liebt die Arbeit in der Entwicklungsumgebung. Er bietet Seminare und Workshops zu unterschiedlichen Themen der Softwareentwicklung.