Category Archives: Programmieren

Programmieren vor dem Hintergrund von Kontingenz und Kommunikation

Dies sind einige Überlegungen zu Rolf Todescos letztem Blogpost “Programmieren und Theorie”. Insofern mein Kommentar dazu etwas zu lange geraten ist, habe ich mich entschlossen, diesen als eigenen Post zu publizieren. Ich hoffe, das kommt der besseren Lesbarkeit zugute.

1) These 1: “Programmieren als soziale Aktivität / Kommunikation”:
Unabhängig davon, wie die “soziale” Dimension nun konzeptualisiert wird (akteursbasiert, als soziale Emergenz, etc.), würde ich “Programmieren” stets auch als “soziale Aktivität”, und das heißt insbesondere als “Kommunikation”, auffassen. Denn die Codeproduktion (sei es als Umarbeitung von Altcode = Legacy Code, sei es als Neuproduktion, bei der idR mit Kunden ausgearbeitete Anforderungen = Requirements realisiert werden), erfolgt m.E. vollständig unter kommunikativen Vorzeichen: Anforderungsinterviews, Pair Programming und sonstige Entwicklerdiskussionen während des Designens, Codierens, Testens, etc., Reviews / Walk Throughs, usw.

Die Sicht “Programmierer und Computer” sollte daher nicht vom Sozialen völlig abstrahieren, weil der ganze Entwicklungsprozeß von der Anforderungserfassung bis zur Programmabgabe / -wartung durch und durch von sozialen Prozessen bestimmt wird.

Die Programm-“Lesbarkeit” ist dabei nicht nur für den einzelnen Programmierer selbst wichtig, sondern auch v.a. für diejenigen, die weiterhin mit der Codebasis arbeiten müssen (Tester, Legacy Code-Programmierer, usf). Und das bedeutet wiederum, es geht hierbei auch um “kommunikative” (= codebasierte und andere medial vermittelte) Anschlußmöglichkeiten!

2) “[…] bei dem die Programmierer im Laufe der Systementwicklung eine Theorie darüber entwickeln, wie die vorhandenen Probleme durch die Progammausführung gelöst werden können.” (Peter Naur)
* Hier wäre zu klären, was der Begriff “Theorie” bedeuten soll.
* Unabhängig von der Interpretation von “Theorie” werden bereits “vor” dem eigentlichen Programmieren eine Unzahl von idR sozial kalkulierten (!) Entscheidungen getroffen:
– Wie wird welches Software-Projekt angenommen (wer, wo, wann, mit welchem Budget, welchen Zeitvorgaben, welcher Qualität, usw.) oder verworfen?
– Neuprogrammierung oder Redeskription von Altcode?
– Welche Anforderungen sollen mit welcher Prioritität wie realisiert werden?
– Technische Vorgaben:
Zielplattform als Hard- und Softwre (Betriebssystem, etc.),
welche Tools (Programmier- und Designnotationen, Frameworks, IDEs, Test- und Debuggingwerkzeuge, usw.).
etc.
– Welche Software-Projektmanagement-Modelle werden gewählt (non-agil / agil oder irgendwie hybrid)? Das hat wiederum Auswirkungen z.B. auf die Vertragsgestaltung und Dokumentationsweise.
– Welche Designleitentscheidungen werden getroffen? Stichworte: Das zentrale Architekturdesign (Schichtenarchitektur, etc.) mit welchen Architekturdesignpatterns?
– Orientierung an welchen Programmierparadigmen mit welchen (Design- und Implementierungspatterns, Refaktorisierungs-, Test- und Debugging-Möglichkeiten, etc.)?
usf.

All das erfolgt bereits “vor” (!) dem Schreiben der ersten Programmzeile – unter der Voraussetzung, daß man nicht, ohne viel nachzudenken, sogleich wild und wirr zu codieren beginnt, was man idR höchstens im Hobbybereich tut.

