Meillo hat geschrieben: 22.01.2021 16:56:30
paedubucher hat geschrieben: 22.01.2021 15:51:32
Ich möchte lieber zweierlei beantworten: 1) Ist meine Argumentation stichhaltig? 2) Gibt es Kriterien, anhand derer man zwischen "Programmieren auf Vorrat" und angemessener Generalisierung unterscheiden kann?
Gerade die zweite Frage ist für meine Programmierpraxis und mein Verständnis derselben auch sehr relevant.
Generalisierung macht den Code meist kuerzer und klarer. Wenn er stattdessen komplexer wird, in einer Weise die derzeit nicht noetig ist oder direkt absehbar ist, dann ist es auf Vorrat.
Kurz und klar können aber auch gegensätzlich sein, wie z.B. in meinem Beispiel: Ein weiterer Parameter macht die Parameterliste länger, schafft aber mehr Klarheit.
In den zwei Implementierungen sehe ich keinen Unterschied in der Komplexitaet. Ich finde die Variante mit den separaten Indices auch klarer, weil eindeutig ist, welche Elemente getauscht werden. Die Frage, ob mit dem davor oder mit dem danach -- die in beiderlei Weise gleich viel Sinn macht -- entfaellt. (Falls man nur einen Index verwendet, dann sollte man die Frage mittels des Funktionsnamens beantworten: swapWithNext() oder so.)
Mit dem Funktionsnamen kann man auch vieles Ausdrücken. Aber bloss Swap() drückt halt die Nachbarschaft nicht aus.
Ein bisschen finde ich deine zweite Frage zu akademisch, zu theoretisch, zu abstrakt. Wenn ich mich beim Programmieren an die Ziele vom Cover von Kernighan und Pikes ``The Practice of Programming'' -- Simplicity, Clarity, Generality -- halte, dann komme ich selten an den Punkt, wo ich mich fragen wuerde, ob etwas eine angemessene Generalisierung oder auf Vorrat ist. Dieses ``auf Vorrat'' scheint mir typisch fuer Projekte in denen man Pflichtenhefte mit Anforderungslisten umsetzt. Wenn man dagegen konkrete Probleme loest indem man Software inkrementell schreibt, die man selber einsetzt und ganz eng mit den Nutzern verzahnt ist, dann besteht wohl wenig Gefahr ueberhaupt in diese Richtung abzurutschen. (Okay, wenn man natuerlich in Studium oder Ausbildung jahrelang auf Software-Engineering getrimmt worden ist, dann wird es womoeglich schon eine Schwierigkeit sein, das und die damit direkt verbundene Gefahr des Overengineerings und des Auf-Vorrat-Programmierens abzuwehren.)
Das "auf Vorrat" ist sicherlich in Projekten eher ein Kriterium als bei Programmieraufgaben. Wenn ich in einem Kontext einen Bubble Sort implementiere, weil der für den Moment gut genug ist, kann dieser doch später der Flaschenhals sein. Bubble Sort schreit als Algorithmus ja gerade nach seiner Ersetzung
In der Domäne (Sortierung) ist nun der Gedanke an andere Sortieralgorithmen nicht weit. Mit meiner Swap()-Funktion erhalte ich in diesem Kontext einen generellen Baustein, der für Bubble Sort kein Overkill ist, aber auch wiederverwendet werden kann.
Wahrscheinlich ist das wie wenn man Picasso fragen wuerde, wie er weiss, wie viele oder wie wenige Striche noetig sind um die Essenz des Stieres darzustellen. Er hat sich halt jahrelang damit beschaeftigt, genau das rauszufinden. Und dann konnte er es umsetzen, aber eine konkrete Antwort koennte nur erklaeren wie er seinen Stier nun malt. Sie kann nicht erklaeren wie man es in irgend einem anderen Fall macht. Die einzige Antwort dafuer ist wohl: Man muss es genau so machen wie Picasso: viele, viele Versuche um selber die Essenz zu finden. Man muss es lernen zu spueren. Man muss den passenden Blick entwickeln. Man braucht die Erfahrung der vielen, vielen Fehlschlaege. Die zeigen einem den Weg.
Hier habe ich in der Praxis auch schon bemerkt, dass junge Programmierer es oft mit Prinzipientreue übertreiben (z.B. das Aufschieben von konkreten Entscheidungen in Java-Projekten, wo man manches auf Vorrat mal dynamisch hält). Erfahrene Programmierer haben hier öfters mehr Feingefühlt. Oder vielleicht werden sie auch nur bequemer, und gehen ein kleines Risiko für ein kleines Refactoring ein?
Wenn ich wuesste wie es mit dem Stil beim Programmieren so genau waere, dann wuerde ich ein Buch darueber schreiben. Ich habe wenig Hoffnung, dass das passieren wird. Ich kenne aber Buecher, die gute Hilfen sind, um es selber fuer sich rauszufinden. Das oben erwaehnte ist eines davon.
Wie du das hier machst, finde ich schon ganz gut. Du analysierst deine eigene Umsetzung im Vergleich zu alternativen. (Danke bei Gelegenheit dem Korrektor, dass er dir Punkte abgezogen hat, weil er damit deine Motivation dazu angestachelt hat!) Nun solltest du die beiden Implementierungsvarianten im naechsten Projekt umsetzen und schauen was passiert, wenn du es auf die eine oder andere Weise machst. Was hat es fuer Auswirkungen und wie fuehlt es sich an? (Dafuer ist das konkrete Beispiel hier etwas zu trivial.) Ich glaube, dass es immer beides braucht: die theoretische Analyse (inkl. Argumentation und Verteidigung) und die praktische Umsetzung. In Kombination kommst du zu den Erkenntnissen und entwickelst einen Blick und ein Gefuehl fuer die Dinge.
Vielleicht ist das Problem an diesem Kurs auch, dass die einzelnen Programmieraufgaben nicht zusammenhängen. Hier möchte ich erneut den "Machine Learning"-Kurs hervorheben. Man entwickelt da z.B. eine Funktion zur Initialisierung von Gewichtsmatritzen und erhält die Dimensionsparameter dazu. Wenn man da nicht aufpasst, und konkrete Werte statt eines zur Verfügung stehenden Parameters verwendet, funktioniert zwar der nächste Schritt; bei einer späteren Wiederverwendung mit einem grösseren neuronalen Netzwerk funktioniert dann aber plötzlich gar nichts mehr, und man startet wieder auf Feld 1. In diesem Sinne macht es der isolierte und triviale Kontext schon schwierig, hier Lösungsprinzipien zu finden.
Ich stelle fest, dass es kaum moeglich ist, pauschale Aussagen zum Stil zu machen. Das ist alles hochgradig abhaengig vom Kontext. Das ist ganz grundsaetzlich ein Abwaegen in einem komplexen System. Was ich im einen Projekt sehr hilfreich finde, kann ich im anderen Projekt auch katastrophal finden. Nur die anzustebenden Ziele (sowas wie Simplicity, Clarity und Generality) bleiben gleich.
Ich hoffe, diese Gedanken -- einfach mal wild in den Raum -- bringen dir etwas. Wir koennen uns gerne thematisch auch wieder auf Teilaspekte fokussieren, nachdem ich hier eher gross ausgeholt habe.
Ich sollte vielleicht besser mal "The Practice of Programming"
fertig durcharbeiten statt auf Coursera Videokurse zu machen.
Aber ich schlafe noch einmal über dieses Thema.