{"id":1897,"date":"2013-05-28T00:28:02","date_gmt":"2013-05-27T22:28:02","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=1897"},"modified":"2013-05-28T00:28:02","modified_gmt":"2013-05-27T22:28:02","slug":"imperative-und-funktionale-programmierung","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2013\/05\/imperative-und-funktionale-programmierung\/","title":{"rendered":"Imperative und funktionale Programmierung"},"content":{"rendered":"<p>In irgendeiner Weise muss ein Entwickler sein Problem in Programmform beschreiben, damit der Computer es letztendlich ausf\u00fchren kann. Hier gibt es verschiedene Beschreibungsformen, die wir Programmierparadigma nennen. Bisher haben wir uns immer mit der imperativen Programmierung besch\u00e4ftigt, bei der Anweisungen im Mittelpunkt stehen. Wir haben im Deutschen den Imperativ, also die Befehlsform, die sehr gut mit dem Programmierstil vergleichbar ist, denn es handelt sich in beiden F\u00e4llen um Anweisungen der Art \u201etue dies, tue das\u201c. Diese \u201eBefehle\u201c mit Variablen, Fallunterscheidungen, Spr\u00fcngen beschreiben das Programm und den L\u00f6sungsweg.<\/p>\n<p>Zwar ist imperative Programmierung die technisch \u00e4lteste, aber nicht die einzige Form Programme zu beschreiben; es gibt daneben die deklarative Programmierung, die nicht das \u201ewie\u201c zur Probleml\u00f6sung beschreibt, sondern das \u201ewas\u201c, also was eigentlich gefordert ist ohne sich in genauen Abl\u00e4ufen zu verstricken. Auf den ersten Blick klingt das abstrakt, aber f\u00fcr jeden, der schon einmal<\/p>\n<p>\u00b7 einen Selektion wie im <i>*.html<\/i> auf der Kommandozeile genutzt,<\/p>\n<p>\u00b7 eine Datenbankanfrage mit SQL geschrieben,<\/p>\n<p>\u00b7 eine XML-Selektion mit XQuery get\u00e4tigt,<\/p>\n<p>\u00b7 ein Build-Skript mit Ant oder make formuliert,<\/p>\n<p>\u00b7 eine XML-Transformation mit XSLT beschrieben hat, wird das Prinzip kennen.<\/p>\n<p>Bleiben wir kurz bei SQL, um einen Punkt deutlich zu machen. Nat\u00fcrlich ist im Endeffekt die Abarbeitung der Tabellen und Auswertungen der Ergebnisse von der CPU rein imperativ, doch es geht um die Programmbeschreibung auf einem h\u00f6heren Abstraktionsniveau. Deklarative Programme sind \u00fcblicherweise wesentlicher k\u00fcrzer und damit kommen weitere Vorteile wie leichtere Erweiterbarkeit, Verst\u00e4ndlichkeit ins Spiel. Da oftmals deklarative Programme einen mathematischen Hintergrund haben, lassen sich die Beschreibungen leichter formal in ihrer Korrektheit beweisen.<\/p>\n<p>Deklarative Programmierung ist ein Programmierstil, und eine deklarative Beschreibung braucht eine Art \u201eAblaufumgebung\u201c, denn SQL kann zum Beispiel keine CPU direkt ausf\u00fchren. Aber statt nur spezielle Anwendungsf\u00e4lle wie Datenbank- oder XML-Abfragen zu behandeln, k\u00f6nnen auch typische Algorithmen deklarativ formuliert werden, und zwar mit funktionaler Programmierung. Damit sind imperative Programme und funktionale Programme gleich m\u00e4chtig in ihren M\u00f6glichkeiten.<\/p>\n<h5><font style=\"font-weight: bold\">Funktionale Programmierung und funktionale Programmiersprachen<\/font><\/h5>\n<p>Bei der funktionalen Programmierung stehen Funktionen im Mittelpunkt und ein im Idealfall zustandsloses Verhalten, in dem viel mit Rekursion gearbeitet wird. Ein typisches Beispiel ist die Berechung der Fakult\u00e4t. Es ist n! = 1 \u00b7 2 \u00b7 3 \u00b7 &#8230; \u00b7 n, und mit Schleifen und Variablen, dem imperativen Weg, sieht es so aus:<\/p>\n<p>public static int factorial( int n ) {<\/p>\n<p>int result = 1;<\/p>\n<p> for ( int i = 1; i &lt;= n; i++ )<\/p>\n<p>&#160; result *= i;<\/p>\n<p> return result;<\/p>\n<p>}<\/p>\n<p>Deutlich sind die vielen Zuweisungen und die Fallunterscheidung durch die Schleife abzulesen; die typischen Indikatoren f\u00fcr imperative Programme. Bei der rekursiven Variante ist das ganz anders, hier gibt es keine Zuweisungen im Programm und die Schreibweise erinnert an die mathematische Definition:<\/p>\n<p>public static int factorial( int n ) {<\/p>\n<p> return n == 0 ? 1 : n * factorial( n &#8211; 1 );<\/p>\n<p>}<\/p>\n<p>Mit der funktionalen Programmierung haben wir eine echte Alternative zur imperativen Programmierung. Die Frage ist nur: Mit welcher Programmiersprache lassen sich funktionale Programme schreiben? Im Grunde mit jeder h\u00f6heren Programmiersprache! Denn funktional zu programmieren ist ja ein Programmierstil, und Java unterst\u00fctzt funktionale Programmierung, wie wir am Beispiel mit der Fakult\u00e4t ablesen k\u00f6nnen. Da das im Prinzip schon alles ist, stellt sich die Frage, warum funktionale Programmierung einen so schweren Stand hat und bei den Entwicklern gef\u00fcrchtet ist. Das hat mehrere Gr\u00fcnde:<\/p>\n<p><b>Lesbarkeit.<\/b> Am Anfang der funktionalen Programmiersprachen steht historisch LISP aus dem Jahr 1958, eine sehr flexible, aber schwer zu lesende Programmiersprache. Unsere Fakult\u00e4t sieht in LISP so aus:<\/p>\n<p>(defun factorial (n) (if (= n 1) 1 (* n (factorial (- n 1)))))<\/p>\n<p>Die ganzen Klammern machen die Programme nicht einfach lesbar und die Ausdr\u00fccke stehen in der Pr\u00e4fix-Notation &#8211; n 1 statt der \u00fcblichen Infix-Notation n &#8211; 1. Bei anderen funktionalen Programmiersprachen ist es anders, dennoch f\u00fchrt das zu einem gewissen Vorurteil, dass alle funktionalen Programmiersprachen schlecht lesbar sind.<\/p>\n<p><b>Performance und Speicherverbrauch<\/b>. Ohne clevere Optimierungen von Seiten des Compilers und der Laufzeitumgebung f\u00fchren insbesondere rekursive Aufrufe zu prall gef\u00fcllten Stacks und schlechter Laufzeit.<\/p>\n<p><b>Rein funktional<\/b>. Es gibt funktionale Programmiersprachen, die als \u201erein\u201c oder \u201epur\u201c bezeichnet werden und keine Zustands\u00e4nderungen erlauben. Die Entwicklung von Ein-\/Ausgabeoperationen oder simplen Zufallszahlen ist ein gro\u00dfer Akt, der f\u00fcr normale Entwickler nicht mehr nachvollziehbar ist. Die Konzepte sind kompliziert, doch zum Gl\u00fcck sind die meisten funktionalen Sprachen nicht so rein und erlauben Zustands\u00e4nderungen, nur Programmierer greifen so selten wie n\u00f6tig darauf zur\u00fcck.<\/p>\n<p><b>Funktional mit Java.<\/b> Wenn es darum geht nur mit Funktionen zu arbeiten, kommen Entwickler schnell zu einem Punkt, dass Funktionen andere Funktionen als Argumente \u00fcbergeben oder Funktionen zur\u00fcckgeben. So etwas l\u00e4sst sich in Java in der traditionellen Syntax nur sehr umst\u00e4ndlich schreiben, dass alles so unlesbar wird, dass der ganze Vorteil der kompakten deklarativen Schreibweise verloren geht.<b><\/b><\/p>\n<p>Aus heutiger Sicht stellt sich eine Kombination aus beiden Konzepten als zukunftsweisend da. Mit der in Java 8 eingef\u00fchrten Schreibweise der Lambda-Ausdr\u00fccke sind funktionale Programme kompakt und relativ gut lesbar und die JVM hat gute Optimierungsm\u00f6glichkeiten. Java erm\u00f6glicht beide Programmierparadigmen und Entwickler k\u00f6nnen den Weg w\u00e4hlen, der f\u00fcr eine Probleml\u00f6sung gerade am Besten ist. Diese Mehrdeutigkeit schafft nat\u00fcrlich auch Probleme, denn immer wenn es mehrere L\u00f6sungswege gibt, entstehen Auseinandersetzungen um die Beste der Varianten \u2013 und hier kann von Entwickler zu Entwickler eine kontr\u00e4re Meinung herrschen. Funktionale Programmierung hat unbestritten Vorteile und das wollen wir uns genau anschauen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In irgendeiner Weise muss ein Entwickler sein Problem in Programmform beschreiben, damit der Computer es letztendlich ausf\u00fchren kann. Hier gibt es verschiedene Beschreibungsformen, die wir Programmierparadigma nennen. Bisher haben wir uns immer mit der imperativen Programmierung besch\u00e4ftigt, bei der Anweisungen im Mittelpunkt stehen. Wir haben im Deutschen den Imperativ, also die Befehlsform, die sehr gut [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11],"tags":[],"class_list":["post-1897","post","type-post","status-publish","format-standard","hentry","category-insel"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1897","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=1897"}],"version-history":[{"count":0,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1897\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=1897"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=1897"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=1897"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}