Vorlesung Programmieren Programmierparadigmen Prof. Dr. Stefan Fischer Institut für Telematik, Universität zu Lübeck http://www.itm.uni-luebeck.de/people/fischer Programmiersprachen-Paradigmen Eine Programmiersprache dient dem Aufschreiben von Algorithmen Ein Compiler übersetzt in Maschinensprache Die Art und Weise des Aufschreibens unterscheidet sich je nach Programmiersprache sehr deutlich Verschiedene Paradigmen existieren Bisher: Imperative Programmierung Security - 04 Cryptology #2 Unterschiedliche Sprachenkonzepte Imperative Programmiersprachen Grundprinzip: Folge von Variablenzuweisungen Wesentlich: Prozedurale Programmierung Beispiele: Algol, Fortran, Cobol, Pascal, C, Basic Spezialfall: Objektorientierte Programmierung Grundprinzip: Interaktionen zwischen Objekten Beispiele: SmallTalk, Java, C++ Funktionale Programmiersprachen Grundprinzip: Term-Ersetzung Beispiele: Lisp, HOPE, Miranda, SML, Haskell Logikbasierte Programmiersprachen Grundprinzip: Prädikatenlogik Beispiel: Prolog 5-3
Motivation Security - 04 Cryptology #4 Beispiel: Mehrmals Leerzeichen zählen Aufgabe: Zähle Leerzeichen in beiden folgenden Sätzen und gebe beides aus Man muss die Welt nicht verstehen, man muss sich nur darin zurechtfinden. (Albert Einstein) Die besten Dinge im Leben sind nicht die, die man für Geld bekommt.(albert Einstein) Security - 04 Cryptology #5 Mögliches Programm public class Zeichenzaehlen { public static void main(string[] args){ char text[] = "Man muss [ ] darin zurechtfinden. (Albert Einstein)".toCharArray(); int anzahlleerzeichen = 0; for(int aktuelleszeichen = 0; aktuelleszeichen < text.length; aktuelleszeichen++) { if( text[aktuelleszeichen] == ' ' ) { anzahlleerzeichen++; System.out.print(anzahlLeerzeichen); char text2[] = "Die besten Dinge [ ] Geld bekommt. (Albert Einstein)".toCharArray(); int anzahlleerzeichen2 = 0; for(int aktuelleszeichen2 = 0; aktuelleszeichen2 < text2.length; aktuelleszeichen2++) { if( text2[aktuelleszeichen2] == ' ' ) { anzahlleerzeichen2++; System.out.print(anzahlLeerzeichen2); Bildquelle: http://www.konsumer.info/?p=15528, Programm: 08-Programmierparadigmen\1-Zeichenzaehlen\Zeichenzaehlen.java Security - 04 Cryptology #6
Ausgabe des Programms 2 x 13 Leerzeichen? Kann das stimmen? Zufällig gleich viele? Haben wir einen Fehler gemacht beim Anpassen des Programms? Security - 04 Cryptology #7 Beliebter Fehler public class Zeichenzaehlen { public static void main(string[] args){ char text[] = "Man muss [ ] darin zurechtfinden. (Albert Einstein)".toCharArray(); int anzahlleerzeichen = 0; for(int aktuelleszeichen = 0; aktuelleszeichen < text.length; aktuelleszeichen++) { if( text[aktuelleszeichen] == ' ' ) { anzahlleerzeichen++; System.out.print(anzahlLeerzeichen); char text2[] = "Die besten Dinge [ ] Geld bekommt. (Albert Einstein)".toCharArray(); int anzahlleerzeichen2 = 0; for(int aktuelleszeichen2 = 0; aktuelleszeichen2 < text2.length; aktuelleszeichen2++) { if( text[aktuelleszeichen2] == ' ' ) { anzahlleerzeichen2++; System.out.print(anzahlLeerzeichen); Copy/Paste-Fehler Bildquelle: http://www.konsumer.info/?p=15528, Programm: 08-Programmierparadigmen\1-Zeichenzaehlen\Zeichenzaehlen.java Security - 04 Cryptology #8 Motivation Bisher möglich: Lange Abfolge von Code Probleme Lesbarkeit Fehleranfälligkeit Viel Copy & Paste Keine zentrale Fehlerbehebung Große Programme nicht wartbar Betriebssystem Windows NT 3.1 Windows NT 4.0 Windows 2000 Windows XP Windows Server 2003 OpenSolaris FreeBSD Mac OS X 10.4 Linux Kernel 2.6.0 Linux Kernel 2.6.35 Codezeilen 4-5 Mio. 11-12 Mio. >29 Mio. 45 Mio. 50 Mio. 9.7 Mio. 8.8 Mio. 86 Mio. 5.2 Mio. 13.5 Mio. #9
Prozedurale Programmierung Prozedurale Programmierung Zerlegung von Programmen in kleinere, wiederverwendbare Einheiten sog. Prozeduren Vorteile Kapselung einzelner Funktionalitäten Monolithisches Programm Bessere Wiederverwendbarkeit Lesbarerer Code Was tut er? (z.b. Zeichen zählen) statt Wie tut er es? (die ganzen Instruktionen) Fehlerbehebung an einer Stelle #11 Prozedur (auch: Funktion) Eingabeparameter Übergabe von Werten an die Funktion Definiert als Menge von Variablen mit bestimmtem Datentyp Rückgabe Wert mit einem bestimmten Datentyp Spezieller Datentyp für keine Rückgabe: void Beispiele für Deklarationen (sog. Signatur) void main(string[] args); int zaehleleerzeichen(char[] text); char[] rueckwaerts(char[] text); boolean istleerzeichen(char zeichen); boolean istkontogedeckt(int konto, int blz); Eingabewerte Prozedur / Funktion (Black Box) Ausgabewert #12
Signatur und Implementierung Signatur (auch: Deklaration) int zaehleleerzeichen(char[] text) { // Hier steht die Implementierung der Funktion // (in einer Blockanweisung) Implementierung (auch: Body oder Definition) #13 Signatur und Implementierung int zaehleleerzeichen(char[] text) { int anzahlleerzeichen = 0; for(int i = 0; i < text.length; ++i) if ( text[i] == ' ' ) anzahlleerzeichen++; return anzahlleerzeichen; Rückgabe der Funktion (wichtig: Datentyp) #14 Exkurs: Blockanweisung Blockanweisungen definieren einen eigenen Scope (Bereich) Beispiele class MeinProgramm Prozedur main Security - 04 Cryptology #15
Exkurs: Blockanweisung Begrenzen Sichtbarkeit bzw. Lebensdauer von Elementen (z.b. Variablen) Beispiele Variable i (Zeile 3) gehört zur Klasse Blockanweisung (globale Variable) Variable i (Z. 6) gehört zu main (lokale Variable) Variable i2 lebt nur innerhalb der Blockanweisung (Z. 9-11) Variable i3 von Z. 15-22 Variable i4 in Z. 19 Security - 04 Cryptology #16 Implementierung einer Funktion Wie eine Erweiterung der Blockanweisung Es gibt ein paar weitere lokale Variablen Stellen die Parameter einer Funktion dar Parameter werden wie normale lokale Variablen verwendet werden Werte der Parameter werden beim Aufruf festgelegt Security - 04 Cryptology #17 Aufruf von Funktionen Aufruf über Namen (Identifier) der Funktion Übergabe von Parametern an die Funktion Richtige Anzahl Richtiger Datentyp Security - 04 Cryptology #18
Ausgabe des Programms Programm verhält sich identisch zu dem Copy & Paste-Programm Es unterscheidet sich daher nicht im Ergebnis Aber das Programm ist lesbarer, einfacher, wartbarer, wiederverwendbarer,... Security - 04 Cryptology #19 Weiteres Beispiel: Inverter Security - 04 Cryptology #20 Mit Prozeduren Zerlegen in einzelne Operationen Zeichen lesen Auf Enter prüfen Prüfen, ob noch Platz im Puffer ist Invers ausgeben Aufrufen im Hauptprogramm Security - 04 Cryptology #21
Prozedurale Programmierung Zerlegen des Programms in Prozeduren / Funktionen Wesentlich: Übergabe von Parametern an Funktionen Programm besteht aus Sequenz von Funktionsaufrufen Erste Funktion: main Prozeduren können auch globale Variablen verändern Zustand über mehrere Aufrufe hinweg Security - 04 Cryptology #22 Beispiel: Bankkonto Bankkonto hat einen Zustand... Kontostand...und Operationen Einzahlen, Auszahlen, Kontostand erfragen Mögliche Implementierung? Security - 04 Cryptology #23 Problem: Vergessen der Zuweisung erzeugt falsche Semantik #24
Ausgabe des Programms #25 Etwas besser: Verwendung einer statischen Variable #26 Ausgabe des Programms #27
#28 Ausgabe des Programms #29 Probleme prozeduraler Programmierung Bisher Aufteilung des Programms in Prozeduren mit bestimmten Aufgaben Hauptprogramm steuert Programmfluss über Funktionsaufrufe Übergabe von Daten über Parameter oder globale Variablen Probleme Verwendung globaler Variablen ist problematisch Ausführung einer Funktion abhängig vom Zustand (Inhalt) der globalen Variable Man nennt dies auch Seiteneffekt Alternatives Konzept: Funktionale Programmierung Security - 04 Cryptology #30
Funktionale Programmierung Funktionale Programmierung Inspiriert von mathematischen Funktionen Wir besprechen hier nur die Grundidee Funktionale Programmierung ist viel mehr Es gibt auch funktionale Programmiersprachen Security - 04 Cryptology #32 Funktionale Programmierung Mathematische Funktionen sind wie eine große Tabelle Abhängig von den Parametern, findet man das (immer konstante) Ergebnis in einer Tabelle Wichtiges Prinzip: Termersetzung f(2) 4 f(4) 16 Security - 04 Cryptology #33
Funktionale Programmierung Vereinfacht dargestellt ist funktionale wie prozedural ohne globale Variablen Denkweise ist sehr wichtig für gut testbare und wartbare Programme Security - 04 Cryptology #34 Zusammenfassung und Ausblick Prozedurale und funktionale Programmierung hilft, Programme besser wartbar, fehlerfreier, etc. zu machen Bringt keine weitere Mächtigkeit der Programmiersprache Mittel, um den Quelltext für Menschen besser verständlich zu machen Prozedural: Aufteilen von Programmen in kleine, handliche Prozeduren Dürfen auch globale Variablen verändern Funktional: Wie prozedural, nur ohne globale Variablen #35