entwickler.de

Die Welt ist grau und Nuancen sind wichtig

Gerade habe ich einen Artikel gelesen, in dem es um funktionale Programmierung in JavaScript geht. Der Artikel ist sehr interessant und ich empfehle, ihn zu lesen. Der Titel ist „Functional programming in JavaScript is an antipattern“ von Alex Dixon, und er sollte leicht online zu finden sein. Ich hatte einige unterschiedliche Gedanken zu diesem Artikel. Zunächst möchte ich in eigenen Worten wiedergeben, was der Autor sagt.

Funktionale Programmierung ist ein Stil, der sich in JavaScript (und anderswo) mittlerweile sehr verbreitet hat. Ich habe selbst seit Jahren zu diesem Thema geschrieben und vorgetragen. Viele Entwickler wissen die Vorteile des Stils zu schätzen: pure Funktionen, unveränderbare Daten und die daraus resultierenden Vorteile beim Testen, Debuggen, Parallelisierung und bei der Pflege einer größeren Codebasis.

Leider ist es so, dass funktionale Programmierung in vielen Umgebungen eine freiwillige Disziplin ist. Das gilt auch für JavaScript, wo ein Entwickler oder ein Team bewusst die Entscheidung treffen muss, funktional zu entwickeln. Für neue (und oft auch für alte!) Teammitglieder besteht jederzeit die Möglichkeit, einen philosophisch falschen Schritt zu machen, wenn neuer Code geschrieben wird, da an keiner Stelle erzwungen wird, funktionale Ansätze zu bevorzugen.

Zusätzlich muss ein Entwickler, der sich freiwillig für funktionale Programmierung entscheidet, oft Lücken füllen bzw. überbrücken, die zwischen den bevorzugten Elementen oder Techniken der funktionalen Idee und denen der tatsächlichen Zielplattform bestehen. Ein wichtiges Beispiel findet sich etwa im Umgang mit Daten. Die sollen unveränderbar sein, um möglichst weitgehend von funktionalen Ideen zu profitieren. Aber die Zielplattform JavaScript, wie auch etwa .NET/C#, kennt eigene Typen, die sich nicht an solche Ideen halten. Diese Standardtypen müssen oft verwendet werden, um mit bestehendem Code zu arbeiten, selbst geschrieben oder von dritter Hand. Von einem Entwickler, der funktional arbeiten möchte, ist deshalb ein breites Verständnis gefordert, und er muss ununterbrochen aufmerksam unterschiedliche Anwendungsfälle für jedes neue Stück Code betrachten, um effizient mit verschiedenen APIs zu arbeiten und den Overhead unnötiger Datenkonversionen zu vermeiden.

Gute Idee: ClojureScript

In dem Artikel stellt der Autor anhand vieler spezifischer Punkte dieses Szenario als nicht wünschenswert dar, und ich stimme dem weitgehend zu. Er empfiehlt außerdem, die Verwendung von ClojureScript in Betracht zu ziehen, und auch da stimme ich zu! Ich denke, ClojureScript könnte ein interessantes Thema für eine zukünftige Kolumne sein.

