ja, wenn daten auftauchen die so nicht erwartet werden wird eine Exception ausgelöst.Engywuck schrieb:Wie sieht das eigentlich aus mit Size, Terrain und Difficulty für Addis? Werfen die jetzt alle eine IllegalArgumentException ?
also wenn dann bitte "last man standing". du hast nicht zufällig debug output angeschaltet? es gab eine menge stellen, die frühe mit einem catch (Exception e) {} einfach alles weggebügelt haben und nun bekommt man mit dem debugschalter doch tatsächlich eine meldung.Engywuck schrieb:Ich versuche hier gerade, ein V1-Profil einzulesen, und mir fliegen die Exceptions um die Ohren wie Bruce Willis die Pistolenkugeln in Die Hard.
es behauptet niemand dass alles rund ist und ich freue mich über rückmeldungen von testern. wenn die nun noch schreiben würden wie sie die fehler ausgelöst haben statt sie nur aufzulisten ...Engywuck schrieb:Ich verstehe auch nicht ganz, wieso man Variablen explizit auf Werte setzt, die dann an anderer Stelle Exceptions auslösen....
Mir scheint das noch alles andere als rund zu sein.
mit der meldung kann ich doch etwas anfangen. da werde ich mal nachsehenEngywuck schrieb:Es sieht so aus, als ob die Konstante CW_DT_ADDITIONAL nur beim Spidern benutzt wird. Beim Einlesen aus einem V1-Format wird dagegen eine Angabe wie terrain = "", wie sie für Addis typisch ist, als ungültig erachtet und mit dem Wert CW_DT_ERROR versehen und so abgespeichert. Womit jetzt in Version 3 alle Addis vermutlich erstmal eine ungültige Angabe zu terrain und size haben. Nicht so toll...
dann sollte ich mir vermutlich auch den oc xml impoter nochmal ansehen. danke für den hinweis.Engywuck schrieb:P.S.: Das aktualisieren von OC-Virtuals führt immer zu incomplete-Caches.
die habe ich doch dann wohl glatt übersehenEngywuck schrieb:Ach ja: Custom Waypoints bekommen auch immer den Stempel "ungültig" für Terrain und Size.
Klar, hab ich. Deshalb ist es mir ja auch aufgefallen: Vor Deinen Änderungen war an der Front alles ruhig, jetzt kommen die ganzen Exceptions....greiol schrieb:du hast nicht zufällig debug output angeschaltet? es gab eine menge stellen, die frühe mit einem catch (Exception e) {} einfach alles weggebügelt haben und nun bekommt man mit dem debugschalter doch tatsächlich eine meldung.
Dies bezog sich auf folgendes: Du setzt die Size- und Terrain-Werte auf eine Ungültig-Konstante, wenn ein Wert geparst wird, mit dem Du nichts anfangen kannst. Das ist ja in Ordnung. Die Funktionen, die dann aus den internen Daten wieder extern darstellbare machen (String, Bilder...), werfen aber wiederum eine Exception, wenn sie auf den von Dir selbst gesetzten Error-Wert stoßen, und das ist eigentlich nicht richtig. Exceptions sollen dann verwendet werden, um unerwartete Werte abzufangen - aber ein Wert, den man selber gesetzt hat, kann man guten Gewissens nicht als unerwartet bezeichnen. Vielleicht ungewollt, aber das ist eine ganz andere Baustelle.greiol schrieb:es behauptet niemand dass alles rund ist und ich freue mich über rückmeldungen von testern. wenn die nun noch schreiben würden wie sie die fehler ausgelöst haben statt sie nur aufzulisten ...Engywuck schrieb:Ich verstehe auch nicht ganz, wieso man Variablen explizit auf Werte setzt, die dann an anderer Stelle Exceptions auslösen....
- wer debug output anschaltet darf sich nicht wundern wenn er auch welchen bekommtEngywuck schrieb:Klar, hab ich. Deshalb ist es mir ja auch aufgefallen: Vor Deinen Änderungen war an der Front alles ruhig, jetzt kommen die ganzen Exceptions....greiol schrieb:du hast nicht zufällig debug output angeschaltet? es gab eine menge stellen, die frühe mit einem catch (Exception e) {} einfach alles weggebügelt haben und nun bekommt man mit dem debugschalter doch tatsächlich eine meldung.
ich kann die verwunderung verstehen, werde aber versuchen zu erklären was da warum geschieht.Engywuck schrieb:Dies bezog sich auf folgendes: Du setzt die Size- und Terrain-Werte auf eine Ungültig-Konstante, wenn ein Wert geparst wird, mit dem Du nichts anfangen kannst. Das ist ja in Ordnung. Die Funktionen, die dann aus den internen Daten wieder extern darstellbare machen (String, Bilder...), werfen aber wiederum eine Exception, wenn sie auf den von Dir selbst gesetzten Error-Wert stoßen, und das ist eigentlich nicht richtig. Exceptions sollen dann verwendet werden, um unerwartete Werte abzufangen - aber ein Wert, den man selber gesetzt hat, kann man guten Gewissens nicht als unerwartet bezeichnen. Vielleicht ungewollt, aber das ist eine ganz andere Baustelle.greiol schrieb:es behauptet niemand dass alles rund ist und ich freue mich über rückmeldungen von testern. wenn die nun noch schreiben würden wie sie die fehler ausgelöst haben statt sie nur aufzulisten ...Engywuck schrieb:Ich verstehe auch nicht ganz, wieso man Variablen explizit auf Werte setzt, die dann an anderer Stelle Exceptions auslösen....
Ich beschwere mich ja nicht darüber, dass ich welchen bekomme - aber die Tatsache, dass ich vor der Umstellung keinen bekomme und nach der Umstellung jede Menge, lässt mich stutzig werden. Schließlich hat mein Profil ja auch vor der Umstellung super funktioniert und kann deshalb nicht komplett fehlerhaft sein.greiol schrieb:- wer debug output anschaltet darf sich nicht wundern wenn er auch welchen bekommt![]()
Ich fände eine zweite Log-Methode schön, die nur dann zuschlägt, wenn debug=true.greiol schrieb:- sollten exceptions ausgegeben werden ohne dass ein if (Global.getPref().debug) davor steht würde ich das allerdings auch als bug ansehen
Ok.greiol schrieb:- eingaben sind grundsätzlich nicht vertrauenswürdig, egal woher sie stammen (das betrifft natürlich erst mal die importer)
Anderer Meinung.greiol schrieb:- der cacheholder selber ist streng genommen auch ein importer
Ok.greiol schrieb:- würde ich die daten im cacheholder aber auch bei jedem lesen von v3 vollständig validieren, wäre der gesamte performance vorteil der format umstellung dahin
Das mag sein. Aus performance- und übersichtlichkeitsgründen würde ich mich allerdings darauf verlassen. Es ist schließlich nur der Cachewolf, und kein Kernkraftsicherungsprogramm. Der Cachewolf schreibt richtige Daten, und wenn andere Leute falsche Daten reinschreiben, sollte das nicht unser Bier sein und wir unseren Code vollstopfen, um anderer Leute Fehler auszubauen. Meiner Meinung nach ist die index.xml "unsere" Datei und wir sollten uns darauf verlassen können, das die Daten unseren Erwartungen entsprechen.greiol schrieb:- dadurch enthält das profil nicht vertrauenswürdige daten (wer weiss schon wie der anwender sein index file erzeugt hat ...)
Bitte immer immer berücksichtigen: Wir haben es hier nicht mit Java zu tun (auch wenn es so aussieht), sondern mit Ewe! Und das Erzeugen von Exceptions ist in "normalen" Programmiersprachen schon teuer, unter Ewe vermutlich erst recht. Daher sollte man Exceptions auf keinen Fall zur Steuerung der Programmlogik verwenden (das ist schon im Normalfall schlechter Stil).greiol schrieb:- also gibt es als "zweite verteidigungslinie" die validierung vor der anzeige, insbesondere im details panel, hier wird dann geprüft ob ich mit den daten die im cache stehen etwas anfangen kann und ggf. eingegriffen, da der overhead bei einer einzelnen anzeige eben deutlich geringer ist als beim einlesen des profils zuzuschlagen
- ziel ist es nicht "irgendwas anzeigen", sondern über die prüfungen zu "das richtige anzeigen" zu gelangen
don't shoot the messenger.Engywuck schrieb:Ich beschwere mich ja nicht darüber, dass ich welchen bekomme - aber die Tatsache, dass ich vor der Umstellung keinen bekomme und nach der Umstellung jede Menge, lässt mich stutzig werden. Schließlich hat mein Profil ja auch vor der Umstellung super funktioniert und kann deshalb nicht komplett fehlerhaft sein.greiol schrieb:- wer debug output anschaltet darf sich nicht wundern wenn er auch welchen bekommt![]()
Engywuck schrieb:Ich fände eine zweite Log-Methode schön, die nur dann zuschlägt, wenn debug=true.greiol schrieb:- sollten exceptions ausgegeben werden ohne dass ein if (Global.getPref().debug) davor steht würde ich das allerdings auch als bug ansehen
das ist sicherlich auch eine methode. im moment geht es mir aber vor allem darum herauszufinden welche fehler auftreten (können) und diese möglichst weit vorne abzufangen. das kann ich aber nicht wenn ich sie einfach unter den tisch fallen lasse. genau aus diesem grund brauche ich auch informationen welche eingabedaten die probleme auslösen um vielleicht den migrationsprozess besser gestalten zu können. auch wenn cw keine kraftwerkssteuerung ist, sollten wir doch nicht einfach die augen verschliessen und so tun als wäre alles gut.Engywuck schrieb:Hier könnte man zur Sicherheit eine Methode unter "Verwalten" einbauen, die die Daten des Profils prüft.
ich möchte die exceptions auch nicht werfen um der exceptions willen, sondern um herauszufinden wo es im aktuellen datenbestand / migrationsprozess probleme gibt. der normalfall sollte natürlich sein, dass keine exception geworfen wird. eine exception die gar nicht erst geworfen wird, weil wir schon viel früher einen integeren bestand haben, kostet auch keine performance. egal in welcher sprache. richtig schlechter stil ist es fehler zu haben und nicht zu erkennen.Engywuck schrieb:Bitte immer immer berücksichtigen: Wir haben es hier nicht mit Java zu tun (auch wenn es so aussieht), sondern mit Ewe! Und das Erzeugen von Exceptions ist in "normalen" Programmiersprachen schon teuer, unter Ewe vermutlich erst recht. Daher sollte man Exceptions auf keinen Fall zur Steuerung der Programmlogik verwenden (das ist schon im Normalfall schlechter Stil).
Dann müssten aber schon sehr viele Fehler vorhanden gewesen sein... (Aber Du hast ja jetzt schon einiges gemacht. Da muss ich heute Abend mal gucken, wie viel von den Exceptions jetzt überhaupt noch übrig ist.)greiol schrieb:die tatsache, dass die alten versionen keine fehlermeldungen ausgeben, bedeutet nicht, dass keine fehler vorhanden sind.
Genau. Ich würde es gerne in eine eigene Methode kapseln. Also neben log noch debuglog, oder so. Information-hiding ist das Zauberwort: Den Verwender der Methode sollte es nicht interessieren, mit welchem Mechanismus abgeprüft wird, ob wir im Debug-Modus sind oder nicht. Er gibt an, ob die Logausgabe für den Debug-Zweck gedacht ist - das ermitteln, ob ein Debug-Zustand vorhanden ist oder nicht, macht die Methode selber.greiol schrieb:hmm. ich schrieb doch, dass die fehlermeldung nur ausgegeben wird wenn debug auf true steht. ich bin jetzt verwirrt
Aaaah, ok. Derzeit ist also noch Code drin, den Du eher zum debuggen benötigst, damit der Wolf geschwätziger ob der Fehler ist? Wenn das so ist, bin ich einverstanden.greiol schrieb:im moment geht es mir aber vor allem darum herauszufinden welche fehler auftreten (können) und diese möglichst weit vorne abzufangen.
[...]
nur mal zur erinnerung: wir sind im entwicklungszweig und suchen fehler, wir sind noch nicht in der nächsten stable
private void long2byteFields(long value) {
setHard(byteFromLong(value, 1));
setTerrain(byteFromLong(value, 2));
setType(byteFromLong(value, 3));
setCacheSize(byteFromLong(value, 4));
setNoFindLogs((byteFromLong(value, 5)));
if (( getHard() == -1 || getTerrain() == -1 || getCacheSize() == -1 ) || getType() == -1 ) {
setIncomplete(true);
}
}
das kann man so oder so betrachten. einen kritischen zustand sollte die methode auf alle fälle ausgeben. eine debug information imho nur auf explizite anforderung. persönlich würde ich zum loggen lieber log4j nehmen da man das logging noch granularer lösen könnte, aber es läuft ohnehin nicht mit ewe und wäre ohnehin vermutlich auf einem pocketpc zu inperformant.Engywuck schrieb:Genau. Ich würde es gerne in eine eigene Methode kapseln. Also neben log noch debuglog, oder so. Information-hiding ist das Zauberwort: Den Verwender der Methode sollte es nicht interessieren, mit welchem Mechanismus abgeprüft wird, ob wir im Debug-Modus sind oder nicht. Er gibt an, ob die Logausgabe für den Debug-Zweck gedacht ist - das ermitteln, ob ein Debug-Zustand vorhanden ist oder nicht, macht die Methode selber.greiol schrieb:hmm. ich schrieb doch, dass die fehlermeldung nur ausgegeben wird wenn debug auf true steht. ich bin jetzt verwirrt
ziel ist es schon nach der migration oder nach dem spidern einen zustand zu haben in dem 99+.x% aller probleme bereits abgefangen und gelöst wurden. es kann dann zwar immer noch eine exception auftreten, aber ab und an sollten wir das abkönnen. derezit gehe ich noch davon aus, dass ein try {} catch {} besser sein dürfte, als ein if (wertistok) { setzewert } else { setzefehler } bzw. if (wertistok) { zeigewert } else { zeigewasanderes }. aber das könnte man natürlich auch mal messen.Engywuck schrieb:Aaaah, ok. Derzeit ist also noch Code drin, den Du eher zum debuggen benötigst, damit der Wolf geschwätziger ob der Fehler ist? Wenn das so ist, bin ich einverstanden.greiol schrieb:im moment geht es mir aber vor allem darum herauszufinden welche fehler auftreten (können) und diese möglichst weit vorne abzufangen.
[...]
nur mal zur erinnerung: wir sind im entwicklungszweig und suchen fehler, wir sind noch nicht in der nächsten stable
ich würde gerne so viel wie möglich von beidem haben wollen. dieses ziel zu erreichen ist die aktuelle herausforderung.Engywuck schrieb:Ansonsten aber würde ich dafür plädieren, eher auf Performance als auf lupenrein saubere Daten zu achten.
korrekt. die perfekte stelle das z.b. abzufangen wäre nach dem manuellen anlegen eines tradis direkt diese "fehler" abzufangen und auch auf incomplete zu erkennen. das würde auch meinem ansinnen die eingangskanäle zur prüfung zu nutzen am nächsten kommen. dann kann der user sich überlegen ob er mit der warnung leben möchte oder nicht. da der teil des codes leider noch fehlt bekommt er die warnung (noch) auf einem anderen weg.Engywuck schrieb:Wenn jemand einen Tradi anlegt und nicht aktualisiert, hat dieser zwar keine Angaben zur Größe, aber damit würde ich leben, wenn ich stattdessen darauf verzichten kann, für jeden Cache beim Einlesen zu prüfen, ob denn die Werte für Größe, Schwierigkeit etc. wirklich richtig sind:Das letzte IF mag ok sein zum debuggen, in regulärer Produktivumgebung finde ich diesen Test jedoch höchst überflüssig: Der zu erwartende Gewinn an Datenreinheit steht in keinem Verhältnis zum zusätzlichen Aufwand, der jedes Mal beim Lesen des Profils geleistet werden muss.Code:private void long2byteFields(long value) { setHard(byteFromLong(value, 1)); setTerrain(byteFromLong(value, 2)); setType(byteFromLong(value, 3)); setCacheSize(byteFromLong(value, 4)); setNoFindLogs((byteFromLong(value, 5))); if (( getHard() == -1 || getTerrain() == -1 || getCacheSize() == -1 ) || getType() == -1 ) { setIncomplete(true); } }
Da das eine eine einfache Abfrage ist, das andere aber ein (mehr oder weniger komplexes) Objekt erzeugt, nehme ich schwer an, dass das Erzeugen des Exception-Objektes auf jeden Fall die langsamere Variante ist. Es sei denn, man hat sehr viele oder teure Vergleiche... Siehe auch hier: http://tinyurl.com/2p6jd9 (ab "When should I use exceptions?")greiol schrieb:Derezit gehe ich noch davon aus, dass ein try {} catch {} besser sein dürfte, als ein if (wertistok) { setzewert } else { setzefehler } bzw. if (wertistok) { zeigewert } else { zeigewasanderes }. aber das könnte man natürlich auch mal messen.
mir ist klar, dass das erzeugen der exception teuer ist, aber die frage war in meinen augen:Engywuck schrieb:Da das eine eine einfache Abfrage ist, das andere aber ein (mehr oder weniger komplexes) Objekt erzeugt, nehme ich schwer an, dass das Erzeugen des Exception-Objektes auf jeden Fall die langsamere Variante ist. Es sei denn, man hat sehr viele oder teure Vergleiche... Siehe auch hier: http://tinyurl.com/2p6jd9 (ab "When should I use exceptions?")greiol schrieb:Derezit gehe ich noch davon aus, dass ein try {} catch {} besser sein dürfte, als ein if (wertistok) { setzewert } else { setzefehler } bzw. if (wertistok) { zeigewert } else { zeigewasanderes }. aber das könnte man natürlich auch mal messen.
es sieht so aus als hätten wir einen sieger. aber ich schau mir das versuchssetup nochmal angreiol schrieb:is es teurer in 100% aller fälle eine abfrage zu machen oder in x% (x <<< 100) eine exception zu erzeugen und abzufangen?
das dürfte auch bei alten versionen der fall sein. beim import wird nur das gefunden-flag ggf. korrigiert, während es sich auch sicht des importers beim status eher um ein notizfeld handelt. hmmmd0wnl0rd schrieb:Eine Sache, die mir noch in der 1846 aufgefallen ist:
habe ich einen Cache bereits gefunden, aber noch nicht geloggt (Status "Gefunden"), und bügele über mein Profil eine PQ drüber, so bleibt zwar der Status erhalten, aber die Farbgebung (grün vs. weiß) stimmt nicht mehr.
public static final boolean isValidTD(byte td) {
switch (td) {
case CW_DT_10: return true;
case CW_DT_15: return true;
case CW_DT_20: return true;
case CW_DT_25: return true;
case CW_DT_30: return true;
case CW_DT_35: return true;
case CW_DT_40: return true;
case CW_DT_45: return true;
case CW_DT_50: return true;
default: return false;
}
}
long max = 100000000;
String dummy;
byte terr;
ewe.util.Random rnd = new ewe.util.Random();
Vm.debug("check with if");
for (int fehler = 0 ; fehler <= 100; fehler=fehler+10) {
long start = new Time().getTime();
for (long j=0;j<max/100*(100-fehler);j++) {
terr = (byte) (rnd.nextInt(5)*10);
if (CacheTerrDiff.isValidTD(terr)) {
dummy = CacheTerrDiff.longDT(terr);
} else {
dummy = "";
}
}
for (long j=0;j<max/100*fehler;j++) {
terr = (byte) (rnd.nextInt(5)*-10);
if (CacheTerrDiff.isValidTD(terr)) {
dummy = CacheTerrDiff.longDT(terr);
} else {
dummy = "";
}
}
long end = new Time().getTime();
Vm.debug(fehler+"% fehler "+(end-start)+" ms");
}
Vm.debug("check with exception");
for (int fehler = 0 ; fehler <= 100; fehler=fehler+10) {
long start = new Time().getTime();
for (long j=0;j<max/100*(100-fehler);j++) {
terr = (byte) (rnd.nextInt(5)*10);
try {
dummy = CacheTerrDiff.longDT(terr);
} catch (IllegalArgumentException ex) {
dummy = "";
}
}
for (long j=0;j<max/100*fehler;j++) {
terr = (byte) (rnd.nextInt(5)*-10);
try {
dummy = CacheTerrDiff.longDT(terr);
} catch (IllegalArgumentException ex) {
dummy = "";
}
}
long end = new Time().getTime();
Vm.debug(fehler+"% fehler "+(end-start)+" ms");
}