Datumsformate

English

Es kommt recht oft vor, dass man bei einer Software ein Datum eingeben oder ablesen muss, oft gepaart mit einer Uhrzeit. Das kann ja so etwas erfreuliches wie ein Geburtstag sein oder aber ein Termin, den man lieber vergessen würde, weil er sowieso mal wieder viel zu früh kommt.

Bei Datums- und Uhrzeitformaten in Softwareapplikationen sollte man zwischen der internen Darstellung und der angezeigten Darstellung unterscheiden.
Wenn nicht irgendwelche Altlasten dem entgegenstehen, sollte man für eine interne Darstellung unbedingt ISO 8601 beachten, wenn nicht eine rein numerische oder binäre Darstellung zur Anwendung kommt. Wenn dem Altlasten entgegenstehen, ist das ein guter Anlass, diese Altlasten zu entsorgen.

ISO 8601 ist dieses Datumsformat: <Jahr>-<Monat>-<Tag>, z.B. 2012-11-16 (Varianten: 20121116 121116 12-11-16). Ich benutze das schon seit 20 Jahren praktisch überall, auch in Papierform. Mir gefällt daran, dass man bei dieser Schreibweise sofort weiß, was das Jahr, der Monat und der Tag ist. Diese Reihenfolge ist konsequent, denn man schreibt ja bei Zahlen auch die größeren Tausender vor den Hundertern, also sollten die Jahre zuerst stehen. Vor allem entfällt die Frage, ob jetzt der Monat oder der Tag zuerst kommt, was ja bei einem Datum wie 06/07/08 nie ganz klar ist. Wenn man eine Datei sortiert, in der solche Datumsangaben am Anfang der Zeilen stehen, stimmt die Sortierung. Ein weiterer Vorteil ist, dass dieses Format international (und damit neutral) ist, also nicht ein bestimmtes Land bevorzugt, so dass es auf die Dauer universell verstanden und akzeptiert werden wird. Inzwischen hat wohl jeder dieses Datumsformat oft genug gesehen, um es zu verstehen, weil immer mehr Webseiten das verwenden. Die Schreibweisen ohne Bindestrich und mit zweistelliger Jahreszahl finde ich übrigens nicht so brauchbar, weil sie für menschliche Leser nicht so schnell als Datum erkennbar und zerlegbar sind.

Für die Darstellung gegenüber dem Benutzer kann man in guten Applikationen die Präferenzen des Benutzers berücksichtigen. Es gibt eine kleine Unstimmigkeit, weil seit einigen Jahren in der Schweiz, Deutschland und Österreich das ISO 8601-Format das offizielle Standardformat für die Schreibweise eines Datums geworden ist. Ja, darüber freue ich mich. Aber diese Konvention verbreitet sich erst langsam, so dass übliche Locale-Einstellungen an Rechnern meistens noch auf das eigentlich veraltete Format Tag.Monat.Jahr gehen, immerhin mit einer vierstelligen Jahreszahl. So wie auf Wochenmärkten noch lange Pfund verwendet wurde, obwohl das kg schon seit Jahrzehnten galt. Ich würde mir wünschen, dass man als Anwender die Wahl hat, welches Datumsformat Software verwendet, insbesondere sollte ISO 8601 immer als eine Möglichkeit zur Verfügung stehen. Im Prinzip gibt es die Mechanismen, aber sie sind in vielerlei Hinsicht unzulänglich implementiert:
– Es ist mühsam, die Datumseinstellung zu ändern.
– Die meiste Software ignoriert diese Locale-Einstellungen
– Ein großer Teil der Software verwendet fälschlicherweise lokalisierte Datumsformate auch intern, verträgt also nur eine bestimmt oder einige bestimmte Einstellungen.

Ich empfehle hier, Software mal mit Einstellung für weit entfernte Sprache wie z.B. „Usbekisch“, „Chinesisch“ oder „Arabisch“ zu testen, um solche Abhängigkeiten zu erkennen, selbst wenn vorerst (und für „alle Zeiten“) nur eine deutschsprachige und eine englischsprachige Version zum Einsatz kommt.

Für Datumseingaben hat sich bewährt, dass man einen kleinen Kalender einblenden kann und sich dort im richtigen Monat den richtigen Tag auswählen kann. Aber auch hier sollte für denjenigen, der weiß, was er oder sie will, die Eingabe des Datums als Zeichenkette ohne Wechsel zur Mausbedienung möglich sein. Und das ISO-8601-Format sollte dabei immer verstanden werden, gerne zusätzlich auch das Format der aktuellen Locale-Einstellung, also z.B…

Auf jeden Fall muss aber das Datum nach der Eingabe in ein kanonisches Format übersetzt werden, um sicherzustellen, dass 2012-11-16 und 16.11.2012 gleich sind.

Ein Vorschlag zu den Posix-, Unix- und GNU-Tools: Das Programm „date“ ist seit Jahrzehnten in der Unix- und Linux-Welt etabliert und gibt leider ein Datum in einem obskuren US-Format aus. Ich glaube, dass man das nicht ändern kann, aber man sollte diesem Daten konsequent einen Begleiter „idate“ („international date“) geben, der ohne Parameter aufgerufen ein ISO-8601-Datumsformat verwendet, in diesem Fall zusammen mit der Zeit, also z.B.

$ idate
2012-11-16T17:33:12

Vielleicht schlage ich das den Entwicklern der core-Utils, zu denen die unter Linux übliche GNU-Variante von Date gehört, einmal vor. Immerhin versteht das GNU-date beim Setzen des Datum schon lange das ISO-Format. Bis dann kann man sich ganz gut behelfen, wenn man folgendes in die .bashrc einträgt:
export TIME_STYLE=long-iso
alias idate=’date „+%F %T“‚
Oder für tcsh in die .tcshrc:
setenv TIME_STYLE long-iso
alias idate ‚date „+%F %T“‚

Es gibt noch zwei Varianten für das Datumsformat, die weniger bekannt sind:
Datum mit Kalenderwoche und Wochentag (1=Montag, 7=Sonntag):
2012-W46-5
Und Jahr mit Tagesnummer (1..366):
2012-321

Zur Konvertierung in diese Formate:

$ date +%G-W%V-%u --date=2012-11-16
2012-W46-5
$ date +%Y-%j --date=2012-11-16
2012-321

Links

Share Button

Ruby 2.0 coming soon

This is a translation of Ruby 2.0 in Sicht

According to blade.nagaokaut.ac.jp Ruby 2.0 is almost finished. The new features are already known and a release 2.0.0-p0 is planned for Q1 2013.

Share Button

Ruby 2.0 in Sicht

Gemäß blade.nagaokaut.ac.jp ist Ruby 2.0 fast fertig. Man kennt die neuen Features schon und plant die Fertigstellung einer 2.0.0-p0 etwa im ersten Quartal 2013.

Share Button

Automatisierte Tests: Unit-Tests

Bekanntlich sind Softwaretests sehr teuer. Erst einmal verursacht das Testen selbst schon viel Aufwand. Und dann ist es zumindest bei guten Testern noch schlimmer, weil dabei eventuell Fehler gefunden werden, deren Behebung dann auch noch einmal teuer ist.

Nun ist leider das Ignorieren von Fehlern auch teuer, wenn die Software für einen ernsthaften Zweck eingesetzt wird. Man sagt, daß es umso teurer wird, je später der Fehler gefunden wird. Das fängt teilweise schon vor der eigentlichen Entwicklung des entsprechenden Features an. Wenn man das falsche entwickelt oder nur auf das falsche Konzept setzt, dann wird der Aufwand, daraus am Ende eine brauchbare Lösung zu machen, auch groß. Das trifft auch bei agilen Entwicklungsprozessen zu.

Ein anderes, gar nicht so seltenes Ärgernis sind Fehler, die schon einmal behoben waren und irgendwann wieder auftauchen. Wie kann das passieren? Es ist leider so, daß man beim Arbeiten Fehler macht, außer vielleicht Donald E. Knuth bei der Entwicklung von TeX, das ja praktisch komplett fehlerfrei ist.

Hier geht es um automatisierte Tests, insbesondere während der Entwicklung, also vor allem Unit-Tests. Eine ganz neue Erfindung sind diese automatisierten Unit-Tests nicht. Schon in den 90er Jahren war es bei in C geschriebener Unix- und Linux-Software recht üblich, daß man nach
./configure
make
ein
make check
oder
make test
aufrufen konnte. Das gibt es so übrigens auch heute noch. TeX und Metafont von Donald E. Knuth haben den sogenannten „Trip“/“Trap“-Test, der recht rabiat vorgehen soll, also versucht, die Software „gegen die Wand zu fahren“.

Aber heute werden diese Unit-Tests durch leicht verfügbare Frameworks, wie z.B. JUnit für Java unterstützt oder sind sogar schon Teil des normalen Lieferumfangs der Sprache, wie bei Ruby. Sinnvoll ist es bei Projekten, die die entsprechende Infrastruktur haben oder haben können, diese Tests regelmäßig automatisch auf den neuesten Stand aus dem Repository anzuwenden und Fehler zu melden. Vielleicht sogar mit einer roten Fußgängerampel beim Ausgang des Gebäudes, in dem die Entwickler der Software arbeiten? 😉

Andererseits macht es auch Spaß, wenn die Unit-Tests nach einer heftigen Änderung durchlaufen und alles grün ist, sogar die Fußgängerampel bei der Tür.

Nun ist die Frage, wie man dieses Mittel einsetzt, wie weit man automatisiserte Tests treibt und wann man sie entwickelt.

Erfahrungsgemäß werden Unit-Tests gerne bei der Zeitabschätzung eingeplant. Später wird dann die Zeit knapp und sie werden dann doch weggelassen. Es gibt eigentlich häufiger zu wenige als zu viele solcher Unit-Tests. Warum kann es überhaupt zu viele geben? Natürlich wird es irgendwann lästig, wenn das Ausführen der Unit-Tests mehrere Stunden dauert und wenn die Entwicklungsaufwände für die Tests unverhältnismäßig groß werden. Wobei ich in manchen Fällen 60% des Aufwands für die Tests und 40% für die eigentliche Funktionalität noch für angemessen halte. Das Problem ist aber, daß man einige Dinge nur mit sehr großem Aufwand automatisiert testen kann. Damit geht die Flexibilität verloren. Änderungen, die man mal eben macht, verhindern schnell mal, daß die Tests erfolgreich durchlaufen. Dann werden sie mal kurz „vorläufig“ deaktiviert, auskommentiert oder sogar ganz gelöscht, weil sie nicht mehr anwendbar sind, ohne daß die entsprechende neue Funktionalität Tests bekommt. Oder man erinnert sich, wie mühsam es war, die Tests zu schreiben und verzichtet dann deshalb auf eine an sich sinnvolle Änderung.

Daher würde ich empfehlen, automatisierte Tests für Funktionalitäten, die sich noch oft ändern, eher in einer späten Phase des Projekts zu schreiben. Dagegen lohnt es sich für Basisfunktionalitäten, von denen im Gesamtsystem viel abhängt und die sich wahrscheinlich kaum ändern, höchstens erweitert werden, sehr umfangreiche Unit-Tests.

Schön ist es, wenn man beim Beheben von Fehlern „Test Driven Development“ praktiziert, also einen oder mehrere Unit-Tests schreibt, die eigentlich erfolgreich („grün“) durchlaufen sollten, aber die aufgrund des Fehlers scheitern. Das schaut man sich an, es muß wirklich „rot“ werden, und zwar wegen des Fehlers, den man gerade behebt, sonst ist der Test falsch. Dann behebt man den Fehler und am Schluß läuft der neue Test erfolgreich durch. Weil man ihn dann in die Menge der automatisiert aufgerufenen Unit-Tests aufnimmt, ist die Wahrscheinlichkeit, daß derselbe Fehler bei einer späteren Änderung wieder hereinkommt, sehr verringert worden.

Share Button

Why are Laptop displays having so poor resolutions?

Deutsch

On google+ you can find a post Linus Torvalds himself about this issue.
The post is in English, not in his native language (Swedish).

P.S. I will continue to write a blog entry about every Friday in German and translate some (but not all) of these to English.

Share Button

Warum haben Laptop-Displays so geringe Auflösungen?

English

Hier ein Beitrag von Linus Torvalds zu der Frage auf google+.
Der Beitrag ist auf Englisch, nicht auf Schwedisch geschrieben.

P.S. Ich werde in der nächsten Zeit dabei bleiben, normalerweise so etwa am Freitag einer Woche einen Artikel für den Blog zu schreiben.
Manchmal fällt mir aber zwischendurch noch etwas ein, was dann halt auch hier erscheint.

Share Button

Mathematische Formeln in WordPress

English

In diesem Blog ist nun das Plugin WP QuickLaTeX installiert, das das \LaTeX-Rendering bei QuickLaTeX durchführen lässt.

Wenn eine Seite nur mit [{\sf latexpage}] beginnt, kann man Formeln mittels \backslash(\ldots\backslash) oder \backslash[\ldots\backslash] einbetten und in LaTeX-Notation formulieren.

