AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Sinnvoller Einsatz von goto

Ein Thema von Luckie · begonnen am 20. Mär 2010 · letzter Beitrag vom 22. Mär 2010
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#1

Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 00:36
Der Einsatz von goto wird ja immer so verteufelt. Ich habe das bisher eigentlich schon immer etwas differenziert gesehen, hatte bisher nur nie die Situation, in der ein goto sinnvoll gewesen wäre. Aber ich denke, gerade eben bin ich über einen sinnvollen Einsatz gestolpert:

Delphi-Quellcode:
function DemoThread(p: Pointer): Integer;
var
  i: Integer;
  ParentHandle: THandle;
  label CLEANUP;
begin
  ParentHandle := PThreadParams(p)^.ParentHandle;
  for i := 0 to 9 do
  begin
    if Abort then
    begin
      SendMessage(ParentHandle, CM_ABORT, 0 , 0);
      goto CLEANUP;
    end;
    SendMessage(ParentHandle, CM_STATUS, Integer(PChar('Durchlauf:')), i);
    Sleep(500);
  end;
  SendMessage(ParentHandle, CM_FINISHED, 0, 0);
CLEANUP:
  Dispose(p);
  Result := 0;
end;
Ich stelle das hier einfach mal zur Diskussion.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 01:00
Moin Michael,

ja, da könnte man wohl goto verwenden, aber mir gefällt folgende Lösung besser:

Delphi-Quellcode:
function DemoThread(const AParentHandle : THandle): Integer;
var
  i: Integer;

begin
  for i := 0 to 9 do
  begin
    if Abort then
    begin
      SendMessage(AParentHandle, CM_ABORT, 0 , 0);
      break;
    end else begin
      SendMessage(AParentHandle, CM_STATUS, Integer(PChar('Durchlauf:')), i);
      Sleep(500);
    end;
  end;
  if not Abort then SendMessage(AParentHandle, CM_FINISHED, 0, 0);
  Result := 0;
end;
BTW:
Den Speicher in der Funktion freizugeben, halte ich nicht für sinnvoll, da er ja dort nicht belegt wird.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 01:06
Das wäre natürlich eine Lösung. Allerdings finde ich meine besser lesbar.

Wollte ich den Speicher nicht in der Thread-Funktion frei geben, müsste ich die Variable global machen und doch wieder an anderer Stelle im Code freigeben. So hat man den direkten Bezug, auch wenn es natürlich oftmals schöner ist den Speicher dort wieder frei zu geben, wo man ihn anfordert. Da stimme ich dir zu.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 01:37
Nunja ein try-finally wäre wohl die richtige Wahl in dieser Situation

Delphi-Quellcode:
function DemoThread(p: Pointer): Integer;
var
  i: Integer;
  ParentHandle: THandle;
begin
  try
    ParentHandle := PThreadParams(p)^.ParentHandle;
    for i := 0 to 9 do
    begin
      if Abort then
      begin
        SendMessage(ParentHandle, CM_ABORT, 0 , 0);
        exit;
      end;
      SendMessage(ParentHandle, CM_STATUS, Integer(PChar('Durchlauf:')), i);
      Sleep(500);
    end;
    SendMessage(ParentHandle, CM_FINISHED, 0, 0);
  finally
    Dispose(p);
    Result := 0;
  end;
end;
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 01:47
Stellt sich die Frage, ob nach dem Exit der finally-Abschnitt noch abgearbeitet wird. Wenn dem so ist, dann spricht natürlich nichts gegen deine Lösung.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 01:53
Der wird noch abgearbeitet. Ist mir auch erst vor kurzem eher rein zufällig beim Debuggen aufgefallen
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#7

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 01:55
Das try-finally gefällt mir sogar besser, weil da sicher gestellt wird, dass der Speicher wieder freigegeben wird.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 02:05
Zitat von Neutral General:
Der wird noch abgearbeitet. Ist mir auch erst vor kurzem eher rein zufällig beim Debuggen aufgefallen
Hätte mich aber auch gewundert, wenn nicht.

War try...finally nicht so definiert, dass der finally-Teil in jedem Fall abgearbeitet wird,
egal was zwischen try und finally passiert?

Gut es gibt da schon Ausnahmen, die aber von dieser Betrachtung ausgeschlossen werden können:

- Stromausfall
- internationaler Weltuntergang
- etc.

um nur einige zu nennen
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#9

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 03:18
Zitat von Sir Rufo:
- internationaler Weltuntergang
Nationale wären nicht so schlimm?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#10

Re: Sinnvoller Einsatz von goto

  Alt 20. Mär 2010, 07:39
Da die Funktion zwei Aufgaben erfüllt (sende Nachrichten und räume auf), teilen wir sie. Da ein Goto zu 99.9% der Fälle eine Aufgabe beendet, fällt das Goto nun automatisch weg. Das ist kein Trick, sondern sowieso Pflicht, um das SRP (Single Responsibility Princip) auf funktionaler Ebene einzuhalten.
Delphi-Quellcode:
procedure TryHardToSendMessages (aParentHandle : THandle);
var
  i: Integer;

begin
  for i := 0 to 9 do begin
    if Abort then begin
      SendMessage(ParentHandle, CM_ABORT, 0 , 0);
      exit;
    end;
    SendMessage(ParentHandle, CM_STATUS, Integer(PChar('Durchlauf:')), i);
    Sleep(500);
  end;
  SendMessage(ParentHandle, CM_FINISHED, 0, 0);
End;

function DemoThread(p: Pointer): Integer;
begin
  Try
    TryHardToSendMessages (PThreadParams(p)^.ParentHandle);
  Finally
    Dispose(p);
  End;
  Result := 0;
end;
Hmm. Das mit der Schleife und dem Abort-Flag geht ja nun mal gar nicht (Abort ist ein reserviertes Schlüsselwort):
Außerdem und überhaupt ist nicht so richtig klar, wie die Nachrichten verwendet werden sollen. Mal sehen:

Wir senden 10x eine Nachricht 'CM_STATUS'. Nach jeder Nachricht warten wir 500ms.
Wenn alle 10 Nachrichten verschickt haben, senden wir ein 'CM_FINISHED'.
Wurden wir ausnahmsweise (<-Zaunpfahl) unterbrochen, senden wir ein CM_ABORT.
Delphi-Quellcode:
Procedure TryHardToSendMessages (aParentHandle : THandle);
var
  i: Integer;

begin
  Try
    for i := 0 to 9 do
      if ExternalAbort then
        abort
      else begin
        SendMessage(ParentHandle, CM_STATUS, Integer(PChar('Durchlauf:')), i);
        Sleep(500);
      end
  
    SendMessage(ParentHandle, CM_FINISHED, 0, 0);
  Except
// TODO: Vollständige Exceptionbehandlung
    SendMessage(ParentHandle, CM_ABORT, 0 , 0);
   end;
end;
Hier eine Alternative ohne Exceptions, sondern mit einer Funktion, die den Erfolg als Rückgabewert liefert.
Delphi-Quellcode:
Function Sending10MessagesWasNotAborted(aParentHandle) : Boolean;
Var
  i : Integer;

Begin
  for i := 0 to 9 do
    if ExternalAbort then
      break
    else begin
      SendMessage(ParentHandle, CM_STATUS, Integer(PChar('Durchlauf:')), i);
      Sleep(500);
    end;
  Result := ExternalAbort;
End;
  
Procedure TryHardToSendMessages (aParentHandle : THandle);
begin
  If Sending10MessagesWasNotAborted(aParentHandle) Then
    SendMessage(ParentHandle, CM_FINISHED, 0, 0)
  else
    SendMessage(ParentHandle, CM_ABORT, 0 , 0);
end;
Das ist -finde ich- noch lesbarer.
Nachteil der 2.Variante bzw. des dort verwendeten Verfahrens: Wenn dieses Paradigma durchgezogen wird, entstehen schnell verschachtelte und unleserliche If-Then-Abläufe, z.B.:
Delphi-Quellcode:
..
  If Action1IsSuccessfull then
    If Action2IsSuccessfull then
      If Action3IsSuccessfull then
        DoSomething
      else
        HandleException
    else
      HandleException
  else
    HandleException
..
Dann lieber so (Try-Except-Paradigma)
Delphi-Quellcode:
...
Try
  Action1;
  Action2;
  Action3;
Except
  HandleException;
End;
Paradigmen sollten zwar stringent durchgezogen werden, aber wozu sind solche Regeln da, wenn nicht zum brechen?
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:21 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz