Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi verschachtelte function? (https://www.delphipraxis.net/75560-verschachtelte-function.html)

alienous 21. Aug 2006 14:02


verschachtelte function?
 
hi, beim durchforsten der DP is mir mal aufgefallen, das eine function in einer procedure gab, so in der art:

Delphi-Quellcode:
procedure haupt;
  function verschachteln(...):String;
  var ...
  begin
    //inhalt der function
  end;
var ...
begin
  //inhalt der procedure (zb aufruf der function)
end;
kann mir jemand erklären wieso die function nich einfach über der procedure steht? wo liegt denn da der vorteil und was für unterschiede gibt es da? wollte mich selbst informieren, aber ich weiss nich wie dieses verfahren heisst! auf die schnelle viel mir nur "verschachtelte function ein :D

wenn ihr mir sagt wie das verfahren nun heisst, dann editier ich das topic versprochen!

danke

freak4fun 21. Aug 2006 14:08

Re: verschachtelte function?
 
Die Funktion verschachteln(...):String; ist in diesen Fall eine lokale Funktion und nur in der Prozedur haupt; sichtbar. Du kannst so in vielen Methoden eine Methode mit gleichen Namen aufrufen, ohne sie überladen zu müssen. Ob es Resourcenschonender ist kann ich jetzt nicht mit SIcherheit sagen, aber ich glaube schon. ;)

MfG
freak

JasonDX 21. Aug 2006 14:09

Re: verschachtelte function?
 
Zitat:

Zitat von alienous
hi, beim durchforsten der DP is mir mal aufgefallen, das eine function in einer procedure gab, so in der art:

Delphi-Quellcode:
procedure haupt;
  function verschachteln(...):String;
  var ...
  begin
    //inhalt der function
  end;
var ...
begin
  //inhalt der procedure
end;
kann mir jemand erklären wieso die function nich einfach über der procedure steht? wo liegt denn da der vorteil und was für unterschiede gibt es da?

Ums mal mit einem anderen Beispiel zu zeigen:
Delphi-Quellcode:
procedure Blubb(x, y: integer);
var
  a, b: integer;
  procedure Bla(f: string);
  begin
  end;
var
  s, t: integer;
begin
end;
Das hat folgenden Sinn: Die Prozedur Bla ist nur innerhalb der Prozedur Blubb aufrufbar. Zudem kann Bla auf die Parameter von Blubb, sowie auf die vor ihr deklarierten Variablen zugreifen.
Gebraucht werden kann es bspw., wenn man laengere Methoden hat, in denen bestimmte Codestuecke oefters vorkommen. Um dann nicht eigene private-Methoden dafuer in die Klasse zu schieben, die das redundante Codestueck implementiert, kann diese "Funktionsintern" deklariert werden.
Ob das allerdings zum schoenen Programmierstil gehoert, diese Entscheidung sei jedem selbst ueberlassen.

greetz
Mike

St.Pauli 21. Aug 2006 14:16

Re: verschachtelte function?
 
Zitat:

Zitat von JasonDX
Ob das allerdings zum schoenen Programmierstil gehoert, diese Entscheidung sei jedem selbst ueberlassen.

Jetzt möchte ich aber auch ne schönere Alternative hören. Wie würdest du denn sowas lösen? :stupid:

mkinzler 21. Aug 2006 14:18

Re: verschachtelte function?
 
Zitat:

kann mir jemand erklären wieso die function nich einfach über der procedure steht? wo liegt denn da der Vorteil und was für unterschiede gibt es da?
Der Unterschied liegt am Scope (Sichtbarkeitsbereich). Die Unterfunktion ist nur in der Überfunktion sichtbar.

RavenIV 21. Aug 2006 15:06

Re: verschachtelte function?
 
Zitat:

Zitat von St.Pauli
Zitat:

Zitat von JasonDX
Ob das allerdings zum schoenen Programmierstil gehoert, diese Entscheidung sei jedem selbst ueberlassen.

Jetzt möchte ich aber auch ne schönere Alternative hören. Wie würdest du denn sowas lösen? :stupid:

Also mir kommt auch immer die Galle hoch, wenn ich eine Procedure/Function in einer Procedure/Function sehe (sogenannte lokale Proceduren/Funktionen).
Mit OO hat dies nix mehr zu tun, da kann ich ja grad alles in eine Main-Function reinschreiben. :kotz:

Ich löse sowas immer mit einer Klassenmethode, evtl wird diese überladen oder mit Default-Parametern versehen...

xaromz 21. Aug 2006 16:16

Re: verschachtelte function?
 
Hallo,
Zitat:

Zitat von RavenIV
Also mir kommt auch immer die Galle hoch, wenn ich eine Procedure/Function in einer Procedure/Function sehe (sogenannte lokale Proceduren/Funktionen).
Mit OO hat dies nix mehr zu tun, da kann ich ja grad alles in eine Main-Function reinschreiben. :kotz:

Ich löse sowas immer mit einer Klassenmethode, evtl wird diese überladen oder mit Default-Parametern versehen...

Da würde ich sagen, es kommt ganz auf den Zweck an.
Wenn man z. B. eine lange Schleife in eine eigene Prozedur auslagert, dann bleibt die eigentliche Methode schön klein und übersichtlich und durch die logische Trennung in mehrere Unter-Prozeduren erhöht sich die Übersichtlichkeit noch. Natürlich kann man jede Unterfunktion in eine eigene Methode packen. Aber: Was ist, wenn ich 20 lokale Variablen der eigentlichen Methode in den einzelnen Prozeduren benötige? Soll ich dann den einzelnen Prozeduren jeweils 20 Variablen übergeben? Und welchen Sinn haben diese Methoden, wenn sie doch nur im Kontext der eigentlichen Methode sinnvoll sind?
Das Beispiel mag konstruiert erscheinen, aber ich habe hier eine Methode mit 7(!) Unterfunktionen, dia alle ihre Berechtigung haben (die gesamte Methode incl. Unterfunktionen ist ca. 500 Zeilen lang).

Gruß
xaromz

RavenIV 21. Aug 2006 16:33

Re: verschachtelte function?
 
Zitat:

Zitat von xaromz
Das Beispiel mag konstruiert erscheinen, aber ich habe hier eine Methode mit 7(!) Unterfunktionen, dia alle ihre Berechtigung haben (die gesamte Methode incl. Unterfunktionen ist ca. 500 Zeilen lang).

Ich möchte Dir nicht zu nahe treten, aber da würde ich das Design der Software nochmal überdenken...

xaromz 21. Aug 2006 16:42

Re: verschachtelte function?
 
Hallo,
Zitat:

Zitat von RavenIV
Ich möchte Dir nicht zu nahe treten, aber da würde ich das Design der Software nochmal überdenken...

Diese Antwort war klar :roll: . Leider sind aber nicht alle Aufgaben so einfach, dass sie sich in drei Zeilen abhandeln lassen. Die Funktion was überigens früher bei geringerer Funktionalität ca. doppelt so lang. Ich habe die Funktion schon drei mal komplett neu geschrieben und dabei jedesmal vereinfacht, und bin mit dem jetzigen Ergebnis sehr zufrieden. Insbesondere, da sie sich durch die Aufteilung leicht erweitern lässt.

Gruß
xaromz

SirThornberry 21. Aug 2006 16:44

Re: verschachtelte function?
 
@xaromz: Was spricht in deinem Fall dagegen die Funktionen als eigenständige Funktionen zu Handhaben?

xaromz 21. Aug 2006 16:48

Re: verschachtelte function?
 
Hallo,
Zitat:

Zitat von SirThornberry
@xaromz: Was spricht in deinem Fall dagegen die Funktionen als eigenständige Funktionen zu Handhaben?

