Der-Dennis: Return in try-catch-Block

Hallo zusammen,

mir ist neulich aufgefallen, dass bei den meisten Anwendungen (oder Frameworks: Zend Framework ist so ein Beispiel) ein return nicht in einem try-catch-Block verwendet wird.

Es wird also nicht (wie von mir favorisiert) so etwas wie

  
class Test  
{  
	public function returnInTryCatchBlock()  
	{  
		try {  
			return $this->throwsException();  
		} catch (Exception $e) {  
			return 'Catched!';  
		}  
	}  
}  

verwendet, sondern so etwas

  
class Test  
{  
	public function returnInTryCatchBlock()  
	{  
		try {  
			$var = $this->throwsException();  
		} catch (Exception $e) {  
			$var = 'Catched!';  
		}  
		return $var;  
	}  
}  

Das kann ich mir nicht wirklich erklären, warum das sehr häufig so gemacht wird. Übersichtlicher finde ich persönlich auf jeden Fall die erste Schreibweise. Dann dachte ich, es liegt eventuell an der Geschwindigkeit und hab's getestet: Die zweite Schreibweise benötigt in etwa doppelt so lange wie die erste. Ist also auch kein Grund.

Hat jemand eine Idee, warum dies häufig so gemacht wird? Das Beispiel mit dem try-catch-Block ist nur eine von mehreren Schreibweisen, die mir nicht so ganz einleuchten. Wenn mir jemand exemplarisch bei diesem Beispiel weiterhelfen kann, kann ich eventuell auch die anderen Schreibweisen davon ableiten.

Gruß und Danke, Dennis

  1. Hi!

    mir ist neulich aufgefallen, dass bei den meisten Anwendungen (oder Frameworks: Zend Framework ist so ein Beispiel) ein return nicht in einem try-catch-Block verwendet wird.
    Hat jemand eine Idee, warum dies häufig so gemacht wird?

    An einem theoretischen Beispiel kann man eine Menge Theorien entwickeln. An einer echten Anwendung könnte man zumindest versuchen, die Intention dahinter aus dem Kontext zu finden.

    Du könntest aber erst einmal die Coding-Style-Guidelines durchsuchen, ob darin etwas zu finden ist.

    Lo!

    1. Hey dedlfix,

      wie einmal danke für Deine Antwort.

      mir ist neulich aufgefallen, dass bei den meisten Anwendungen (oder Frameworks: Zend Framework ist so ein Beispiel) ein return nicht in einem try-catch-Block verwendet wird.
      Hat jemand eine Idee, warum dies häufig so gemacht wird?

      An einem theoretischen Beispiel kann man eine Menge Theorien entwickeln.

      Ja, da hast Du recht. Da war mein Beispiel nicht glücklich gewählt.

      An einer echten Anwendung könnte man zumindest versuchen, die Intention dahinter aus dem Kontext zu finden.

      Genau da habe ich bei einigen Dingen Probleme, also die Intention dahinter zu finden. Hier ein Beispiel aus dem Zend Framework, genauer gesagt die Methode getLocale() aus der Klasse Zend_Controller_Router_Route (die hab ich grad als erstes gefunden):

        
          public function getLocale()  
          {  
              if ($this->_locale !== null) {  
                  return $this->_locale;  
              } else if (($locale = self::getDefaultLocale()) !== null) {  
                  return $locale;  
              } else {  
                  try {  
                      $locale = Zend_Registry::get('Zend_Locale');  
                  } catch (Zend_Exception $e) {  
                      $locale = null;  
                  }  
        
                  if ($locale !== null) {  
                      return $locale;  
                  }  
              }  
        
              return null;  
          }  
      
      

      Hierbei wird ein try-catch-Block wie im vorherigen Beispiel verwendet (mal ganz abgesehen davon, dass die if-Abfrage innerhalb des else-Zweigs für mich sinnlos ist. Genauso gut könnte ich die weglassen und am Ende $locale zurückgeben).

      Du könntest aber erst einmal die Coding-Style-Guidelines durchsuchen, ob darin etwas zu finden ist.

      Das ist ein super Tipp! Da habe ich ewig nicht mehr reingeschaut. Auf die Schnelle habe ich unter http://pear.php.net/manual/en/standards.errors.php im Beispiel "Rethrowing an exception" bei "Error Signaling in PHP 5 PEAR packages" auch schon gefunden, dass ein return innerhalb eines try stattfindet.

      So, jetzt werde ich mir erst einmal wieder in Ruhe die Coding Standards zu Gemüte führen.

      Für alle, die es auch interessiert, hier ein paar Einsteiger-Links:
      http://pear.php.net/manual/en/standards.php
      http://framework.zend.com/wiki/display/ZFDEV/PHP+Coding+Standard+(draft)
      http://framework.zend.com/manual/de/coding-standard.coding-style.html

      Gruß, Dennis

      1. Kurze Ergänzung:

        public function getLocale()
            {
                if ($this->_locale !== null) {
                    return $this->_locale;
                } else if (($locale = self::getDefaultLocale()) !== null) {
                    return $locale;
                } else {
                    try {
                        $locale = Zend_Registry::get('Zend_Locale');
                    } catch (Zend_Exception $e) {
                        $locale = null;
                    }

        if ($locale !== null) {
                        return $locale;
                    }
                }

        return null;
            }

        
        >   
        > Hierbei wird ein try-catch-Block wie im vorherigen Beispiel verwendet (mal ganz abgesehen davon, dass die if-Abfrage innerhalb des else-Zweigs für mich sinnlos ist. Genauso gut könnte ich die weglassen und am Ende $locale zurückgeben).  
          
        Wobei sich natürlich die Frage stellt, ob in diesem Fall die Verwendung von try...catch überhaupt Sinn macht. Zend\_Registry erweitert ja ArrayObject, sodass ich mit einer einfachen if-Abfrage prüfen kann, ob ein Schlüssel im Array (Zend\_Registry) existiert. Denn meines Wissens ist ein try...catch die schlechtere Alternative zu einer if-Abfrage.  
          
        Gruß, Dennis
        
        1. Hi!

          public function getLocale()

          {
                  if ($this->_locale !== null) {
                      return $this->_locale;
                  } else if (($locale = self::getDefaultLocale()) !== null) {
                      return $locale;
                  } else {
                      try {
                          $locale = Zend_Registry::get('Zend_Locale');
                      } catch (Zend_Exception $e) {
                          $locale = null;
                      }

          if ($locale !== null) {
                          return $locale;
                      }
                  }

          return null;
              }

          
          > >   
          > > Hierbei wird ein try-catch-Block wie im vorherigen Beispiel verwendet (mal ganz abgesehen davon, dass die if-Abfrage innerhalb des else-Zweigs für mich sinnlos ist. Genauso gut könnte ich die weglassen und am Ende $locale zurückgeben).  
            
          Also, ich sehe da auch keinen Sinn dahinter. Möglicherweise hat da einer, nach seinen Versuchen den Code für die Aufgabe zu erstellen, vergessen aufzuräumen. Das ist eine der Stellen, die nach einer Revision dazu führt, dass man in der Nachfolgeversion stolz einen Geschwindigkeitszuwachs berichten kann.  
            
          Jedenfalls kann man den Code kürzen zu  
            
            public function getLocale()  
            {  
              if ($this->\_locale !== null) {  
                return $this->\_locale;  
              }  
              if (($locale = self::getDefaultLocale()) !== null) {  
                return $locale;  
              }  
              try {  
                return Zend\_Registry::get('Zend\_Locale');  
              } catch (Zend\_Exception $e) {  
                return null;  
              }  
            }  
            
          Der Original-Code zeigt übrigens auch mal wieder sinnlose else-Zweige. Wenn der if-Zweig garantiert mit return beendet wird, kann der alternative Code gar nicht mehr ausgeführt werden und muss deshalb nicht in einem else-Block versteckt werden.  
            
          
          > Wobei sich natürlich die Frage stellt, ob in diesem Fall die Verwendung von try...catch überhaupt Sinn macht. Zend\_Registry erweitert ja ArrayObject, sodass ich mit einer einfachen if-Abfrage prüfen kann, ob ein Schlüssel im Array (Zend\_Registry) existiert. Denn meines Wissens ist ein try...catch die schlechtere Alternative zu einer if-Abfrage.  
            
          Naja, man könnte das mit dem if wie bei self::getDefaultLocale() lösen, aber dann hat man immer noch nicht eventuelle Exceptions der Registry aus anderen Gründen als Nichtvorhandensein gefangen. Das try-catch muss also bleiben und macht das if überflüssig.  
            
            
          Lo!
          
          1. Hey dedlfix,

            public function getLocale()

            {
                    if ($this->_locale !== null) {
                        return $this->_locale;
                    } else if (($locale = self::getDefaultLocale()) !== null) {
                        return $locale;
                    } else {
                        try {
                            $locale = Zend_Registry::get('Zend_Locale');
                        } catch (Zend_Exception $e) {
                            $locale = null;
                        }

            if ($locale !== null) {
                            return $locale;
                        }
                    }

            return null;
                }

            
            > > >   
            > > > Hierbei wird ein try-catch-Block wie im vorherigen Beispiel verwendet (mal ganz abgesehen davon, dass die if-Abfrage innerhalb des else-Zweigs für mich sinnlos ist. Genauso gut könnte ich die weglassen und am Ende $locale zurückgeben).  
            >   
            > Also, ich sehe da auch keinen Sinn dahinter.  
              
            Wenn Du das sagst, bin ich beruhigt :-) (wo ich mir das grad in der Vorschau nochmal durchlese, kann man das auch anders verstehen. Ist aber tatsächlich so gemeint!)  
              
            
            > Möglicherweise hat da einer, nach seinen Versuchen den Code für die Aufgabe zu erstellen, vergessen aufzuräumen.  
              
            Das wäre auf jeden Fall "wünschenswert", also dass dies einer schlicht und einfach vergessen hat. Auf jeden Fall besser, als wenn es absichtlich so geschrieben wurde (ich werde das Gefühl nicht los, dass das insbesondere im Zend Framework hin und wieder der Fall ist, was ich in einem anderen Thread ja bereits erwähnt hatte).  
              
            
            > Das ist eine der Stellen, die nach einer Revision dazu führt, dass man in der Nachfolgeversion stolz einen Geschwindigkeitszuwachs berichten kann.  
              
            Sollte man deshalb vielleicht doch manchmal Absicht unterstellen... ;-)  
              
            
            > Jedenfalls kann man den Code kürzen zu  
            >   
            >   public function getLocale()  
            >   {  
            >     if ($this->\_locale !== null) {  
            >       return $this->\_locale;  
            >     }  
            >     if (($locale = self::getDefaultLocale()) !== null) {  
            >       return $locale;  
            >     }  
            >     try {  
            >       return Zend\_Registry::get('Zend\_Locale');  
            >     } catch (Zend\_Exception $e) {  
            >       return null;  
            >     }  
            >   }  
            >   
            > Der Original-Code zeigt übrigens auch mal wieder sinnlose else-Zweige. Wenn der if-Zweig garantiert mit return beendet wird, kann der alternative Code gar nicht mehr ausgeführt werden und muss deshalb nicht in einem else-Block versteckt werden.  
              
            So weit hatte ich bei dieser Funktion gar nicht gedacht. Guter Vorschlag!  
              
            
            > > Wobei sich natürlich die Frage stellt, ob in diesem Fall die Verwendung von try...catch überhaupt Sinn macht. Zend\_Registry erweitert ja ArrayObject, sodass ich mit einer einfachen if-Abfrage prüfen kann, ob ein Schlüssel im Array (Zend\_Registry) existiert. Denn meines Wissens ist ein try...catch die schlechtere Alternative zu einer if-Abfrage.  
              
            Bei dem folgenden Absatz bin ich mir nicht ganz sicher, wie Du das meinst:  
              
            
            > Naja, man könnte das mit dem if wie bei self::getDefaultLocale() lösen,  
              
            wie würdest Du das machen? In dem Fall kann ich doch nicht auf null prüfen, oder?  
              
            
            > aber dann hat man immer noch nicht eventuelle Exceptions der Registry aus anderen Gründen als Nichtvorhandensein gefangen.  
              
            Da wäre die Frage: Will man das denn? Ich möchte doch eigentlich nur auf Vorhandensein eines Schlüssels prüfen. Wenn die Registry aus welchem Grund auch immer eine andere Exception wirft, kann ich die in einer Funktion wie der oben genannten doch nicht sinnvoll verarbeiten. Würde ich auch die anderen Ausnahmen fangen (was hier ja passiert), hätte doch beispielsweise der Front-Controller keine Möglichkeit etwas zu "korrigieren".  
            Oder fehlt mir da wieder etwas Verständnis der Materie?  
              
            
            > Das try-catch muss also bleiben und macht das if überflüssig.  
              
            Wäre nicht beispielsweise folgendes Konstrukt ohne try...catch denkbar (und wie sinnvoll wäre es?):  
              
            ~~~php
              
            return (array_key_exists('Zend_Locale', Zend_Registry::getInstance())) ? Zend_Registry::get('Zend_Locale') : null;  
            
            

            Gruß, Dennis

            1. Hi!

              Wobei sich natürlich die Frage stellt, ob in diesem Fall die Verwendung von try...catch überhaupt Sinn macht. Zend_Registry erweitert ja ArrayObject, sodass ich mit einer einfachen if-Abfrage prüfen kann, ob ein Schlüssel im Array (Zend_Registry) existiert. Denn meines Wissens ist ein try...catch die schlechtere Alternative zu einer if-Abfrage.
              Bei dem folgenden Absatz bin ich mir nicht ganz sicher, wie Du das meinst:
              Naja, man könnte das mit dem if wie bei self::getDefaultLocale() lösen,
              wie würdest Du das machen? In dem Fall kann ich doch nicht auf null prüfen, oder?

              Einfach nur try-catch und fertig, also so wie in meinem Code. Wenn du trotzdem if nehmen willst, musst du schauen, was für potentielle Ergebnisse du bekommen kannst, dann weißt du, auf was du prüfen kannst.

              aber dann hat man immer noch nicht eventuelle Exceptions der Registry aus anderen Gründen als Nichtvorhandensein gefangen.
              Da wäre die Frage: Will man das denn?

              Kommt drauf an. Dazu müsste man sich die Registry ansehen, um herauszufinden, welche Exceptions sie werfen kann und wie sinnvoll ein Abfangen und Ignorieren (wie in diesem Fall) ist.

              Ich möchte doch eigentlich nur auf Vorhandensein eines Schlüssels prüfen. Wenn die Registry aus welchem Grund auch immer eine andere Exception wirft, kann ich die in einer Funktion wie der oben genannten doch nicht sinnvoll verarbeiten. Würde ich auch die anderen Ausnahmen fangen (was hier ja passiert), hätte doch beispielsweise der Front-Controller keine Möglichkeit etwas zu "korrigieren".

              Für diesen speziellen Fall kann man sich die Auswirkungen anschauen, wenn man den Registry-Code kennt. Dan kann man entscheiden, ob das try-catch da sinnvoll ist oder nicht. Es kann gut sein, dass es ebenfalls ein Überbleibsel aus einer Zeit ist, als die Registry Exceptions warf, wenn sie das jetzt nicht mehr machen sollte. (Ich weiß das nicht, weil ich es mir nicht angesehen habe.) Dann könnte man das streichen und mit einem if arbeiten.

              Der FrontController kann aber auch mit einem null-Ergebnis "korrigieren". Vermutlich bringt es ihm keine Zusatzpunkte, wenn er die genaue Ursache des Locale-Holen-Misslingens kennt.

              Wäre nicht beispielsweise folgendes Konstrukt ohne try...catch denkbar (und wie sinnvoll wäre es?):
              return (array_key_exists('Zend_Locale', Zend_Registry::getInstance())) ? Zend_Registry::get('Zend_Locale') : null;

              Ja, wenn einerseits es keine Exceptions beim Abarbeiten des Codes geben kann oder aber du Exceptions unbehandelt weiterreichen willst.
              Allerdings musst du dann im aufrufenden Code sowohl auf null prüfen als auch Exceptions abfangen (angenommen es gibt potentiell welche).

              Lo!

              1. Hey dedlfix,

                Naja, man könnte das mit dem if wie bei self::getDefaultLocale() lösen,
                wie würdest Du das machen? In dem Fall kann ich doch nicht auf null prüfen, oder?

                Einfach nur try-catch und fertig, also so wie in meinem Code. Wenn du trotzdem if nehmen willst, musst du schauen, was für potentielle Ergebnisse du bekommen kannst, dann weißt du, auf was du prüfen kannst.

                Dann habe ich das doch richtig verstanden. Dachte nur zwischenzeitlich, Du könntest so etwas wie (Pseudo-Code)

                  
                if (($locale = self::getDefaultLocale()) !== Exception) {}  
                
                

                meinen. Und das wäre etwas mir Unbekanntes gewesen.

                aber dann hat man immer noch nicht eventuelle Exceptions der Registry aus anderen Gründen als Nichtvorhandensein gefangen.
                Da wäre die Frage: Will man das denn?

                Kommt drauf an. Dazu müsste man sich die Registry ansehen, um herauszufinden, welche Exceptions sie werfen kann und wie sinnvoll ein Abfangen und Ignorieren (wie in diesem Fall) ist.

                Zum besseren Verständnis in diesem Fall, hier die statische get-Methode von Zend_Registry:

                  
                    public static function get($index)  
                    {  
                        $instance = self::getInstance();  
                  
                        if (!$instance->offsetExists($index)) {  
                            require_once 'Zend/Exception.php';  
                            throw new Zend_Exception("No entry is registered for key '$index'");  
                        }  
                  
                        return $instance->offsetGet($index);  
                    }  
                
                

                Ich möchte doch eigentlich nur auf Vorhandensein eines Schlüssels prüfen. Wenn die Registry aus welchem Grund auch immer eine andere Exception wirft, kann ich die in einer Funktion wie der oben genannten doch nicht sinnvoll verarbeiten. Würde ich auch die anderen Ausnahmen fangen (was hier ja passiert), hätte doch beispielsweise der Front-Controller keine Möglichkeit etwas zu "korrigieren".

                Für diesen speziellen Fall kann man sich die Auswirkungen anschauen, wenn man den Registry-Code kennt. Dan kann man entscheiden, ob das try-catch da sinnvoll ist oder nicht. Es kann gut sein, dass es ebenfalls ein Überbleibsel aus einer Zeit ist, als die Registry Exceptions warf, wenn sie das jetzt nicht mehr machen sollte. (Ich weiß das nicht, weil ich es mir nicht angesehen habe.) Dann könnte man das streichen und mit einem if arbeiten.

                Wie oben in der Methode gezeigt wirft die Registry noch immer Exceptions. Allerdings in diesem Fall, wenn ein Schlüssel nicht existiert.
                Was würdest Du in diesem Fall empfehlen? Try...catch oder if...else?

                Der FrontController kann aber auch mit einem null-Ergebnis "korrigieren". Vermutlich bringt es ihm keine Zusatzpunkte, wenn er die genaue Ursache des Locale-Holen-Misslingens kennt.

                Da bin ich mir nicht so sicher. Wie gesagt, vielleicht hab ich das Prinzip noch nicht richtig verstanden. Aber wenn ich einen null-Wert bekomme, gebe ich die Verantwortung - im Gegensatz zu einer Exception - nicht zum Front-Crontroller zurück. Daher kann der dann auch nichts machen.
                Zu dem Punkt, dass es ihm "keine Zusatzpunkte" bringt (übrigens sehr schön!) kann ich Dir aber nur zustimmen.

                Wäre nicht beispielsweise folgendes Konstrukt ohne try...catch denkbar (und wie sinnvoll wäre es?):
                return (array_key_exists('Zend_Locale', Zend_Registry::getInstance())) ? Zend_Registry::get('Zend_Locale') : null;

                Ja, wenn einerseits es keine Exceptions beim Abarbeiten des Codes geben kann oder aber du Exceptions unbehandelt weiterreichen willst.

                Das war immer mein Gedanke, dass ich eine Exception so weit durchreichen lasse, bis sich eine Instanz meldet, die mit diesem Fehler umgehen kann. Im "schlimmsten" Fall wäre das also ein Exception-Handler, der eine Fehlerseite ausgibt.

                Danke und Gruß, Dennis

                1. Hi!

                  aber dann hat man immer noch nicht eventuelle Exceptions der Registry aus anderen Gründen als Nichtvorhandensein gefangen.
                  Da wäre die Frage: Will man das denn?
                  Zum besseren Verständnis in diesem Fall, hier die statische get-Methode von Zend_Registry:

                  public static function get($index)

                  {
                          $instance = self::getInstance();

                  if (!$instance->offsetExists($index)) {
                              require_once 'Zend/Exception.php';
                              throw new Zend_Exception("No entry is registered for key '$index'");
                          }

                  return $instance->offsetGet($index);
                      }

                    
                  getInstance() wirft praktisch keine Exceptions (habs grad nachgesehen), also ist die einzige die, wenn der Key nicht existiert.  
                    
                  
                  > Wie oben in der Methode gezeigt wirft die Registry noch immer Exceptions. Allerdings in diesem Fall, wenn ein Schlüssel nicht existiert.  
                  > Was würdest Du in diesem Fall empfehlen? Try...catch oder if...else?  
                    
                  In dem Fall kannst du auf das Vorhandensein prüfen und hättest keine weitere Exception mehr zu befürchten. Hier wäre meiner Meinung nach auch eine Vorherprüfung angebracht, denn das ist ja ein ganz normaler Zustand und keine Ausnahme.  
                    
                  
                  > > Der FrontController kann aber auch mit einem null-Ergebnis "korrigieren". Vermutlich bringt es ihm keine Zusatzpunkte, wenn er die genaue Ursache des Locale-Holen-Misslingens kennt.  
                  > Da bin ich mir nicht so sicher. Wie gesagt, vielleicht hab ich das Prinzip noch nicht richtig verstanden. Aber wenn ich einen null-Wert bekomme, gebe ich die Verantwortung - im Gegensatz zu einer Exception - nicht zum Front-Crontroller zurück. Daher kann der dann auch nichts machen.  
                    
                  Es kommt drauf an, was es für dich bedeutet, wenn keine Locale verfügbar ist. Daraufhin musst du deine Fehlerbehandlung (hier das Reagieren, wenn null zurückgegeben wird) ausrichten - also entweder hier reagieren oder das in einer anderen Ebene des Aufrufstacks behandeln, dann gibt es nur eine Benachrichtigung "nach oben", in welcher Form auch immer (nicht gefangene oder wieder ausgelöste Exception oder ein spezieller Rückgabewert).  
                    
                  
                  > Das war immer mein Gedanke, dass ich eine Exception so weit durchreichen lasse, bis sich eine Instanz meldet, die mit diesem Fehler umgehen kann. Im "schlimmsten" Fall wäre das also ein Exception-Handler, der eine Fehlerseite ausgibt.  
                    
                  Ich würde mir da kein Prinzip auferlegen, sondern fallweise entscheiden, welches die beste Behandlungsweise und -ort ist.  
                    
                    
                  Lo!
                  
                  1. Hey dedlfix,

                    Was würdest Du in diesem Fall empfehlen? Try...catch oder if...else?

                    In dem Fall kannst du auf das Vorhandensein prüfen und hättest keine weitere Exception mehr zu befürchten. Hier wäre meiner Meinung nach auch eine Vorherprüfung angebracht, denn das ist ja ein ganz normaler Zustand und keine Ausnahme.

                    Das freut mich, dass Du das auch empfehlen würdest. So komme ich den Best Practices immer ein Stück näher.

                    Da fällt mir grad noch etwas ein. In welcher Reihenfolge schreibt man als Best Practice eigentlich die verschiedenen Statements? Also, ich meine folgendes: Schreibt man besser

                      
                    if ($test == 1) {  
                    } elseif ($test == 2) {  
                    }
                    

                    oder

                      
                    if (1 == $test) {  
                    } elseif (2 == $test) {  
                    }
                    

                    ? Ich weiß, das ist eine unwichtige Frage, weil's ja das gleiche ist, es interessiert mich aber. Ich habe mal gelesen (weiß leider nicht mehr wo und finde grade auf die Schnelle auch nichts), dass das zweite Beispiel zu bevorzugen sei, da es übersichtlicher ist. Man könne schneller die relevante Information erkennen (wobei mein obiges Beispiel nicht sehr gut ist, für so ein Konstrukt könnte ich auch switch verwenden). Intuitiv würde ich die erste Variante bevorzugen.

                    [...]
                    Es kommt drauf an, was es für dich bedeutet, wenn keine Locale verfügbar ist. Daraufhin musst du deine Fehlerbehandlung (hier das Reagieren, wenn null zurückgegeben wird) ausrichten - also entweder hier reagieren oder das in einer anderen Ebene des Aufrufstacks behandeln, dann gibt es nur eine Benachrichtigung "nach oben", in welcher Form auch immer (nicht gefangene oder wieder ausgelöste Exception oder ein spezieller Rückgabewert).

                    Gut, dann habe ich das doch soweit verstanden. In diesem Fall würde ich also wohl den Fehler in der Methode, die getLocale() aufruft, behandeln. Und dann, wenn ich eine Lokalisierung zwingend brauche, wohl erst hier eine Exception werfen. Wenn ich die Lokalisierung nicht zwingend brauche, würde ich den Fehler bzw. null-Wert einfach übergehen.
                    Da muss ich mir nochmal was mehr Mühe bei jeder einzelnen Methode geben, wenn es um solch eine Fehlerbehandlung geht. Bisher hab ich in den meisten Fällen eine Exception geworfen, die dann immer weiter nach oben gereicht wurde (meist bis zum FC). In den seltensten Fällen hat eine aufrufende Methode evtl. auftretende Fehler abgefangen und verarbeitet (einzige Ausnahme, die mir gerade einfällt, war ein Aufruf meiner Klasse File; hier wurden Fehler direkt aufgefangen, beispielsweise wenn eine Datei nicht vorhanden war, da man damit rechnen konnte).

                    Das war immer mein Gedanke, dass ich eine Exception so weit durchreichen lasse, bis sich eine Instanz meldet, die mit diesem Fehler umgehen kann. Im "schlimmsten" Fall wäre das also ein Exception-Handler, der eine Fehlerseite ausgibt.

                    Ich würde mir da kein Prinzip auferlegen, sondern fallweise entscheiden, welches die beste Behandlungsweise und -ort ist.

                    Da muss ich mir, wie oben gesagt, mehr Mühe geben. Aber Du jetzt die fallweise Betrachtung erwähnst: So werde ich es in Zukunft machen.

                    Danke, dedlfix!

                    Gruß, Dennis

                    1. Hi!

                      In welcher Reihenfolge schreibt man als Best Practice eigentlich die verschiedenen Statements? Also, ich meine folgendes: Schreibt man besser

                      if ($test == 1) {
                      } elseif ($test == 2) {
                      }

                      
                      >   
                      > oder  
                      >   
                      > ~~~php
                        
                      
                      > if (1 == $test) {  
                      > } elseif (2 == $test) {  
                      > }
                      
                      

                      ? Ich weiß, das ist eine unwichtige Frage, weil's ja das gleiche ist, es interessiert mich aber. Ich habe mal gelesen (weiß leider nicht mehr wo und finde grade auf die Schnelle auch nichts), dass das zweite Beispiel zu bevorzugen sei, da es übersichtlicher ist. Man könne schneller die relevante Information erkennen (wobei mein obiges Beispiel nicht sehr gut ist, für so ein Konstrukt könnte ich auch switch verwenden). Intuitiv würde ich die erste Variante bevorzugen.

                      Wie du so schön sagt, beides kommt aufs Gleiche raus - wenn man sich nicht vertippt und statt == nur ein = nimmt. Dann ergibt die zweite Variante einen Syntaxfehler, weil einem konstanten Ausdruck nichts zugewiesen werden kann. Das wäre insofern ein Vorteil. Andererseits sollte das eigentlich spätestens beim Testen des Programms auffallen, dass wa was unerwartetes passiert. Dann kann man den Fehler beseitigen und der eine kleine Vorteil ist nicht mehr relevant.

                      Ich persönlich finde die zweite Variante nicht übersichtlicher, weil sie umgekehrt zur außerhalb des Programmierens üblichen Anordnung ist. "Wenn 2 gleich dem Inhalt von $test ist" empfinde ich sprachlich unschöner als "Wenn der Inhalt von $test gleich 2 ist".

                      Da muss ich mir nochmal was mehr Mühe bei jeder einzelnen Methode geben, wenn es um solch eine Fehlerbehandlung geht. Bisher hab ich in den meisten Fällen eine Exception geworfen, die dann immer weiter nach oben gereicht wurde (meist bis zum FC). In den seltensten Fällen hat eine aufrufende Methode evtl. auftretende Fehler abgefangen und verarbeitet (einzige Ausnahme, die mir gerade einfällt, war ein Aufruf meiner Klasse File; hier wurden Fehler direkt aufgefangen, beispielsweise wenn eine Datei nicht vorhanden war, da man damit rechnen konnte).

                      Um Fehlerbehandlung oder auch Alternativen sinnvoll zu implementieren sollte man nicht nur aus der Sicht des Programmierers schauen, sondern vor allem auch aus der Sicht der Anwender (diese Gestalten vor dem UI) und der Verwender (andere Codeteile, die die entsprechende Routine aufrufen).

                      Lo!

                      1. Hey dedlfix,

                        Deine Ausführung überzeugt mich.

                        Um Fehlerbehandlung oder auch Alternativen sinnvoll zu implementieren sollte man nicht nur aus der Sicht des Programmierers schauen, sondern vor allem auch aus der Sicht der Anwender (diese Gestalten vor dem UI) und der Verwender (andere Codeteile, die die entsprechende Routine aufrufen).

                        Das halte ich für besonders wichtig, wird aber (auch von mir) häufig vergessen.

                        Danke für Deine guten Beiträge,

                        Dennis

  2. Hi,

    mir ist neulich aufgefallen, dass bei den meisten Anwendungen (oder Frameworks: Zend Framework ist so ein Beispiel) ein return nicht in einem try-catch-Block verwendet wird.

    [...]

      } catch (Exception $e) {  
      	return 'Catched!';  
      }  
    

    das ist zurückzuführen auf die berühmt-berüchtigte Boygroup "Catched in the Act", *hust*.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hey Cheatah,

      mir ist neulich aufgefallen, dass bei den meisten Anwendungen (oder Frameworks: Zend Framework ist so ein Beispiel) ein return nicht in einem try-catch-Block verwendet wird.
      [...]
      } catch (Exception $e) {
      return 'Catched!';
      }

      das ist zurückzuführen auf die berühmt-berüchtigte Boygroup "Catched in the Act", *hust*.

      das *hust* ist völlig angebracht. Keine Ahnung, warum ich da so einen Mist geschrieben hab...

      Danke, Dennis

  3. Hi,

    public function returnInTryCatchBlock()
    {
    try {
    $var = $this->throwsException();
    } catch (Exception $e) {
    $var = 'Catched!';
    }
    return $var;
    }

    
    >   
    > Das kann ich mir nicht wirklich erklären,  
      
    Es gibt Leute, die sind der Meinung, daß eine Funktion/Methode nur einen einzigen Ausgang haben sollte.  
      
    cu,  
    Andreas
    
    -- 
    [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
    [O o ostern ...](http://ostereier.andreas-waechter.de/)  
      
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
    
    
    1. Hi!

      Es gibt Leute, die sind der Meinung, daß eine Funktion/Methode nur einen einzigen Ausgang haben sollte.

      Das könnte eine Erklärung sein. Sich streng an ein solches Prinzip zu halten, finde ich jedoch ungefähr so sinnvoll, wie eine Schleife stets bis zum Ende durchlaufen zu lassen, statt sie mit break abzubrechen, wenn das Ergebnis feststeht.

      Lo!

      1. Hey MudGuard, hey dedlfix,

        Es gibt Leute, die sind der Meinung, daß eine Funktion/Methode nur einen einzigen Ausgang haben sollte.

        dass es diese Leute gibt, habe ich schon mitbekommen. Mir fällt allerdings kein vernünftiger Grund dafür ein. Gibt's denn einen?

        Das könnte eine Erklärung sein. Sich streng an ein solches Prinzip zu halten, finde ich jedoch ungefähr so sinnvoll, wie eine Schleife stets bis zum Ende durchlaufen zu lassen, statt sie mit break abzubrechen, wenn das Ergebnis feststeht.

        So würde ich auch sehen.

        Gruß, Dennis

        1. Hi,

          Es gibt Leute, die sind der Meinung, daß eine Funktion/Methode nur einen einzigen Ausgang haben sollte.

          dass es diese Leute gibt, habe ich schon mitbekommen. Mir fällt allerdings kein vernünftiger Grund dafür ein. Gibt's denn einen?

          Na ja, ggf. Übersichtlichkeit - *ein* return-Statement am Ende ist leichter zu finden, als mehrere returns die irgendwo im „mehrere Seiten langen“ Code einer Methode stecken, vielleicht auch noch in mehrere if-else-elseif-Ebenen verschachtelt.
          Wobei das auch nicht so viel hilft, wenn ich dann immer noch suchen muss, wo denn jetzt der Wert, der zurückgegeben wird, befüllt wird ...

          Als alleinige Maßnahme also zu dem Zweck auch kein Allheilmittel, und kann ausführliche Kommentare nicht ersetzen.

          Und zu gunsten dieser Konvention Konstrukte a la

          if(kritische_bedingung_erfuellt) {  
            return true;  
          }  
          else {  
            return false;  
          }
          

          auf Teufel komme raus durch

          if(kritische_bedingung_erfuellt) {  
            $returnValue = true;  
          }  
          else {  
            $returnValue =false;  
          }  
          return $returnValue;
          

          zu ersetzen, erscheint mir auch nicht immer und unbedingt sinnvoll.

          MfG ChrisB

          --
          RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
          1. Hi!

            Na ja, ggf. Übersichtlichkeit - *ein* return-Statement am Ende ist leichter zu finden, als mehrere returns die irgendwo im „mehrere Seiten langen“ Code einer Methode stecken, vielleicht auch noch in mehrere if-else-elseif-Ebenen verschachtelt.

            Dem kann ich prinzipiell zustimmen. Aber was hilft es, zu sehen, dass das return einen Variableninhalt zurückgibt, wenn ich von unten gesehen das Befüllen der Variable im meterlangen Code suchen muss und von oben gesehen den Rest des Codes durchsuchen muss, nur um festzustellen, dass die Variable nicht weiter verwendet wird. Hier kürzt ein klares return die Recherche ab.

            Wie immer plädiere ich weder ausschließlich für das eine noch das andere, sondern dafür, mit Verstand zu entscheiden, was im konkreten Fall sinnvoller sein mag.

            Und zu gunsten dieser Konvention Konstrukte a la

            if(kritische_bedingung_erfuellt) {

            return true;
            }
            else {
              return false;
            }

            
            > auf Teufel komme raus durch [...] zu ersetzen, erscheint mir auch nicht immer und unbedingt sinnvoll.  
              
            Ja, sinnvoller wäre es, sie ohne das else zu notieren, denn das hat wegen des return im if-Block keine nützliche Funktion mehr.  
              
            ~~~php
            if(kritische_bedingung_erfuellt) {  
              return true;  
            }  
              
            return false;
            

            Lo!

            1. Hi,

              if(kritische_bedingung_erfuellt) {

              return true;
              }

              return false;

                
              Warum überhaupt ein if?  
                
              `return kritische_bedingung_erfuellt; `{:.language-php}  
                
              reicht doch auch.  
              Notfalls, wenn's wirklich auf true/false ankommt statt auf Werte, die zu true/false konvertiert werden können:  
                
              `return kritische_bedingung_erfuellt ? true : false;`{:.language-php}  
                
              cu,  
              Andreas
              
              -- 
              [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
              [O o ostern ...](http://ostereier.andreas-waechter.de/)  
                
              Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
              
              
              1. Hi!

                if(kritische_bedingung_erfuellt) {

                return true;
                }
                return false;

                
                > Warum überhaupt ein if?  
                >   
                > `return kritische_bedingung_erfuellt; `{:.language-php}  
                > reicht doch auch.  
                  
                Stimmt, in dem Fall ja. Bei anderen als booleschen Rückgabewerten wäre das wie oben angebracht.  
                  
                
                > Notfalls, wenn's wirklich auf true/false ankommt statt auf Werte, die zu true/false konvertiert werden können:  
                > `return kritische_bedingung_erfuellt ? true : false;`{:.language-php}  
                  
                Wenn dann ein Typecast. Denn dem sieht man sofort an, dass der Wert direkt nach Boolean konvertiert wurde und nicht noch eine Negation stattgefunden hat.  
                  
                  
                Lo!
                
                1. Hallo zusammen,

                  danke für Eure Antworten. Ihr habt meine Frage vollstänig beantwortet. Ich werde wohl, wenn nötig und möglich, weiterhin mehrere Rückgabewerte innerhalb einer Funktion definieren.
                  Danke auch für das Aufzeigen der verschiedenen Möglichkeiten, wie man (insbesondere Booleans) zurückgeben kann.
                  Wobei mir am besten
                  return (bool) kritische_bedingung_erfuellt
                  gefällt. Das habe ich so bisher nicht gemacht.

                  Gruß, Dennis

            2. Hi!

              Aber was hilft es, zu sehen, dass das return einen Variableninhalt zurückgibt, wenn ich von unten gesehen das Befüllen der Variable im meterlangen Code suchen muss und von oben gesehen den Rest des Codes durchsuchen muss, nur um festzustellen, dass die Variable nicht weiter verwendet wird. Hier kürzt ein klares return die Recherche ab.

              Nur dann, wenn du einen konkreten Durchlauf durchspielen willst. Wenn du erfassen willst, was der grundsätzliche Zweck einer Methode ist, wofür sie gedacht ist, was sie tun soll, dann erschweren mehrere returns das Verständnis mMn durchaus.

              Und grundsätzlich gilt natürlich: Das Problem bei meterlangen Methoden ist, dass sie meterlang sind. Dieses Problem lässt sich weder durch ein einziges noch durch mehrere returns beheben, sondern nur durch ein Aufteilen des Codes auf mehrere Methoden.

              Ist eine Methode angemessen kurz, dann ist sie sicherlich auf beide Arten verständlich; ich empfinde allerdings die Variante mit einem return als eleganter.

              Wie immer plädiere ich weder ausschließlich für das eine noch das andere, sondern dafür, mit Verstand zu entscheiden, was im konkreten Fall sinnvoller sein mag.

              Ich plädiere für angemessen kurze Methoden, s.o. ;-)

              Ja, sinnvoller wäre es, sie ohne das else zu notieren, denn das hat wegen des return im if-Block keine nützliche Funktion mehr.

              if(kritische_bedingung_erfuellt) {

              return true;
              }

              return false;

                
              Der else-Zweig ist aber auch überflüssig, wenn man nur ein return verwendet:  
                
              ~~~php
              $returnValue = false;  
              if(kritische_bedingung_erfuellt) {  
               $returnValue = true;  
              }  
              return $returnValue;
              

              Abgesehen davon, dass dieses konkrete Beispiel wie schon geschrieben ein schlechtes (return $kritische_bedingung_erfuellt; ist mit Abstand am elegantesten) ist.

              Grüße
              Bernhard

              1. Hi!

                Nur dann, wenn du einen konkreten Durchlauf durchspielen willst. Wenn du erfassen willst, was der grundsätzliche Zweck einer Methode ist, wofür sie gedacht ist, was sie tun soll, dann erschweren mehrere returns das Verständnis mMn durchaus.

                Wie gesagt, ein return ist eine unmissverständliche und direkte Anweisung. An anderer Stelle bewertete Ergebnisvariablen müssen erst angelegt und dann noch durch den Code verfolgt werden. Sie bewirken etwas indirektes.

                Und grundsätzlich gilt natürlich: Das Problem bei meterlangen Methoden ist, dass sie meterlang sind. Dieses Problem lässt sich weder durch ein einziges noch durch mehrere returns beheben, sondern nur durch ein Aufteilen des Codes auf mehrere Methoden.

                Jein. Wenn der Code nur ein einziges Mal verwendet wird, erstelle ich ungern eine Funktion, weil dadurch auch der Mehraufwand des Aufrufens und der Parameter- und Rückgabewertbehandlung hinzukommt. Zudem verschwindet die Komplexität der gewünschten Funktionalität nicht, sie wird nur verlagert und ich muss nun zwei oder mehr Stellen im Auge behalten. Übersichtlichkeit kann man sich durch Code-Einklappen bewahren (wenn es der Editor / die IDE bietet).

                Aber das ist jetzt nur eine theoretische Betrachtung, und ich argumentiere vor allem auch deshalb so, um mir das Gefühl zu geben, in dieser Diskussion Recht zu behalten :-) Im konkreten Anwendungsfall könnte ich durchaus anders entscheiden, je nachdem, was ich dann als sinnvoller empfinde.

                Lo!

                1. Hi!

                  Wie gesagt, ein return ist eine unmissverständliche und direkte Anweisung. An anderer Stelle bewertete Ergebnisvariablen müssen erst angelegt und dann noch durch den Code verfolgt werden. Sie bewirken etwas indirektes.

                  Nachdem es nur ein return geben soll, braucht es auch höchstens eine "Ergebnisvariable". Wo eine Bewertung dieser Variablen stattfinden soll, verstehe ich nicht.

                  Sofern das "durch den Code verfolg[en]" heißen soll, dass man nachsehen muss, ob nicht noch etwas mit ihr passiert, stimme ich zu. Bei angemessen kurzen[tm] Methoden ist das auch kein Problem. "Bewirken" tut eine Ergebnisvariable auch nix; sie wird einfach zurückgegeben. Was du damit sagen willst, mir also auch nicht 100%ig klar.

                  Und grundsätzlich gilt natürlich: Das Problem bei meterlangen Methoden ist, dass sie meterlang sind. Dieses Problem lässt sich weder durch ein einziges noch durch mehrere returns beheben, sondern nur durch ein Aufteilen des Codes auf mehrere Methoden.

                  Wenn der Code nur ein einziges Mal verwendet wird, erstelle ich ungern eine Funktion, weil dadurch auch der Mehraufwand des Aufrufens und der Parameter- und Rückgabewertbehandlung hinzukommt.

                  Aus Performancegründen auf Subroutinen zu verzichten ist heutzutage kein gültiges Argument mehr. Das zieht maximal noch bei Code der derartig kritisch ist, dass er sowieso in Assembler geschrieben werden muss.

                  Zudem verschwindet die Komplexität der gewünschten Funktionalität nicht, sie wird nur verlagert

                  Vom Verschwinden hat auch niemand was gesagt. Sie ist nur besser gegliedert und kann so leichter erfasst werden.

                  und ich muss nun zwei oder mehr Stellen im Auge behalten.

                  Wenn du was tust?

                  Übersichtlichkeit kann man sich durch Code-Einklappen bewahren (wenn es der Editor / die IDE bietet).

                  Jesses, die Code-Einklapperei! Ihr einziger Effekt ist, dass die Leute noch ermutigt werden, kilometerweise Code in eine einzige Methode zu packen. Hinfort damit! (Google e.g. "C# regions considered harmful")

                  Das Einklappen von ganzen Methoden ist was anderes, dagegen gibt es nix zu sagen. Logisch, es hilft ja nur, wenn der Code auf mehrere Methoden verteilt ist. ;-)

                  Aber das ist jetzt nur eine theoretische Betrachtung, und ich argumentiere vor allem auch deshalb so, um mir das Gefühl zu geben, in dieser Diskussion Recht zu behalten :-) Im konkreten Anwendungsfall könnte ich durchaus anders entscheiden, je nachdem, was ich dann als sinnvoller empfinde.

                  Jämmerlicher Opportunist! ;-)

                  Grüße
                  Bernhard

                  1. Hi!

                    Wie gesagt, ein return ist eine unmissverständliche und direkte Anweisung. An anderer Stelle bewertete Ergebnisvariablen müssen erst angelegt und dann noch durch den Code verfolgt werden. Sie bewirken etwas indirektes.
                    Nachdem es nur ein return geben soll, braucht es auch höchstens eine "Ergebnisvariable".

                    Meinst du das "ein" jetzt als Anzahl oder als unbestimmten Artikel? Zwischen der Anzahl der möglichen returns und möglichen Ergebnisvariablen besteht keine Abhängigkeit. Beides kann unabhängig voneinander ein oder mehrmals vorhanden sein.

                    Wo eine Bewertung dieser Variablen stattfinden soll, verstehe ich nicht.

                    Als Abbruchkriterium der Schleife - dafür sind sie ja vorgesehen. Und potentiell können sie auch noch im restlichen Code ausgewertet und geändert werden. Es könnte ja Ausnahmen geben, bei denen doch nicht abgebrochen werden soll. Diese will man vielleicht der Übersichtlichkeit wegen nicht auch noch mit in eine einzige Bedingung einarbeiten. Und das sind nur die beabsichtigten Änderungen. Natürlich kann man für solche Anwendungsfälle die return-Variante nicht mehr nehmen.

                    Sofern das "durch den Code verfolg[en]" heißen soll, dass man nachsehen muss, ob nicht noch etwas mit ihr passiert, stimme ich zu. Bei angemessen kurzen[tm] Methoden ist das auch kein Problem. "Bewirken" tut eine Ergebnisvariable auch nix; sie wird einfach zurückgegeben. Was du damit sagen willst, mir also auch nicht 100%ig klar.

                    An der Stelle, an der sie mit dem Abbruchwert gefüllt wird, passiert nichts weiter. Die Wirkung des Schleifenabbruchs entfaltet sich erst an der Stelle, an der sie ausgewertet wird.

                    Wenn der Code nur ein einziges Mal verwendet wird, erstelle ich ungern eine Funktion, weil dadurch auch der Mehraufwand des Aufrufens und der Parameter- und Rückgabewertbehandlung hinzukommt.
                    Aus Performancegründen auf Subroutinen zu verzichten ist heutzutage kein gültiges Argument mehr. Das zieht maximal noch bei Code der derartig kritisch ist, dass er sowieso in Assembler geschrieben werden muss.

                    Akzeptiert. Bleibt der Mehraufwand beim Erstellen, der sich wenigstens mit Übersichtlichkeit rentieren sollte. Auch wenn man (bei PHP weniger üblich, aber z.B. im Visual Studio sehr gut nutzbar) mit schrittweisem Debugging einem Fehler auf der Spur ist, bewirkt so ein Abtauchen in eine Funktion eine Unterbrechung des Flusses und einen Ortswechsel im Code. Andererseits kann man den Funktionsaufruf auch überspringen. Doch dafür kann man im Geradeaus-Code einen Breakpoint bemühen, zu dem man springen kann.

                    Zudem verschwindet die Komplexität der gewünschten Funktionalität nicht, sie wird nur verlagert
                    Vom Verschwinden hat auch niemand was gesagt. Sie ist nur besser gegliedert und kann so leichter erfasst werden.

                    Oder auch nicht.

                    und ich muss nun zwei oder mehr Stellen im Auge behalten.
                    Wenn du was tust?

                    Durch das Verlagern hat man nun den übrig gebliebenen Code hier und den ausgelagerten Code in der Funktion oder in mehreren woanders. Ergibt mehrere Stellen, die zu beachten sind (statt einer großen). Auf alle Fälle muss man zum ausgelagerten Code springen (zumindest wenn man den Ablauf das erste Mal studiert), und verliert dabei vielleicht die andere Stelle aus dem Auge/Editor-Fenster.

                    Das ist alles sehr theoretisch betrachtet. Im konkreten Fall kann das durchaus weniger tragisch sein, als ich es hier beschreibe.

                    Übersichtlichkeit kann man sich durch Code-Einklappen bewahren (wenn es der Editor / die IDE bietet).
                    Jesses, die Code-Einklapperei! Ihr einziger Effekt ist, dass die Leute noch ermutigt werden, kilometerweise Code in eine einzige Methode zu packen. Hinfort damit! (Google e.g. "C# regions considered harmful")

                    <del>Unfug.</del><ins>Das sehe ich nicht so.</ins> Jedes Werkzeug kann unsachgemäß verwendet werden. Monstercode ensteht sicher nicht primär duch klappbaren Code sondern durch unüberlegtes Programmieren.

                    Und ich google jetzt nicht, denn ich setze #region sehr gern ein. Nicht nur, um den gerade nicht benötigten Code einklappen und mich damit schnell zwischen Codestellen hin- und herbewegen zu können, zwischen denen anderer Code liegt, sondern auch um die Methoden nach organisatorisch sinnvollen Gesichtspunkten zu bündeln.

                    Lo!

                    1. Hi!

                      Als Abbruchkriterium der Schleife - dafür sind sie ja vorgesehen.

                      Ich glaube, du bist hier etwas durcheinander gekommen: Hier geht's um Funktionen und return-Statements; um Schleifen gehts im anderen Subthread.

                      Wie dem auch sei, ich kann dir nicht folgen. Du hast ursprünglich geschrieben:

                      Wie gesagt, ein return ist eine unmissverständliche und direkte Anweisung. An anderer Stelle bewertete Ergebnisvariablen müssen erst angelegt und dann noch durch den Code verfolgt werden. Sie bewirken etwas indirektes.

                      Bitte erläutere das an einem Beispiel: Was sind/ist die "Ergebnisvariable(n)"? Wo werden sie bewertet? Ich fürchte, ohne Beispiel versteh ich dich nicht.

                      Sofern das "durch den Code verfolg[en]" heißen soll, dass man nachsehen muss, ob nicht noch etwas mit ihr passiert, stimme ich zu. Bei angemessen kurzen[tm] Methoden ist das auch kein Problem. "Bewirken" tut eine Ergebnisvariable auch nix; sie wird einfach zurückgegeben. Was du damit sagen willst, mir also auch nicht 100%ig klar.

                      An der Stelle, an der sie mit dem Abbruchwert gefüllt wird, passiert nichts weiter. Die Wirkung des Schleifenabbruchs entfaltet sich erst an der Stelle, an der sie ausgewertet wird.

                      Ja, soweit d'accord.

                      Grüße
                      Bernhard

                      1. Hi!

                        Wie dem auch sei, ich kann dir nicht folgen. Du hast ursprünglich geschrieben:

                        Wie gesagt, ein return ist eine unmissverständliche und direkte Anweisung. An anderer Stelle bewertete Ergebnisvariablen müssen erst angelegt und dann noch durch den Code verfolgt werden. Sie bewirken etwas indirektes.
                        Bitte erläutere das an einem Beispiel: Was sind/ist die "Ergebnisvariable(n)"? Wo werden sie bewertet? Ich fürchte, ohne Beispiel versteh ich dich nicht.

                        Direkt:

                        function foo() {
                          ...
                          return 42;
                        }

                        Indirekt:

                        function foo() {
                          ...
                          $ergebnisvariable = 42;
                          ...
                          return $ergebnisvariable;
                        }

                        Bei Schleifen ist das ähnlich, da beinhaltet die Ergebnisvariable das Signal zum Abbrechen. Bei den "an anderer Stelle bewerteten Ergebnisvariablen" bezog ich mich auf Schleifen, bei denen aus dem Ergebnis der eigentlichen Abbruchbedingung erst noch eine Hilfsvariable befüllt wird, bevor sie an anderer Stelle (Kopf oder Fuß) ausgewertet den Abbruch bewirkt.

                        Im Grunde genommen ist die Betrachtung von Notationsweisen der Abbruchbedingungen von Schleifen und dem Rückgabewert von Funktionen nicht weiter verschieden.

                        Lo!

                    2. Hi!

                      Auch wenn man (bei PHP weniger üblich, aber z.B. im Visual Studio sehr gut nutzbar) mit schrittweisem Debugging einem Fehler auf der Spur ist, bewirkt so ein Abtauchen in eine Funktion eine Unterbrechung des Flusses und einen Ortswechsel im Code. Andererseits kann man den Funktionsaufruf auch überspringen. Doch dafür kann man im Geradeaus-Code einen Breakpoint bemühen, zu dem man springen kann.

                      Den Breakpoint kann man doch auch in die Subfunktion setzen. Das Rein- oder Übersteppen in/über die Subfunktion kostet mich einen zusätzlichen Tastendruck einer Taste, die ich sowieso beim Debuggen permanent drücken muss (F10 in der Visual-Studio-Standardkonfiguration). Den nehme ich gerne in Kauf, wenn meine Funktionen dafür sauber gegliedert sind.

                      Zudem verschwindet die Komplexität der gewünschten Funktionalität nicht, sie wird nur verlagert
                      Vom Verschwinden hat auch niemand was gesagt. Sie ist nur besser gegliedert und kann so leichter erfasst werden.

                      Oder auch nicht.

                      Naja, was macht man jetzt mit sowas? ;-)

                      Durch das Verlagern hat man nun den übrig gebliebenen Code hier und den ausgelagerten Code in der Funktion oder in mehreren woanders. Ergibt mehrere Stellen, die zu beachten sind (statt einer großen). Auf alle Fälle muss man zum ausgelagerten Code springen (zumindest wenn man den Ablauf das erste Mal studiert), und verliert dabei vielleicht die andere Stelle aus dem Auge/Editor-Fenster.

                      Geht es nur um das nachvollziehen des Ablaufs? Wenn ja, dann bieten Subfunktionen für mich gerade dabei den großen Vorteil des Drübersteppen-Könnens. Das geht bei einer langen Wurst nur mit zusätzlichen Breakpoints und man muss statt "F10 F10 F10" "F10 F5 F10" drücken. Und die zusätzlichen Zeilen, die ich eigentlich gar nicht sehen will, irritieren mich trotzdem, denn sie stehen ja da, auch wenn ich über sie drüber hinweg steppe.

                      Eben ganz grundsätzlich: Wenn die lange Wurst in Unteraufgaben aufgedröselt ist, dann habe ich den Überblick und die vielen mit Details beschäftigten Codezeilen lenken mich nicht ab.

                      <del>Unfug.</del><ins>Das sehe ich nicht so.</ins> Jedes Werkzeug kann unsachgemäß verwendet werden. Monstercode ensteht sicher nicht primär duch klappbaren Code sondern durch unüberlegtes Programmieren.

                      100%ig d'accord. Ich habe groteskt übertrieben. Dachte, das wäre offensichtlich, sorry. :-)

                      Und ich google jetzt nicht, denn ich setze #region sehr gern ein. Nicht nur, um den gerade nicht benötigten Code einklappen und mich damit schnell zwischen Codestellen hin- und herbewegen zu können, zwischen denen anderer Code liegt, sondern auch um die Methoden nach organisatorisch sinnvollen Gesichtspunkten zu bündeln.

                      Methoden mit regions gruppieren ist natürlich sinnvoll; s.o. Dass regions eben verwendet werden können, um überlangen Code zu kaschieren, birgt aber eben ein gewisses Missbrauchs

                      Grüße
                      Bernhard

                      1. Hi!

                        Geht es nur um das nachvollziehen des Ablaufs? Wenn ja, dann bieten Subfunktionen für mich gerade dabei den großen Vorteil des Drübersteppen-Könnens. Das geht bei einer langen Wurst nur mit zusätzlichen Breakpoints und man muss statt "F10 F10 F10" "F10 F5 F10" drücken. Und die zusätzlichen Zeilen, die ich eigentlich gar nicht sehen will, irritieren mich trotzdem, denn sie stehen ja da, auch wenn ich über sie drüber hinweg steppe.

                        Das Drübersteppen nimmt sich nichts mit dem Anspringen eines Breakpoints - beides ein Tastendruck. Der Mehraufwand durch mindestens zwei Schritte bei jedem Funktionsaufruf entsteht, wenn ein Fehler im Zusammenspiel mit dem Code in der Funktion gesucht wird und man (immer wieder) dahinein abtauchen muss. Dann hat man die Schritte am Funktionskopf und -ende mitzunehmen.

                        Nun gut, in Afrika haben die Kinder noch nicht mal einen Computer und ich bemühe hier solche Kinkerlitzchen, nur um Recht zu behalten. :-)

                        Lo!

                  2. Wenn der Code nur ein einziges Mal verwendet wird, erstelle ich ungern eine Funktion, weil dadurch auch der Mehraufwand des Aufrufens und der Parameter- und Rückgabewertbehandlung hinzukommt.
                    Aus Performancegründen auf Subroutinen zu verzichten ist heutzutage kein gültiges Argument mehr. Das zieht maximal noch bei Code der derartig kritisch ist, dass er sowieso in Assembler geschrieben werden muss.

                    Es bringt aber auch nichts, einfach so Subfunktionen zu erstellen.
                    Sie bringen nur dann etwas, wenn du hoffst oder erwartest, dass es sich um wiederverwendbaren Code handelt.

                    Zudem verschwindet die Komplexität der gewünschten Funktionalität nicht, sie wird nur verlagert
                    Vom Verschwinden hat auch niemand was gesagt. Sie ist nur besser gegliedert und kann so leichter erfasst werden.

                    Das ist nicht unbedingt der Fall. Sofern die Funktionen allgemein genug sind und gute Namen haben, ist die Gliederung besser. Wenn aber dies nicht der Fall ist, dann musst du immer zwischen Stellen wechseln um den Zusammenhang der Verarbeitung zu erfassen.

                    Spaghetticode kann man auch in Funktionen zerstückeln, es sind dann handelt zerstückelte Spaghetti.

                    und ich muss nun zwei oder mehr Stellen im Auge behalten.
                    Wenn du was tust?

                    Wenn du eine zu spezifische Sache in eine Funktion auslagerst.

                    Übersichtlichkeit kann man sich durch Code-Einklappen bewahren (wenn es der Editor / die IDE bietet).
                    Jesses, die Code-Einklapperei! Ihr einziger Effekt ist, dass die Leute noch ermutigt werden, kilometerweise Code in eine einzige Methode zu packen. Hinfort damit! (Google e.g. "C# regions considered harmful")

                    Hmmm tatsächlich sind Funktionen ideal, weil ich ohne spezielle Markings das Folding im Editor erhalte.
                    Jedoch:  um so wichtiger wird die erste Funktionszeile.

                    Und das bringt mich zum return: Was der Standard return-typ ist, möchte ich gern im head einer Funktion lesen, nicht im footer.
                    Von daher ist die Frage, wieviele Ausgänge die Standardhose haben soll, für mich irrelevant.

                    Das Einklappen von ganzen Methoden ist was anderes, dagegen gibt es nix zu sagen. Logisch, es hilft ja nur, wenn der Code auf mehrere Methoden verteilt ist. ;-)

                    yup.

                    mfg Beat

                    --
                    ><o(((°>           ><o(((°>
                       <°)))o><                     ><o(((°>o
                    Der Valigator leibt diese Fische
      2. Hi!

        eine Schleife stets bis zum Ende durchlaufen zu lassen, statt sie mit break abzubrechen, wenn das Ergebnis feststeht.

        Sowas ist natürlich blödsinnig und mir ist sowas auch noch nie untergekommen. Durchaus sinnvoll finde ich allerdings etwas wie (Pseudocode):

        Iterator it = liste.getIterator();  
        bool found = false;  
          
        while (it.getNext() && !found) {  
         if (it.CurrentElement ... ) { // prüfen, ob das das gesuchte Element ist  
          // hier irgendwas damit anstellen  
          found = true;  
         }  
        }
        

        Dabei ist nämlich die Abbruchbedingung im Schleifenkopf ersichtlich, was bei

        Iterator it = liste.getIterator();  
        while (it.getNext()) {  
         if (it.CurrentElement ... ) { // prüfen, ob das das gesuchte Element ist  
          // hier irgendwas damit anstellen  
          break;  
         }  
        }
        

        nicht der Fall ist. Oder spricht irgendwas gegen die obere Variante?

        Grüße
        Bernhard

        1. Hi!

          Durchaus sinnvoll finde ich allerdings etwas wie (Pseudocode):

          Iterator it = liste.getIterator();

          bool found = false;

          while (it.getNext() && !found) {
          if (it.CurrentElement ... ) { // prüfen, ob das das gesuchte Element ist
            // hier irgendwas damit anstellen
            found = true;
          }
          }

          
          >   
          > Dabei ist nämlich die Abbruchbedingung im Schleifenkopf ersichtlich, was bei  
          >   
          > ~~~java
          
          Iterator it = liste.getIterator();  
          
          > while (it.getNext()) {  
          >  if (it.CurrentElement ... ) { // prüfen, ob das das gesuchte Element ist  
          >   // hier irgendwas damit anstellen  
          >   break;  
          >  }  
          > }
          
          

          nicht der Fall ist. Oder spricht irgendwas gegen die obere Variante?

          In meinen Augen schon. Die drei Zeilen sind noch recht übersichtlich. Aber wenn da noch weiterer Code hinzukommt, besonders welcher zwischen "found = true" und dem Schleifenende, braucht es noch ein continue. Das ist aber irgendwie logisch nicht sehr sinnvoll, denn es soll ja nicht weitergehen sondern die Schleife beendet werden. Man benötigt aber dieses "fortsetzen", um zum Schleifenanfang und damit zur Auswertung von found zu gelangen.

          Auch ansonsten empfinde ich das als einen unnötigen Zwischenschritt. Das break ist klar. Beim found=true muss ich erst verfolgen, was mit diesem Wert demnächst angestellt wird. Es suggeriert vielleicht ein Ende, aber verlassen würde ich mich darauf nicht. Fehler verstecken sich am liebsten hinter nicht überprüftem aber angenommenen Verhalten. Und dass die Schleife beim Finden abgebrochen wird, kann man auch als Kommentar hinterlassen, wenn der Code so <del>unübersichtlich</del><ins>komplex</ins> ist, dass man das nicht auf einen Blick erkennt.

          Lo!

          1. Hi!

            Aber wenn da noch weiterer Code hinzukommt, besonders welcher zwischen "found = true" und dem Schleifenende, braucht es noch ein continue.

            Dem widerspreche ich einfach mal und behaupte: Es geht sicherlich auch ohne continue. Wenn du ein Beispiel lieferst, das ich nicht in eines ohne continue verwandeln kann, gebe ich mich geschlagen. ;-)

            Ich behaupte weiter: In den allermeisten Fällen ist die Variante mit continue nicht essentiell eleganter. Guten Gegenbeispielen stehe ich aber aufgeschlossen gegenüber.

            Das break ist klar. Beim found=true muss ich erst verfolgen, was mit diesem Wert demnächst angestellt wird.

            Liest du den Schleifenkopf nicht vor dem Rumpf??

            Es suggeriert vielleicht ein Ende, aber verlassen würde ich mich darauf nicht.

            Äh, das found wird im Schleifenkopf verwendet. Die Schleife wird abgebrochen, wenn diese Variable true ist. Das ist nicht bloß eine Suggestion, das ist ein Fakt. Oder übersehe ich etwas?

            Fehler verstecken sich am liebsten hinter nicht überprüftem aber angenommenen Verhalten.

            Das ist ein Allgemeinplatz. Unter dem Gesichtspunkt, dass der Schleifenabbruch nicht bloß suggeriert ist (s.o.), verstehe ich nicht, was er hier aussagen soll.

            Und dass die Schleife beim Finden abgebrochen wird, kann man auch als Kommentar hinterlassen, wenn der Code so <del>unübersichtlich</del><ins>komplex</ins> ist, dass man das nicht auf einen Blick erkennt.

            Und wenn sich jemand auf den Kommentar verlässt, _dann_ greift in meinen Augen dein Allgemeinplatz von oben. Kommentar und Code divergieren leider bisweilen...

            Grüße
            Bernhard

            1. Hi!

              Aber wenn da noch weiterer Code hinzukommt, besonders welcher zwischen "found = true" und dem Schleifenende, braucht es noch ein continue.
              Dem widerspreche ich einfach mal und behaupte: Es geht sicherlich auch ohne continue. Wenn du ein Beispiel lieferst, das ich nicht in eines ohne continue verwandeln kann, gebe ich mich geschlagen. ;-)

              Das Ergebnis steht fest. Und es kommt auch kein Code, der noch irgendwas sinnvolles tun soll, denn sonst hätte die return-Variante nicht eingesetzt werden können. Warum also sollte man den nachfolgenden Code noch ausführen? Vielleicht macht oder veranlasst er sogar etwas, was gleich gar nicht gewünscht ist?

              Ich behaupte weiter: In den allermeisten Fällen ist die Variante mit continue nicht essentiell eleganter. Guten Gegenbeispielen stehe ich aber aufgeschlossen gegenüber.

              Eben, deswegen return und fertig.

              Das break ist klar. Beim found=true muss ich erst verfolgen, was mit diesem Wert demnächst angestellt wird.
              Liest du den Schleifenkopf nicht vor dem Rumpf??

              Es suggeriert vielleicht ein Ende, aber verlassen würde ich mich darauf nicht.
              Äh, das found wird im Schleifenkopf verwendet. Die Schleife wird abgebrochen, wenn diese Variable true ist. Das ist nicht bloß eine Suggestion, das ist ein Fakt. Oder übersehe ich etwas?

              Das ist erst dann ein Fakt, wenn ich mich davon überzeugt habe. Dazu muss ich den gesamten Code kennen und brauch nicht nur das break zu sehen. Natürlich muss ich auch den gesamten Code sehen, um mir ein Bild von der Funktionalität zu machen. Aber ich muss es doch durch nicht wirklich benötigte Variablen nicht noch einen Zahn komplexer gestalten. (Wer sowas aus Prinzip macht, macht das dann sicher auch, wenn es überhaupt nicht mehr sinnvoll ist, nur um sein Prinzip zu bedienen.)

              Fehler verstecken sich am liebsten hinter nicht überprüftem aber angenommenen Verhalten.
              Das ist ein Allgemeinplatz. Unter dem Gesichtspunkt, dass der Schleifenabbruch nicht bloß suggeriert ist (s.o.), verstehe ich nicht, was er hier aussagen soll.

              Wie gesagt, erst alle Beweise sichten, dann zum Urteil kommen. Ein unanzweifelbarer Fakt kann diese Prozedur abkürzen. Dass wir hier Allgemeinplätze bemühen, finde ich nicht weiter tragisch. Das liegt in der Natur unserer Diskussion, denn wir reden ja nicht über konkreten Code sondern über allgemeine Vorgehensweisen.

              Und dass die Schleife beim Finden abgebrochen wird, kann man auch als Kommentar hinterlassen, wenn der Code so <del>unübersichtlich</del><ins>komplex</ins> ist, dass man das nicht auf einen Blick erkennt.
              Und wenn sich jemand auf den Kommentar verlässt, _dann_ greift in meinen Augen dein Allgemeinplatz von oben. Kommentar und Code divergieren leider bisweilen...

              Nunja, mit Fehlern sollte man immer rechnen. Davor ist die Abbruchvariablen-Variante auch nicht gefeit. Rein rechnerisch steigt dabei die Fehlerwahrscheinlichkeit durch die zusätzliche Variable sogar noch.

              Lo!

              1. Hi!

                Aber wenn da noch weiterer Code hinzukommt, besonders welcher zwischen "found = true" und dem Schleifenende, braucht es noch ein continue.
                Dem widerspreche ich einfach mal und behaupte: Es geht sicherlich auch ohne continue. Wenn du ein Beispiel lieferst, das ich nicht in eines ohne continue verwandeln kann, gebe ich mich geschlagen. ;-)

                Das Ergebnis steht fest. Und es kommt auch kein Code, der noch irgendwas sinnvolles tun soll, denn sonst hätte die return-Variante nicht eingesetzt werden können. Warum also sollte man den nachfolgenden Code noch ausführen? Vielleicht macht oder veranlasst er sogar etwas, was gleich gar nicht gewünscht ist?

                Diese abstrakte Diskussion fällt mir sehr schwer. Mir wäre lieber du brächtest ein dir möglichst fies erscheinendes Beispiel, über das wir reden können.

                Ich behaupte weiter: In den allermeisten Fällen ist die Variante mit continue nicht essentiell eleganter. Guten Gegenbeispielen stehe ich aber aufgeschlossen gegenüber.

                Eben, deswegen return und fertig.

                Das verstehe ich wieder nicht: Ich sage ein continue a)nicht notwendig und b)obwohl möglich, auch nicht eleganter. Du sagst ein continue ist notwendig. Du merkst doch, dass wir uns widersprechen?

                Das ist erst dann ein Fakt, wenn ich mich davon überzeugt habe. Dazu muss ich den gesamten Code kennen und brauch nicht nur das break zu sehen. Natürlich muss ich auch den gesamten Code sehen, um mir ein Bild von der Funktionalität zu machen.

                Vielleicht liegt der Unterschied einfach darin, dass ich eher an einen Top-Down-Approach denke: Wenn ich eine Schleife lesen will, dann fange ich als erstes mit dem Kopf an und finde es da enorm hilfreich, wenn die dort angegebene Abbruchbedinung wirklich zutrifft. Natürlich muss ich den gesamten Schleifenrumpf auch kennen, um zu wissen, was da genau passiert.

                Dem liegt die Annahme zu Grunde, dass eine _vernünftige_ Schleife (1:1-Übertragungen mathematischer Algorithmen vielleicht ausgeschlossen) sowieso nie so lang sein wird, dass man sie nicht als ganzes erfassen kann.

                Du gehst vielleicht eher von einer unübersichtlich langen Schleife aus, von der du _nur einen Teil_ betrachten willst. Für mich wäre da schon wieder Kern des Problems, dass die Schleife zu lang ist. Wie auch bei unserer Diskussion über die sinnvolle Länge von Funktionen.

                Dass wir hier Allgemeinplätze bemühen, finde ich nicht weiter tragisch. Das liegt in der Natur unserer Diskussion, denn wir reden ja nicht über konkreten Code sondern über allgemeine Vorgehensweisen.

                Wie gesagt, mir wäre ein Beispiel eh viel lieber.

                Nunja, mit Fehlern sollte man immer rechnen. Davor ist die Abbruchvariablen-Variante auch nicht gefeit. Rein rechnerisch steigt dabei die Fehlerwahrscheinlichkeit durch die zusätzliche Variable sogar noch.

                Du hast aber nicht mit der Fehlerwahrscheinlichkeit argumentiert. Die halte ich durch die Einführung einer einzigen, sinnvoll benannten und verwendeten booleschen Variable nur für unwesentlich erhöht.

                Du hast damit argumentiert, dass das found jemanden vielleicht auf die falsche Fährte lockt. Und dieses Argument gilt auch für eine Schleife mit einem zusätzlichen Kommentar statt einer booleschen Variable.

                Grüße
                Bernhard

                1. Hi!

                  Aber wenn da noch weiterer Code hinzukommt, besonders welcher zwischen "found = true" und dem Schleifenende, braucht es noch ein continue.
                  Dem widerspreche ich einfach mal und behaupte: Es geht sicherlich auch ohne continue. Wenn du ein Beispiel lieferst, das ich nicht in eines ohne continue verwandeln kann, gebe ich mich geschlagen. ;-)

                  Ja gut, du kannst statt des continue mit if-else-Gebilden die Abarbeitung von Code verhindern. Das ergibt dann ungefähr so einen Code

                  *
                      *
                        *
                          *

                  statt einem solchen mit Abbrüchen

                  *
                    *
                    *
                    *

                  Das Ergebnis steht fest. Und es kommt auch kein Code, der noch irgendwas sinnvolles tun soll, denn sonst hätte die return-Variante nicht eingesetzt werden können. Warum also sollte man den nachfolgenden Code noch ausführen? Vielleicht macht oder veranlasst er sogar etwas, was gleich gar nicht gewünscht ist?
                  Diese abstrakte Diskussion fällt mir sehr schwer. Mir wäre lieber du brächtest ein dir möglichst fies erscheinendes Beispiel, über das wir reden können.

                  Ein einfaches Beispiel kommt gleich.

                  Ich behaupte weiter: In den allermeisten Fällen ist die Variante mit continue nicht essentiell eleganter. Guten Gegenbeispielen stehe ich aber aufgeschlossen gegenüber.
                  Eben, deswegen return und fertig.
                  Das verstehe ich wieder nicht: Ich sage ein continue a)nicht notwendig und b)obwohl möglich, auch nicht eleganter. Du sagst ein continue ist notwendig. Du merkst doch, dass wir uns widersprechen?

                  Ein continue ist nicht in jedem Fall notwendig. Es ist dann notwendig, wenn man den Rest des Schleifenkörpers nicht weiter durchlaufen möchte. Sei es, weil die Abarbeitung nur Zeit verbraucht, oder weil sie Änderungen vornimmt, die man nicht will.

                  Gegeben sei eine Datenstruktur. Zum Beispiel ein Array. Der Arrayzeiger steht auf einem der Elemente.

                  $found = false;  
                  while ($found) {  
                    if (current($array) == ...) {  
                      $found = true;  
                      continue;  
                    }  
                    next($array);  
                  }  
                  unset($found);
                  

                  Ergebnis ist, dass der Arrayzeiger nun auf dem gesuchten Element steht. Ohne continue stünde er auf dem nächsten Element. Das continue verhindert das unerwünschte Weiterstellen des Arrayzeigers.

                  Nicht nur, dass nun eine Variable namens $found rumliegt, die man mit einem weiteren Schritt aufräumen müsste/kann, auch sprachlich ist es verwirrend. Wenn das Element gefunden ist, soll die Suche abgebrochen werden und nicht fortgesetzt. Da du aber eine Schleife mit $found-Variable haben willst, muss sie fortgesetzt werden.

                  do {  
                    if (!(current($array) == ...))  
                      next($array);  
                  } while (current($array) == ...);
                  

                  Mit einer fußgesteuerten Schleife wird es auch nicht besser, da der Zeiger nicht unbedingt weitergestellt werden soll. Wenn er bereits auf dem gesuchten Element steht, dann muss er dort bleiben. Wenn man die Bedingung nicht noch einmal auswerten möchte, braucht man wieder die Hilfsvariable:

                  $found = false;  
                  do {  
                    if (current($array) == ...)  
                      $found = true;  
                    else  
                      next($array);  
                  } while ($found);  
                  unset($found);
                  

                  Eine Alternative zum Preis einer komplexeren Bedingung wäre:

                  $found = false;  
                  do {  
                    if (!($found = current($array) == ...))  
                      next($array);  
                  } while ($found);  
                  unset($found);
                  

                  Meine Variante mit break

                  while (true) {  
                    if (current($array) == ...)  
                      break;  
                    next($array);  
                  }
                  

                  hat zwar den Makel des true als Schleifenbedingung, aber da es (außer goto) keine Schleifen ohne Bedingung gibt, kommt man daran nicht vorbei.

                  Dies war jetzt nur ein ganz kleines Beispiel. Nun stell dir eins vor, bei dem noch mehr Abbruchbedingungen getestet werden müssen.

                  while (true) {  
                    $current = current($array);  
                    
                    if ($current == dies)  
                      break;  
                    
                    if ($current == das)  
                      break;  
                    
                    if ($current == jenes)  
                      break;  
                    
                    next($array);  
                  }
                  

                  So wie ich das eben notiert habe, kann man sicher dies, das und jenes in einem if testen. Es muss aber einzeln bleiben, wenn vor dem jeweiligen break noch jeweils unterschiedlicher Code ausgeführt werden soll.

                  Das ist erst dann ein Fakt, wenn ich mich davon überzeugt habe. Dazu muss ich den gesamten Code kennen und brauch nicht nur das break zu sehen. Natürlich muss ich auch den gesamten Code sehen, um mir ein Bild von der Funktionalität zu machen.
                  Vielleicht liegt der Unterschied einfach darin, dass ich eher an einen Top-Down-Approach denke: Wenn ich eine Schleife lesen will, dann fange ich als erstes mit dem Kopf an und finde es da enorm hilfreich, wenn die dort angegebene Abbruchbedinung wirklich zutrifft. Natürlich muss ich den gesamten Schleifenrumpf auch kennen, um zu wissen, was da genau passiert.

                  Ja, aber das was du da im Kopf siehst, ist nur das Auswerten einer Hilfsvariable und nicht die eigentliche Abbruchbedingung. Diese steckt weiterhin im Schleifenkörper. Wenn sie wirklich im Kopf steckte, braucht es dafür weder return/break noch Hilfsvariablen/continue.

                  Dem liegt die Annahme zu Grunde, dass eine _vernünftige_ Schleife (1:1-Übertragungen mathematischer Algorithmen vielleicht ausgeschlossen) sowieso nie so lang sein wird, dass man sie nicht als ganzes erfassen kann.

                  Naja, du kannst eine komplexe Aufgabenstellung nicht weniger komplex machen, indem du sie aufteilst. Wenn du Glück hast, wird sie durch das Aufteilen übersichtlicher, dafür erhöht sich aber die Komplexität.

                  Es ist im Grunde wie mit Hundekot. Wenn da ein großer Haufen liegt, ist das zwar ärgerlich, aber wenn du ihn in Kotabschnitte auf- und über den Fußweg verteilst, kann man diese zwar einzeln betrachten, benötigt aber auch gezielte Sprünge und Schritte um alle Teile (zwecks Beseitung) erfassen zu können. Ganz abgesehen von den unschönen Nebenwirkungen beim unbeabsichtigten Fortführen des Kots ...

                  Du gehst vielleicht eher von einer unübersichtlich langen Schleife aus, von der du _nur einen Teil_ betrachten willst. Für mich wäre da schon wieder Kern des Problems, dass die Schleife zu lang ist. Wie auch bei unserer Diskussion über die sinnvolle Länge von Funktionen.

                  Um Code zu erfassen, muss ich das sicherlich Stück für Stück machen. Ich bin mir nur nicht sicher, ob es generell besser sein soll, diese Teile zu separieren oder sie an einem Ort zu lassen. Ich denke, für diesen Punkt der Diskussion gibt es keine allgemeingültige Lösung.

                  Nunja, mit Fehlern sollte man immer rechnen. Davor ist die Abbruchvariablen-Variante auch nicht gefeit. Rein rechnerisch steigt dabei die Fehlerwahrscheinlichkeit durch die zusätzliche Variable sogar noch.
                  Du hast aber nicht mit der Fehlerwahrscheinlichkeit argumentiert. Die halte ich durch die Einführung einer einzigen, sinnvoll benannten und verwendeten booleschen Variable nur für unwesentlich erhöht.

                  Diese eine Variable kommt an mindestens zwei Stellen vor. Eher an noch mehr, denn ansonten könnte man die eigentliche Bedingung vermutlich gleich im Schleifenkopf oder -fuß unterbringen. Jede Stelle ist einen weitere potentielle Fehlerstelle.

                  Lo!

                  1. Hi!

                    Hat etwas länger gedauert, sorry. Ich hab auch nicht lang Zeit; zur return-Diskussion vielleicht morgen mehr.

                    Ja gut, du kannst statt des continue mit if-else-Gebilden die Abarbeitung von Code verhindern. Das ergibt dann ungefähr so einen Code

                    *
                        *
                          *
                            *

                    statt einem solchen mit Abbrüchen

                    *
                      *
                      *
                      *

                    Ja, aber: die Fälle, wo wirklich 4 Verschachtelungsebenen nötig sind, sind meiner Einschätzung nach extrem rar. Das abstrakt zu diskutieren geht mir aber wieder zu weit. Beispiele wäre mir wieder lieber; falls deines von unten ein solches ein soll, dann siehe ebendort.

                    Gegeben sei eine Datenstruktur. Zum Beispiel ein Array. Der Arrayzeiger steht auf einem der Elemente.

                    $found = false;

                    while ($found) {
                      if (current($array) == ...) {
                        $found = true;
                        continue;
                      }
                      next($array);
                    }
                    unset($found);

                    
                    >   
                    > Ergebnis ist, dass der Arrayzeiger nun auf dem gesuchten Element steht. Ohne continue stünde er auf dem nächsten Element. Das continue verhindert das unerwünschte Weiterstellen des Arrayzeigers.  
                      
                    Erstens hast du im Kopf das ! vergessen. Außerdem ist  
                    ~~~php
                    $found = false;  
                    while ($found) {  
                      if (current($array) == ...) {  
                        $found = true;  
                      } else {  
                        next($array);  
                      }  
                    }
                    ~~~ in meinen Augen weder unübersichtlich noch schlecht nachzuvollziehen. Ohne break; ohne continue.  
                      
                    Vergleich mit deiner Variante:  
                    ~~~php
                      
                    $found = false;  
                    while ($found) {                 while (true) {  
                      if (current($array) == ...) {    if (current($array) == ...) {  
                        $found = true;                   break;  
                      } else {                         }  
                        next($array);                  next($array);  
                      }                              }  
                    }
                    

                    Eingespart hast du eine aus einer schließenden Klammer bestehende Zeile (neben der booleschen Variable).

                    Nicht nur, dass nun eine Variable namens $found rumliegt, die man mit einem weiteren Schritt aufräumen müsste/kann

                    Bitte, das ist eine lokale Variable innerhalb einer Funktion, die geht ex nach Ende des Funktionsaufrufs. Speicherlecks sind da nicht zu befürchten.

                    Und dein

                    while (true) {

                    $current = current($array);

                    if ($current == dies)
                        break;

                    if ($current == das)
                        break;

                    if ($current == jenes)
                        break;

                    next($array);
                    }

                    würde ich als  
                    ~~~php
                      
                    $found = false;  
                    while(!$found) {  
                      if ($current == dies || $current == das || ...) {  
                       found = true;  
                      } else {  
                        next($array);  
                      }  
                    }
                    

                    schreiben.

                    Bei keinem deiner beiden Beispiele kann ich in meinen Varianten gröbere Nachteile entdecken. Wie gesagt, ich setz mich aber auch gern mit deiner Ansicht nach möglichst fiesen Beispielen auseinander, falls du noch welche liefern möchtest.

                    Ja, aber das was du da im Kopf siehst, ist nur das Auswerten einer Hilfsvariable und nicht die eigentliche Abbruchbedingung. Diese steckt weiterhin im Schleifenkörper. Wenn sie wirklich im Kopf steckte, braucht es dafür weder return/break noch Hilfsvariablen/continue.

                    Nun ja, ich möchte mich hier nicht an der Terminologie aufhängen. Fakt ist: betrachtet man einen derartigen Schleifenkopf ohne die Variable found, dann sagt der Kopf eindeutig, dass die _gesamte_ Liste (oder das gesamte Array) durchlaufen wird. Das trifft aber nicht zu.

                    Dem liegt die Annahme zu Grunde, dass eine _vernünftige_ Schleife (1:1-Übertragungen mathematischer Algorithmen vielleicht ausgeschlossen) sowieso nie so lang sein wird, dass man sie nicht als ganzes erfassen kann.

                    Naja, du kannst eine komplexe Aufgabenstellung nicht weniger komplex machen, indem du sie aufteilst. Wenn du Glück hast, wird sie durch das Aufteilen übersichtlicher, dafür erhöht sich aber die Komplexität.

                    Wenn für dich ein Funktionsaufruf mit (Hausnummer) 2 Parametern und möglicherweise einem Rückgabewert "Komplexität" darstellt, dann schon. Für mich sind Funktionsaufrufe keine Komplexität sondern einfach normal und gut.

                    Es ist im Grunde wie mit Hundekot. Wenn da ein großer Haufen liegt, ist das zwar ärgerlich, aber wenn du ihn in Kotabschnitte auf- und über den Fußweg verteilst, kann man diese zwar einzeln betrachten, benötigt aber auch gezielte Sprünge und Schritte um alle Teile (zwecks Beseitung) erfassen zu können. Ganz abgesehen von den unschönen Nebenwirkungen beim unbeabsichtigten Fortführen des Kots ...

                    Eine, wie soll ich sagen, sehr bildliche Metapher... ;-)

                    Du gehst vielleicht eher von einer unübersichtlich langen Schleife aus, von der du _nur einen Teil_ betrachten willst. Für mich wäre da schon wieder Kern des Problems, dass die Schleife zu lang ist. Wie auch bei unserer Diskussion über die sinnvolle Länge von Funktionen.

                    Um Code zu erfassen, muss ich das sicherlich Stück für Stück machen. Ich bin mir nur nicht sicher, ob es generell besser sein soll, diese Teile zu separieren oder sie an einem Ort zu lassen. Ich denke, für diesen Punkt der Diskussion gibt es keine allgemeingültige Lösung.

                    Ja, wir streiten natürlich im Grunde hier über Geschmack.

                    Nunja, mit Fehlern sollte man immer rechnen. Davor ist die Abbruchvariablen-Variante auch nicht gefeit. Rein rechnerisch steigt dabei die Fehlerwahrscheinlichkeit durch die zusätzliche Variable sogar noch.
                    Du hast aber nicht mit der Fehlerwahrscheinlichkeit argumentiert. Die halte ich durch die Einführung einer einzigen, sinnvoll benannten und verwendeten booleschen Variable nur für unwesentlich erhöht.

                    Diese eine Variable kommt an mindestens zwei Stellen vor. [...] Jede Stelle ist einen weitere potentielle Fehlerstelle.

                    Ich muss dir natürlich grundsätzlich zustimmen, jedoch halte ich die Fehlerwahrscheinlichkeit für in der Praxis (wieder habe ich angemessen kurze Schleifen vor Auge) zu vernachlässigen.

                    Grüße
                    Bernhard

                    1. Hi!

                      Erstens hast du im Kopf das ! vergessen.

                      Ich wollte nur wissen, ob du aufpasst :-) Ich korrigier das mal in den Zitaten

                      Außerdem ist

                      $found = false;

                      while (!$found) {
                        if (current($array) == ...) {
                          $found = true;
                        } else {
                          next($array);
                        }
                      }

                        
                      Das sind ja nur Minimalbeispiele. Nun stell dir was Größeres und/oder Komplexeres vor, von dem deine Aufmerksamkeit schon genug in Anspruch genommen wird.  
                        
                      
                      > Vergleich mit deiner Variante:  
                      > ~~~php
                        
                      
                      > $found = false;  
                      > while (!$found) {                 while (true) {  
                      >   if (current($array) == ...) {    if (current($array) == ...) {  
                      >     $found = true;                   break;  
                      >   } else {                         }  
                      >     next($array);                  next($array);  
                      >   }                              }  
                      > }
                      
                      

                      Eingespart hast du eine aus einer schließenden Klammer bestehende Zeile (neben der booleschen Variable).

                      Nicht das eine Klammernpaar mit dem else ist der Punkt, sondern dass ich mich nicht um die ordnungsgemäße Behandlung der booleschen Variable zu sorgen brauche. Auch muss ich nicht darauf achten, ob nicht vielleicht noch die Logik durch diese Variable negiert wird. Und mein !-Fehler zeigt ja auch sehr schön, dass ich unbewusst eine der potentiellen Fehlerquellen erfolgreich ausgenutzt habe.

                      Nicht nur, dass nun eine Variable namens $found rumliegt, die man mit einem weiteren Schritt aufräumen müsste/kann
                      Bitte, das ist eine lokale Variable innerhalb einer Funktion, die geht ex nach Ende des Funktionsaufrufs. Speicherlecks sind da nicht zu befürchten.

                      Vielleicht. Was ist, wenn die Schleife nicht in der einzige Code in diesem Geltungsbereich ist?

                      Und dein

                      while (true) {

                      $current = current($array);

                      if ($current == dies)
                          break;

                      if ($current == das)
                          break;

                      if ($current == jenes)
                          break;

                      next($array);
                      }

                      
                      > würde ich als  
                      > ~~~php
                        
                      
                      > $found = false;  
                      > while(!$found) {  
                      >   if ($current == dies || $current == das || ...) {  
                      >    found = true;  
                      >   } else {  
                      >     next($array);  
                      >   }  
                      > }
                      
                      

                      schreiben.

                      Nun, das sagte ich ja, dass man das in dem einfachen/vereinfachten Fall so notieren kann. Und ich führte auch an, wann man das nicht mehr kann.

                      Bei keinem deiner beiden Beispiele kann ich in meinen Varianten gröbere Nachteile entdecken. Wie gesagt, ich setz mich aber auch gern mit deiner Ansicht nach möglichst fiesen Beispielen auseinander, falls du noch welche liefern möchtest.

                      Nein, möchte ich eigentlich nicht, da ich es für das Prinzipverständnis der möglichen Probleme auch ohne irrelevanten Füllcode verständlich finde. Aber gut, da lief mir die Tage doch ein Beispiel, wie man es nicht machen sollte, über den Weg (auch wenn ich damit wieder von Schleife auf Funktion wechsle). In ZendFramework/Controller/Router/Route.php ganz am Ende die Methode getLocale(). Abgesehen vom überflüssigen Einstellen des Codes in else-Zweige, könnte man mit zwei returns in dem try-catch-Block auskommen und kann sich das umständliche nachfolgende Auswerten sparen. Selbst wenn man die elses drinlässt und auch die Zwischenvariable im try-catch-Block, braucht es das abschließende return null; nicht. Ein einfaches return $locale; unterhalb try-catch hätte es auch getan, weil der Code sowieso keine andere Chance hat, an einem der returns vorbeizukommen.

                      Ja, aber das was du da im Kopf siehst, ist nur das Auswerten einer Hilfsvariable und nicht die eigentliche Abbruchbedingung. Diese steckt weiterhin im Schleifenkörper. Wenn sie wirklich im Kopf steckte, braucht es dafür weder return/break noch Hilfsvariablen/continue.
                      Nun ja, ich möchte mich hier nicht an der Terminologie aufhängen. Fakt ist: betrachtet man einen derartigen Schleifenkopf ohne die Variable found, dann sagt der Kopf eindeutig, dass die _gesamte_ Liste (oder das gesamte Array) durchlaufen wird. Das trifft aber nicht zu.

                      while(true) sagt mir erst einmal nur, dass das eine Endlosschleife ist. Dass Endlosschleifen üblicherweise doch abgebrochen werden, sollte einem die Erfahrung gelehrt haben. Also muss es da eine Abbruchbedingung geben.

                      Wenn für dich ein Funktionsaufruf mit (Hausnummer) 2 Parametern und möglicherweise einem Rückgabewert "Komplexität" darstellt, dann schon. Für mich sind Funktionsaufrufe keine Komplexität sondern einfach normal und gut.

                      Verwechsle bitte nicht die allgemeine Komplexität mit deinem Empfinden für Kompliziertheit.

                      Lo!

                      1. Hi!

                        Nicht das eine Klammernpaar mit dem else ist der Punkt, sondern dass ich mich nicht um die ordnungsgemäße Behandlung der booleschen Variable zu sorgen brauche.

                        Muss ich dir natürlich grundsätzlich zustimmen, ...

                        Auch muss ich nicht darauf achten, ob nicht vielleicht noch die Logik durch diese Variable negiert wird.

                        ... aber ich empfinde halt die aus dem Schleifenkopf sprechende Logik "solange (while) ich nichts (!) gefunden ($found) habe, suche ich weiter ({...})" sehr natürlich und muss da nicht viel nachdenken.

                        Vielleicht. Was ist, wenn die Schleife nicht in der einzige Code in diesem Geltungsbereich ist?

                        Naja, was soll dann sein? Dann ist halt mehr Code in dem Geltungsbereich. Du musst die Variable dann nicht mehr verwenden, wenn du sie nicht mehr brauchst. Du kannst sie natürlich z.B. für eine weitere Schleife verwenden. Der Geltungsbereich ist aber immer eine Funktion oder etwas vergleichbares (ich kenne zumindest keine Programmiersprachen, wo Schleifen außerhalb einer Funktion auftreten können) und wenn du aus der Funktion rauskommst, dann verschwinden die lokalen Variablen.

                        Nein, möchte ich eigentlich nicht, da ich es für das Prinzipverständnis der möglichen Probleme auch ohne irrelevanten Füllcode verständlich finde. Aber gut, da lief mir die Tage doch ein Beispiel, wie man es nicht machen sollte, über den Weg (auch wenn ich damit wieder von Schleife auf Funktion wechsle). In ZendFramework/Controller/Router/Route.php ganz am Ende die Methode getLocale(). Abgesehen vom überflüssigen Einstellen des Codes in else-Zweige, könnte man mit zwei returns in dem try-catch-Block auskommen und kann sich das umständliche nachfolgende Auswerten sparen. Selbst wenn man die elses drinlässt und auch die Zwischenvariable im try-catch-Block, braucht es das abschließende return null; nicht. Ein einfaches return $locale; unterhalb try-catch hätte es auch getan, weil der Code sowieso keine andere Chance hat, an einem der returns vorbeizukommen.

                        Jo, da kommen wir wieder von den Schleifen weg. Aber gut; ich glaube, das Thema haben wir durch. ;-) Meine Variante von getLocale() wäre jedenfalls:

                          
                            public function getLocale()  
                            {  
                                $locale = $this->_locale;  
                                if ($locale == null) { // null?  
                                  $locale = self::getDefaultLocale(); // dann probieren wir das  
                                  if ($locale == null) { // noch immer null?  
                                    try {  
                                        $locale = Zend_Registry::get('Zend_Locale'); // dann letzter Versuch  
                                    } catch (Zend_Exception $e) {  
                                    }  
                                  }  
                                }  
                                return $locale;  
                            }  
                        
                        

                        while(true) sagt mir erst einmal nur, dass das eine Endlosschleife ist.

                        Ja, richtig. Ich habe an mein ursprüngliches Beispiel mit dem Iterator gedacht, mein Fehler.

                        Dass Endlosschleifen üblicherweise doch abgebrochen werden, sollte einem die Erfahrung gelehrt haben.

                        Hintergrundprozesse (die z.B. an Ports lauschen) o.ä. bestehen meines Wissens durchaus aus Endlosschleifen, aus denen man nicht auf saubere Art rauskommt. Ich kenne mich da aber nicht wahnsinnig gut aus und kann auf die Schnelle kein Beispiel liefern.

                        Wenn für dich ein Funktionsaufruf mit (Hausnummer) 2 Parametern und möglicherweise einem Rückgabewert "Komplexität" darstellt, dann schon. Für mich sind Funktionsaufrufe keine Komplexität sondern einfach normal und gut.

                        Verwechsle bitte nicht die allgemeine Komplexität mit deinem Empfinden für Kompliziertheit.

                        Ok, ich bin neugierig: Wie verstehst/definierst du den Begriff "(allgemeine) Komplexität" in diesem Zusammenhang?

                        Grüße
                        Bernhard

                        1. Hi!

                          Verwechsle bitte nicht die allgemeine Komplexität mit deinem Empfinden für Kompliziertheit.
                          Ok, ich bin neugierig: Wie verstehst/definierst du den Begriff "(allgemeine) Komplexität" in diesem Zusammenhang?

                          Jedes Element, das hinzukommt, sowie jede seiner Verwendungen erhöhen die Komplexität eines Programms. Durch die Vorkommen wird der Code umfangreicher und damit die auch potientiellen Fehlerquellen. In den diskutierten Fällen ist die neue Variable und jede ihrer Verwendungen ein weiterer Schritt zur Komplexitätserhöhung. Mit "allgemein" meine ich, dass ich das unabhängig von subjektiven Empfindungen betrachte.

                          Lo!

                          1. Hi!

                            Wenn für dich ein Funktionsaufruf mit (Hausnummer) 2 Parametern und möglicherweise einem Rückgabewert "Komplexität" darstellt, dann schon. Für mich sind Funktionsaufrufe keine Komplexität sondern einfach normal und gut.

                            Verwechsle bitte nicht die allgemeine Komplexität mit deinem Empfinden für Kompliziertheit.
                            Ok, ich bin neugierig: Wie verstehst/definierst du den Begriff "(allgemeine) Komplexität" in diesem Zusammenhang?

                            Jedes Element, das hinzukommt, sowie jede seiner Verwendungen erhöhen die Komplexität eines Programms.

                            Betreffend einer zusätzlichen Variable stimme ich dir da grundsätzlich zu, halte die zusätzliche Komplexität aber wie erwähnt in der Praxis für verschwindend gering.

                            Es ging aber um Funktionsaufrufe.

                            Ich kann mir nicht vorstellen, dass du auch einen Funktionsaufruf als zusätzliche Komplexität einstufst: Wenn ich z.B. irgendwo in einem Programm mal den größten gemeinsamen Teiler von 2 Zahlen brauche, dann schreibe ich dafür eine Funktion, selbst wenn ich den GGT nur ein einziges Mal im gesamten Programm ausrechnen muss. Ein Funktionsaufruf int x = ggT(y, z); ist doch nicht "komplexer", als wenn ich da eine Schleife stehen habe. Noch dazu, wo nur die Auslagerung in eine eigene Methode die elegante Möglichkeit der rekursiven Berechnung ermöglicht.

                            (Klar, für den GGT gibt's sicher schon den jeweiligen Standardbibliotheken haufenweise Funktionen; für das Beispiel habe ich das mal ausgeklammert.)

                            Grüße
                            Bernhard

                            1. Hi!

                              Jedes Element, das hinzukommt, sowie jede seiner Verwendungen erhöhen die Komplexität eines Programms.
                              Ich kann mir nicht vorstellen, dass du auch einen Funktionsaufruf als zusätzliche Komplexität einstufst:

                              Doch, natürlich. Es ist Code und: Mehr Code == ... du weißt schon. Aus der Sicht des laufenden Programms ist der Funktionsaufruf und die Rückkehr immer wieder auszuführen. Das ist natürlich gegenüber direkt dastehendem Code komplexer, doch das stört uns als Programmierer wenig, denn wir müssen nur einmalig dafür sorgen, dass es läuft. Allerdings müssen wir auch darauf achten, dass es soweit abstrahiert wird, dass es einigermaßen universell verwendbar ist, was gegebenenfalls durch hinzukommende Fehlerbehandlung mehr Code benötigt.

                              Wenn ich z.B. irgendwo in einem Programm mal den größten gemeinsamen Teiler von 2 Zahlen brauche, dann schreibe ich dafür eine Funktion, selbst wenn ich den GGT nur ein einziges Mal im gesamten Programm ausrechnen muss. Ein Funktionsaufruf int x = ggT(y, z); ist doch nicht "komplexer", als wenn ich da eine Schleife stehen habe.

                              Gerade wenn du etwas nur einmal anwendest, wird es insgesamt komplexer, weil der einmalig hinzukommende Overhead sich nicht durch Mehrfachnutzung rentiert.

                              Noch dazu, wo nur die Auslagerung in eine eigene Methode die elegante Möglichkeit der rekursiven Berechnung ermöglicht.

                              Bei Rekursion hat man ja wieder eine Mehrfachnutzung.

                              Es ist ja nicht so, als ob ich auf Teufel komm raus die Komplexitätssteigerung vermeiden will, sie sollte nur ein aus meiner Sicht akzeptables Verhältnis zwischen Aufwand und Nutzen haben.

                              Lo!

            2. Hallo,

              Das break ist klar. Beim found=true muss ich erst verfolgen, was mit diesem Wert demnächst angestellt wird.
              Liest du den Schleifenkopf nicht vor dem Rumpf??

              doch, schon. Aber die Abbruchbedingung für die Schleife wird erst bewertet, wenn der nächste Schleifendurchlauf fällig ist.

              Es suggeriert vielleicht ein Ende, aber verlassen würde ich mich darauf nicht.
              Äh, das found wird im Schleifenkopf verwendet. Die Schleife wird abgebrochen, wenn diese Variable true ist.

              Nein. Sie wird abgebrochen, wenn vor dem Beginn des nächsten Schleifendurchlaufs festgestellt wird, dass die Abbruchbedingung erfüllt ist. Das ist ein Unterschied.

              Oder übersehe ich etwas?

              Ja, anscheinend: Die Tatsache, dass zwischen der Zuweisung found=true und dem Beginn des nächsten Schleifendurchlaufs (denn erst dann wird die Bedingung überprüft) noch viele weitere Anweisungen liegen können, die vielleicht gar nicht mehr erwünscht sind.

              Gute Nacht,
               Martin

              --
              Die letzten Worte des Hardware-Bastlers:
              Das Netzkabel lass ich wegen der Erdung lieber dran.
              Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  4. Hallo Zusammen,

    mal in diesem Zusammenhang mal eine grundsätzliche Frage: PHP lässt ja in Funktionen bzw. Methoden als return Wert jeden Typ gelten:

      
    public function getVal(){  
      
    if($this->someValue)return true;  
      
    return "ein kleiner String";  
      
    }  
    
    

    Da ich kein PHPler bin, frage ich mich nun, ob das guter Stil ist. Oder sollte eine Funktion (auch in PHP) immer nur einen Return-Typen unterstützen?

    +++

    Und dann hätte ich noch eine PHP-Frage, die im Zusammenhang mit der Typisierung steht. PHP unterstützt ja Ducktyping. Wie ist es denn in so einem Fall:

      
    a = "langer String"; // deklarieren und implizit typisieren (=String)  
    a = 3; //typ wechseln (=Integer)  
    
    

    Für eine Variable (Objekt) vom Typ String muss ja entsprechender Speicher reserviert werden. Wenn ich nun den Typ der Variable wechsle, was passiert dann mit dem ursprünglich reservierten Speicher?

    Fragen über Fragen

    1. Hi!

      mal in diesem Zusammenhang mal eine grundsätzliche Frage: PHP lässt ja in Funktionen bzw. Methoden als return Wert jeden Typ gelten:
      Da ich kein PHPler bin, frage ich mich nun, ob das guter Stil ist. Oder sollte eine Funktion (auch in PHP) immer nur einen Return-Typen unterstützen?

      PHP selbst macht es ja vor, dass im Fehlerfall ein anderer Typ geliefert wird als im Gutfall. Ich denke, aus PHP-Sicht und dem lockeren Typ-Konzept ist das nicht unangemessen.

      Für eine Variable (Objekt) vom Typ String muss ja entsprechender Speicher reserviert werden. Wenn ich nun den Typ der Variable wechsle, was passiert dann mit dem ursprünglich reservierten Speicher?

      Da muss noch nicht mal eine Typumwandlung erfolgen. Speicher wird beispielweise auch frei, wenn ein String verkürzt wird. Der Garbage Collector kümmert sich um die Leichen - oder das Script-Ende.

      Lo!