Daher meine These 2:
Programmierer(innen) denken und kommunizieren (!) entlang bestimmter Design- und Programmierparadigmen, die insbesondere das “Problemlösungsverhalten” orientieren
. So macht es bspw. einen erheblichen Unterschied, ob man ein Problem prozedural, objektorientiert (OO) oder funktional bearbeitet.
Von Vorteil ist es hierbei, ein Problem auf “kontingente” Weise bearbeiten zu können. Man sucht dann durch eine Art “Paradigma-Switching”, die ungeeigneten / uneleganten Problemlösungsweisen zu vermeiden.
Wenn man nun Paradigmen mit Theorien gleichzusetzen gewillt ist, dann orientieren “multiple Theorien” das Problemlösungsverhalten.

* Wenn man sich im Rahmen eines (dominanten) Programmierparadigmas bewegt, dann stellen sich ganz “konkrete” Probleme, die zuerst allgemein “formuliert” werden:
– Wie baue ich eine Verbindung zum Server auf?
– Wie baue ich eine GUI entsprechend den Anforderungen?
– Wie speichere ich etwas in welcher Art von Datenbank?
M.E. handelt es sich hier um Problem-Problemlösungsrelationen, die als einzelne Aufgabenstellungen entsprechend des divide-et-impera-Prinzips (komplizierte Aufgabestellungen werden in einzelne, gut zu bewältigende Aufgabenpakete heruntergebrochen) bearbeitet werden. Beim Prozeß des “stepwise refinement” würde dann programmiersprachenunabhängiger Pseudocode solange reformuliert, bis geeignete Codezeilen entstehen. Der Pseudocode kann dann für Dokumentationszwecke im Programm stehen bleiben.
In einfachen Fällen (wie Datei xy öffnen, einlesen, etc.) kopiert man auch einfach direkt “code snippets”, ohne sich großartig mit stepwise refinement herumzuplagen.
– Eine weitere Frage wäre freilich: “Code first, test later” oder “test first”? Schon das sind zwei prinzipiell unterschiedliche Herangehensweisen ans Codieren.
– Eine andere Frage betrifft die Wahl und Implementierung welcher Algorithmen, was sich für die Programmexekution als zentral (gerade mit Blick auf die Geschwindigkeit der Programmausführung) erweisen kann.
etc.

Kommt bei diesen konkreten Problemlösungsprozessen (innerhalb einer Programmiersprachen, die sich an einem oder mehreren Programmierparadigmen orientieren kann. Bspl: “Scala” entspricht einer hybriden Sprache, die je nach Aufgabenstellung einen prozeduralen, objektorientierten oder funktionalen Programmierstil erlaubt – und das u.U. mit Blick auf ein und denselben Codeblock) “eine” Theorie zum Einsatz?
Ich würde sagen “Nein”, wenn man unter Theorie einen konsistenten Aussagenzusammenhang versteht, der dann praktisch realisiert werden soll.
So funktioniert das konkrete Problemlösungsverhalten nicht. Das heißt auch: Das upfront-Design, bei dem antizipativ und theoretisch alle relevanten Probleme gelöst und dann umgesetzt werden, ist hier idR irreführend. Man muß eher mit ständigen Re-Deskriptionsprozessen rechnen, bei denen zwischen Mini-Design, Testen/ Debuggen, Codieren und Refaktorisieren geswitcht wird. Der Prozeß ist daher eher etwas “sprunghaft” – analog zum Schreiben komplizierterer Texte!

Bei den obigen Aussagen zur “Rekonstruierbarkeit von Theorien” ist daher zu hinterfragen, ob hier nicht ganz klassisch (sensu “alteuropäisch” wg. der Orientierung an altgriechischen Leitentscheidungen!) die praktische Realisierung (up front und antizipativ) eines theoretischen Rahmens zugrunde gelegt wird.
Das wird dem Komplexitätsmanagement in Software-orientierten Design- und Programmierprozessen aber in keinster Weise gerecht – zumal hier auch nicht “eine” Theorie zugrunde gelegt werden könnte, sondern ein ebenfalls komplexer und kreativer, vorab nicht prognostizierbarer “Problemlösungsprozeß” abläuft, der nicht nur rein mental, sondern auch sozial (recherchieren, diskutieren, usf.) zu konzipieren ist (These 3).