Nun geht der Autor noch einen Schritt weiter, wie schon der Titel des Artikels verriet, und bezeichnet funktionale Programmierung in JavaScript als Antipattern. Er begründet diese Sichtweise damit, dass ein typisches Antipattern gewöhnlich entsteht, wenn Entwickler gewissen Versprechungen eines Patterns Glauben schenken, aber unter den Umständen, mit denen sie sich konfrontiert sehen, letztlich kein vorteilhaftes Resultat erzielt wird. Vielleicht ist das Pattern falsch umgesetzt worden, vielleicht wurde die Idee zu weit getrieben, vielleicht haben die Umstände nicht gepasst. Wenn Sie sich, wie der Autor, in der Situation finden, dass funktionale Programmierung in JavaScript (oder C#!) mehr Probleme zu erzeugen scheint als sie löst, dann bezeichnen Sie diesen Ansatz somit eventuell zu Recht als Antipattern.

Nun habe ich persönlich abseits der formellen Richtigkeit allerdings ein Problem mit dem Begriff Antipattern in diesem Zusammenhang. Genau gesagt sind es sogar zwei Probleme. Erstens basiert die Einschätzung in diesem Fall auf persönlichem Empfinden. Wie beschrieben ergeben sich für den funktionalen Programmierer in einer nicht funktionalen Umgebung gewisse Herausforderungen. Es ist aber dem Programmierer – oder seinem Team – überlassen, zu bewerten, ob diese Herausforderungen zu komplex oder zu „teuer“ sind – es gibt keinen objektiven, standardisierten Maßstab.

Natürlich hängt eine solche Bewertung auch davon ab, wie genau funktionale Ideen umgesetzt werden, und dieser Gedanke bringt mich zu meinem zweiten Kritikpunkt. Vielfach werden funktionale Ideen auf nicht funktionalen Plattformen graduell angewendet, also genau in bestimmten Kontexten und in solcher Weise, dass relevante Teile eines Anwendungssystems von den Vorteilen profitieren. Zum Beispiel benutzen C#-Entwickler heute sehr gerne LINQ, ohne viel darüber nachzudenken, während Currying sich in C# nie zu einem Alltagswerkzeug entwickelt hat. Anonyme Funktionen und Lambdaausdrücke sind sehr beliebt, wie auch die Verwendung von Funktionen höherer Ordnung (von denen der Standardtyp Array in JavaScript mehrere anbietet).

Der Umgang mit unveränderbaren Daten ist ein besonderes Thema, da hierfür in C# wie in JavaScript besondere Schritte notwendig sind, möglicherweise die Verwendung spezialisierter Libraries. Ob das zum Problem wird, hängt allerdings auch von Fragen der Architektur ab – je spezifischer modularisiert wird und je deutlicher die Grenzen zwischen architekturellen Modulen sind, desto weniger beeinflusst die Entscheidung für ein Programmiermodell in einem Modul die Arbeit an einem anderen.

Antipatterns sollten objektiv definiert sein

Der Begriff Antipattern suggeriert eine objektive Empfehlung, das beschriebene Pattern unter den beschriebenen Umständen zu vermeiden. Ich selbst möchte deshalb die Idee der funktionalen Programmierung in JavaScript oder in C# nicht als Antipattern bezeichnen, da dies eine Form von Schwarz-Weiß-Sicht darstellt.

Nun ist Schwarz-Weiß-Sicht in der Softwareentwicklung erstaunlich verbreitet. Es geht los mit der beliebten „strategischen Plattform“. Diese gibt es oft in Firmen, in denen Software für interne Verwendung entwickelt wird. Vielleicht ist Windows eine strategische Plattform, oder auch .NET für Entwickler, oder noch spezifischer WPF oder ASP.NET MVC. Natürlich hat die Wahl einer strategischen Plattform Gründe: Entwickler und Administratoren kennen sich mit der Technologie aus, fürchten den Overhead oder die Kosten beim Umgang mit anderen, zusätzlichen Plattformen. Sich „strategisch“ festzulegen, soll gewöhnlich bewirken, dass Investitionen gesichert sind und Effizienz gesteigert werden kann.

Nun erwähne ich im Beispiel ASP.NET MVC. Bekanntlich wird diese Plattform derzeit von Microsoft stark in Richtung von Systemunabhängigkeit vorangetrieben. .NET Core soll es sein, und das ist auch für Entwickler interessant, die sich auf Windows konzentrieren. Gleichzeitig wird aber auch eine kostengünstige Linux-VM auf einer Cloud-Plattform zu einem gangbaren Weg, der vor ein paar Jahren gar nicht zur Wahl stand. Es ist also die Frage zu stellen, wie ein Unternehmen langfristig seine Investitionen am besten sichern kann: indem vorhandene Kenntnisse des Personals so lange wie möglich auf aktuellem Stand genutzt werden, oder indem Neuerungen aktiv aufgegriffen und genutzt werden und dem Personal eine gewisse Lernfähigkeit abverlangt wird? Die Befürworter strategischer Plattformen denken gewöhnlich schwarz-weiß: Wenn wir uns nicht mehr darauf verlassen können, dass alles mit .NET unter Windows läuft, ist dem Chaos kein Einhalt mehr zu bieten.

Strategische Plattformen gibt es auch in Firmen, die Software für Kunden entwickeln, oder bei Beratern, die die Entwickler eines Kunden auf den richtigen Weg schicken sollen. Gewissermaßen hat das bessere Gründe als bei den In-House-Entwicklern, denn die Fähigkeiten eines Entwicklerteams werden in diesem Fall letztlich extern angeboten. Wenn die Entwickler C# können, ist ein JavaScript-Projekt oder gar eines in Objective C vermutlich schwer umzusetzen. Es ist gut, die eigenen Fähigkeiten und die Grenzen derselben richtig einzuschätzen. Wie oft haben Sie aber den Chef, oder einen Berater, gegenüber einem Kunden sagen hören: „Wir haben Ihr Problem analysiert und sind der Auffassung, dass die Lösung möglichst auf Plattform X basieren sollte. Leider haben wir von Plattform X keine Ahnung, da wir strategisch auf Y setzen, und möchten deshalb von einem Angebot Abstand nehmen.“ Das kommt vor, aber nicht oft, und schon gar nicht oft genug.

Strategie kann nützlich sein

Sollte es also strategische Plattformen geben? Ich denke schon – soweit deren Definition dazu verwendet wird, Wissensgebiete abzugrenzen und administrativ notwendige Standardisierung zu schaffen. Wichtig ist, die Vorsätze, die aus der Wahl einer strategischen Plattform herzuleiten sind, in der Praxis jeweils richtig, also nutzbringend, zu interpretieren. Als Administrator etwa sollte ich neue verfügbare Plattformen in Betracht ziehen, wenn sie kostengünstiger, einfacher pflegbar, besser skalierbar oder in anderer Weise meiner bisherigen Wahl überlegen sind. Als projektverantwortlicher Kundenkontakt muss ich die Kenntnisse meiner Entwickler verstehen und diesbezüglich auf aktuellem Stand bleiben, darf aber mein Unternehmen gegenüber Kunden nicht falsch repräsentieren.

Für Entwickler und Softwarearchitekten ist Schwarz-Weiß-Sicht meines Erachtens am schlimmsten. Oft werde ich gefragt: „Wie löst man denn dieses Problem heute?“ In einer solchen Frage spiegelt sich die Erkenntnis wider, dass die Lösung heute anders sein mag als gestern, aber andere Randumstände werden nicht bedacht. Natürlich kann ich auf die Frage reagieren, indem ich eine oder mehrere verbreitete Lösungswege darstelle. Die eigentlich korrekte Antwort ist jedoch immer „das hängt von Ihren Umständen ab“. Der oft genannte Kenntnisstand der Entwickler ist dabei gar nicht so wichtig, denn Entwickler sind lernfähig. Es gibt aber wenige Projekte, die „auf der grünen Wiese“ stattfinden, und dementsprechend viel bestehende Architektur, vorhandenen Code, tief verwurzelte Anwendungsstrukturen, Vorbehalte und Gewöhnungen, die berücksichtigt werden sollten. Technische Gegebenheiten spielen ebenfalls eine Rolle, denn kein Kunde ist glücklich, wenn die neue Software zunächst nicht auf vorhandenen Systemen läuft.

Fehlschlag ist einfach

Das wichtige Fazit aus meinen Überlegungen lautet: Wer eine technische Vorgabe, eine Situation, einen Plan schwarz-weiß sieht, sich weigert, Nuancen zu analysieren und angemessen zu berücksichtigen, der kann in jeder Idee ein Antipattern nach der Definition des eingangs besprochenen Artikels finden. Oft habe ich in meinem Leben, beruflich oder nicht, etwas getan und nachher gedacht: „Das hätte ich genau so besser nicht machen sollen“. Diese Erlebnisse sind Erfahrungen, aus denen wir lernen können und sollten. Wer zweimal dasselbe tut und unterschiedliche Ergebnisse erwartet, ist auf dem Weg zum Irrsinn. Für die Definition eines Antipatterns hingegen ist eine Fallbeschreibung, die nicht im Erfolg endete, trotzdem nicht unbedingt geeignet.

Ich halte persönlich die Idee des Pragmatismus für hilfreich bei der Entscheidungsfindung. Wenn es eine Entscheidung zu treffen gilt, muss über die Konsequenzen jeder potenziellen Entscheidung möglichst vollständig nachgedacht werden. Es gibt auch ein umgangssprachliches Verständnis des Pragmatikers als „jemand, der aus dem Bauch heraus entscheidet“ – das meine ich natürlich nicht. In der Softwareentwicklung ist es zugegebenermaßen oft schwierig, sich ein vollständiges Bild aller Konsequenzen einer möglichen Entscheidung zu machen. Trotzdem finde ich die Disziplin nützlich, die dieser gedankliche Ansatz befürwortet: Ich möchte nicht unter Umgehung gedanklicher Schritte an ein Ziel gelangen, an dem ich zuvor schon einmal angelangt bin, also durchdenke ich alle Schritte so genau und objektiv wie möglich und beziehe so die Details der aktuellen Problemstellung ein.

Fazit

Ich hoffe, ich habe Sie mit den Gedanken dieser Kolumne nicht auf verwirrende Wege geführt. Zusammenfassend: Wenn Ihre Arbeit durch funktionale Programmierung in JavaScript dauerhaft und langfristig schwieriger wird, sollten Sie nach anderen Wegen suchen. Ich finde ClojureScript gut und empfehle Ihnen, sich kundig zu machen. Ich hasse Schwarz-Weiß-Sicht und ich denke gerne nach – die Welt ist grau!

Windows Developer

Dieser Artikel ist im Windows Developer erschienen. Windows Developer informiert umfassend und herstellerneutral über neue Trends und Möglichkeiten der Software- und Systementwicklung rund um Microsoft-Technologien.

Natürlich können Sie den Windows Developer über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist der Windows Developer ferner im Abonnement oder als Einzelheft erhältlich.