Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Procedure in Procedure (https://www.delphipraxis.net/179765-procedure-procedure.html)

Metschu 31. Mär 2014 09:29

Delphi-Version: XE2

Procedure in Procedure
 
Hallo zusammen,

auf der Suche nach einer XML-Komponente wurde mehrfach der xml Paraser empfohlen.
In dem Beispielcode ist unter anderem eine Procedure innerhalb einer Procedure:
Delphi-Quellcode:
PROCEDURE TFrmMain.FillTree;

  PROCEDURE ScanElement (Parent : TTreeNode);
  VAR
    Node : TTreeNode;
    Strg : AnsiString;
    EN  : TElementNode;

  BEGIN
    WHILE XmlParser.Scan DO BEGIN
      Node := NIL;
      CASE XmlParser.CurPartType OF
        ptXmlProlog : BEGIN
                        Node := TrvDoc.Items.AddChild (Parent, '<?xml?>');
                        Node.ImageIndex := Img_Prolog;
                        EN := TElementNode.Create (StrSFPas (XmlParser.CurStart, XmlParser.CurFinal), NIL);
                        Node.Data := EN;
                      END;
{noch weitere CASE abfragen...}
     END;
      IF Node <> NIL THEN
        Node.SelectedIndex := Node.ImageIndex;
      END;
  END;

BEGIN
  TrvDoc.Items.BeginUpdate;
  TrvDoc.Items.Clear;
  XmlParser.Normalize := TRUE;
  XmlParser.StartScan;

  ScanElement (NIL);

  TrvDoc.Items.EndUpdate;
END;
Was hat dies für einen Hintergrund?
"ScanElement" wird ja nur einmal aufgerufen.

Danke schonmal.

Gruß

Torsten

Nersgatt 31. Mär 2014 09:33

AW: Procedure in Procedure
 
Übersichtlichkeit. Durch die Namensgebung der 2. Procedure wird automatisch dokumentiert, was dieser Codeabschnitt bewirkt.
Technisch hätte man es auch direkt in die 1. Procedure schreiben können.

bernau 31. Mär 2014 10:17

AW: Procedure in Procedure
 
Übersichtlich ist das Beispiel gar nicht. In dem Besipiel macht es m.E. keinen Sinn. Es macht Sinn, wenn die entsprechende Procedure mehrfach in der umschliessenden Procedure aufgerufen wird.

bernau 31. Mär 2014 10:21

AW: Procedure in Procedure
 
Ach ja. Sollten in der äusseren Procedure Variablen deklariert sein, kann die innere Procedure darauf zugreifen. Ist im Besispiel aber nicht gegeben.

vagtler 31. Mär 2014 10:40

AW: Procedure in Procedure
 
Zitat:

Zitat von bernau (Beitrag 1254107)
Übersichtlich ist das Beispiel gar nicht. [...]

Das ist Ansichtssache.

bernau 31. Mär 2014 10:50

AW: Procedure in Procedure
 
Stimmt. Ansichtssache ;-)

Aber in dem Fall hätte man die innere Procedure komplett auslagern können, da ja nicht auf Variablen der äusseren Procedure zurückgegriffen wird.

EWeiss 31. Mär 2014 10:53

AW: Procedure in Procedure
 
Zitat:

Zitat von bernau (Beitrag 1254116)
Stimmt. Ansichtssache ;-)

Aber in dem Fall hätte man die innere Procedure komplett auslagern können, da ja nicht auf Variablen der äusseren Procedure zurückgegriffen wird.

Welchen sinn macht das ?
Wenn diese Procedure im gesamten Code nur einmal verwendet wird.
Irgendwie unlogisch oder?

gruss

Nersgatt 31. Mär 2014 10:55

AW: Procedure in Procedure
 
Das mit der Übersichtlichkeit ist natürlich immer subjektiv.

Man hätte sich hier auch den Parameter sparen können, da offensichtlich immer NIL übergeben wird. Es sieht so aus, als wäre die innere Procedure ein Relikt aus Zeiten, wo der Aufruf noch öfter (mit verschiedenen Parameterwerten) vorkam.

Trotzdem kann die Aufteilung schon Übersichtlichkeit bringen (wie gesagt, die Funktion des Codeabschnitts ergibt sich hier schon aus dem Namen).
Ich persönlich nutze diese Procedure-in-Procedure-Konstrukte recht selten. Hier in dem Fall hätte ich auch eine private procedure von TfrmMain davon gemacht.

himitsu 31. Mär 2014 11:09

AW: Procedure in Procedure
 
Eventuell war in der Procedur früher mal ein rekursiver Code, der dann später zu diesem iterativen Code umgebaut wurde?
Und der Einfachheit halber ließ man den Code dann ganz einfach dort.

Zitat:

Zitat von bernau (Beitrag 1254116)
Aber in dem Fall hätte man die innere Procedure komplett auslagern können, da ja nicht auf Variablen der äusseren Procedure zurückgegriffen wird.

Auslagern gut und schön, aber dann auch bitte richtig!
Also XmlParser und TrvDoc gehören gefälligst in den Parametern übergeben.

Dejan Vu 31. Mär 2014 11:21

AW: Procedure in Procedure
 
Variante 1;
Delphi-Quellcode:
Procedure Something();
Begin
  if Foobar>23 then Stuff:=Bar;
  For bar in foo do begin
  ...
  end;
end;
Variante 2:
Delphi-Quellcode:
Procedure Something();
  Procedure SetStuff();...
  Procedure ProcessAllFoos();...
Begin
  SetStuff();
  ProcessAllFoos();;
end;
Variante 2 *dokumentiert* ohne Kommentar. Prozeduren sind ja nicht nur dazu da, um Redundanz zu vermeiden, sondern sollen die Lösung (also den Code) in Teillösungen unterteilen. Im Idealfall so, das jede Teillösung (aka Prozedur, Methode) nur eine einzige Aufgabe hat (=> Clean Code).

Die Sache mit den lokalen Prozeduren ist ein Überbleibsel aus der Vor-OOP-Zeit. Mittlerweile würde man das eher als private Methode umsetzen.

bernau 31. Mär 2014 11:21

AW: Procedure in Procedure
 
Zitat:

Zitat von EWeiss (Beitrag 1254117)
Zitat:

Zitat von bernau (Beitrag 1254116)
Stimmt. Ansichtssache ;-)

Aber in dem Fall hätte man die innere Procedure komplett auslagern können, da ja nicht auf Variablen der äusseren Procedure zurückgegriffen wird.

Welchen sinn macht das ?
Wenn diese Procedure im gesamten Code nur einmal verwendet wird.
Irgendwie unlogisch oder?

gruss

Wie ich oben schon geschrieben hatte, finde ich es unübersichtlich diesen Code als Nested Procedure zu definieren. Daß dies eine Ansichtssache ist, stimme ich zu.

Aber Unlogisch finde ich es nicht, die Funktion komplett auszulagern und nicht Nested zu verwenden. Auch wenn diese nur einmal verwendet wird. Wer sagt, daß dieser Codeabschnitt nicht doch noch irgendwann ein zweites mal mal verwednet werden soll?

OlafSt 31. Mär 2014 11:24

AW: Procedure in Procedure
 
Ist es noch immer so, das lokale Prozeduren einen heftigen Aufruf-Penalty innehaben ? Ich meine mich zu erinnern, das dem so war und ich deswegen diese Konstrukte meide wie die Pest...

Ansonsten habe ich schon genug Beispiele gesehen, in denen lokale Prozeduren ein Alptraum an Unübersichtlichkeit produziert haben (Prozedur, 40k Zeilen lang (an sich schon ein Problem), darin eingebaut 15 lokale Prozeduren im 100-Zeilen-Bereich) - schier undurchdringlich, das Dickicht ;))

Nersgatt 31. Mär 2014 11:25

AW: Procedure in Procedure
 
Ich finde immer, bei normale privaten Methoden ist klarer, welchen Scope die lokalen Variablen haben.
Bei Nested procedures hab ich da immer so meine Probleme. Klar, technisch ist ganz klar, welchen Scope die Variablen haben. Es lässt sich aber etwas mühsam aus dem Quelltext rauslesen.
Das ist mein Hauptgrund, eher eine private Methode als eine nested procedure zu verwenden. Auch wenn sie nur 1x aufgerufen wird.