3) “Der Programmierer verwendet keine Theorie, sondern eine Programmiersprache. ” (Rolf Todesco)
Das würde ich als eine sehr simplizistische “Verkürzung” auffassen. Man verwendet eine Vielzahl von Problemlösungsweisen (visuell, oral, textuell, Prototypen, Designnotationen, u.U. sogar diverse Programmiersprachen und Programmierstile /-Paradigmen) in einem komplexen, immer auch sozial vermittelten Problemlösungsprozeß (s.o. These 3),  und das oft schon “vor” dem Schreiben der ersten Codezeile.
Zudem gibt es seit einiger Zeit den Approach des “visuellen Programmierens”, bei dem “Modelle” durch entsprechende Engines in exekutierbaren Code transformiert werden sollen (Stichworte: Automatisierung von Geschäftsprozessen durch entsprechende Business Process Engines).
Ziel: Das Programmieren (und damit die teuren Programmierer / -innen!) überflüssig machen, was m.E. aber letztlich nicht gelingen wird, so daß es eher um eine “Minimierung” des Codierungsaufwands geht.

4) “Er weiss dabei, was er sagen kann, aber nicht, was er sagen könnte. Er trifft eine Wahl aus dem Kontingent” (Rolf Todesco)
Bei dem obigen, relativ oberflächlich skizzierten Problemlösungsprozeß ist das “Kontingenzbewußtsein”, also: das Bewußtsein um alternative Problemlösungsweisen, recht geschärft. Und das heißt auch, es läßt sich, insbesondere bei zentralen Modellierungs-, Design- und Programmier-Entscheidungen, auch “explizieren”, z.B. in der programminternen bzw. -externen Dokumentation. Also:
* Warum wurde dieses Design (Pattern) – und zwar schon auf der Ebene der Leitunterscheidungen, z.B. der Architektur – und nicht ein anderes zugrunde gelegt? Was sind die Vor- und Nachteile?
* Warum dieser Algorithmus und nicht ein anderer? (Vor- und Nachteile?)
* Warum diese Datenstruktur und nicht eine andere? (Vor- und Nachteile?)
* Warum dieser Programmierstil für diese Aufgabe (z.B. OO und nicht funktional) und nicht ein anderer? (Vor- und Nachteile?)
* Warum diese Codeimplementierungen (und nicht eine refaktorisierte, andere Lösung), z.B. eine polymorphe Methodenlösung anstelle einer Fallunterscheidung mit switch, u.ä.? (Vor- und Nachteile?)
etc.

Da man hierbei von komplexen (nicht antizipativen) Re-Deskriptionsprozessen ausgehen muß, ist das Durchspielen von Alternativen 1A. Bref: Es wird durchgespielt, was man codieren “könnte”. Dann probiert man dies und jenes aus, sieht, daß es nichts ist, verwirft es, recherchiert neu, probiert wieder dies und jenes aus, usf. – um am Ende, hoffentlich, etwas vor sich zu haben, das funktioniert.
Das führt zu meiner These 4: Das Kontingenz- und Komplexitätsmanagement ist dem Software-Entwicklungsprozeß i.a. und dem Programmierprozeß i.b. “immanent”. 

5) “Sie ist kritisierbar – also vergleichbar – durch ein anderes Programm, also durch eine andere Wahl.” (Rolf Todesco)
Das Suchen nach Alternativen erfolgt  design-, modell- bzw. programm”intern” (!)  immer schon während” des Designens, Modellierens und Programmierens Es werden hierbei eine Vielzahl von Möglichkeiten durchgespielt und permanenten Redeskriptionprozessen unterworfen (und das sogar ganz explizit: als “Refaktorisieren” von Programmteilen).
Die “Explizierung” wichtiger Entscheidungen erfolgt mitunter sogar “im” Code selbst. Und in Code Reviews / Walkthroughs wird das ggf. nochmals durchgekaut.

Ergo, meine These 5:
In allem, was man bei der Softwareproduktion tut (und das geht über das eigentliche “Programmieren” im strikten Sinne von “Codieren / Implementieren” hinaus!), ist ein geschärftes Kontingenzempfinden notwendig – und das betrifft die Ebene des individuellen Bewußtseins wie der sozialen Kommunikation (Beispiele: Diskussionen mit Projekt-Stakeholders, Pair Programmierung bzw. sonstigen Diskussionen unter Entwicklern bzw. nachträgliche Reviews / Walk Throughs, etc.).

~Peter Bormann

Advertisements
%d bloggers like this: