Re: Fehlerbehandlung
- From: Thomas 'PointedEars' Lahn <PointedEars@xxxxxx>
- Date: Sat, 17 Dec 2005 18:02:43 +0100
Andreas Born wrote:
> Thomas 'PointedEars' Lahn wrote:
>>> Wenn der Seitenbetreiber den Aufbau seiner HTML-Dokumente ändert
>>> (z.B. IDs umbenennt), würde das Script nicht mehr funktionieren,
>>> weil es die entsprechenden Tags nicht mehr findet. Tritt dieser Fall
>>> bei einem Benutzer des Plugins ein, dann speichere ich die
>>> Fehlermeldung in einem Errorlog auf dem Server. Und werde so darüber
>>> informiert.
>> Das ist doch Käse. Überprüfe, ob das Elementobjekt existiert, und
>> sende meinetwegen die Fehlermeldung, wenn es (das Objekt) das
>> explizit nicht tut.
>
> Ok, das wäre eine Möglichkeit.
> Ich verstehe aber noch nicht so ganz -abgesehen von dem Argument
> "sauberer code"- wo genau hierin ein Vorteil liegen soll.
Der Vorteil ist beispielsweise, dass Du reale Fehler von Markup-basierten
"Fehlern" unterscheiden kannst.
> Zu den Nachteilen zählt jedenfalls die schlechtere Performance.
Die ist vernachlässigbar klein.
> Dazu müsste ich ich den FehlerStatus in einer Variable speichern und vor
> jedem Funktionsaufruf prüfen, denn im Fehlerfalle soll das script ja
> nichts mehr tun.
Es genügt, die verwendeten Methoden und ihr Ergebnis zu testen. Wird die
Methode für ein Objekt mehrfach verwendet, reicht es, die Existenz einmal
zu testen. Das Ergebnis muss latür jedes Mal getestet werden, denn es
gibt verschiedene Gründe, weshalb ein (DOM-)Feature nicht wie erwartet
funktioniert.
> Und ich hätte Verschachtelungen mit einer Tiefe von bis zu 10 oder 20
> Ebenen, wenn ich jedes einzelne objekt vor Verwendung prüfe.
Nein, hättest Du wahrscheinlich nicht.
> Damit das wieder "sauber" wird muß ich entweder auf
> Verschachtelungen verzichten und vermehrt mit Fehlerflags arbeiten, oder
> alles in viele kleine Funktionen auslagern, was mit wieder zusätzliche
> Performanceeinbußen bringt.
Non sequitur.
> Ok, ich könnte bei jeder Überprüfung im Fehlerfall gleich eine
> entsprechende Info über den Fehlerort/Grund loggen, aber m.E. überwiegen
> dennoch die Nachteile. Try..Catch löst das Problem mit ein paar wenigen
> Zeilen.
Und liefert im Wesentlichen den Fehler "Es ist ein Fehler aufgetreten".
Toll.
>>> Das eigentliche script wird durch das Plugin vom Server geladen (d.h.
>>> mittels createElement wird ein Script-Element mit entsprechendem
>>> src-Attribut in das Dokument eingefügt).
>>
>> Das funktioniert schon nicht zuverlässig. Das Element wird vermutlich
>> eingefügt, ob aber auch der referenzierte Script-Code ausgeführt wird,
>> steht auf einem anderen Blatt.
>
> Bisher hat es bei allen Tests funktioniert.
Mit welchen Browsern hast Du getestet? Mit welchen Versionen/Service Packs?
Mit welchen Betriebssystemen? Auf welchen Plattformen?
> Daß es bei manchen Browsern (wie Opera?) nicht funktioniert, braucht
> mich ja nicht interessieren, weil bei denen das Plugin eh nicht läuft.
> Sogesehen erhält jeder unterstützte Browser eine "Maßanfertigung". Wenn
> ich für alle Fälle das selbe Script verwenden kann, wäre das natürlich
> von Vorteil.
Es ist nicht nötig und daher Unfug, jedem Browser eine Maßanfertigung zu
liefern. Tatsächlich sollte jedes verbreitete DOM bedient werden, sofern
es zutreffen kann. Das sind hier derzeit W3C DOM Level 2 und IE4-DOM.
> Zudem: Wenn es bei einem Browser nicht funktioniern sollte, so ist das
> DOM "defekt".
Nein. Denn _nirgendwo_ ist dokumentiert, wie und ob nachträglich
eingefügte script-Elemente _verarbeitet_ werden sollen. D.h. es
ist nicht dokumentiert, dass die Script-Engine mit dem Parsen
des Inhalts dieses Elements betraut wird.
> Falls es nur deshalb nicht klappt weil der Benutzer JS
> deaktiviert hat, reagiert das Plugin in adäquater Weise.
Gut.
>>> Ich brauche also nur das Script (auf dem Server) ändern und die
>>> Plugin-Benutzer profitieren davon.
>>>
>>> Nur muß ich eben von der Notwendigkeit einer Änderung erfahren.
>>
>> Weshalb? Entweder das Script ist universell, dann spielt es keine
>> Rolle, ob ein Nutzer eine andere ID benutzt, da das dann _sein_
>> Fehler ist; eine Änderung fände zu Lasten aller anderen Benutzer
>> statt.
>>
>> Oder es ist nicht universell, dann ist es erst recht erforderlich,
>> dass der Benutzer die Benennung einhält, die Du vorgibst. Für den
>> unwahrscheinlichen Fall, dass er das nicht tut, kannst Du Dich latür
>> benachrichtigen lassen. Dann reicht dafür aber auch ein Feature-Test
>> aus, Du musst keinen Fehler provozieren.
>
> Beides trifft nicht zu, stattdessen liegt Fall 3 vor:
> Benutzer != Seitenbetreiber != ich
Was soll dann die Fehlerberichtsfunktion basierend auf fehlenden
Elementen im Markup? Weder der Benutzer noch Du wirst den Anbieter
veranlassen können, sein Markup zu ändern, da er ja nicht wirklich
betroffen ist.
>>> ok, ich gebe ja zu, daß ich mich primär auf das IE-DOM konzentriert
>>> habe, weil hier die meisten der von mir benötigten Funktionen bereits
>>> existieren. Und bei Gecko-basierten Browsern kann man eben schön die
>>> "fehlenden" Funktionen ergänzen.
>> Man braucht es doch aber dort gar nicht mehr.
>
> ???
Nur Gecko-basierte Browser stellen W3C-DOM-Interfaces wie HTMLDocument als
Konstruktoren bereit. Sie implementieren aber auch W3C DOM Level 2 HTML,
welches Document::getElementById() bereitstellt.
>> Umgekehrt wird ein Schuh draus: Für das IE-DOM, d.h. IE 4.x,
>
> ehm - vielleicht ein Mißverständnis meinerseits:
> Ich bezog mich schon auf die vom IE > 5.x unterstützten Methoden.
Internet Explorer (für Windows) ab Version 5.0 unterstützt W3C DOM Level 2
hinreichend für Deine Zwecke.
> Wie sich das DOM nennt weiß ich nicht, ich schrieb halt IE-DOM und
> meine das lt. MS(DN)-Specs dokumentierte Objektmodell.
Deshalb braucht man für IE/Win > 4.x keine Sonderlösung zu fahren.
>> muss man Methoden entwickeln, die ungefähr das tun, was
>> DOM-Level-2-Methoden tun, indem man dort vorhandenen proprietären
>> aufruft.
>>
>> Vgl. <URL:http://PointedEars.de/dhtml.js>
>
> 404, findet sich aber unter /scripts/
Ja, sorry, das meinte ich.
>> Und dann gibt es noch das KHTML-DOM (Konqueror, Safari), auch das
>> unterstützt Document::getElementById(). Andere weitverbreitete
>> DOMs als das IE-DOM, das Gecko-DOM, das Opera-DOM und das KHTML-DOM
>> gibt es derzeit nicht (im NN4-DOM, welches nur noch wenig verbreitet
>> ist, gibt es keine verlässliche Möglichkeit des "Script-Nachladens").
>> Zukünftige DOMs werden sich an einem dieser Quasi-Standards oder
>> eben am Standard W3C-DOM Level 2+ orientieren müssen, damit der
>> entsprechende UA konkurrenzfähig ist.
>>
>> Siehe news:2235001.F5vJG4v19I@xxxxxxxxxxxxxx
>
> Interessant.
> Gibt es denn eine vernünftige Javascript-referenz?
Das ist keine Ja-oder-Nein-Frage und auch keine, die sich in einem Satz
beantworten lässt (wer das dennoch tut, hat schlicht keine Ahnung).
Zunächst mal muss man Folgendes verstehen:
0. Javascript gibt es nicht.
1. ECMAScript Edition 1 basiert auf JavaScript 1.1 und JScript 1.0.
_JavaScript_ seit ist Netscapes ECMAScript-Implementation; in NN, NES
und inzwischen Mozilla/5.0 (d.h. Gecko-basierten Browsern), wobei
Brendan Eich, der Erfinder von JavaScript, jetzt bei der Mozilla
Foundation arbeitet (seit der Schliessung der Netscape-Browser-
abteilung durch AOHell/TW).
<URL:http://developer.mozilla.org/en/docs/JavaScript>
_JScript_ ist Microsofts ECMAScript-Implementation; in IE und
IIS (per ASP[.NET]).
<URL:http://msdn.microsoft.com/library/en-us/script56/html/1e9b3876-3d38-4fd8-8596-1bbfe2330aa9.asp>
<URL:http://msdn.microsoft.com/library/en-us/jscript7/html/jsoriJScript.asp>
Opera implementiert im wesentlichen ECMAScript ohne Erweiterungen.
<URL:http://opera.com/docs/specs/#ecmascript>
KJS ist anscheinend als Implementation von ECMAScript und JScript
konzipiert: <URL:http://developer.kde.org/documentation/library/3.3-api/>
2. JavaScript ist eine objektorientierte Programmiersprache.
Bis JavaScript 1.3 (NN4) war das (NN4-)DOM Bestandteil der Sprache.
JScript ist eine objektorientierte Programmiersprache.
AFAIK war das IE-DOM niemals Bestandteil dieser Sprache.
DOM ist das Document Object Model eines UAs. Auf dieses kann mittels
Programmiersprachen, optimal objektorientierten, zugegriffen werden.
Der Web-Standard für das DOM ist das W3C-DOM. Dieses wird von
verschiedenen UA-DOMs implementiert, d.h. das vorhandene proprietäre
DOM wird mit Implementationen von W3C-DOM-Interfaces erweitert.
> Was ist ECMAScript, über das hier häufig diskutiert wird?
ECMAScript (ECMA-262) ist der Standard für ECMAScript-Implementationen.
Es definiert die Grundlage dieser Sprachen und die Möglichkeit der
Erweiterbarkeit für konforme Implementationen.
<URL:http://ecma-international.org/publications/standards/Ecma-262.htm>
<URL:http://mozilla.org/js/language/>
Aus einem mir unverständlichen Grund werden ECMAScript und JavaScript
oft gleichgesetzt (etwa so: "JavaScript (ECMAScript)"), was fhcsal ist.
> Warum schlägt man eigentlich den Weg ein, unvollständig oder falsch
> imlementierte DOMs zu unterstützen, indem man auf Funktionen prüft, die
> lt. DOM eigentlich implementiert sein sollten? Hat man nichts von den
> Problemen in der HTML-Entstehungsgeschichte gelernt?
Weil jeder UA andere Funktionen hat und Abwärtskompatibilität bei
UA-Versionen nicht unwichtig ist, ergeben sich zwangsläufig Unterschiede
zwischen den implementierten DOMs verschiedener UAs und UA-Versionen.
Dies gilt vor allem für Web-Browser.
> Oder anders gefragt:
> Wenn mein Plugin z.B. ab Firefox 0.9.3 laufen soll, warum könnte man
> nicht einfach prüfen, ob es sich tatsächlich um das Gecko-DOM handelt,
> um dann ggf. abhängig von DOM-Version evtl. fehlende aber benutzte
> Routinen nachzubilden..?
Dazu müsstest Du auf proprietäre DOM-Features prüfen, die aufgrund
ihrer Natur nicht zuverlässig sind. Schon in der nächsten Version
könnte das Feature nicht oder anders implementiert sein und es wird
das fhcsale DOM erkannt. Bei standardisierten Features kann man sich
solche Änderungen nicht so einfach erlauben, weil das Inkompatibilität
zu Browsern bedeuten würde, die den Standard weiterhin oder dann wie
spezifiziert implementieren.
> Falls es keine Möglichkeit gibt, DOM-'provider' und -Version
> abzufragen, dann ist das doch schon wieder eine Fehlkonstruktion?
Worauf beziehst Du Dich damit?
Übrigens gibt es eine standardkonforme Möglichkeit, das unterstützte
DOM-Level abzufragen:
<URL:http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-102161490>
`DOMImplementation' ist im Gecko-DOM, IE-DOM und Opera 7+-DOM (getestet
in Opera 8.5/Debian Linux) als `document.implementation' implementiert:
<URL:http://mozref.com/reference/objects/DOMImplementation>
<URL:http://xulplanet.com/references/objref/DOMImplementation.html>
<URL:http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/implementation.asp>
(Microsoft verweist hier unzulässig auf ein Working Draft von
W3C-DOM Level 1. DOMImplementation ist aber auch Bestandteil
der W3C-DOM Level 1-REC.)
<URL:http://www.opera.com/docs/specs/opera6/js/dom/>
<URL:http://www.opera.com/docs/specs/opera7/js/dom/>
<URL:http://www.opera.com/docs/specs/js/dom/>
Der entsprechende Test wäre also dort wahrscheinlich
function isMethod(s)
{
return (s == "function" || s == "object");
}
if (document.implementation
&& isMethod(typeof document.implementation.hasFeature)
&& document.implementation.hasFeature("HTML", "2.0"))
{
// ...
}
Voraussetzung ist jedoch, dass diese Möglichkeit sowie _alle_ Teile des
entsprechenden DOM-Levels auch standardkonform implementiert sind, daher
ist der Test IMHO nicht zuverlässig.
>>> Daneben habe ich u.a., insertAdjacentHTML,
>>> [...]
>>> Ich nehme an, daß diese im Gegensatz zu getElementById nicht
>>> überall definiert sind?
>> Richtig, da zum Teil proprietär. Was nicht heisst, dass man die
>> definieren muss.
>
> Ja, erschien mir aber im ersten Moment ganz praktisch.
> Man kann natürlich eigene Funktionen schreiben, z.B. getInnerText(node).
> Allerdinsg glaube ich, daß die bereits im DOM implementierten Funktionen
> schneller abgearbeitet werden, weshalb ich beim IE gerne .innerText
> benutze, und die langsamere eigene Funktion nur wenn wirklich notwendig.
Da es offenbar ausser in IE nur in Firefox laufen soll: Inwiefern
ist .textContent langsamer oder unbequemer als .innerText?
Bei insertAdjacentHTML() kann ich verstehen, dass es eleganter
wirkt als .appendChild(document.createElement(...)) bzw.
..appendChild(document.createTextNode(...)). Ob es auch
schneller ist, ist eine andere Frage, denn sowohl die vorhandene
Implementation in IE als auch eine Emulation in z.B. Mozilla/5.0
erfordert zusätzlich Markup-Parsing; die Emulation wäre dann nicht
nur langsamer als das Original, sondern auch langsamer als die
verfügbare standardkonforme Alternative -- letzteres dürfte auch
für `innerHTML' gelten.
> Prototyping ist hierfür doch ideal?`
Wenn es unterstützt wird _und_ notwendig ist.
> id und className sind beim Firefox scheinbar nicht für alle Elemente
> implementiert,
Das verwundert nicht, sind doch diese Attribute in HTML nicht für jedes
Element definiert.
> daher hab ich das für HTMLElement nachdefiniert.
Kann man machen, man darf aber nicht damit rechnen, dass es auch überall
wie erwartet funktioniert. Immerhin bildet das DOM das Markup ab und
umgekehrt, und ein HTML-Parser sollte sich an HTML halten. Auch, aber
nicht nur, im Standards Compliance Mode.
> Es dürfen ja nicht alle tags diese Attribute enthalten (so gesehen ist
> das Verhalten nachvollziehbar), doch interessiert das die Webdesigner oft
> nicht.
Ja, es gibt viel Inkompetenz da draussen.
Übrigens: Elemente haben Attribute und bestehen aus Tags (Start- und
End-Tag, können jeweils optional sein) sowie Inhalt (kann leer, d.h.
nicht vorhanden, sein).
>>>>> if (typeof(myScript) == 'undefined') {
>>>>> var myScript = new objMyScript();
>>>>> }
>>> In meinem Fall gibt es nur zwei Situationen:
>>> 1. Das Objekt wurde bereits von mir erstellt
>> Was auf unsaubere Programmierung hindeutet.
>
> Wieso? Seit wann ist es unsauber, Objekte zu erstellen, bzw. darauf
> zu prüfen, ob das objekt bereits erstellt wurde?
Entweder weisst Du, dass Du das Objekt weiter "oben" im Quelltext schon
erzeugt hast bzw. der Wert der Referenz != `undefined' ist (somit der
Typ auch != "undefined"), dann ist ein Test überflüssig. Oder Du
weisst es nicht oder es interessiert Dich nicht, dann brauchst/solltest
Du auch nicht testen. Sobald ein Objekt nicht mehr referenziert wird
(das passierte, falls es "oben" schon erzeugt worden wäre; die Referenz
zeigte dann auf ein anderes, neues Objekt), räumt es der Garbage Collector
weg.
> Unsauber -weil ein notwendiger workaraound- ist höchstens, daß ich beim
> IE ein script zur Ausführung bringe, auch bzw. genau dann wenn der
> Benutzer JS deaktiviert hat. (keine Sorge, die Sicherheit des IE wird
> hierbei nicht verletzt).
Das ist ein Widerspruch.
>>> Der 3. Fall, daß das objekt existiert, aber _nicht_ von mir
>>> erstellt wurde, kann im Grunde ausgeschlossen werden.
>>
>> Also bei sauberer Programmierung schlicht
>>
>> var myScript = new objMyScript();
>
> s.o.
> Bei "HTML-seitigem" JS wäre das klar, aber die Sache liegt komplexer.
Das verstehe ich nicht.
> Prioritäten:
>
> 1. Performance, jede ms zählt.
Was sollen dann die Deinen Aussagen nach doch eigentlich überflüssigen
_Variablen_tests?
> [...]
> 2. Stabilität
>
> egal was im skript passiert, das HTML-Dokument und dort
> eingebundener JS-Code bzgl. Events muß weiterhin funktionieren.
ACK
> 3. Ladezeiten/traffic
>
> Das durch das erste Skript geladene zweite Skript soll so klein
> wie möglich sein,
Wenn es denn geladen wird. Aus welchem Grund das zweite Script nicht ins
erste integriert werden kann (und damit immer funktioniert), verstehe ich
auch nicht.
> da das im Gegensatz zum ersten nicht gecached werden darf/kann.
Das kannst Du gar nicht wissen. Z.B. gibt es Browser mit Speichercaches.
>>> erscheint mir jedoch effektiver.
>> Das täuscht. Eine nachträgliche Fehlerbehandlung ist deutlich teurer,
>> sowohl was die Laufzeit als auch den Entwicklungsaufwand betrifft.
>
> Eine nachträgliche Fehler_behandlung_ wird es nicht geben.
Du willst also Deine Fehler bei der Programmierung kaschieren.
Denn es ist ein Fehler, Referenzen nicht vor der Verwendung zu
testen (um einen ReferenceError zu vermeiden).
Wohlgemerkt: Ich bin _nicht_ gegen nachträgliche Fehlerbehandlung;
sie sollte aber nur dann eingesetzt werden, wenn Fehler abgefangen
werden sollen, die man nicht testen kann, d.h. die von Ralf erwähnten
_Ausnahmen_. Das trifft hier nicht zu.
>> Merke: Unsaubere Programmierung ist niemals effizienter als saubere.
>
> Ich sehe immer noch kein Argument dafür, warum die Verwendung von
> try..catch in meinem Fall unsauber sein sollte.
Du benutzt Deinen Aussagen nach Exception-Behandung nur dafür, dass man
als Benutzer nicht merkt, dass Du Fehler gemacht hast. Würdest Du auf
den Zielplattformen und vor allem zur Laufzeit testen, entstünden gar
keine Fehler, die man vor dem Benutzer verstecken müsste. Vielmehr
könnte man ihm genau mitteilen, weshalb es nicht so funktioniert, wie
es funktionieren soll.
> Hauptproblem ist eben, daß ich möglichst einfach bei einem Fehler das
> komplette script verlassen kann, ohne jede Anweisung in irgendein
> if-kontrukt stecken zu müssen.
Es ist nicht mal garantiert, dass ein DOM-Feature eine Exception
wirft oder einen error-Event auslöst (insbesondere Letzteres nicht),
insofern ist ein rein fehlerbehandelnder Ansatz auch und gerade für
DOM-Zugriffe ungeeignet.
PointedEars
.
- Follow-Ups:
- Re: Fehlerbehandlung
- From: Andreas Born
- Re: Fehlerbehandlung
- References:
- Fehlerbehandlung
- From: Andreas Born
- Re: Fehlerbehandlung
- From: Thomas 'PointedEars' Lahn
- Re: Fehlerbehandlung
- From: Andreas Born
- Re: Fehlerbehandlung
- From: Thomas 'PointedEars' Lahn
- Re: Fehlerbehandlung
- From: Andreas Born
- Re: Fehlerbehandlung
- From: Thomas 'PointedEars' Lahn
- Re: Fehlerbehandlung
- From: Andreas Born
- Fehlerbehandlung
- Prev by Date: Re: Fehlerbehandlung
- Next by Date: Re: Fehlerbehandlung
- Previous by thread: Re: Fehlerbehandlung
- Next by thread: Re: Fehlerbehandlung
- Index(es):
Relevant Pages
|