Ein Schlechtes Exception Beispiel
 
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern

Hier ein paar echte (leicht vereinfachte) Beispiele aus C++, wo Exceptions falsch gebraucht werden. Dies sind nicht irgenwelche erfundene Beispiele, alle wurden in der freien Natur gesichtet:

Exceptions statt Bedingung

In MS-Visual C++ können Access Violations als Exceptions behandelt werden. Naive Programmierer versuchen dann folgendes:

  try {
    strCaption = "Enter Data for " + pContract->GetCustomer()->GetName();
  } catch(...) {
    strCaption = "Enter Data for new Customer";
  }

Hier soll der catch-Block dafür sorgen, dass die Access Violation, die auftritt, wenn GetCustomer() NULL liefert, abgefangen wird. Leider werden dadurch auch alle anderen Exceptions die da auftreten können versteckt.

Richtiger wäre:

  Customer *pCustomer = 0;
  if (0 != pContract && 0 != (pCustomer = pContract->GetCustomer())) {
    strCaption = "Enter Data for " + pCustomer->GetName();
  } else {
    strCaption = "Enter Data for new Customer";
  }

Dies ist aber noch lange kein guter Code, denn er verletzt das Gesetz von Demeter, also wäre weiteres Refactoring angesagt. Aber zumindest ist hier das gefährliche catch(...) beseitigt.

Exceptions vergessen

In C++ wird man nicht gezwungen, Exceptions zu deklarieren (ähnlich wie in Java RuntimeException?).

  ++m_nDepth;
  Iterator *pI = col->CreateIterator(); // ruft new() auf
  while (!pI->Done()) {
     // mach was mit dem Objekt pI->GetItem();
     pI->Next();
  }
  delete pI;
  --m_nDepth;

Wird in der while Schleife eine Exception geworfen, haben wird der Iterator nicht mehr dealloziert und m_nDepth wird nicht dekrementiert, Memory- und Ressourcenlecks sind die Folge. Um sicher aufzuräumen kann man in Java mit finally, in C++ mit Destruktoren arbeiten. Hier eine exceptionssichere Version:

  Inkrementor incDepth(m_nDepth);
  AutoPtr<Iterator> pI = col->CreateIterator(); // ruft new() auf
  while (!pI->Done()) {
     // mach was mit dem Objekt pI->GetItem();
     pI->Next();
  }
  // delete pI nicht nötig, der Destruktor von AutoPtr kümmert sich darum
  // --m_nDepth nicht nötig, der Destruktor von Inkrementor kümmert sich darum

Das ist natürlich auch noch nicht schön. Warum muss man pI löschen obwohl nirgends new aufgerufen wurde? Iterator ist eine abstrakte Klasse, man könnte sie daher erweitern:

  class Iterator {
  private:
    InternalIterator *m_pI;
  public: 
    Iterator(Collection const& con) {
      m_pI = con.CreateIterator();
    }
    ~Iterator() {
      delete m_pI;
    }
    ...
  }

  ...

  Inkrementor incDepth(m_nDepth);
  Iterator i(col); 
  while (!i.Done()) {
     // mach was mit dem Objekt pI->GetItem();
     i.Next();
  }
  // --m_nDepth nicht nötig, der Destruktor von Inkrementor kümmert sich darum


Siehe auch: EinGutesExceptionBeispiel ExceptionDiskussion ExceptionsDiskussion
KategorieProgrammierung KategorieException
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 21. Januar 2004 19:58 (diff))
Suchbegriff: gesucht wird
im Titel
im Text