Die vielen lokalen Variablen, von denen ich oben schrieb. Außerdem finde ich die lokale Sichtbarkeit den Funktionen irgendwie logischer, da es sich ja um "Unterstützungsfunktionen" der Hauptfunktion handelt, die nur im Kontext dieser sinvoll sind. Wozu also auslagern?

Gruß
xaromz

Der_Unwissende 21. Aug 2006 16:49

Re: verschachtelte function?
 
Zitat:

Zitat von xaromz
Hallo,
Leider sind aber nicht alle Aufgaben so einfach, dass sie sich in drei Zeilen abhandeln lassen.

Dann nimm doch 4 Zeilen :mrgreen:

Nein, mal ganz ehrlich, wozu ist denn so etwas wie Objekt Orientierung gut? Soweit ich weiß ist das eine Möglichkeit Programme die etwas mehr als 3 Zeilen haben sinnvoll zu strukturieren. Wie gut jmd. diese gegebene Möglichkeit nutzt ist natürlich etwas anderes.
Übersichtlich finde ich (ist nur eine Meinung) die lokalen Funktionen gar nicht. Zwar kann ich hier auf Variablen zugreifen, aber wenn ich eine 500 Zeilen Funktion (mit all ihren lokalen Funktionen zusammen) habe und 20 Parameter, dann frage ich mich warum das keine eigene Klasse ist. Natürlich kann man nicht pauschal sagen > 5 Zeilen = Klasse draus machen, aber eigene Problematik gelöst = Klasse draus machen schon!
Deswegen sorry, muss ich RavenIV zustimmen, dass du eventuell einfach nur ungeeignet designst. Ich denke es gibt andere Sprachen, die keine Lokalen Funktionen erlauben (auch keine Makros oder ähnliches) die auch übersichtlichen Code hinbekommen (mit > 3 Zeilen).

Gruß Der Unwissende

[EDIT]
Zitat:

Zitat von xaromz
Die vielen lokalen Variablen, von denen ich oben schrieb. Außerdem finde ich die lokale Sichtbarkeit den Funktionen irgendwie logischer, da es sich ja um "Unterstützungsfunktionen" der Hauptfunktion handelt, die nur im Kontext dieser sinvoll sind. Wozu also auslagern?

UPS, wo kommt das denn her? Na ja, dann auch dazu noch was

Na ja, wenn du ein Problem löst (und es auch noch eine gewisse Komplexität übersteigt), dann lohnt sich auslagern immer. Du hast deine Methode und ihre Implementierung nach eigener Aussage mehrfach verändert. Das kannst du natürlich noch viel leichter mit einem Objekt machen. Du kannst hier einfach neue Klassen schaffen (mit gleicher Schnittstelle) und die beliebig austauschen und das alles als Basis für weitere Spezialisierungen verwenden. Taucht dein Problem noch einmal auf, kannst du einfach die Klasse (die hier die ausgelagerte Funktion ist) verwenden.
Ich denke es wäre auch lesbarer, da sich alle Prozeduren immer auf einer Ebene befinden. Vorallem sehen Leute die nicht häufig (oder nie) mit lokalen Prozeduren arbeiten sofort wo Anfang und Ende einer Prozedur stehen.
[/EDIT]

RavenIV 21. Aug 2006 16:53

Re: verschachtelte function?
 
Wenn man sich der Namensgebung ein wenig widmet, kann man das Logische auch recht gut abbilden.
Delphi-Quellcode:
function Rechnen ();
function Rechnen_BerechneWas ();
function Rechnen_HoleWerte ();
function Rechnen_WerteAusgeben ();
usw.
Da sieht man doch auch auf einen Blick, was zusammen gehört.

SirThornberry 21. Aug 2006 16:56

Re: verschachtelte function?
 
Zitat:

Zitat von xaromz
Hallo,
Zitat:

Zitat von SirThornberry
@xaromz: Was spricht in deinem Fall dagegen die Funktionen als eigenständige Funktionen zu Handhaben?

Die vielen lokalen Variablen, von denen ich oben schrieb. Außerdem finde ich die lokale Sichtbarkeit den Funktionen irgendwie logischer, da es sich ja um "Unterstützungsfunktionen" der Hauptfunktion handelt, die nur im Kontext dieser sinvoll sind. Wozu also auslagern?

Gruß
xaromz

Ist es da aber nicht sinnvoller die Funkion zu einer Klasse umzuformen wenn so viel abgrenzbare Dinge (derzeit lokale Proceduren) gemacht werden?

r2c2 21. Aug 2006 18:01

Re: verschachtelte function?
 
Ich finde die "Nested Functions" - so heißen die Viecher IMHO - manchmal auch praktisch. Zugegeben nicht immer. Aber in C# und C++(Hab grad n Ferienjob, bei dem ich C++Builder progge) fehlen sie mir manchmal sogar. Und zwar genau dann, wenn man Funktionen in Teilfunktionen aufteilen will, sich das Ganze aber nicht bzw. nur schwer oder nur eingeschränkt sinnvoll in eine Klasse auslagern lässt[1]. In gewissem Sinne(Information- bzw. FunctionHiding) entspricht das sogar den Prinzipien der OOP.

N Beispiel, das jeder kennt, und wo NestedFunctions IMHO sinnvoll eingesetzt werden: QuickSort...

[1] zugegebn n schmaler Bereich...

mfg

Christian

Meflin 21. Aug 2006 18:05

Re: verschachtelte function?
 
Zitat:

Zitat von RavenIV
Ich möchte Dir nicht zu nahe treten, aber da würde ich das Design der Software nochmal überdenken...

:wall: dann nenne ich dir mal ein anderes Beispiel: ich hatte mal eine thread-Funktion, in der eine bestimmte Operation ausgeführt werden sollte. Diese Funktion war so etwa 15,20 Zeilen lang (wie süß :mrgreen: ) Der Rest der Threadfunktion, das ganmze Verwaltungs-drumherum war um einiges länger.

Und was spricht jetzt bitteschön dagegen diese 15 Zeilen Code in eine Lokale function auszulagern und in der Threadfunktion aufzurufen? Wie unübersichtlich! Welch schlechtes Softwaredesign! :roll: So findet man jedenfalls die eigenltiche *Funktion* des Threads wesentlich schneller...


TBx 21. Aug 2006 19:58

Re: verschachtelte function?
 
also mal ganz ehrlich: alienous hatte gefragt, worin die Bedeutung der Functionen/Prozeduren innerhalb anderer Funktionen/Prozeduren liegt. Das ist mit der Erklärung des Scopes beantwortet worden.
Jetzt entsteht hier wieder mal eine Debatte darüber, ob die Verwendung eines Faetures von Delphi guter oder schlechter Programmierstil ist.
Muß das denn sein? Dann können wir ja auch gleich in diesem Thread weitermachen. :wall: :wall: :wall:

Entschuldigt bitte, wenn das etwas säuerlich klingt, aber ich finde, das Diskussionen sachlich sein sollten. Anderen ein schlechtes Design vorzuwerfen, ohne dessen Programmierung zu kennen, ist sicherlich keine konstruktive Kritik.

Ich für meinen Teil kann sagen, daß sowohl nested Functions als auch Auslagerung in entsprechende Klassen Ihre Berechtigung haben. Welches Mittel man wann wählt, ist dem Programmierer nunmal selbst überlassen.

Gruß

onlinekater

Der_Unwissende 21. Aug 2006 20:28

Re: verschachtelte function?
 
Zitat:

Zitat von onlinekater
Jetzt entsteht hier wieder mal eine Debatte darüber, ob die Verwendung eines Faetures von Delphi guter oder schlechter Programmierstil ist.
...
Entschuldigt bitte, wenn das etwas säuerlich klingt, aber ich finde, das Diskussionen sachlich sein sollten. Anderen ein schlechtes Design vorzuwerfen, ohne dessen Programmierung zu kennen, ist sicherlich keine konstruktive Kritik.

Ja, sachlich diskutieren ist ja schön und gut! Das würde damit anfangen, dass ich jetzt nicht die Stelle finde wo der Programmierstil von jmd. kritisiert wurde. Was die Kritik am Softwaredesign anging, so wird hier sehr kontextfrei das Zitat
Zitat:

Zitat von RavenIV
Ich möchte Dir nicht zu nahe treten, aber da würde ich das Design der Software nochmal überdenken...

[/quote]
verwendet. Allerdings wurde direkt vorher von einer Funktion mit 20 benötigten Parametern und 500 Zeilen (inkl. allen Unterfunktionen) gesprochen. Ich denke da ist es durchaus angebracht Kritik an der Funktion zu üben, 500 Zeilen sind doch wohl mit sehr hoher Wahrscheinlichkeit teilbar (und für mich komplett unleserlich).

Natürlich verbietet einem keiner Funktionen in andere einzubetten. Natürlich ist das kein schlechter Programmierstil, aber definitiv kein OO Design. Imho wurde mehr nicht gesagt. Es verlangt keiner dass Delphi Programmierer OO arbeiten! Aber es bietet Möglichkeiten und ein Hinweis auf diese denke ich sind total ok.

Ich seh ehrlich gesagt noch nicht den sachlichen Vorteil darin, dass ich eine Funktion innerhalb einer Funktion verwende. Als Nachteile sehe ich weiterhin, dass die Lesbarkeit reduziert wird. Man sieht meiner Meinung nach nicht sofort, wo was herkommt. Insbesondere das Variablen aus der umgebenden Funktion verwendet werden können senkt schon alleine die Lesbarkeit. Die dürften sich schwer qualifizieren lassen und sind weder als Parameter übergeben, noch in der Funktion lokal! Habe ich also 3 solcher Funktionen in einer Funktion kann ich erstmal suchen wo welche Funktion aufhört und von der untersten aus suchen, wo die Variablen deklariert sind.
Insbesondere Anfänger haben (meiner Erfahrung nach) sehr viele Probleme mit dem lesen solcher Funktionen. Ohne Frage, man bekommt jedes Programm unleserlich, aber es gibt Dinge die etwas erleichtern oder erschweren. Ich sehe hier eine Möglichkeit die Lesbarkeit zu verringern, aber noch keinen Vorteil. Warum sollte eine private Methode eine andere private Methode nicht kennen? Da ich von Methoden spreche gehören sie zu einem Objekt, da sie privat sind, können beide nicht von aussen gesehen werden. Ich habe hier also eine (imho gute) Alternative. Methoden sehen immer gleich aus und ich würde sofort sehen ob es sich um lokale Variablen oder Instanzvariablen handelt (mit Qualifizierung durch self.).

negaH 21. Aug 2006 20:36

Re: verschachtelte function?
 
Zitat:

Also mir kommt auch immer die Galle hoch, wenn ich eine Procedure/Function in einer Procedure/Function sehe (sogenannte lokale Proceduren/Funktionen).
Mit OO hat dies nix mehr zu tun, da kann ich ja grad alles in eine Main-Function reinschreiben. Uaaargs!

Ich löse sowas immer mit einer Klassenmethode, evtl wird diese überladen oder mit Default-Parametern versehen...
Tja, dann scheinst du die Grundlagen der prozeduralen Programmierung, genauer gesagt der Modularisierung, Abstraktion und BlackBox Prinzip, nicht vestanden.

Nested Functions -> verschachtelte lokale Funktionen, sind ein sehr starkes Instrument in der Programmierung um ein komplexes und nicht weiter reduzierbares Problem (reduzierbar zb. per OOP) einfacher und modularisierter umzusetzen.

Defakto sind nested Functions die konsequente Umsetzung des Prinzips der Abstraktion, das zb. auch in Delphi über Program -> Units -> Interface -> Implementation -> Function -> nested Function.

Ich persönlich erachte also nested Functionen als sehr guten Stil. Das hat mehrere Gründe:

1.) abstraktion eines Problems durch Zerlegung in immer kleinere und übersichtlichere Teilprobleme
2.) besser Lesbar, da man wenn man eine Funktion als BlackBox verstanden hat, deren Implementierung quasi wieder vergessen kann, es interessiert dann nur noch der Name, In/Out Parameter dieser Funktionen
3.) da nested Funktionen nun mit sehr wenigen Sourcezeilen, Parameter und lokalen Variablen auskommen (entgegen eine rießigen komplexen single Funktion) kann der Delphi Compiler den erzeugten Code optimieren.
4.) es gibt keine andere Möglichkeit als eine nested Funktion wenn man ein Problem als Black Box so stark abstrahieren möchte das diese Details nirgends von aussen sichtbar sind. Dh. wenn man innerhalb einer Funktion einen Code mehrmals benötigt und diesen in eine Funktion auslagert, dann ist die stärkste Un-sichtbarkeits-stufe nur eine nested Funktion. Eine nicht-nested Funktion wäre also sichtbar für andere Funktionen, das ist aber unerwünscht.

Mit nested Funktionen kann man also ein Problem nicht nur sauberer lösen sondern der erzeugte Maschinencode wird auf Grund der besseren optimierung durch den Compiler auch schneller sein.

Dazu muß man aber auch wissen wie der Compiler überhaupt einen Code optimiert. In diesem Falle interessiert uns nur die Frage wie der Compiler mit den vorhandenen Prozessorregistern umgeht. Und da ist es so das diese Register der CPU in ihrer Anzahl begrenzt sind und der Compiler immer versucht möglichst viele lokale Variblen in Registern zu halten. Je komplexer eine Funktion ist desto mehr lokale Variablen wird sie benötigen und um so mehr steht der Optimierer unter Registerdruck, dh. er hat normalerweise nicht genügend CPU Register zur Verfügung um alle lokalen Variablen der Funktion darin zu optimieren.

Mit nested Funktionen zerlegt man nun diese komplexe Funktion in so viele Teil-Funktionen (nested) das jede dieser Funktionen nun mit wesentlich weniger lokalen Variablen auskommen. Nun kann der Compiler diese Teil-Funktionen weit besser optimieren.

Der Compiler betrachtet nämlich einen Code innerhalb einer Funktion immer als Optimierungs-Einheit, als Ganzes das er optimieren soll. Der Delphi Compiler kann NICHT Code über Funktionsgrenzen hinweg optimieren und um so wichtiger wird es das man die eigenen Funktionen so weit vereinfacht das er möglichst alle lokalen Variablen in Registern halten kann.

Gruß Hagen

xaromz 21. Aug 2006 20:40

Re: verschachtelte function?
 
Hallo,
Zitat:

Zitat von Der_Unwissende
Ja, sachlich diskutieren ist ja schön und gut! Das würde damit anfangen, dass ich jetzt nicht die Stelle finde wo der Programmierstil von jmd. kritisiert wurde. Was die Kritik am Softwaredesign anging, so wird hier sehr kontextfrei das Zitat
Zitat:

Zitat von RavenIV
Ich möchte Dir nicht zu nahe treten, aber da würde ich das Design der Software nochmal überdenken...

verwendet. Allerdings wurde direkt vorher von einer Funktion mit 20 benötigten Parametern und 500 Zeilen (inkl. allen Unterfunktionen) gesprochen. Ich denke da ist es durchaus angebracht Kritik an der Funktion zu üben, 500 Zeilen sind doch wohl mit sehr hoher Wahrscheinlichkeit teilbar (und für mich komplett unleserlich).

Zu den 500 Zeilen: Die Zahl bezog sich eben auf die Prozedur mit sämtlichen Unterfunktionen. Ich habe also die Prozedur schon aufgeteilt.
Zitat:

Zitat von Der_Unwissende
Ich seh ehrlich gesagt noch nicht den sachlichen Vorteil darin, dass ich eine Funktion innerhalb einer Funktion verwende. Als Nachteile sehe ich weiterhin, dass die Lesbarkeit reduziert wird. Man sieht meiner Meinung nach nicht sofort, wo was herkommt.

So ein großer Unterschied ist es jetzt nicht, ob erst ein Prozedurkopf kommt und dann einige Funktionen, oder erst die ganzen Funktionen und dann die Hauptprozedur. Das ist alles eine Frage der Formatierung.
Zitat:

Zitat von Der_Unwissende
Insbesondere das Variablen aus der umgebenden Funktion verwendet werden können senkt schon alleine die Lesbarkeit. Die dürften sich schwer qualifizieren lassen und sind weder als Parameter übergeben, noch in der Funktion lokal! Habe ich also 3 solcher Funktionen in einer Funktion kann ich erstmal suchen wo welche Funktion aufhört und von der untersten aus suchen, wo die Variablen deklariert sind.

Wenn ich also aus der Prozedur eine Klasse baue, in der die Unterfunktionen private Methode sind, dann muss ich sämtliche Variablen, die vorher lokal in der Funktion deklariert waren, jetzt als Member in die Klasse aufnehmen. Außer einer anderen Quellcode-Formatierung habe ich damit eigentlich nichts gewonnen. Die Trennung der Variablen nach ihrer Verwendung lässt sich nämlich auch mit Nested Procedures bewerkstelligen.

Gruß
xaromz

negaH 21. Aug 2006 20:55

Re: verschachtelte function?
 
Zitat:

Ich seh ehrlich gesagt noch nicht den sachlichen Vorteil darin, dass ich eine Funktion innerhalb einer Funktion verwende. Als Nachteile sehe ich weiterhin, dass die Lesbarkeit reduziert wird. Man sieht meiner Meinung nach nicht sofort, wo was herkommt.
Siehst du und da meine ich arbeitest du ineffizient.

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:
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;
Das ist das was du propagierst ;)

Delphi-Quellcode:
  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;
1.) man sieht wohl den Unterschied in der Lesbarkeit
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

alienous 21. Aug 2006 23:02

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:

Der_Unwissende 22. Aug 2006 09:21

Re: verschachtelte function?
 
Zitat:

Zitat von alienous
alles klar, habs verstanden! vielen dank.
wieder etwas gelernt! :dancer:

Das ist gut (wirklich!)

Zitat:

Zitat von negaH
Zitat:

Ich seh ehrlich gesagt noch nicht den sachlichen Vorteil darin, dass ich eine Funktion innerhalb einer Funktion verwende. Als Nachteile sehe ich weiterhin, dass die Lesbarkeit reduziert wird. Man sieht meiner Meinung nach nicht sofort, wo was herkommt.
Siehst du und da meine ich arbeitest du ineffizient.

Interessante Meinung

Zitat:

Zitat von negaH
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.

Was genau möchtest du mir denn hier unterstellen?! Mir wäre nicht klar, dass man alle Details einer Implementierung im Kopf finden könnte (oder alle Programme bestehen nur aus einem Kopf). Dass Delphi seine Variablen/Methoden immer schon vor ihrer Implementierung bekannt macht ist keineswegs ein Feature das ich beführworte. Finde das andere Sprachen, wie Java, die Dinge erst einführen wenn sie wirklich verwendet werden sehr viel besser.
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:

Zitat von negaH
Was ist den das Gegenteil der Funktionen, und eben nested Funktionen ? Spaghetti-code !

Von welchen Funktionen redest du denn bitte? Erstmal ist Spaghetti-Code auch innerhalb von Funktionen ohne weiteres Möglich und auch in einer nested Function kann ich sicherlich welchen unterbringen. Das hat doch nichts mit Alternativen zu tun. Ich (und kein anderer hier) habe doch nie behauptet, dass man keine Funktionen verwenden soll. Bleib doch einfach erstmal bei dem was hier gesagt wurde!
Es geht um so genannte nested Functions! Und wo ist jetzt der gut leserliche Vorteil zwischen :

Delphi-Quellcode:
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;
und dem was ich wirklich propagiere!

Delphi-Quellcode:
type
  TConverter = class(TObject)
    private
      function Convert(K : Integer): String;
    public
      doFoo;
  end;

....
function Convert(K: Integer): String;
begin
  Result := '';
  while K <&gt; 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 negaH

Zitat:

Zitat von negaH
1.) man sieht wohl den Unterschied in der Lesbarkeit

Klar, finde die Klasse ist sehr leicht lesbar. Ich sehe dass es sich hier um zwei Methoden handelt und kann die sehr leicht getrennt voneinander betrachten.
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:

Zitat von negaH
2.) Convert() als Funktion wird ausschließlich nur in dieser Funktion benötigt und um Namens Kollisionen zu vermeiden machen wird sie nested

Was natürlich ein weiterer Nachteil ist. Was ist denn wenn ich eine äussere Funktion habe, die auch convert heißt? Jetzt merke ich mir nicht alle nested Functions und komme schnell zu dem Punkt, an dem ich zwei Funktionen verwechsel (und mir Ergebnisse nicht erklären kann).
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 von negaH
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

Ok, darüber habe ich mir keine Gedanken gemacht, aber wieviel bringt das ganze? Ich meine klar die Relationen sind hier schon klar, doch der erste Cache-Miss könnte die Vorteile hier schon deutlich dominieren (was so pauschal auch falsch ist, aber egal).

Zitat:

Zitat von negaH
Gibt es eine procedurale Modularisierung in einer Programmiersprache so gibt es dort auch konsequenter Weise die nested Funktionen als stärkste Abstraktionsebene.

Dazu kann ich nur nochmal sagen, dass es nie darum ging. Alles was ich sagte ist, dass es andere Mittel gibt (da stimmen wir ja völlig überein) um Abstraktion zu erreichen. Ich finde einfach, dass die Lesbarkeit vom Code durch nested-Functions eingeschränkt wird. Der Vorteil (den ich nicht kannte und jetzt dazu gelernt habe) liegt in dem Perfomanteren übergeben von Parametern an die nested Function.

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:
procedure doA;
  var x : Integer;
 
  procedure doB;
  var y : Integer;
     
     procedure doC;
     var z : Integer;
     begin
       //....
     end;

   begin
     // ....
   end;

begin
  // ...
end;
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.
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

xaromz 22. Aug 2006 10:19

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:

Zitat von Der_Unwissende
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!)).

In meinem konkreten Beispiel ist es nicht möglich, einzelne Funktionen auszulagern. Wenn die ginge, dann hätte ich es auch gemacht. Ich muss sagen, Vorschläge zu machen, ohne das Problem zu kennen, finde ich etwas komisch.
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:
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;
Das sieht übersichtlich aus und benötigt sicher keine Klasse.

Gruß
xaromz
Gruß
xaromz

Der_Unwissende 22. Aug 2006 11:47

Re: verschachtelte function?
 
Zitat:

Zitat von xaromz
Delphi-Quellcode:
type
  TItem = class(TList);

procedure GoThroughTrees(Trees: TList);
Das sieht übersichtlich aus und benötigt sicher keine Klasse.

Ausser TItem und TList :wink:

xaromz 22. Aug 2006 11:53

Re: verschachtelte function?
 
Zitat:

Zitat von Der_Unwissende
Ausser TItem und TList :wink:

:mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:19 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