Reading, Meaning and Sense
Reading a line of code feels like one act. It is at least three. We form a meaning from our own context, we compare it - if we bother - with the meaning the author had, and we form an opinion about whether what it describes makes any sense. The first two are reading. The third is judgement, and it arrives uninvited, mixed into the same moment, wearing the same clothes.
This part of the Hardly Readable series is about keeping them apart, using an example that failed at two of the three steps while looking flawless at the first: a line so easy to read that it took me a while to notice it was describing the wrong thing, and then the wrong design.
Warum ich künftig häufiger nur auf Englisch schreibe
Bisher habe ich viele Artikel auf Deutsch und Englisch veröffentlicht. Künftig werde ich viele neue Beiträge nur noch auf Englisch schreiben. Es wird weiterhin deutsche Artikel geben, aber nicht mehr selbstverständlich zu jedem englischen Beitrag eine deutsche Fassung. Das ist keine Entscheidung gegen die deutsche Sprache oder gegen deutschsprachige Leser. Es ist eine Entscheidung gegen die doppelte Arbeit, denselben Gedanken in zwei Sprachen zu formulieren und dauerhaft in zwei Fassungen zu pflegen.
Source Code Is Language
Code is read far more often than it is written, and “hard to read” has a measurable substrate: working memory (see Code and Cognition). We tend to discuss readability in terms of names, length, and nesting, but there is an older structure underneath all of it. A line of code that performs an action can be read as a sentence, and sentences have a word order. When the order matches the one our language gave us for free, the line reads itself; when it does not, the reader has to re-assemble the meaning before they can use it.
This part of the Hardly Readable series is about that order: a method call written in the grammar we already know - subject, predicate, object - reads almost for free, and the common ways of breaking that grammar are exactly the ways a call gets hard to read.
Literal Composition Is Not Abstraction
Code is read far more often than it is written, and “hard to read” has a measurable cognitive substrate (Code and Cognition). Every piece of information a reader encounters should either have a strong association in long-term memory or a short resolution path through working memory. When neither is true, comprehension becomes costly.
This part of the Hardly Readable series is about a common misunderstanding: removing duplication can support readability, but it can also have the opposite effect. The latter occurs quite often if we do not introduce an abstraction but a Literal Composition.
Go - how Opinions Differ on Simplicity
As a software engineer I always recommend keeping code as simple as possible. And so I was quite open-minded about Go, which claimed to offer only the simplest features. And my default programming language is dead boring Java. So I expected to learn some elegant language concepts that make it easier to write and understand code.
Code und Kognition
Vor einigen Jahren hatte ich die Idee, dass das Verständnis von Code von unserem Gehirn abhängen muss. Ich hatte von George Millers “Magischer Sieben” gehört und versuchte, sie anzuwenden. Eine Freundin wies mich darauf hin, dass sie nie von der 7 gehört hatte, sondern von der 4. Anfangs interessierte mich nur, was davon stimmte, aber schließlich dauerte die Nachforschung einige Jahre und das Modell wurde immer ausgefeilter. Was war das Ergebnis?
Naming - in der Literatur
Naming ist ja, glaubt man Phil Karlton, eines der schwierigsten Probleme in der Informatik. Offensichtlich nicht nur da. Zumindest drängte sich mir beim Lesen von G.R.R. Martins Hauptwerk “Das Lied von Eis und Feuer” in deutscher Übersetzung auf, dass hier jemand mit Namen gekämpft hat:
Tiefe Assertions
Gelegentlich hat man es beim Unit-Testing nicht mit einfachen Typen zu tun, sondern z.B. mit
- Ergebnissen von Webservice-Schnittstellen (REST/SOAP)
- ORM-gemappte Datenbank-Ergebnissen
- generierte Parse-Bäumen
- jegliche Arten von Graphen oder Bäumen
Solche Typen sind oft tief (oder rekursiv) geschachtelt und deswegen nicht ganz so einfach zu testen. Mit dem richtigen Werkzeug geht es aber – z.B. mit dem IsEquivalent-Matcher von XrayInterface …
Testgenerierung in Java - eine Übersicht
So langsam möchte ich meine Erkenntnisse über Testgenerierung zusammenfassen. Seit etwa einem Jahr habe ich einen Vortrag über Testgenerierung in Java auf diversen Konferenzen positioniert und inzwischen gibt es so etwas wie eine Essenz aus diesen Vorträgen …
Test-Generatoren - Stand der Technik
Vielleicht interessiert den einen oder anderen eine Übersicht über Testgeneratoren. Eine ziemlich vollständige Liste findet man auf der Zusammenfassung von Zoltán Micskei über Code-based test generation. Die meisten der hier gelisteten Projekte sind eher akademischer Natur und bestenfalls für Beispielcode einsetzbar.
Reguläre Ausdrücke in Java
Unkritisch habe ich jahrelang reguläre Ausdrücke (java.util.regex) in Java verwendet. Auf der Universität hatte man ja gelernt, dass reguläre Ausdrücke effizient ausgewertet werden können.
Als ich in einem Projekt in einer großen Menge von Dokumenten (>10.000) eine große Menge von Wörtern (>1.000) suchen wollte, erinnerte ich mich an die Universität. Anstatt jedes Wort einzeln zu suchen, wollte ich den regulären Ausdruck <Wort1>|<Wort2>|...|<Wort1000> suchen. Das müsste theoretisch deutlich effizienter sein, als nacheinander alle Wörter in jedem Dokument zu durchsuchen … Aber regulärer Ausdruck ist nicht regulärer Ausdruck und die schnellen Automaten der Vorlesung sind nicht die, die in Java verwendet werden.
Exaktes String Matching in der Praxis
Zunächst war mein Interesse an Textsuchalgorithmen eher akademischer Natur - ich wollte den Algorithmus lediglich verstehen und implementieren können. Nachdem aus dieser Leidenschaft ein kleines Projekt (StringSearchAlgorithms) entstanden ist, begann ich Vergleiche anzustellen …
Es stellte sich heraus, dass viele Algorithmen zwar im akademischen Sinne funktionieren, aber in der Praxis erschwert (oder gar nicht) einzusetzen sind. Tatsächlich sind die akademischen Algorithmen für ganz bestimmte Situationen optimiert und sehr spezifisch gebunden an:
- Prozessorarchitekturen
- Encoding-Formate
- Programmiersprachen (APIs)
Es folgt eine Übersicht über die Herausforderungen, die die Praxis an Textsuche stellt.
Testrecorder – Quo Vadis
Nach meinem Vortrag auf dem Karlsruher Entwicklertag habe ich jetzt auch einmal Zeit, ein wenig über die Zukunft von Testrecorder zu reden … Testrecorder ist ein Java-Werkzeug zum Aufzeichnen von Laufzeitsituationen. Ausgehend von einem Methodenaufruf werden der Zustand davor und der Zustand danach aufgezeichnet. Das Ergebnis wird dann als JUnit-Test ausgegeben.
Naming von Interfaces und Implementierungen
Viele kennen vielleicht die Konstellation, dass man zu einem Interface FormDataValue eine Implementierungsklasse FormDataValueImpl vorfindet. Auf meine leicht überhebliche Kritik bekomme ich dennoch oft Zustimmung und eine Entschuldigung der Form: “Wir haben uns teamintern gegen Interface-Namenskonventionen wie z.B. IFormDataValue entschieden.”
Da fühle ich mich dann etwas missverstanden. Beim Naming gibt es nun mal mehr Möglichkeiten. Warum kommen manche Teams nur auf diese zwei? Ich versuche das Problem einmal etwas tiefer zu analysieren …
Textsuche in Java (mit der JDK-API)
Textsuche ist eine recht häufige Problemstellung, die immer dann auftritt, wenn wir prüfen, ob ein String in einem anderen vorkommt. Die JDK-Standard-API bietet hier ein paar Grundfunktionalitäten, allerdings gibt es deutlich effizientere Methoden, insbesondere für größere Muster und größere Texte.
Dieser Beitrag könnte für diejenigen von Interesse sein, die sich für Textsuche und die Möglichkeiten der Java-API (bzw. Alternativen darüber hinaus) interessieren.
Private Variablen erreichen mit XRayInterface
In diesem Beitrag möchte ich eine Möglichkeit eröffnen, wie man auf private Variablen und Methoden zugreifen kann, indem man seine Klassen an passende Interfaces adaptiert. Warum? In meinem früheren Beitrag über das Reparieren von Legacy-Code habe ich kurz erwähnt, dass eine große Herausforderung beim Testen der Zugriff auf den verborgenen Zustand (private Variablen/Felder) vor und nach der Ausführung der Methoden ist.
Reparieren von Legacy-Code – Automatisch
Viele Projekte verwenden bereits automatisierte Regressionstests. Leider ist das genau dann nicht gegeben, wenn man es am nötigsten hat, nämlich bei Übernahme von fremdem (ungetesteten) Legacy-Code. Hier wünsche ich mir nicht nur automatisierte Regressionstests, sondern auch automatisierte Testerstellung. Warum gibt es so etwas nicht?
Meine Präsentationen
Ich habe auf diversen Konferenzen Vorträge gehalten. Eine volle Liste findet man bei Talks.
Meine Projekte
Ich habe diverse Open-Source-Projekte auf Github, Meine erfolgreichsten Projekte haben eine eigene Webpräsenz bekommen:
- Allotropy - JUnit-Engine und Assertions für Responsive-Layout-Testing
- Testrecorder - Testgenerierung aus typischen Anwendungsmustern
- XRayInterface - Objektorientierte Adapter für private Felder und Methoden
- String Search Algorithms - Sammlung von String-Suchalgorithmen