Nun ist es möglich, in diesem Blog mathematische Formeln zu verwenden, z.B.:

    \[ \bigwedge_{z\in\Bbb C}\, \sin z = \sum_{k=0}^\infty \frac{(-1)^k z^{2k+1}}{(2k+1)!}=z-\frac{z^3}{6}+\frac{z^5}{120}-\frac{z^7}{5040}+\ldots \]

    \[ \bigwedge_{z\in\Bbb C}\, \cos z = \sum_{k=0}^\infty {\frac{(-1)^k z^{2k}}{(2k)!}}=1-\frac{z^2}{2}+\frac{z^4}{24}-\frac{z^6}{720}+\ldots \\ \]

    \[ {\bigwedge_\stackrel{z\in\Bbb C}{\cos z \ne 0}} \tan z = \frac{\sin z}{\cos z} \\ \]

    \[ {\bigwedge_\stackrel{z\in\Bbb C}{\sin z \ne 0}} \cot z = \frac{\cos z}{\sin z} \\ \]

    \[ {\bigwedge_\stackrel{z\in\Bbb C}{\cos z \ne 0}} \sec z = \frac{1}{\cos z} \\ \]

    \[ {\bigwedge_\stackrel{z\in\Bbb C}{\sin z \ne 0}} \csc z = \frac{1}{\sin z} \\ \end{align} \]

    \[ \sec(z) = 4\pi \, \sum_{k=0}^{\infty} \frac{(-1)^k(2k+1)} {(2k+1)^2 \pi^2 - 4 z^2 } \]

    \[ \csc(z) = \frac{1}{z} - 2z \, \sum_{k=1}^{\infty}\frac{(-1)^k} {k^2\pi^2-z^2} = \sum_{k=-\infty}^\infty \frac{(-1)^k \, z}{z^2-k^2\pi^2} \]

Ich werde also, wenn es sinnvoll ist, entsprechende mathematische Formeln damit schreiben und nicht mehr irgendwelches unübersichtliches ASCII-Gebastel dafür benutzen.

Warum benutzt man sowas nicht für Entwicklungsumgebungen von Programmiersprachen? Wenn eine Formel „steht“, könnte man sie viel schöner anzeigen als mit diesem Zeichensalat im Editor. Nun ja, ich glaube, Donald Knuth hat das vor einigen Jahrzehnten auch mal gemeint und dann das sogenannte „literate programming“ erfunden. Der Quelltext ist also eine Datei, aus der man mit weave und tangle (oder fweave und ftangle oder cweave und ctangle) einerseits eine .tex-Datei und andererseits eine kompilierbare nicht-literarische Quelltext-Datei generieren kann. So läßt sich für den Leser ein wunderschöner Ausdruck erzeugen und der Compiler baut das auführbare Programm. Eine kleine Spur dieser Ideen ist ja mit javadoc und rubydoc und perldoc verwirklicht worden, aber das mit den Formeln fehlt natürlich noch.

Share Button

Automatic Test of Links

Deutsch

Running a web site with hundreds or thousands of links it is essential to have automatic mechanisms for testing these links. Many tools are available for this. I am using the Perl library LWP. My page www.it-sky-consulting.com has only about 130 links, but off course I want to establish processes that scale.

The problem is that in some cases naïve automatic tests do not work very well, mostly because the web servers react differently to test scripts than to a real browser. Some examples:

  • Language settings of the browser sometimes lead to language specific pages. It would be best to test with several language settings.
  • Some pages result in an error code (usually 500) when accessed by a script, but work fine in a browser.
  • Some servers avoid returning the error code 404 (or maybe 403) for pages that no longer exist. Instead they forward to a human readable error page with code 200, which looks ok to the script. The page forwarded to contains a friendly description of the error, which is hard (but not totally impossible) to recognize by a script. Often the name of the error page contains „404“.
  • Domains are actually given up.  Usually some company grabs these domains and puts their content on them, hoping to gather some part of the traffic of the former web site.  This is often commercial, but might even be x-rated content.

So automatic checking of web links remains difficult and still requires some manual work.  5% of the links cause about 95% of the work.

I am interested in improving these processes in order to increase the quality of the tests and to decrease the effort.

Share Button

Links automatisch überprüfen

English

Bei einer Webseite mit hunderten oder tausenden von Links ist es sehr hilfreich, wenn man diese automatisiert überprüfen kann. Dafür gibt es viele Hilfsmittel. Ich verwende die Perl-Library LWP.  Ja, www.it-sky-consulting.com hat heute nur etwa 130 verschiedene Links, aber ich möchte natürlich auch dafür Prozesse haben, die skalieren.

Ein Problem ist aber, daß einige Webseiten auf solche Testskripte anders reagieren als auf einen Browser. Ein paar Beispiele:

  • Spracheinstellungen des Browsers führen dazu, dass zu einer sprachspezifischen Seite weitergeleitet wird.  Man müsste also mit etlichen Spracheinstellungen testen.
  • Manche Seiten ergeben beim automatisierten Test einen Fehler, z.B. Fehlercode 500, funktionieren aber im Browser.
  • Manche Server geben bei längst nicht mehr vorhandenen Seiten nicht den Fehlercode 404 (oder eventuell 403), sondern leiten an eine Seite weiter, auf der freundlich auf die Fehlersituation hingewiesen wird.  Wenn man die Sprache der Seite versteht, ist das gut.  Für ein Skript relativ schwierig zu lernen, auch wenn man gewisse Muster beachten kann:  Die Weiterleitung geht häufig auf die Home-Seite des Servers oder auf eine Seite, in deren Dateiname „404“ vorkommt.
  • Es wird immer mal wieder eine Domain aufgegeben.  Meistens wird die dann sofort von einer Firma übernommen, die dort ihren Content, z.B. Werbung, plaziert, in der Hoffnung den Traffic der etablierten Seite erben zu können.

So bleibt die automatische Überwachung der Links immer noch schwierig und erfordert gewisse manuelle Tätigkeiten.  Nicht die 80-20-Regel gilt hier, sondern es ist eher so, dass 5% der Links etwa 95% der Arbeit machen.

Ich interessiere mich dafür, diese Prozesse weiter zu verbessern, also die Qualität der Überprüfungen zu erhöhen und den Aufwand zu verringern.

Share Button

Overflow of Integer Types

Deutsch

Handling of integral numbers has always been one of the basic capabilities of our computing devices. Any common programming language since the fifties provides this in some way.

There are some significant differences between the ways integral numbers are handled in different programming languages.

Dealing with the overflow

There are several approaches:

  1. Integral numbers can have any number of digits, as far as the memory allows. Results of calculations that need more bytes to be stored than the input are stored in as many bytes as needed to be represented completely. There is no need to deal with overflow, unless the numbers are so big and so many that they eat up the available memory. Examples: Common Lisp, Ruby
  2. Integral numbers have a fixed number of bits. If a calculation results in a number that cannot be expressed in these many bits, the upper bits are tacitly discarded, unless each operation is accompanied by elaborate indirect checks for overflow. Examples: C, Java
  3. Integral numbers have a fixed number of bits. If a calculation results in a number that cannot be expressed in these many bits, an exception is thrown. I do not have any examples, maybe someone can suggest an example.
  4. Integral numbers have a fixed number of bits. For results of a multiplication, a type with twice as many bits as the two factors is used. For results of addition, a type with as many bits as the summands is used, but a carry bit is provided, too. This is the extra bit that is needed to express the result in all possible cases. Using this carry bit and feeding it into the next addition, it is possible to add numbers of arbitrary length, as needed for solution 1. Multiplication, Division and Subtraction can be implemented in a similar manner. Example: Assembly language
  5. Not integers are available and floating point numbers have to be used instead. Example: Lua

Evaluation

Solution 1 is exactly what is needed for application development. Counting of bits, checking for overflow and such practices are just absurd during the development of business logic. This is quite a strong argument in favor of using Ruby (or Lisp) for application development.

Solution 2 is simply crap. I consider this the most serious design bug of C and Java. Rounding is something that we can accept in many cases, but that discards the lower bits. Here we tacitly discard the upper bits. Average software developers do not really want to deal with these issues, sometimes they are simply ignored, because the bugs do not occur frequently and are not discovered during the testing phase. Throwing away the carry bit, which contains very important information for implementing solution 1 or for just recognizing overflows is not a good idea. There are workarounds for this, but they double the runtime of certain calculation intensive software.

Solution 3 would be acceptable, but I consider solution 4 better. Low level code should leave it to the developer if an exception is thrown or if the situation can be handled.

Solution 4 is quite acceptable and useful for low level programming, but not for typical application development. Sometimes access to bits and bytes is needed explicitly, for example to talk to external hardware, to implement the lower layers of network protocols or similar issues. It can be useful for very performance critical calculations, where it can be guaranteed that no overflows occur. The possibility to deal with a carry bit at least optionally cannot do any harm. Unfortunately this is currently only (or almost only?) possible in assembly languages. For implementing integer arithmetic for languages like Ruby or Lisp, some implementation that works with solution 2 by doing crappy workarounds needs to be provided, but for common CPU-architectures it is possible to provide an implementation in assembly language based on solution 4, that will run about twice as fast.

Solution 5 is just an unnecessary restriction.

Conclusion

Many software developers think that this does not interest them or is not their problem. I recommend to take this issue serious. The bugs caused by the tacit overflow are hard to find, because they can occur anywhere and they might not show during testing. But then they occur with some weird combination of data on the productive system. Who wants to find the cause of a weird bug, that surfaces far away from the real cause? Only solution 1 allows the application developer to safely ignore these problems.

Share Button