Tach!
Die Wurzel allen Übels ist die Funktion get_next_row
[^1]. Die Funktion versteckt den Zugriff auf eine Datenbank-Ergebnismenge. Da würde ich ansetzen: Die versteckte Abhängigkeit auflösen und explizit machen. Angenommen die Ergebnismenge liegt in einem Array result_set
vor, dann ließe sich der Code schon deutlich reduzieren:
const processed_rows = [];
for (let row of result_set) {
processed_rows.push(process_row(row));
}
Statt den drei Zeilen dient nun nur noch eine Zeile der Iteration und auch die können wir schnell eleminieren:
const processed_rows = result_set.map(process_row)
Das setzt voraus, dass der Datenbankmechanismus das Resultset im Array zur Verfügung stellt oder in einer Art, dass es wie ein Array verarbeitbar ist. Traditionell war das unter PHP zum Beispiel nicht gegeben. Auch die funktionale Programmierung war noch nicht sehr ausgereift. Mittlerweile lässt es sich so schreiben:
function process_row($row) {
return $row;
}
$processed_rows = array_map(
function ($row) {
return process_row($row);
},
$result->fetch_all(MYSQLI_ASSOC));
Ist aber mehr Code als die nachfolgende herkömmliche Variante. $result ist nur Traversable, aber kein Array und array_map() möchte ein echtes Array haben. Das heißt, wenn es nicht wie im Falle PHPs bereits sowieso im Hintergrund passieren würde, dass erstmal das gesamte Resultset in den Speicher muss (fetch_all), statt zeilenweise verarbeitet werden zu könnnen. Moderne Systeme verhindern sowas, indem sie Generatoren verwenden, die sich nach außen hin wie Arrays geben, aber die Daten nur einzeln holen und herausgeben.
function process_row($row) {
return $row;
}
$processed_rows = [];
while ($row = $result->fetch_assoc()) {
$processed_rows[] = process_row($row);
}
Die array_map-Zeile lässt sich vereinfachen, indem man die anonyme Funktion durch einen Callback ersetzt:
function process_row($row) {
return $row;
}
$processed_rows = array_map('process_row', $result->fetch_all(MYSQLI_ASSOC));
Nun hat man einen schönen Einzeiler wie bei dir am Ende. Aber wie ist es nun mit der Verständlichkeit? Unter PHP gibt es keine Möglichkeit einer Funktionsreferenz. Man muss deren Namen als String angeben. Das empfinde ich als großen Mist, wenn Strings eine code-ähnliche Bedeutung haben, also Magic Strings sind. Man weiß manchmal nicht, wenn zwei Strings zufällig oder unachtsamerweise denselben Wert haben, ob sie dann auch dieselbe Bedeutung haben. Das Dilemma entsteht nicht, wenn man richtige Code-Elemente verwendet. Die lassen sich eindeutig über den gesamten Code verfolgen, im Gegensatz zu Strings.
Abgesehen davon versteckt das ebenso wie in deinem Javascript-Beispiel die API der Funktion process_row. Dass das map/array_map einen Parameter erzeugt, den es der Funktion übergibt, sieht man nicht, muss man wissen, ist also auch nicht besonders intuitiv.
dedlfix.