bernau 31. Mär 2014 11:29

AW: Procedure in Procedure
 
Zitat:

Zitat von himitsu (Beitrag 1254123)
Auslagern gut und schön, aber dann auch bitte richtig!
Also XmlParser und TrvDoc gehören gefälligst in den Parametern übergeben.

Wer sagt, daß ich das nicht so gemacht hätte ;-)

Aber auch das ist Ansichtssache. XmlParser und TrvDoc sind anscheinend in TFrmMain deklariert. Warum sollte ich keine private Methode zur Form schreiben, die direkt auf diese deklarationen zugreift?

Popov 31. Mär 2014 13:46

AW: Procedure in Procedure
 
Prozeduren/Functionen in Prozeduren sind an sich eine feine Sache. Ob der obere Code nicht auch ohne eine ausgekommen wäre, ist eine Ansichtssache, ich hätte vermutlich es auch so gemacht. Im Grunde nutze ich diese Möglichkeit sogar sehr oft. Der Grund ist simpel - zuerst wie gesagt, man kann es auch über eine Prozedur lösen, aber wenn man sich die zweite Prozedur anguckt, ist sie allgemein gehalten, hat also keinen direkten Bezug zu TFrmMain. Allgemeine Prozeduren kann man immer wieder gebrauchen, ob im gleichen Projekt oder in später in anderen. Hat man alles in einer Prozedur, ist die Prozedur mit den Bezeichnungen andere Komponenten "verunreinigt". Spätere Nutzung ist somit schwieriger, man muss die Prozedur denn erst "bereinigen". Ist sie allgemein gehalten, kann man sie immer wieder nutzen.

Hat man eine allgemeine Prozedur, kann man sie auch direkt in die Unit packen. Wenn aber nur die eine einzige Prozedur sie nutzt, dann packe ich sie auch in die Prozedur. Das erhöht die Lesbarkeit, ich weiß, dass nur die Prozedur die andere Prozedur nutzt.

Womit die erste Aussage im Grunde stimmt: sowas erhöht die Übersichtlichkeit.

Dejan Vu 31. Mär 2014 13:53

AW: Procedure in Procedure
 
Aber eigentlich ist es schon unübersichtlich, die Logik in der Form unterzubringen. Hätte man dafür eine eigene Klasse, wäre dort die private Methode sehr gut aufgehoben. So machen wir das jedenfalls.

himitsu 31. Mär 2014 14:00

AW: Procedure in Procedure
 
Bei kleines Funktionen/Proceduren nutze ich sowas manchmal, um "klarzustellen", daß diese eingebette Funktionen/Proceduren ausschließlich zur Übergeordneten Funktionen/Proceduren/Methode gehört.
[edit] Jupp, im Prinzip ist das so eine private Methode der übergeordneten Prozedur.

Und der einzige "Vorteil" ist, daß man direkten Zugriff auf lokale Variablen der übergeordneten Methode besitzt. (auf Die, welche davor deklariert sind)

stahli 31. Mär 2014 14:51

AW: Procedure in Procedure
 
Ich nutze so etwas auch öfter wegen der (für mich) besseren Übersichtlichkeit:

Delphi-Quellcode:
procedure DoSommething;
 procedure DoA;
 ...
 procedure DoB;
 ...
 procedure DoC;
 ...
begin
 DoA;
 DoB;
 DoC;
end;
Benötigte Parameter übergebe ich meist beim Prozedur-Aufruf (so dass ich die Unterprozeduren generell auch auslagern könnte).

Wie schon geschrieben, letztlich ist das Geschmackssache und ich entscheide das auch von Fall zu Fall unterschiedlich.

himitsu 31. Mär 2014 15:12

AW: Procedure in Procedure
 
Wobei inzwischen (seit über 5 Jahren) auch sowas ginge:
Delphi-Quellcode:
procedure DoSommething;
begin
  {$REGION 'DoA'}
  ...
  {$ENDREGION}
  {$REGION 'DoB'}
  ...
  {$ENDREGION}
  {$REGION 'DoC'}
  ...
  {$ENDREGION}
end;
Regionen lassen sich ja zusammenklappen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:01 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 by Thomas Breitkreuz