Dienstag, 28. Dezember 2010

Hashtable schneller als HashMap





Donnerstag, 23. Dezember 2010

Browsertracking

Es gibt ja ganz unterschiedliche Trackingmethoden. Cookies, Flash, Javascript und Silverlight sind aber nicht die Einzigen Verräter an Bord. Der Browser selbst gibt freiwillig bereits einen ganzen Haufen an Informationen Preis, die mitunter für eine Identifikation ausreichen können. Welche das alles sind und wie eindeutig identifizierbar der Browser ist, lässt sich bei Panopticlick testen.

Link: Panopticlick

42 für Softwarearchitekten

Es gibt wieder einen Vortrag vom Jax TV. Dieses Mal geht es um Architektur- und Designdokumentation. Bestimmt schaffe ich es in den Feiertagen, mir die Zeit zum Gucken zu nehmen.

42 für Softwarearchitekten from JAX TV on Vimeo.

Dienstag, 21. Dezember 2010

Anwendungseigenschaften speichern

Eigentlich gibt es ja kaum eine Anwendung, bei der man nicht ein paar Einstellungs- oder Konfigurationsmöglichkeiten haben möchte. Die Out-of-the-Box-Lösung unter Java ist hier die java.util.Properties Klasse, mit der Eigenschaften gelesen und geschrieben werden können. Aussehen könnte das ganze wie folgt:

    /**
     * Lese properties file.
     */
    public void readProperties() {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("filename.properties"));
        } catch (IOException e) { 
            e.printStackTrace();
        }
    }

    /**
     * Schreibe properties file.
     */
    public void writeProperties(Properties properties) {
        try {
            properties.store(new FileOutputStream("filename.properties"), null);
        } catch (IOException e) { 
            e.printStackTrace(); 
        }
    }

Der Zugriff erfolgt dann, gleich einer HashMap, via props.getProperty("key"). Das ist alles sehr einfach und reicht oftmals aus, um ein paar Werte zur Laufzeit wegzuschreiben. Will man aber Arrays, Objekte oder ganze Wertebeziehungen speichern, muss man diese zunächst in einen String codieren bzw. beim Lesen wieder decodieren. Ist man im Begriff mit so etwas zu beginnen, empfiehlt es sich gleich etwas anderes zu verwenden, weil hier die Rattenschwanzgefahr recht groß ist und letztendlich nur vom Projektziel ablenkt. Gesehen habe ich das allerdings schon mehrfach. Dabei bringt Java für anspruchsvollere Anwendungseigenschaften noch etwas anderes, besseres mit.

Im Package java.util.prefs gibt es die Klasse Preferences, die eine hierarchische Werte- und Objektablage bietet. So ist mittels Preferences.userRoot() eine Rootknoten erhältlich, in den wir bereits verschiedene Objekte ablegen können. Besser ist es aber, einen eigenen Knoten für die Anwendung bereitzustellen, um nicht mit anderen Anwendungen zu kollidieren. Preferences werden nämlich im Benutzerverzeichnis für alle Anwendungen unter .userPrefs/prefs.xml abgelegt. Via Preferences.systemRoot() lassen sich auch systemweite Einstellungen speichern. Um die Anwendungseinstellungen zu laden empfiehlt es sich, einen Unterknoten zu verwenden, der wie folgt erzeugt/geladen werden kann: Preferences.userRoot().node("TestApp"). Dieser Knoten kann nun als Basis für weitere Unterknoten oder für die Werteablage dienen. Um das Laden und Speichern müssen wir uns bequemer Weise nicht kümmern. Unser Knoten befindet sich nach dem Neustarten der Anwendung im gleichen Zustand. Der Zugriff auf die Knoteneigenschaften erfolgt mittels put- und get-Methoden.

java.util.prefs.Preferences appNode = Preferences.userRoot().node("TestApp");
appNode.putInt("fontsize", 10); //Eigenschaft setzen
int fontsize = appNode.getInt("fontsize", 10); //Eigenschaft lesen

Das ganze kann noch weiter getrieben werden, so dass zum Beispiel für jedes Paket ein neuer Knoten verwendet wird.

Preferences packageNode = appNode.node(Test.class.getName())

Bis jetzt lassen sich aber nur die gängigen Wrapper-Klassen sowie Strings und Bytearrays ablegen. Um (fast) beliebige Objekte abzulegen, lässt sich die Serialisierbarkeit von Objektinstanzen nutzen. Die zugrundeliegende Klasse muss also das Serializable-Interface implementieren. Die der Klasse zugrunde liegenden Objektinstanzen können anschließend in ein Bytearray umgewandelt werden, das wiederum mit der Methode putByteArray in den Preferences-Knoten gespeichert werden kann.

   /**
     * Objektinstanzen serialisieren.
     */
    static private byte[] object2Bytes(Object o) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(o);
        return baos.toByteArray();
    }

Der Rückweg, aus dem Bytearray eine Objektinstanz zu erzeugen, ist ebenso einfach.

   /**
     * Serialisierte Objektinstanz wiederherstellen
     */
    static private Object bytes2Object(byte raw[]) throws IOException,
            ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(raw);
        ObjectInputStream ois = new ObjectInputStream(bais);
        Object o = ois.readObject();
        return o;
    }

Bei der Objektserialisierung ist immer darauf zu achten, dass die Member-Variablen der zugrundeliegenden Klasse wiederum serialisierbare Klassen referenzieren. Andernfalls sind die Member-Variablen mit transient zu kennzeichnen. Das Gilt zum Beispiel für Streams, die nicht einfach serialisiert werden können. Bei der Wiederherstellung enthalten diese Member-Variablen den Wert null.

Die Datenablage erfolgt - wie nicht anders zu erwarten - im XML-Format. Das Endergebnis  können wir uns auch ausgeben lassen.

public static void printPreferences(Preferences prefs) throws IOException,
            BackingStoreException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        prefs.exportNode(byteArrayOutputStream);
        System.out.println(new String(byteArrayOutputStream.toByteArray()));
    }

Und die Ausgabe.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
<preferences EXTERNAL_XML_VERSION="1.0">
  <root type="user">
    <map/>
    <node name="TestApp">
      <map>
        <entry key="fontsize" value="10"/>
      </map>
    </node>
  </root>
</preferences> 
 
Links: IBM Developerworks 

Montag, 20. Dezember 2010

Crashkurs Testgetriebene Softwareentwicklung

Testgetriebene Softwareentwicklung ist eigentlich eine tolle Sache, die jeder mal probiert haben sollte. Nicht etwa, weil es die beste Methode wäre, Software zu entwickeln. Es ist viel mehr so, dass häufig viel zu wenig Tests geschrieben werden und nicht selten auch die Einsicht fehlt, warum Tests geschrieben werden sollen. Manchmal ist es auch nur die Faulheit, die davon abhält, ein paar mehr Tests zu schreiben. Einmal testgetrieben zu entwickeln, verschafft die Erfahrung, dass die Qualität der Software signifikant steigt, wenn gute Tests erstellt wurden. Die Erfahrung, was gute Tests sind und worauf es ankommt, bekommt man gleich mit oben drauf.

Sehr gut funktioniert das übrigens in der Java-Welt, wenn man auch gleich bei der Entwicklung darauf abzielt, entkoppelten Code zu schreiben. Spring ist da ziemlich hilfreich.

Zurück zur testgetriebenen Entwicklung. Ein großes Haken ist natürlich, dass testgetriebene Entwicklung zu Beginn des Projektes mehr Zeit benötigt. Außerdem ist es unter Entwicklern meist unbeliebt, Testcode zu schreiben. Dem lässt sich allerdings entgegen wirken, wenn man Teams zu zwei Personen bildet, bei der gemeinsam die Spezifikation ausgearbeitet wird und abwechselnd der eine die Implementierung und der andere die Tests schreibt. Nach einiger Zeit erhält man dann ein Projekt, das eine gute Testabdeckung bietet und wenig fehleranfällig auf Änderungen reagiert.

Tests gleich zu schreiben ist auch deshalb gut, weil ein Test, der nicht unmittelbar nach oder eben vor der Implementierung geschrieben wurde, oft nie geschrieben wird. Zumindest so lange nicht, bis genau dort ein Fehler auftritt.









via krsteski.de

Samstag, 18. Dezember 2010

Mein neues Spielzueg, ein Pocketbook 902

Mein neues Spielzeug ist da. Ein Pocketbook 902 Pro. Bisher waren mir die E-Reader immer zu klein, aber der Trend geht ja zu immer größerem. Das Kindle DX kam für mich nicht in Frage. Zum einen wegen fehlender epub-Unterstützung, zum anderen aus ideellen Gründen. Die Pocketbook-Plattform ist offen und es gibt sogar ein Entwickler-Kit, um eigene Anwendungen auf das Gerät zu bringen.

Als tückisch erweist sich jedoch die MicroSD-Card. Die kann man an der Geräteunterseite hineinschieben, was ich auch tat. Die Karte rastete mit einem Klicken ein, nur tat sich nichts. Tatsächlich muss man die Karte mit leichter Gewalt noch viel weiter hineindrücken, als es mit den bloßen Fingern möglich ist. Das habe ich aber auch erst zwei Speicherkarten später rausgefunden. Frauen, mit langen Fingernägeln, haben hier sicher einen grundlegenden Vorteil.

Inzwischen habe ich mein erstes Buch auf dem Pocketbook fast fertig gelesen. Das elektronische Lesen hat Vor- und Nachteile. Das Gerät lässt sich angenehm halten und an das Blättern per Taster hat man sich schnell gewöhnt. Das E-Ink-Display ist zwar entspiegelt, dennoch reflektiert es leicht, was besonders bei ungleichmäßiger oder geringer Raumausleuchtung stört. Der Kontrast ist nicht ganz so stark, wie bei einem gedruckten Buch, dennoch kann man gut auf dem Display lesen. Ich werde es jedenfalls weiter ausprobieren.

*Update 19.12.10*
Leider sind das Boot- und das Off-image, eher hässlich und nichtssagend. Kein Vergleich zu der stylischen Verpackung. Im Forum von The Electronic Book gibt es eine menge Ersatz, der gut für die E-Paper-Displays geeignet ist.

Visuelles Multiplizieren

Eine interessant ausgestaltete Variante der Multiplikation, auch wenn die Ausgestaltung des Rechenweges wohl etwas eigenwillig ist. Die Darstellungsweise ist nicht taufrisch, aber ich kannte sie bisher noch nicht.

How do japanese multiply??

Worauf es bei Passwörtern im Web ankommt *Update*

Es kommt nicht auf die Länge an. Wenigstens nicht bei Passwörten im Web. Unter Entwicklern herrscht nicht selten die Meinung vor, starke Passwörter würden die Sicherheit erhöhen. Der Zwang zur Auswahl komplexer Passwörter ist eigentlich nur ein Delegieren der Sicherheitsanforderungen an den Benutzer. Weshalb das nicht funktioniert, ist mit einem Blick auf die möglichen Wege eines Passwortverlustes schnell erklärt.

Man-in-The-Middle (MiTM): Besonders populär ist die MiTM-Methode jüngst durch Firesheep geworden. Vor allem in fremden WLAN-Netzen besteht die Gefahr, dass unberechtigte mitlesen und Passwörter ausspähen. Hier würde eine verschlüsselte Verbindung erheblich mehr Nutzen, als ein Passwort, dessen Komplexität dem Mitsniffenden herzlich egal sein kann.

Phishing: Fällt der Benutzer auf eine gefälschte Seite herein, spielt die Passwortkomplexität keine Rolle mehr.

Brute Force: Soll ein Passwort durch reines Durchprobieren erraten werden, sind besonders schwache Passwörter wie 123456 oder der Benutzername als Passwort besonders gefährdet. Aber auch dies erfordert keine starken Passwörter. Eine Blacklist mit gängig schwachen Passwörtern und einer Prüfung auf den Benutzernamen vorwärts, wie rückwärts, verhindert die schlimmsten Passwortpatzer. Gepaart mit Wartezeiten zwischen den Logins und einer Begrenzung der insgesamt erlaubten Fehlschläge ist auch hier ein Erfolg unwahrscheinlich.

Educated guess: Gezieltes Raten durch Umfeldwissen lässt sich von allen Methoden am wenigstens vermeiden und kann tatsächlich zum Erfolg führen, zumal davon auszugehen ist, dass dem Ratenden der Benutzername bekannt ist. Hier wäre ein eingestreutes Sonderzeichen oder ein Ziffer tatsächlich hilfreich. Die Begrenzung der Loginversuche leistet aber ebenfalls gute Dienste, um ein zu häufiges Probieren zu unterbinden. Vor allem ist zu bemerken, dass Benutzer, die zu starken Passwörtern gezwungen werden, die Passwörter häufiger aufschreiben. Ich meine, hier ist abzuwägen, inwiefern das aufgeschriebene Passwort nicht ein höheres Risiko birgt, als ein aus dem Umfeld zu erratenes, schwaches. Vielmehr verführt das zufällig gefundene Passwort sogar zum Missbrauch. Der Zugang über das Umfeld des Benutzers ist nie auszuschließen. Schon gar nicht von Seiten der Webentwickler.

Rainbow-Tabellen: Ist die Datenbank der Webanwendung erst in fremden Händen, lassen sich mittels vorberechneter Hashes (Rainbow Tables) auch starke Passwörter knacken. Dagegen hilft der Einsatz von Salts, die wiederum auch schwache Passwörter schützen.

Natürlich sind starke Passwörter zu bevorzugen. An der Passwortsicherheit hängt aber mehr, als allein die Komplexität des Passworts. Vielmehr sind Softwareentwickler gefragt die Passwörter sicher abzulegen und die Loginprozedur so auszugestalten, dass automatisierte Angriffe an einer begrenzten Anzahl von Versuchen scheitern. Das muss nicht unbedingt mit einer Sperrung des Accounts enden. Eine zeitlich begrenzte Sperre hat bereits den gleichen Effekt. Letztendlich hat der Administrator den Transportweg mittels Https-Verbindungen abzusichern und der Benutzer ist gefragt, verantwortungsbewusst mit seinem Passwort umzugehen.

Update 18.12.10
Vor einigen Tagen sind dem US-Blogbetreibers Gawker u.a. die Benutzerdaten inkl. der DES-Verschlüsselten Passwörter abhanden gekommen. Die Hacker haben die Nutzerdaten veröffentlicht, was interessante Analysen zulässt. Die Passwörter wurden via DES-Hashes gespeichert. Soweit herauszulesen ist, wurden kein Salt verwendet, was eine einfache Dekodierung mittels Wörtbuch/Bruteforce ermöglicht. Unter den Daten waren auch die, des Gawker-Gründer Nick Denton, der das gleiche Passwort auch für seinen Google- und Twitteraccount verwendet hat.

Es lässt sich grundsätzlich nicht vermeiden, dass Benutzer ihre Passwörter mehrfach verwenden. Der Gawker-Fall zeigt aber deutlich, wo die eigentliche Gefahr liegt. Nämlich nicht etwa im schwachen Passwort, sondern darin, dass die Passwörter nicht gut genug gesichert wurden.

Einen nutzen können wir jedoch trotzdem daraus ziehen. Nämlich die Top250 ermittelten Passwörter für die Blacklist.

via heise, duosecurity

Mittwoch, 15. Dezember 2010

WindowBuilder und CodePro Profiler

Zwei Geschenke an die Community. Google übergibt WindowBuilder und CodePro Profiler an die Eclipse Foundation. Mit WindowBuilder lassen sich SWT- und Swingoberflächen zusammenklicken, CodePro ist ein Profiler. Beides lässt Eclipse bisher missen. Zwar gibt es einige GUI-Designer für Eclipse, aber spätestens bei Swing ist es mit überzeugenden Lösungen nicht weit her. Noch schlechter steht es um einen Profiler. Da gibt es eigentlich nur brauchbares bei den kommerziellen Tools. Wäre natürlich toll, wenn sich die Eclipse Foundation auch wirklich darum kümmern würde. Ich erinnere mich da an einige Plugins, die in den Aktualisierungen nicht mitgezogen wurden und irgendwann in der Versenkung verschwanden. Beide Tools halte ich für eine absolute Bereicherung, zumal die eigenen Bemühungen, bei der Entwicklung eines SWT/Swing-Designer (VEP), nie brauchbare Ergebnis zu Tage gefördert haben.

Insofern gute Nachrichten und ein dickes Danke an google. Die machen es einem manchmal wirklich schwer, sie nicht zu mögen.

Links:
CodePro: http://www.eclipse.org/proposals/tools.rat/
WindowBuilder: http://www.eclipse.org/proposals/tools.windowbuilder/ und http://code.google.com/intl/de-DE/javadevtools/download-wbpro.html

via it-republik.de

Paygames für Linux

Ich bin immer wieder erfreut, wenn auch kommerzielles für Linux entwickelt wird. Ein Spielebundle für Linux, Mac und Windows gibt es derzeit auf Basis einer freiwilligen Spende bei The Humble Indie Bundle. Ich bin zwar für Spiele nur bedingt zu haben, diese wollte ich aber gern ausprobieren. Von den fünf Spielen laufen immerhin vier auf Anhieb. Nur der Cortex Commander wollte, trotz 64bit Installer, auf meiner Maschine leider nicht. Die anderen vier Spiele habe ich angespielt und ich bin sehr angetan von der Ideenvielfalt.

Braid: Ein Jump and Run der besonderen Sorte. Weil Videos manchmal mehr als viele Worte sagen, hier der Trailer zum Game.




Machinarium: Definitiv ein Highlight, wenn man das Adventure-Genre mag.




Osmos: Ein Spiel, mit dem man Stunden verbringen kann, ohne es zu merken. atmosphärisch und suchterregend wären die beiden Attribute, die mir zuerst einfallen würden.




Refenge of the Titans: Passt am besten in die Kategorie Retrogames. Ebenfalls schön gestaltet, aber ehrlich gesagt nicht mein Fall.



via stadt-bremerhaven.de

*Update 22.12.10*
Echt fair ist übrigens, dass Humbler Bundle sich entschieden hat, einfach die Spiele vom letzten Bundle auch noch dazuzugeben. Außerdem bekommt man die noch auf seinen Steam-Account. Sowas habe ich aber sowieso nicht.

Freitag, 10. Dezember 2010

Swing Komponenten in XPS Drucken

Java und Drucken ist ja so eine Sache, mit der ich mich bereits viel herumgeärgert habe. In einem aktuellen Fall werden Swingkomponenten ausgedruckt. Das funktioniert soweit ganz ordentlich. Einzig, wenn man den Microsoft XPS-Drucker verwendet, erscheint ausschließlich die letzte Komponente im Ausdruck - der Rest fehlt. Zeichnet man ohne Swing-Komponenten auf dem Graphics-Object des XPS-Drucker, erscheint das Ergebnis wie erwartet. Woran es nun genau gelegen hat, vermag ich auch nicht zu sagen. Ich bin letztendlich darauf hängen geblieben, dass der Ausdruck auf dem XPS-Drucker korrekt herauskommt, wenn man nach dem paintAll der Swing-Komponenten ein drawLine auf das oberste Graphics-Object ausführt. Besonders hinterhältig ist immer die Aussage der Benutzer, dass ganze würde ja schließlich mit Word gut funktionieren. Das sind die Stellen, an denen sich die Maschinenferne von Java rächt. Man hat im Grunde kaum Manipulationsmöglichkeiten um so einem zickigen Druckertreiber beizukommen. In diesem Fall war es ja zum Glück recht unkompliziert.

Mittwoch, 8. Dezember 2010

Bibliotheken Guava und op4j

Guava: Die Google Collections Library ist veraltet, seit einiger Zeit benutzt man Guava. Das Guava-Projekt entwickelt die Google-Bibliotheken weiter. Die Bestandsfunktionalität der Google Collections bleibt erhalten, es sind aber neue Funktionalitäten hinzugekommen, Bugfixes eingearbeitet und Performanceverbesserungen durchgeführt worden. Die gesamte Bibliothek umfasst inzwischen weitaus mehr, als nur Collections. Was es da inzwischen alles gibt, muss ich bei nächster Gelegenheit mal evaluieren.

*Update 23.01.11*
Eine ganz ordentlichen Einblick in die Möglichkeiten von Guava gibt es bei Thomas Ferris Nicolaisen.

op4j: Eine Bibliothek die den Einsatz der Fluent-Schreibweise schmackhaft macht. Nach kurzer Eingewöhnung kann man damit semantisch sehr gut lesbaren Code erzeugen.

Sonntag, 5. Dezember 2010

10 typische Fehler in Enterprise-Java-Anwendungen

Eine Teil der beschriebenen Fehler lassen sich auch auf alle anderen Java-Anwendungen transportieren. Den Vortrag hält Eberhard Wolff auf der W-JAX 2009. Die Fehler, die er beschreibt, sind viel mehr Designschwächen, die man tatsächlich in sehr vielen Anwendungen wiederfindet. Alles in allem ein außerordentlich empfehlenswerter Vortrag!

Donnerstag, 2. Dezember 2010

Java ist auch eine Insel die 9te

Seit November ist es draußen. Das Buch, dass vermutlich jeder, der sich jemals mit Java befasst hat, zumindest dem Namen nach kennt. Von "Java ist auch eine Insel" gibt es die 9te, überarbeitete Fassung zum online- und offline lesen, sowie als Buch zum Kaufen.

http://openbook.galileocomputing.de/javainsel9/

Dienstag, 30. November 2010

Pixel aus BufferedImage auslesen

An die Pixel eines BufferedImage kann man ganz einfach gelangen. Den Sniplet brauchte ich vor Ewigkeiten mal und habe ihn gerade wiedergefunden. Super einfach eigentlich:

public static void main(String[] args) {
        try {
            final BufferedImage img =  ImageIO.read(new File("images/example.jpg"));
            final int w = img.getWidth();
            final int h = img.getHeight();
            final int pixels[] = new int[w * h];

            img.getRGB(0, 0, w, h, pixels, 0, w);
            
            for (int i = 0; i < pixels.length; i++) {
                System.out.println("R:" + ((pixels[i] >> 16) & 0xff) + " G:"
                        + ((pixels[i] >> 8) & 0xff) + " B:" + (pixels[i] & 0xff));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Schreibweise für String-Concatenation

Das man mal einen String zusammensetzen will, kommt ja häufig vor und ist einfach. Beispiel:
String s = "[Attribute: " + getQualifiedName() + "=\"" + value + "\"]"; 
Daran gibt es ansich auch nicht viel zu mäkeln, außer eben, dass diese Schreibweise, je nach Länge, schnell unübersichtlich aussieht. Viel netter ist es eigentlich, den StringBuilder mit seiner Kettenschreibweise zu verwenden.
String s = new StringBuilder()
            .append("[Attribute: ")
            .append(getQualifiedName())
            .append("=\"")
            .append(value)
            .append("\"")
            .append("]")
            .toString();
Wenn man nun ganz korrekt sein will, kann man außerdem abschätzen, wie groß der String werden könnte, und dem StringBuilder gleich die dazu passende Größe mitgeben, so dass er möglichst selten mitwachsen muss. Merklich performanter dürfte keine der beiden Lösungen sein, da der Hotspot-Compiler das String-Concatenieren ohnehin optimiert, wenn er es denn kann. Probleme hingegen gibt es da schnell mal in Schleifenkonstrukten. Ist die Logik zum String bauen umfangreicherer, empfiel sich ohnehin immer der StringBuilder bzw. der StringBuffer, wenn man das synchronisierte Derivat braucht, oder kein Java 1.5 zur Verfügung hat, was hoffentlich selten geworden ist.

Donnerstag, 25. November 2010

jsoup: Java HTML Parser

Das hier gehört in die Kategorie: Muss ich mir merken. Eine Java-API, die von sich behauptet, Wildbahn-HTML parsen zu können. Mit anderen Worten, dass Ding soll recht fehlertolerant sein.Zur Projektseite geht es hier: http://jsoup.org/

via Schockwellenreiter

PR-Aktionen im Web 2.0 und wie man sie besser nicht umsetzt

Aral hat gerade eine Werbeaktion laufen, bei der sie jedem ein belegtes Baguettbrötchen schenken, der Fan ihrer Facebookseite wird. Das ist eine Variante von Marketing, der ich durchaus etwas abgewinnen kann. Einzig bei der Umsetzung hätte Aral wohl auf erfahrenere Entwickler zurückgreifen sollen. Anfangs funktionierte das ganz gut. Bis auch ich darauf aufmerksam wurde, war der Traffic auf die Gutscheinapp vermutlich schon in die Höhe geschnellt. Ich werde also erstmal nur von einer weißen Seite begrüßt. Ein Blick auf die Aral-Pinnwand offenbart, dass der Mob die Ankündigung mit passenden Kommentaren flutet. Im Hintergrund scheint fleißig gewerkelt zu werden und nach einiger Zeit scheint das mit dem Gutschein wieder zu klappen. Einzig ungewöhnlich ist die anschließende Meldung:

insert into aral_coupon_user (id, coupon_id, facebook_uid, used_barcode) VALUES (785, 102, '100000112611741', '981035092500') Duplicate entry '785' for key 1

Die sieht so aus, als könne die Gutscheinnummer, die da generiert wurde, nicht in die Datenbank geschrieben werden, weil ein Constraint verletzt wurde. Wenn die Nummern, die da generiert werden, nicht im Nachhinein reproduzierbar sind, werden sicher einige Gutscheinausdrucker ihre Freude haben, wenn sie für den Gutscheincode keine Aralbemme ausgeliefert bekommen. Jedenfalls lassen sich nun beliebig viele Gutscheine mit unterschiedlichem Code generieren. Das wird wohl darauf hinauslaufen, dass entweder Aral bis Jahresende fleißig Futter rausrückt, oder der PR-Schuss nach hinten losgeht. Die Empörung ist bei der Web2.0- und vor allem der Schnäppchenmacher-Zielgruppe erfahrungsgemäß groß, wenn versprochenes nicht eingehalten wird.

Inzwischen funktioniert das ganze übrigens gar nicht mehr und man bekommt eine Sperrseite. Das dürfte wohl die Reißleine sein, die da gezogen wurde.

Und die Moral von der Geschichte? Wenn man eine Anwendung online stellt, bei der mit einer Menge Anfragen zu rechnen ist, empfiehlt sich ein Stresstest. Und wann ist mit vielen Anfragen zu rechnen? Auf jeden Fall immer dann, wenn es was kostenloses gibt.

Facbook-App von Aral,

Dienstag, 23. November 2010

Upgrade von Mint Isadora auf Julia

Heute war zeitlicher Spielraum zum Basteln. Dabei habe ich gleich mal mein Mint auf die nächste Version aktualisiert. Natürlich mittels APT-Distupgrade. Was bei Ubuntu ganz ordentlich funktioniert, ist bei Mint etwas kritischer. Das Paket für das Mint-Menü hat sich ein wenig geziert, und ich musste nachhelfen. Alles weitere hat sich von allein erledigt. Das ganze Prozedere verlief dieses Mal angenehm ereignislos.

Erster Bug nach dem Neustart: die Icons im Mint-Menü waren auf zwei Pixel zusammengeschrumpft. Das lies sich aber mit ein paar Klicks im dazugehörigen Konfigurationsdialog beheben. Etwas hakeliger war es da mit der Kalendererweiterung Lightning, für die es zwar ein Update gab, aber nicht für die X86_64 Architektur. Da hat der automatische Pluginupdater vom Thunderbird irgendwie daneben gegriffen. Aber nach ein wenig Sucharbeit war auch das schnell erledigt.

Summa Summarum ging alles recht flott. Trotzdem finde ich Rolling-Releases irgendwie netter.

Samstag, 20. November 2010

Ubuntu Desktop-Tuning

Als ich mal mein Home-Verzeichnis von der flotten SSD auf meine lahme, Caviar-Green umgelegt hatte, gab es einen unschönen Nebeneffekt. Nämlich der, dass Anwendungen plötzlich für mehrere Sekunden hingen. Das fand ich wenig nachvollziehbar, weil die Platte ja sooo langsam auch wieder nicht war. Ich habe die Änderung einige Zeit später wieder Rückgängig gemacht und nicht weiter darüber nachgedacht. Heute bin ich über einen Artikel gestolpert, der für einen späten AHA-Effekt sorgte.

http://everflux.de/ubuntu-desktop-tuning-mit-elevatordeadline-1681/

Mein Rechner bekommt jetzt mal diese beiden Zeilen spendiert:
echo "noop" | tee /sys/block/sda/queue/scheduler
echo "deadline" | tee /sys/block/sdb/queue/scheduler


*Update 23.11*
Bis dato hat sich kein Beschleunigungsgefühl einstellen wollen. Im Gegenteil hatte ich sogar wieder die Ersten Anwendungshänger seit langem. Die Zeilen fliegen wohl wieder raus.

*Update 22.12*
Zum Thema SSD-Tuning findet sich bei Zockertown noch ein interessante Beitrag.

*Update 27.03.12 *
Zum Thema SSD-Trim unter Linux aktivieren auf jeden Fall mal bei loggn.de reinschauen.

Mittwoch, 17. November 2010

Darktheme für Eclipse

Eigentlich bin ich mit der Farbgebung der Eclipse-Editoren ganz zufrieden und habe auch nie das Bedürfnis gehabt daran etwas zu ändern. Bis ich vor kurzem über ein Textmate-Farbschema gestolpert bin, dass ich unbedingt mal ausprobieren musste. Zwar werde ich es wohl nicht in Dauergebrauch nehmen, finde es aber trotzdem eine sehr nette und vor allem angenehme Variante, die es auf jeden Fall wert ist, ausprobiert zu werden. Leider sieht der Editor anschließend wie ein Alien in der Eclipse-IDE aus, da das Farbschema der restlichen UI beim alten bleibt.

Vor dem Ausprobieren empfiehlt es sich die alte Konfiguration zu sichern. Das geschieht über den Eclipse Preference-Exportwizard im Menü File->Export. Anschließend kann man mittels File->Import den Preference-Importwizard auf das neue Colortheme loslassen.

Das Farbschema kann man bei blog.ronnyristau.de downloaden.

Dienstag, 16. November 2010

Web Designers vs. Web Developers

Klischees sind was schönes. Ich liebe sie. Es ist zwar eigentlich jedem klar, dass die nie komplett passen und die Ausnahme die Regel ist, aber man fühlt sich immer so schön bestätigt, wenn mal wieder eines passt. Ich kenne die Zusammenarbeit mit Grafikdesignern gut. Ich bin immer ausgezeichnet mit ihnen ausgekommen. Interessant wird es aber immer dann, wenn ein Kompromiss gefunden werden will, weil die Idee des Designers technisch nicht oder nur mit Klimmzügen realisierbar ist. Ich hatte auch schon Diskussionen, weil der Entwurf nicht pixelgleich unter IE und Firefox umgesetzt werden konnte.

Der hier deckt zwar bei weitem nicht alles ab, ist aber irgendwie passend:


free website builder
Web Designers vs Web Developers is brought to you by Wix.com
You are most welcome to share this infographic with your audience.

via sixrevisions

Montag, 15. November 2010

Kostenlose SciFi

Der Chiphersteller Intel ist ja durchaus dafür bekannt, dass er die Marketingklaviatur hervorragend beherrscht. Das Buch "Über morgen" gehört, wie ich finde, zu einer sehr netten PR-Aktion. Bekannte Autoren schreiben Kurzgeschichten und Intel gibt noch Links zu den, im weitesten Sinne, behandelten Intel-Technologien dazu. Außerdem noch ein paar Seiten Unternehmensinformationen zum Abschluss. Alles in allem eine coole Aktion, bei der der Nutzwert für den Leser definitiv passt.

Das Buch gibt es als Podcast zum hören, sowie im EPUB- und PDF-Format im Intel newsroom.

via lesen.net

Samstag, 13. November 2010

Flash Mob Gone Wrong by Tom Scott

“The whole world turns upside down in ten years, but you turn upside down with it.” - Spider Robinson, 1977



Das ist natürlich alles Fiktion. Die einzelnen Bestandteile befinden sich aber verdächtig nahe an der Realität, so dass nur zu sagen bleibt: Möglich wäre es.

Donnerstag, 11. November 2010

Buchempfehlung - Aus dem Tagebuch eines Bughunters

Ich hatte neulich die Gelegenheit etwas Zeit beim Fachbuchhändler Lehmanns in der IT-Ecke zu verbringen. Ich war überrascht, wie nett es dort inzwischen geworden ist. Es gibt Leseecken und Kaffee und man kann sich voller Muße und in aller Ruhe umsehen. Ich hatte einige interessante Bücher in der Hand, wovon mich aber eines im Nachhinein besonders angesprochen hat. Natürlich ein Fachbuch, aber mal eines, das man ganz locker lesen kann. Das Buch erzählt über die Arbeit und das Vorgehen eines Bughunters, über seine Werkzeuge und natürlich werden die verschiedenen Sicherheitslücken beleuchtet, die Software so enthalten kann. Das Buch ist unterhaltsam und lehrreich zugleich. Für Softwareentwickler unbedingt empfehlenswert, nicht etwa, weil es die coole Techniken beschreibt, die man vielleicht für das nächste Projekt nutzen könnte, sondern viel mehr das Verständnis für das tägliche Tun fördert. Das ganze ist natürlich etwas C-Lastig, aber auch für Java- und Scriptprogrammierer verständlich.


Aus dem Tagebuch eines Bughunters - Wie man Software-Schwachstellen aufspürt und behebt

E-Mailadresse validieren nach RFC822 mal anders

Und zwar mittels regulärem Ausdruck. Reguläre Ausdrücke gehören im Javabiotop nicht unbedingt zur Best Practice, in PHP und Perl trifft man sie aber häufiger. Einer der Gründe wird wohl mit der oft schlechten Lesbar- und Wartbarkeit zusammenhängen. Wer das richtig beherrscht, der kann da aber einiges mit zaubern. Ein Beispiel hierfür ist ein Ausdruck für die Validierung von E-Mailadressen gemäß RFC822. Ein wahres Monster! Die Java-Pattern-Api scheint aber gut damit zurechtzukommen (Im Gegensatz zum Syntaxhighlighter, deshalb gibt es den Code heute in Plain).

String regexp = "(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[\\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[\\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[\\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*:(?:(?:\\r\\n)?[ \\t])*(?:(?:(?:[^()<>@,;:\\\\\".\\[\\]\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\]\\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*)(?:,\\s*(?:(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*|(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)*\\<(?:(?:\\r\\n)?[ \\t])*(?:@(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*(?:,@(?:(?:\\r\\n)?[\\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*)*:(?:(?:\\r\\n)?[ \\t])*)?(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\"(?:[^\\\"\\r\\\\]|\\\\.|(?:(?:\\r\\n)?[ \\t]))*\"(?:(?:\\r\\n)?[ \\t])*))*@(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*)(?:\\.(?:(?:\\r\\n)?[ \\t])*(?:[^()<>@,;:\\\\\".\\[\\] \\000-\\031]+(?:(?:(?:\\r\\n)?[ \\t])+|\\Z|(?=[\\[\"()<>@,;:\\\\\".\\[\\]]))|\\[([^\\[\\]\\r\\\\]|\\\\.)*\\](?:(?:\\r\\n)?[ \\t])*))*\\>(?:(?:\\r\\n)?[ \\t])*))*)?;\\s*)";
boolean matches = Pattern.compile(regexp).matcher("Mark Mustermann <email@email.de>").matches();
System.out.println(matches);

via Unite-IT

Donnerstag, 4. November 2010

Wie in den guten, alten Zeiten des Web

Erinnert sich noch jemand an die guten alten Zeiten des Web? Zuerst hat AOL die Haushalte mit Online-CDs geflutet und nicht viel später wurde der Webspace-Anbieter Geocities zu einer der größten Anlaufstellen für private, selbst gebastelte HTML-Seiten, die so ein gewisses Feeling hatten. Dieses Feeling kann man sich mit dem Geocities-izer zurückholen.

Freitag, 29. Oktober 2010

PHP4 und das domxml

Vor sehr langer Zeit habe ich mal eine PHP4-Anwendung geschrieben, die jetzt auf einen neuen Server migriert werden soll. Natürlich gibt es da kein PHP4 mehr, was auf Grund der recht brauchbaren Abwärtskompatibilität von PHP5 kein allzu großes Problem darstellt. Die Anwendung ist nämlich eher einfach gehalten. Probleme habe ich nur mit den Konstrukten, bei denen ich die rudimentäre Objektorientierung von PHP4 verwendet habe. Was es aber ganz konkret mit PHP5 nicht mehr gibt, ist die domxml Bibliothek. Mit PHP5 kommt das nämlich alles onboard mit. Damit das ganze trotzdem funktioniert gibt es XML transition from PHP4 domxml to PHP5 dom. Einfach includen und schon stehen die alten domxml-Funktionen wieder zur Verfügung. Der Migrationsaufwand tendiert an dieser Stelle gegen null. So etwas gefällt mir natürlich.

Montag, 25. Oktober 2010

Swingen mit Wingdings, Webdings und Symbol

Auf Windowsplatformen gehören die Symbol-Fonts ja irgendwie zum Inventar. Ich erinnere mich an ein frühes Windows und eine Hand voll Fonts, die da mitgekommen sind. Einer davon natürlich Wingdings. Auf meinem guten alten XP finden sich da inzwischen auch noch ein paar mehr Derivate, wie Windings 1 und 2, sowie Symbol. Ich persönlich kann mich nicht erinnern, die Fonts je gebraucht zu haben und in Zeiten von Unicode sind die ja auch zum Teil obsolet geworden. So kann man locker mit einem "\u263b" und Times New Roman einen Smiley zaubern . Nun wurde ich aber mit Zeichen aus den Symbol-Fonts konfrontiert und damit, dass diese nicht darstellbar seien. Datsächlich gibt es dazu auch einen Bugeintrag, der aber nur lapidar erklärt, dass der Font seine Zeichen eben nur in einem bestimmtem Unicodebereich preis gibt. Für viele Benutzer dürfte das eher wie ein Bug aussehen, wenn sie, wie gewohnt, ein 'S' eingeben und trotz Symbol-Font kein Summenzeichen erhalten, wie es in jeder nativen Anwendung der Fall ist. Weil wir das aber brauchen, habe ich da eben mal ein paar Zeilen zu gebastelt. Es ist zwar nicht die feine Englische den String neu zu bauen, aber eine bessere Möglichkeit bietet sich leider nicht. Besser wäre es natürlich, man würde direkt in die View, bei Swing also in die UI-Klassen, eingreifen.

public static String convertToSymbol(final String s) {
        if(s==null) {
            return null;
        }
        
        final StringBuilder sb = new StringBuilder(s.length());
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            sb.append((char)(c | 0x0000F000));
        }
        return sb.toString();
    }

Freitag, 22. Oktober 2010

Bald kein Java mehr auf OS X

Apple will wohl seine proprietären Ambitionen weiterführen und markiert Java als deprecated für OS X. Das heißt in der Praxis, keine Pflege der OS X-Implementierung von Apples Seite. Vielleicht gibt sich Oracle ja her, glauben tue ich das aber nicht. Bisher hat Oracle wenig Uneigennützigkeit an den Tag gelegt, denn das Interesse für OS X wird sich bei Oracle in deutlichen grenzen halten.

Worauf das ganze abzielt lässt sich nur spekulieren. Bisher wurde die Java-Implementierung von Apple auch eher unregelmäßig gepflegt und Sicherheitslücken standen oft lange offen, bis Besserung kam. Man distanziert sich vermutlich von dem ohnehin ungeliebten Kind Java und setzt weiter voll auf Entwicklungen aus dem eigenen Haus. Wer für OS X entwickeln möchte, der soll das vermutlich am besten mit der eigenen IDE XCode tun. Jedenfalls dann, wenn man Wert darauf legt, seine Anwendung auch im zukünftigen Appstore für OS X zu präsentieren.

In meiner subjektiven Konzern-Unbeliebtheitsskala ringen Apple und Oracle derzeit um den ersten Platz. Wenn auch aus unterschiedlichen Gründen.

via http://javabarista.blogspot.com/2010/10/deprecated-java-fur-mac-os-x.html

Update 13.11
Es geht doch. Ehrlich gesagt bin ich überrascht. via heise

Donnerstag, 21. Oktober 2010

Webanwendungen beschleunigen

Ist schon blöd, wenn sich Webanwendungen langsam anfühlen. Die (leider in PHP geschriebene) Bibliothek CSS-JS-Booster nutzt einige Tricks, um den Webseitenaufbau zu beschleunigen. Besonders nett finde ich den, Dateien zu einem HTTP-Request zusammenzufassen. Einen guten Einstiegsartikel zu der Thematik gibt es bei peterkroener.de.

Unschlagbar ist ansonsten noch die Uralttechnik, mit Sprites zu arbeiten. Kurzbeispiel zum reinschnüffeln gibt es hier: www.websiteoptimization.com

Dienstag, 19. Oktober 2010

Oracle macht sich unbeliebt

Ist schon schlimm, was Oracle sich mit den von Sun zugekauften OpenSource-Projekten erlaubt. Erst mit Opensolaris (www.golem.de/1008/77424.html) dann LibreOffice (www.golem.de/1010/78718.html). Microsoft hat ja auch ziemlich lange gebraucht, um zu lernen, wie man mit Communities umzugehen hat. Bei Oracle steht die Erfahrung wohl noch aus. Ich hoffe, LibreOffice kann sich weiterhin behaupten und Oracle lernt im Umgang mit Community-Projekten dazu. Die Arroganz, mit der der Konzern derzeit auftritt, finde ich einfach unerträglich.

Sonntag, 17. Oktober 2010

Auftraggeber und "Etwas ganz einfaches"

Wenn Auftraggeber bei der Anforderung einer Funktionalität mit Sätzen wie "Muss auch gar nicht kompliziert sein" oder "Da reicht etwas ganz einfaches" kommen, schrillen bei mir immer die Alarmglocken. In den allermeisten Fällen reicht die einfache Lösung nämlich nicht und ein Rattenschwanz an Forderungen wird nachgereicht. Folgendes Verhalten stellt sich im weiteren Verlauf häufig ein:

1. Es soll nach Möglichkeit nichts kosten, was aber nicht heißt, dass die ausgelieferte Lösung den Ansprüchen genügt. Dies ist oft der Auftakt um das Gefeilsche einer jeden weiteren kleinen Funktion.
2. Der Auftraggeber meint eine Funktion, die er von woanders kennt, ist sich aber nicht im klaren, was da in Wirklichkeit alles hinter steckt. Wenn die Ideenquelle benannt wird, lässt sich der Aufwand im Vorfeld evaluieren und der Schaden in Grenzen halten. Leider kommt es meist anders und man kann im Nachhinein jede einzelne Funktion auf Zuruf nachpflegen.
3. Eigentlich hat sich der Auftraggeber gar keine Gedanken gemacht, was er eigentlich will. Entsprechend diffus ist die Beschreibung. Insich widersprechende Funktionalitäten sind da keine Seltenheit.

In vielen solcher Fälle meint der Auftraggeber, außerdem auf so etwas wie ein Pflichtenheft verzichten zu können, was in der Praxis heißt, dass ein solches gemäß dem Gesprächsverlauf erstellt werden muss. Die Überraschung ist oft groß, welchen Umfang dieses dann trotz der geringen Funktionalität doch annimmt.

Benoît Mandelbrot und die rekrusive Mathematik

Die Mandelbrot-Formen, oder Apfelmännchen kennt vermutlich jeder, der mit C= oder älteren Computern aufgewachsen ist. Der Entdecker dieser Formen, Benoît Mandelbrot, ist vor kurzem verstorben. Ein Genie, dessen Ideen in der Fachwelt nicht unumstritten waren. Diese im Grunde ganz einfachen, rekursiven Bilder gehörten bei mir, wie wahrscheinlich auch bei vielen anderen, zu einer der frühen Schritte auf dem Weg zur Programmierung. Umfänglich verstanden, was diese Mandelbrot-Formen eigentlich ausmachen, habe ich aber erst viel später. Aus aktuellem Anlass, möchte ich hierzu eine Dokumentation empfehlen, die die Möglichkeiten und das Vorkommen fraktaler Mathematik auf spannende Weise erzählt. Die vier Videos gehören zusammen.















Und nach der Dokumentation hat man auch gleich doppelten Spaß im Klassiker der Mandelbrot-Darstellung ein wenig herumzuklicken: http://spaz.ca/aaron/SCS/fractals/

Freitag, 17. September 2010

Stackoverflow: Die besten Code-Kommentare

Gerade vorhin habe ich wieder mal einen Hinweis zu einem Beitrag auf Stackoverflow zugespielt bekommen. Dieses Mal handelt es sich um eine Sammlung von Source-Code-Kommentaren.

http://stackoverflow.com

Mittwoch, 1. September 2010

Mp3-Player und die Titel-Reihenfolge

Jedes meiner Mp3-Fähigen Geräte hat die Macke, es mit der Reihenfolge der Titel nicht so genau zu nehmen. Das ist bei Hörbüchern natürlich besonders dämlich, weil ich mir die einzelnen Kapitel nur ungern in mehr oder minder zufälliger Reihenfolge anhören mag. Eine Lösung verspricht das Utility FATSort. Problem ist nämlich häufig, dass die Reihenfolge, mit der die Titel im Dateisystem eingetragen wurden, den Ausschlag gibt.

via Dirks Logbuch

Sonntag, 15. August 2010

Strangest language feature

wieder ein Post bei Stackoverflow, den ich noch nicht kannte, und der eine richtig gute Sammlung von unmöglichen Sprachfeatures bietet.

http://stackoverflow.com/questions/1995113/

LadyJava Music Video for JavaZone

Einfach mal cool gemachtes Musik-Video. Mal gucken, wie lange das online ist, bis das auch wieder gesperrt wird.

Mittwoch, 16. Juni 2010

Dateisystem überwachen

Monitoring von Dateisystemaktivitäten ist mit Java-Bordmitteln im grunde kaum Möglich. Klar, man kann ein Verzeichnis immer wieder einlesen und auf Veränderungen reagieren, was aber mehr eine Krücke darstellt und nur bis zu einer gewissen Menge überwachter Verzeichnisse/Dateien effizient möglich ist.

Abhilfe schaffen will da die JNotify-API, die das Monitoring via JNI auf Betriebssystemebene erledigt. Es gibt Implementierungen für Windows, Linux und Mac, was wohl das Gängigste abdecken dürfte. Mit Java7 bekommen wir ja ohnehin eine finale Lösung für sowas. Und bis es soweit ist, kann man ja ganz gut mit JNotify leben, wenn man es braucht.
Link
http://jnotify.sourceforge.net/index.html

Montag, 14. Juni 2010

Google I/O 2010

Videovorträge der Entwicklerkonferenz I/O 2010 gibt es auch online: http://code.google.com/intl/de-DE/events/io/2010/sessions.html

Es sind ein paar ganz interessante Sachen dabei. Ist schon super, dass man das alles mittlerweile per Stream nach Hause geliefert bekommt. Link

Sonntag, 13. Juni 2010

Linux für den Desktop

Ich benutze ja seit geraumer Zeit Ubuntu bzw. seit kürzerem den Ableger Mint. Der anhaltende Desktop-Produktiveinsatz ist mir tatsächlich erst mit Ubuntu gelungen. Den ersten Anfang hat damals eine Suse 4 gemacht. leider hat die Suse nur ein paar Monate gehalten, bis ich sie endgültig kaputtgespielt hatte. Seit dem hat Linux in verschiedenen Distributionen immer wieder mal einen meiner Rechner besiedelt. Meist allerdings nur für wenige Monate, bis irgendetwas kaputt gegangen ist, was das System unbrauchbar gemacht hat. Am nachhaltigsten habe ich mich damals über Suse und Yast geärgert.

Inzwischen ist Linux auf dem Desktop angekommen. Man kann damit produktiv arbeiten, ohne sich mit den Interna beschäftigen zu müssen, was Linux für den Einsatz bei Eltern und anderen vor "Generation X"ler befähigt. Auf der anderen Seite kann man immer noch basteln, was das Zeug hält. Eine Umgebung, die die technische Kreativität fördert, wie es keine kommerzielle kann.

Weil absehbar ist, dass ich privat kein Windows mehr einsetzen werde, habe ich die Javaprogramme, die ich schon längere Zeit nutze, paketiert. Das kam mir bei meinem Umstieg auf Mint auch zugute, weil nach einer Neuinstallation keine manuelle Nachinstallation mehr nötig war. Den dazugehörigen Webspace für das Repository habe ich ich von einem Freund gesponsert bekommen, weil ich bis heute keine größere Menge Webspace zur Verfügung habe. Irgendwann sollte ich das mal Ändern. Kostet ja auch nicht die Welt.

Mein Repository gibt es übrigens hier: http://fschuster.de/ubuntu/

Freitag, 21. Mai 2010

Videostreams vom Lotus JamCamp 2010

Einige sehenswerte Videostreams der Vorträge vom Lotus JamCamp 2010. Mein Favorit ist "Per Anhalter durch das Enterprise 2.0". Sehr amüsant!

http://www-01.ibm.com/software/de/jamcamp/programm.html

Montag, 17. Mai 2010

Programmiererwitze

Dieser Post bei Stackoverflow war mir noch gar nicht bekannt. Eine inzwischen recht umfangreiche Sammlung von Programmiererwitzen.

http://stackoverflow.com/questions/234075/what-is-your-best-programmer-joke/

Freitag, 30. April 2010

Eindeutige IDs erzeugen

Innerhalb einer Anwendung eine eindeutige ID zu erzeugen ist nicht besonders schwierig. Mir würden spontan Konstrukte mit synchronized, static und einem increment einfallen. Alles viel zu kompliziert. Seit Java 1.5 gibt es für so etwas die Klasse java.util.UUID und die Methode randomUUID. Diese und zwei weiterer Möglichkeiten erklärt javapractice.com.

http://www.javapractices.com/topic/TopicAction.do?Id=56

Dienstag, 27. April 2010

Free GUI Pack von Art.Gen


Art.Gen bietet ein freies Set an GUI-Grafiken als PSD zum Download an. Auch die Verwendung für kommerzielle Zwecke ist gestattet.

Ein Klick auf freebies offenbart übrigens noch ein paar weitere grafische Schätzchen, die der Eine oder Andere als nützlich empfinden könnte.

http://www.webdesignerdepot.com/2010/04/exclusive-free-gui-pack-from-art-gen/

Freitag, 23. April 2010

Videovorlesung

Introduction to Computer Science and Programming von Eric Grimsom und John Guttag vom MIT. Die Videovorlesungen richten sich an Studenten mit geringen oder gar keinen Programmierkenntnissen. Es geht hierbei weniger um syntaktische Sachen, als viel mehr um Problemlösungen. Vierundzwanzig folgen mit je einer Stunde gilt es abzuarbeiten. Verwendet wird übrigens Python.

http://academicearth.org/courses/introduction-to-computer-science-and-programming


via Schockwellenreiter

Donnerstag, 22. April 2010

Wo Müll liegt...

... kommt schnell neuer hinzu. Der Sinnspruch trifft insbesondere auch auf Code zu.

Mittwoch, 3. Februar 2010

Ziparchiv im Speicher entpacken

Neulich gab es den Wunsch die zu verarbeitenden XML-Dateien in Form eines Zip-Archives anliefern zu lassen. Weil sich der Dateizugriff verbot, sollte dies im Speicher geschehen. Hier der (verallgemeinerte) Code:

static List<byte[]> extract(byte[] zipData,
String codepage, boolean verbose) {
try {
final JarInputStream jar = new JarInputStream(new
ByteArrayInputStream(zipData));
final ArrayList<byte[]> result = new ArrayList<byte[]>();

final ByteArrayOutputStream bout = new ByteArrayOutputStream();
final byte[] readBuff = new byte[4096];

while (jar.getNextEntry()!=null) {
int len = 0;
while ((len = jar.read(readBuff))!=-1) {
bout.write(readBuff,0,len);
}

result.add(bout.toByteArray());
bout.reset();
}
jar.close();

return result;
} catch (Exception e) {
return null;
}
}

Donnerstag, 28. Januar 2010

Oracle auf Kurs

Oracle pflegt die Produktpalette von Sun weiter. Die Oracle Datenbank kann nun zusammen auf Sparc Rechnern verkauft werden und Solaris kann direkt auf die Bedürfnisse von Oracle zugeschnitten werden. Ich bin mir sicher, dass bei der Javaentwicklung auch die Eine oder Andere Kursänderung zu verzeichnen sein wird. Die geplante Zusammenlegung von Java SE und ME über eine Abstraktionsschichten finde ich schon mal recht spannend. Harren wir also der Dinge die da kommen.

Artikel:
JNBB - Joschs NetBeans Blog, Heise