![]() |
Re: verschachtelte function?
Zitat:
Warum willst du ALLES im Kopf haben, jedes kleine Detail eine Implementierung, das ist utopisch. Konsequenz ist also das man im BlackBox-Prinzip denkt und auch einen Source liest. Das heist: man schaut sich einmalig zb. eine nested Funktion an und liest deren Implementirung. Wenn man das gemacht hat dann reicht als Information für die Zukunft nur noch der Name, Parameter und Aufgabe zu kennen, NICHT deren Implementierung. Was ist den das Gegenteil der Funktionen, und eben nested Funktionen ? Spaghetti-code ! Ein extremes Beispiel
Delphi-Quellcode:
Das ist das was du propagierst ;)
for I := 0 to x do
begin S := ''; K := I *2; while K > 0 do begin S := S + Char(Ord('0') + K mod 10) K := K div 10; end; Array[i] := S; S := ''; K := I *3; while K > 0 do begin S := S + Char(Ord('0') + K mod 10) K := K div 10; end; Array[i*2] := S; S := ''; K := I *12; while K > 0 do begin S := S + Char(Ord('0') + K mod 10) K := K div 10; end; Array[i*12] := S; end;
Delphi-Quellcode:
1.) man sieht wohl den Unterschied in der Lesbarkeit
function Convert(K: Integer): String;
begin Result := ''; while K <> 0 do begin Result := Result + Char(Ord('0') + K mod 10) K := K div 10; end; end; begin for I := 0 to x do begin Array[i] := Convert(I*2); Array[i*2] := Convert(I*3); Array[i*12] := Convert(I*12); end; 2.) Convert() als Funktion wird ausschließlich nur in dieser Funktion benötigt und um Namens Kollisionen zu vermeiden machen wird sie nested 3.) Convert() benötigt in EAX den Parameter K, und noch ein Register um Result aufzunehmen. Mehr benötigt man an registern auch nicht, dh. Convert() sollte durch den Compiler in einen Maschionencode umgewandelt werden der ohne STack auskommt. 4.) in der Funktion selber werden I,X und @Array benötigt, also 3 CPU Register. Also auch diese Funktion sollte durch den Compiler vollständig in Registern optimiert werden Im Gegensatz zum 1. Beispiel: - Spaghetti Code - I,K,X,@Array[],K,S müssen in Register, das reicht aber nicht es stehen zur Verfügung EAX,EDX,ECX und EDI,ESI,EBX wenn sie auf dem STack gesichert wurden. Nested Funktionen sind ein ganz normales Instrument der heutigen Programmierung. Gibt es eine procedurale Modularisierung in einer Programmiersprache so gibt es dort auch konsequenter Weise die nested Funktionen als stärkste Abstraktionsebene. Das Konzept hinter den nested Funktionen ist also das gleiche Konzept wie hinter dem BackBox Prinzip, der prozeduralen Programmirung, der hierarischen Modularisierung der Sourcen und Programme und auch der OOP (OOP ist nur eine andere Art und Weise der Abstraktion und Modularisierung, ihr Ziel ist aber gleich). Gruß Hagen |
Re: verschachtelte function?
alles klar, habs verstanden! vielen dank.
diskussionen wie diese finde ich persönlich sehr lehrreich. besonders hagens ausführungen waren sehr informationsreich! wieder etwas gelernt! :dancer: |
Re: verschachtelte function?
Zitat:
Zitat:
Zitat:
Aber zur Blackbox, da fahre ich mit einer z.B. abstrakten Klasse oder einem Interface um einiges Schwarzer. Da brauche ich dann gar kein Wissen über die Implementierung! (Stimmt wenn man noch Factory-Pattern und Dependency Injection hinzunimmt, dann kann es Klassen geben die nur die Schnittstelle kennen). Da seh ich jetzt einen sehr einfachen Weg um austauschbare Lösungen bereit zu stellen. Die habe ich durch die Mittel der OOP gegeben. Ich sehe also für Delphi Programme die OO programmiert werden keine Notwendigkeit der nested Functions. Zitat:
Es geht um so genannte nested Functions! Und wo ist jetzt der gut leserliche Vorteil zwischen :
Delphi-Quellcode:
und dem was ich wirklich propagiere!
function Convert(K: Integer): String;
begin Result := ''; while K <> 0 do begin Result := Result + Char(Ord('0') + K mod 10) K := K div 10; end; end; begin for I := 0 to x do begin Array[i] := Convert(I*2); Array[i*2] := Convert(I*3); Array[i*12] := Convert(I*12); end;
Delphi-Quellcode:
type
TConverter = class(TObject) private function Convert(K : Integer): String; public doFoo; end; .... function Convert(K: Integer): String; begin Result := ''; while K <> 0 do begin Result := Result + Char(Ord('0') + K mod 10) K := K div 10; end; end; procedure doFoo; ... for I := 0 to x do begin Array[i] := Convert(I*2); Array[i*2] := Convert(I*3); Array[i*12] := Convert(I*12); end; end; Zitat:
Zitat:
Von aussen ist es eine Black-Box, nur die Methode doFoo ist sichtbar. Ich habe alle Vorteile der OOP offen gehalten. Klar, könnte ich auch mit einer nested Function machen, würde für mich aber immer noch die Lesbarkeit senken (kommen wir noch darauf zurück). Zitat:
Jetzt frage ich mich aber, wie wahrscheinlich in einer Klasse (die man sauber designt) Namenskonflikte sind. Tragen die dann nicht zu einer für sich selbst sprechende Bennenung bei? Ich meine klar, convert konvertiert wohl etwas, keiner weiß jetzt was (und jeder muss in die Implementierung schauen), mir entgeht da der Vorteil. Zitat:
Zitat:
Aber auch ich möchte es noch mal deutlich machen, zerlegt man ein Problem nur innerhalb von einer Funktion in einzelne Teilprobleme und verwendet dazu nested Funktions, würde das in letzter Konsequenz zu Konstrukte führen wie
Delphi-Quellcode:
Wobei hier in doB redundante Teile aus doA auftauchen und in doC solche aus B, natürlich kann man hier noch beliebig weiterschachteln (wieviele Register bleiben da dann übrig?). Klar, ist jetzt auch ein konstruiertes Beispiel, aber die habe ich bisher hier gesehen.
procedure doA;
var x : Integer; procedure doB; var y : Integer; procedure doC; var z : Integer; begin //.... end; begin // .... end; begin // ... end; Auch hier möchte ich nur sagen, dass es Konsequent fortgeführtes Verwenden von nested Functions wäre. Ihr Einsatz lässt sich vermeiden und würde die Lesbarkeit solcher Beispiele mit Sicherheit erhöhen! Weder nested Functions noch OOP oder ein anderes Mittel der Strukturierung und Abstraktion ersetzen also ein sinnvolles Design und ich möchte nocheinmal sagen, 500 Zeilen mit allen nested Functions zusammen klingt nach einem Design, dass man verbessern könnte. Da von xaromz auch gesagt wurde, dass es hier Unterprozeduren gibt, würde ich sagen, dass man einen Teil von ihnen anders auslagern sollte (in eine eigene Unit, die diese Klasse von Problemen löst (auch ohne OOP!)). Gruß Der Unwissende |
Re: verschachtelte function?
Hallo,
ich muss, sagen ich lese die Argumente hier mit großem Interesse. Insbesondere Hagens Ausführungen zum Laufzeitverhalten sind sehr interessant. Dazu fällt mir ein, wenn ich jetzt eine Klasse baue, habe ich zwar auch in sich abgeschlossene Methoden, aber immer ein Argument mehr, welches ein Register belegt, und zwar Self. Zitat:
Vielleicht sollte ich mal schreiben, was mein "Monster" eigentlich macht: Es parst Textbausteine unterschiedlicher Art und richtet diese in einem Rechteck aus (mit Zeilenumbrüchen). Dabei müssen viele Faktoren bedacht werden: Zeilen- und Absatzumbrüche, Tabulatoren, Silbentrennung, Höhe des Rechtecks... Für all diese Teilbereiche (Tabulatorberechnung, Silbentrennung usw.) benutze ich Unterfunktionen, diese werden von der Hauptschleife aufgerufen, die alle Bausteine durchgeht. In den Unterfunktionen werden aber viele Variablen gebraucht, die auch in der Hauptschleife verwendet werden (z. B. das Einfügen einer neuen Zeile in die Bausteinliste bei einem Zeilenumbruch, der in einer Unterfunktion berechnet wurde). Klar kann ich sowas als Klasse schreiben (ich habe das sogar letzte Nacht testweise gemacht), aber: Ich benötige diese Funktion (die sehr lange dauern kann) teilweise mehrmals pro Sekunde, und da kommt es auf jeden Tick an. Ich will also nicht jedesmal erst eine Klasse erzeugen und dann Zeit bei Methodenaufrufen verschwenden. Effizienz ist hier wichtiger als alles andere. Wenn ich es besser als der Compiler könnte, hätte ich die Funktion auch komplett in Assembler gschrieben, dann hätte ich einige Tausend Zeilen. Ich finde außerdem, dass dieses Beispiel kein gutes ist, um das Für und Wider von Nested Procedures zu diskutieren, da es eine sehr spezielle Geschichte ist. Das dürfte auch mit Riesenabstand die größte Funktion sein, die ich je geschrieben habe, und ich möchte sowas eigentlich nicht noch mal machen müssen :zwinker: . Ich habe hier übrigens noch ein schönes Beispiel für Nested Procedures. Angenommen ich habe einen Baum mit mehreren Wurzeln (also eigentlich eher einen Wald). Jetzt möchte ich alle Elemente durchgehen. Das funktioniert am Einfachsten mit einer Rekursion in einer Nested Prodecure:
Delphi-Quellcode:
Das sieht übersichtlich aus und benötigt sicher keine Klasse.
type
TItem = class(TList); procedure GoThroughTrees(Trees: TList); procedure Walk(Item: TItem); var I: Integer; begin // Irgendetwas machen for I := 0 to Item.Count - 1 do Walk(Item[I]); end; var I: Integer; begin for I := 0 to Trees.Count - 1 do Walk(Trees[I]); end; Gruß xaromz Gruß xaromz |
Re: verschachtelte function?
Zitat:
|
Re: verschachtelte function?
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:06 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz