2 Stimmen

Unterklassifizierung von Ausnahmen

Wir sind uns alle einig, dass die Verwendung unterschiedlicher Ausnahmetypen für unterschiedliche Aufgaben der richtige Weg ist.

Aber dann entstehen Geisterdateien wie diese:

/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Dojo
 * @subpackage View
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
 */

/**
 * @see Zend_Dojo_Exception
 */
require_once 'Zend/Dojo/Exception.php';

/**
 * @category   Zend
 * @package    Zend_Dojo
 * @subpackage View
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Dojo_View_Exception extends Zend_Dojo_Exception
{
}

Dann das Gleiche für Zend_Dojo_Exception und dasselbe für Zend_Exception

Gibt es ein allgemeines Konzept für dieses Problem?

Etwas wie throw new \My\Just\Declared\Exception\ (which extends \My\Just\Exception) damit ich nicht all diese Geisterdateien erstellen und benötigen muss?

0 Stimmen

Dieses "Verhalten" wird in zf2 umgeschrieben framework.zend.com/wiki/display/ZFDEV2/

0 Stimmen

Welches Verhalten? Von diesem Link alles, was ich sehe, ist die Fähigkeit, eine Schnittstelle zu deklarieren? Ich sehe nichts über "Lazy-writing"-Ausnahmen (wo der Code der Klasse nicht einmal existiert, bis sie instanziiert wird)? Liege ich falsch und habe den Link nur falsch gelesen?

0 Stimmen

@robert Das ist eine gute Nachricht, löst aber nicht das Problem der Erstellung neuer Ausnahmen. Vielleicht könnte der neue Zend_Autoloader dies tun.

7voto

weierophinney Punkte 1780

Sie scheinen sich auf die Idee zu konzentrieren, dass es sich um "Geisterklassen" handelt - Klassen ohne Implementierung oder Marker-Schnittstellen. Offen gesagt, Sie verstehen nicht, worum es geht.

In ZF1 gibt es die Ausnahmeklassen nur auf Komponentenebene, und alle Ausnahmen auf dieser Ebene erhalten die gleiche Ausnahmeklasse. Damit sind eigentlich nur die folgenden Arten von Catches möglich:

  • Globale Ebene (catch "Exception")
  • Komponentenebene (Abfangen von Ausnahmen auf Komponentenebene)

Dies ist nur geringfügig besser, als einfach überall "Exception" auszulösen; Sie müssen die Ausnahmemeldungen sorgfältig untersuchen, um eine Vorstellung davon zu bekommen, was schief gelaufen ist.

Lesen Sie den Vorschlag sorgfältig durch.

Der Vorschlag zielt darauf ab, zusätzliche Granularitätsebenen bei der Erfassung von Ausnahmen zu ermöglichen:

  • Es ist Ihnen egal, welche Ausnahme es ist? Fangen Sie \Exception.
  • Sie sind auf der Suche nach Ausnahmen von einer bestimmten Komponente, interessieren sich aber nicht weiter für die Einzelheiten? Fangen Sie die Exception-Schnittstelle dieser Komponente.
  • Möchten Sie nach bestimmten Arten von SPL-Ausnahmen suchen? Fangen Sie diese (in ZF2 implementieren Ausnahmeklassen die Komponentenausnahme-Schnittstelle und erweitern die entsprechenden SPL-Ausnahmen).
  • Möchten Sie einen bestimmten Ausnahmetyp innerhalb der Komponente abfangen? Fangen Sie sie einfach ab.

Im Grunde erlauben wir eine größere Granularität nur bei der Ausnahme TYP Sie müssen die Meldung nur dann überprüfen, wenn es mehrere Ausnahmen desselben Typs gibt, die durch die jeweilige Operation ausgelöst werden könnten. Normalerweise sollte dies nicht der Fall sein.

Die SPL-Ausnahmen sind semantisch ziemlich reichhaltig, und viele Ausnahmen innerhalb von ZF würden besser als diese Typen kategorisiert werden (z.B. sollten ungültige Argumente eine InvalidArgumentException auslösen; die Unfähigkeit, ein Plugin aufzulösen, wäre eine gute RuntimeException; usw.). Mit ZF1 ist dies nicht möglich - wir müssen von der Ausnahme auf Komponentenebene erben, Punkt. Durch den Wechsel zu einer Marker-Schnittstelle erhalten wir sowohl die Möglichkeit, Ausnahmen auf Komponentenebene als auch auf SPL-Ebene abzufangen - und auch auf einen spezifischeren Ausnahmetyp.

1voto

Sjoerd Punkte 71416

Einige Leute verwenden die Autoloader um Ausnahmen im laufenden Betrieb zu erstellen.

1voto

ircmaxell Punkte 159431

In der Praxis, nicht wirklich... Es gibt jedoch einige Hacks, die Sie durchführen können, wenn Sie WIRKLICH Ich wollte das tun, aber ich glaube immer noch, dass sie böser sind.

Einer dieser Hacks ist zum Beispiel eval Diese Klassen werden über einen Autoloader ins Leben gerufen. Das ist schlecht, denn wenn jemand jemals grep s für die Definition der Ausnahme oder für die Ausnahmen, die Ihr Paket auslöst, werden sie eine ganze Menge von nada im Gegenzug sein...

public static function load($name) {
    $parts = explode('_', $name);
    if (strtolower(end($parts)) == 'exception') {
        //make it extend the proper exception
        array_pop($parts); //get rid of the last Exception bit
        array_pop($parts);
        $parts[] = 'Exception';
        $parent = implode('_', $parts);
        $code = 'class '.$name.' extends '.$parent . '{}';
        eval($code);
    }
}

Aber ich möchte noch einmal betonen, dass dies in der Regel eine schlechte Idee ist.

Ich persönlich erbe von mehreren "Basisausnahmen" (typischerweise die SPL Ausnahmen ). So kann zum Beispiel ein Database_Connection_Exception könnte erweitern RuntimeException wird beim Versuch, eine nicht offene Transaktion zu übertragen, möglicherweise ein Database_Not_In_Transaction_Exception die sich ausweiten könnten LogicException . Der Punkt ist, dass die Deklaration sie separat können Sie mehr als nur gerade heiarchal Vererbung (nicht zu erwähnen ist besser für die Dokumentation, da die Menschen auf einen Blick auf die definierten Ausnahmen zu sehen, und Sie können tatsächlich Methoden überschreiben, um besser auf Ihre Bedürfnisse, wenn angemessen)...

Bearbeiten: Ausgehend von Ihrer Erwähnung von Zend Die Tendenz, eine Ausnahme pro Unterpaket zu machen, habe ich folgendermaßen umgesetzt...

Grundsätzlich habe ich ein paar "globale" Ausnahmen, die in der gesamten Anwendung verwendet werden. Diese umfassen (sind aber nicht beschränkt auf): ClassNotFoundException , FileNotFoundException , NotCallableException und eine ganze Reihe anderer. Im Grunde nur solche, die nicht paketspezifisch sind, aber mehr Bedeutung vermitteln müssen, als es die PHP-Kernausnahmen können...

Dann deklariere ich Ausnahmen nur auf Paketebene. In diesem Verzeichnis ( package/exceptions ) Ich erkläre jede einzelne Ausnahme als notwendig. So kann ein Unterpaket 5 oder 10 Ausnahmen haben, um verschiedene Bedingungen zu unterscheiden, während ein anderes Unterpaket (innerhalb desselben Pakets) keine haben kann. Ich deklariere sie also nach Bedarf, damit die Ausnahme bedeutet, was passiert ist.

Ich tue dies aus einem einfachen Grund. Ich kümmere mich nicht um where die Ausnahme wurde von ausgelöst (und wenn ich wirklich tat, kann ich die Rückverfolgung, die automatisch innerhalb der Ausnahme generiert wird inspizieren). Ich interessiere mich für why wurde die Ausnahme ausgelöst. Und das lässt mich die Ausnahme richtig behandeln...

0 Stimmen

Ich benutze Zend nicht (ich mag es einfach nicht). Aber ich packe alle Ausnahmen in eine paketspezifische Unterkategorie. So hätte man alle Ausnahmen unter der Kategorie Database der Kategorie/Paket Database_Exceptions Unterkategorie... Ich glaube, es ist einfach eine Tradition, dass die Exception am Ende. Und ja, Sie können grep für die Anrufe, aber ich denke immer noch, dass es besser ist, die Definition zu haben (da die throw new Database_Connection_Exception() sagt wenig über die Ausnahme aus, aber da class Database_Connection_Exception extends RuntimeException können Sie mehr erfahren (die Datenbank ist ein triviales Beispiel).

0 Stimmen

Der andere Nachteil von eval ist nicht mit Code-Vervollständigung in IDE

0voto

Yanick Rochon Punkte 47683

Aus meiner Sicht sind oder sollten Ausnahmen nur im Entwicklungsmodus sichtbar sein. Im Produktionsmodus sollten dem Benutzer/Client keine Ausnahmen angezeigt werden, sondern eine einfache Seite mit der Meldung "Ein Problem ist aufgetreten" oder etwas Ähnlichem. Diese Ausnahmen sollten bestenfalls protokolliert werden. Unterm Strich sind sie vor allem für die Fehlersuche nützlich oder wenn sie notwendig sind, um den Ausführungsablauf zu steuern (wenn sie erwartet werden). Sie könnten einfach Folgendes auslösen Zend_Exception aber das würde Ihre Ausnahme nur zu allgemein machen und es wäre schwierig, die Ursache in try..catch zu finden

Ich erstelle normalerweise Ghost-Dateien -- wie Sie sie nennen -- meist auf der "Paket"-Ebene oder wenn von einer Methode erwartet wird, dass sie die eine oder andere Ausnahme auslöst (damit ich genau diese spezielle Ausnahme abfangen und konsequent behandeln kann).

Sie können mit vielen Ghost-Dateien aber es macht Ihr Projekt nur übersichtlicher und einfacher zu debuggen. Und da diese Ausnahmen nur bei Bedarf geladen werden, wirkt sich eine große Anzahl von Ausnahmen nicht auf die Leistung aus.

0 Stimmen

Das stimmt, aber darum geht es hier nicht. Wie ich schon schrieb, sind wir uns alle einig, dass wir diese Geisterdateien brauchen. Aber es ist eine langweilige Arbeit, sie zu erstellen. Da wir Programmierer sind, könnten wir einen intelligenten Code schreiben, der diese einfache Aufgabe für uns erledigt. Können wir das nicht?

0 Stimmen

@takeshin: Vergessen Sie nie, dass es einen großen Unterschied gibt zwischen can y should . Ein Zitat von Michael Crichton, Yeah, but your scientists were so preoccupied with whether or not they could, they didn't stop to think if they should ... Es gibt einige Abkürzungen, die wir als Entwickler nehmen können, aber es gibt immer einen Kompromiss ... Ich sage nicht, dass Sie das nicht tun sollten, aber konzentrieren Sie sich nicht darauf, ob Sie peut eine Lösung zu schaffen, konzentrieren Sie sich darauf, ob Sie überhaupt sollte stören (oder ob dies mit der Mikro-Optimierung gleichzusetzen ist)...

0 Stimmen

@ircmaxell, Stimmt, stimmt. Ich frage nur, ob wir das sollten oder nicht. Ihr oben beschriebener Ansatz ist nicht perfekt, aber viel nützlicher als der Zend-Ansatz (auch eine separate Ausnahme für jedes Unterpaket). Die ideale Lösung wäre ein separater Namespace mit manuell definierten Basisausnahmen für jedes Paket (um zu sagen, welche Standardausnahmen sie erweitern) und dann automatisch generierte Ausnahmen, wie du beschrieben hast. Allerdings hat diese Lösung auch einige Nachteile, so dass ich denke, das Beste ist, zu bleiben, was wir jetzt haben :)

0voto

julesbou Punkte 5270

In der Tat hat PHP bereits Unterklassen für Ausnahmen, siehe aquí für die vollständige Liste. Daher ist die Dokumentation über ihre Verwendung recht begrenzt, Sie können prüfen dieser Beitrag über php-Ausnahmen um die Bedeutung der einzelnen Wörter zu verstehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X