Folgende Situation sei gegeben: In setup_init() wird is_valid_obj() aufgerufen und in is_valid_obj() wird is_command() aufgerufen. Wenn is_valid_obj() oder is_command() false zurückgeben, soll jeweils eine Fehlermeldung ausgegeben werden. Die Fehlermeldung kann Informationen über die fehlerhaften Variablen/Objekte enthalten. Die Frage lautet: Wo gehören diese Fehlermeldungen hin? Sollen die Fehler direkt in is_valid_obj() und is_command() ausgegeben werden oder in setup_init()? Generell gilt also die Frage, sollen Fehler am Ort ausgegeben werden, wo auf die möglichen Fehler geprüft wird, oder am Ort wo die möglichen fehlerhaften Werte/Objekte benutzt werden?
Häufig wird man da, wo der Fehler erkannt wird, gar nicht wissen, wie eine Fehlermeldung ausgegeben werden soll. Also kann sie dort nur sinnvoll eingetütet und nach oben weitergereicht werden. Irgendwo weiter oben kann dann jemand vernünftig mit dem Fehler umgehen und darauf reagieren, ggf. weiter nach oben durchreichen. Wieso fällt mir da jetzt wieder C++ mit Ausnahmen ein?
Ausgegeben ? Da, wo sie jemand sieht, Konsole, Errorlog, Schnittstelle. Die Frage ist eher, wo die Klartexte im Programm stehen sollen: Im Programm an der Stelle an der sie auftreten, an der sie ausgegeben werden, oder in einer Resource. Wegen Übersetzung sollte der Text in einer Resource stehen, also irgendwo zusammengefasst und je nach Sprache umschaltbar. Problematisch ist dabei die Ergänzung um Parameter, die liegen ja meist nur an der Stelle vor, an der der Fehler entdeckt wird, wenn überhaupt. Interessanter sind Betrachtungen: was passiert mit einem Errorlog wenn ein Fehler dauernd auftritt, läuft dann die Festplatte voll, stockt der Rechner wegen Überlastung weil der Fehler sagt dass die Festplatte voll ist ? Daher am besten Fehler nur ein Mal speichern und auf Abfrage liefern aber nichts vollmüllen. Was passiert wenn die Resource eine extra Datei ist und nicht hefunden wird.
CleanCoder schrieb: > Generell gilt also die Frage, sollen Fehler am Ort ausgegeben werden, wo > auf die möglichen Fehler geprüft wird, oder am Ort wo die möglichen > fehlerhaften Werte/Objekte benutzt werden? Darauf gibt es keine generelle Antwort. Im Gegenteil: Es spaltet die Entwickler unterschiedlicher Horizonte unversöhnlich und ist eine der wirklich kritischen Designebenen. Beispiel 1: Bei PC-Anwendungen kann problemlos eine Fehlermeldung "kein Speicherplatz" bis oben blockierend hochpoppen. Er kann dann welchen Schaffen (Dateien löschen) oder das ganze abbrechen. Im Embedded-Bereich geht das meist nicht. Beispiel 2: Wenn eine erste Aktion nicht klappt, liegt es am Aufrufer (der Funktion), zu entscheiden, ob er dann mit einer Alternative weitermachen kann oder nicht. Ob und wer nun was meldet, hängt auch davon ab, wie oft der Fehler im Fehlerfall auftritt. Meist ist es wichtig, jeden Fehler zu loggen, aber nicht jeden Fehler beliebig oft. Wenn Beispielsweise ein Aktor/Sensor X nicht da ist, sollte das nicht unbedingt jede ms geloggt werden, nur weil er jede ms ausgelesen wird. Da kann es z.B. sinn machen, nur Änderungen zu loggen.
Mal so, mal so. Für das eine Programm ist die direkte Fehlermeldung am besten, für das andere ist es besser, wenn der Aufrufer über die Behandlung entscheidet. Es kommt alles auf die Art des Programmes an. Manchmal gebe ich eine Klartext Fehlermeldung über einen Referenzparameter zurück. Dann kann der Aufrufer entscheiden, wie er damit weiter macht. Ausgeben, oder selber an seinen Aufrufer weiter höher zurück geben. usw
Jede grösser Software schreibt ein Log (oder mehrere), dafür gibts ne API oder was selber gestricktes. Was, wann, wie, musst du selber entscheiden.
Voodoopriester schrieb: > Jede grösser Software schreibt ein Log (oder mehrere), dafür gibts ne > API oder was selber gestricktes. Solange Herr CleanCoder nichts zu seiner Umgebung sagt: MaWin schrieb: > Ausgegeben ? > Da, wo sie jemand sieht, Konsole, Errorlog, Schnittstelle. Wenn der Kram auf einen µC läuft, wird das eng mit Logfile. Als nächstes muß der gwünschte Debugging-Prozess beschrieben werden. Auf einem µC springe ich zum Teil eine eigene Routine an und übergebe der nur eine Nummer, um zu sehen, an welcher Stelle er ausgestiegen ist. Da kommt dann auf der seriellen z.B. "Scheiße passiert 3" und im Quellcode kann ich nachsehen, dass der Abflug #3 zur Spannungsmessung gehört. Dann baue ich mir temporäre Ausgaben in diese Routine und suche den Fehler. Für dauerhaft komfortablere Fehlerausgaben fehlt oftmals der Speicherplatz. Wenn es tatsächlich eine PC-Anwendung mit Logdatei(en) ist: MaWin schrieb: > was passiert mit einem Errorlog wenn > ein Fehler dauernd auftritt, läuft dann die Festplatte voll, Darüber musste ich mich einige Male mit Softwerkern prügeln, weil sie genau das nicht beachtet hatten und auch nicht begreifen wollten - nach wenigen Stunden fliegt Windows ab "Platte voll". Dann antwortet der Dussel, die Fehlerausgabe sei eine Java-Klasse, auf die er keinen Einfluß nehmen könne ...
Die Frage stellt sich mir unabhängig von der Plattform. Gemeint ist wo im Quelltext der Fehler in die Konsole oder in die Logdatei geschrieben werden soll. Konkret habe ich es mit dem Browser mit JavaScript und Rust in der Desktop Konsole zu tun. Vor allem bei JavaScript bin ich total verloren. Arbeite ich mit bool als Rückgabewerten? Doch die böse null nutzen? Oder bastel ich meine eigenen Fehlerklassen? Habe den Eindruck dass ich durch Rust erst merke wie schlimm JavaScript eigentlich ist :D Bin im Grunde geneigt so was wie Result und Option aus Rust in JavaScript nachzuahmen.
In JS nach dem Check "throw" nutzen. Schau dir auch das Error Objekt an. In C würde ich Fehlercodes zurück geben und den Fehler loggen. Beim reinen loggen von Sachen würde ich auch je nach Platform anders vorgehen, In Java und JS gibt es recht gute & bekannte libs & interfaces fürs loggen. Die Implementation ist dort glaube ich auch recht gut austauschbar, oder zumindest, wohin geloggt wird. In C würde ich meine eigenen Logging API definieren, eventuell Factory & Facade pattern nutzen. Beim loggen klassifiziert man oft, wie schlimm / wichtig etwas ist, zu was es gehört, etc. Oft kann man irgendwie filtern, was geloggt werden soll. Muss aber bei kleineren Sachen nicht unbedingt sein. Bei einfachen Programmen reicht normalerweise loggen nach stdout / stderr. Bei grösseren Sachen habe ich gerne zusätzlich die Möglichkeit statt nach stdout / stderr direkt nach syslog zu loggen. Ein logger für Dateien ist ein nettes Extra, aber ich bin kein grosser Fan davon, weil schwieriger zu managen. Das das Programm bei Fehlern beim Loggen nicht abschmiert oder hängt, und eventuell was zum groben Vorfiltern (keine debug Meldungen), erwarte ich von den Entwicklern. Das das system mit unerwarteten Unmengen an Logs klarkommt, erwarte ich hingegen vom Sysadmin. Minimal sollten Logfiles auf einer eigenen Partition, oder einem Ort mit einer Quota abgelegt werden, damit dann nur die Logs betroffen sind. Ob & wann man sie komprimiert, löscht, was man filtert, ob man ein logging daemon mit rate Limiting hat, oder in etwas wie z.B. elastic reinpumpt, etc. sind alles Sachen, um die sich die Sysadmins kümmern müssen, und eventuell Firmenweit vorgegeben werden sollten.
CleanCoder schrieb: > Wo gehören diese Fehlermeldungen hin? Wie immer: Um das Problem soll sich "jemand anderes" kümmern. D.h. wird ein Fehler festgestellt, wird der an den Aufrufer signalisiert. Der soll sich drum kümmern. Also: A() ruft B() auf, in B() entsteht ein Fehler, der wird an A() gemeldet. Der Aufrufer muss entscheiden, was mit dem Fehler passiert. Könnte ja auch sein, dass der Aufrufer etwas anderes probieren möchte oder der Fehler aus seiner Sicht in der aktuellen Situation überhaupt kein Fehler ist. Nötigenfalls reichert er den Fehler aber auch mit zusätzlichen und/oder neuen Informationen an, und signalisiert ihn wiederum an seinen Aufrufer. Irgendwann kommt der Fehler an eine Stelle an, wo es eigentlich nicht mehr höher geht bzw. die Interaktion statt findet und der Fehler dem Benutzer präsentiert werden kann. Davon abzugrenzen sind Log-Dateien. Ganz weit verbreitet ist die Marotte, an der Stelle wo ein Fehler auftritt, einen Log-Eintrag zu erzeugen. Meiner Meinung nach ist das in den meisten Fällen nutzlos. Es werden riesige Logfiles erzeugt, die kaum Informationen enthalten. Denn meistens ist Kontext zu einem Fehler viel interessanter, als der Fehler selbst. Und das fehlt diesen Logdateien. Persönlich erstelle ich Log-Einträge an Schnittstellen. Eine typische Schnittstelle ist z.B. ein API-Call über das Netzwerk, z.B. per HTTP. Wenn da ein Fehlercode zurück kommt, kommt in das Log u.a. eben der Fehlercode, aber auch die relevanten Parameter des Calls etc. CleanCoder schrieb: > Sollen die > Fehler direkt in is_valid_obj() und is_command() ausgegeben werden oder > in setup_init()? Die Funktionen/Methoden is_xyz() sind ziemlich sicher die absolut falschen Stellen, eine Fehlermeldung auszugeben. Die sollen doch nur Testen, ob irgendwas in Ordnung ist. Warum etwas nicht in Ordnung ist, und ob das überhaupt ein (großes) Problem ist, wissen diese Funktionen doch nicht. Der Aufrufer, der is_xyz() aufruft, muss entscheiden, wie mit einem negativen Test zu verfahren ist, einschließlich der Entscheidung, eine Meldung auszugeben oder auch nicht.
In verschiedene Sprachen übersetzte Fehlermeldungen lassen sich schlecht im Internet suchen, da entstehen dann so lokalsprachlich zersplitterte Infoblasen. Auch nicht toll ... LG, Sebastian
CleanCoder schrieb: > Arbeite ich mit bool als Rückgabewerten? Doch die böse null nutzen? Moderne (OOP) Sprachen haben dazu die Exception erfunden, damit eben NICHT ein Rückgabewert als Fehlercode ausgesucht und nach jedem Aufruf geprüft werden muss. Ohne OOP hat man ein Problem, longjmp räumt nicht den geallocten Speicher ab der an Pointern in lokalen Variablen hängt, die beim Abräumen des stacks verloren gehen. Sprachen, die garbage collection intern machen haben es da einfacher und brauchen keine Klassen um Speicherobjekte zu verpacken.
CleanCoder schrieb: > In setup_init() wird is_valid_obj() aufgerufen und in is_valid_obj() > wird is_command() aufgerufen. Daraus würde ich wohl machen: is_command und is_valid_obj geben true/false zurück, weil die nicht wissen können ob "nein" ein Fehler oder ein erwartetes Ergebnis des Tests ist. setup_init ruft die Tests auf und wirft bei einem Fehler eine Exception. Darum kümmert sich dann der Aufrufer von setup_init. Die eigentliche technische Fehlermeldung schreibe ich inzwischen immer auf Englisch, weil meistens die Zusatzinformationen vom System auch auf Englisch sind und man so mehr Hilfe googlen kann. Die Meldung blubbert dann durch das Programm bis zu einer User-Seiten Fehlerbehandlung. Die hat dann ein Fenster mit lokalisierter Beschriftung "ein Fehler ist aufgetreten" und der original Nachricht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.