Freitag, 21. Juni 2013

Book Review: The Clean Coder by Robert C. Martin

In meinem ersten Book Review möchte ich das Buch "The Clean Coder" von Robert C. Martin vorstellen. Ihr findet den Link zum passenden Amazon Artikel in meiner Buchliste unter Nummer 2.

In dem Buch beschreibt Robert C. Martin was für ihn einen "professional programmer" ausmacht. Er beginnt mit einem Erlebnis und zeigt dann Stück für Stück professionelle Verhaltensweisen auf, indem er zunächst das unprofessionelle Gegenteil vorstellt um an diesem zu Erläutern was eben daran unprofessionell ist und wie man es besser macht. So stellt er schrittweise Verhaltensregeln für professionelle Programmierer auf.

Ich habe eigentlich nichts erwartet als ich dieses Buch zur Hand nahm. Ich dachte mir "mal schauen was da drin steht" und wurde nur begeistert. Robert C. Martin lese ich sehr gerne, da seine Art zu schreiben selbst die trockene Theorie anschaulich und witzig darstellt und so den Stoff leicht zugänglich macht. Auch das hat er in "The Clean Coder" wieder unter Beweis gestellt. Witzig führt er durch viele Situationen die ein jeder Programmierer garantiert schon erlebt hat. Seine Charaktere sind sehr stereotypisch und treffen dennoch sehr die Realität. Der Chef, der eigentlich keine Ahnung vom Programmieren hat und nur will dass das Projekt schnell fertig wird, trifft auf den 08/15 Entwickler der zu jeder noch so dämlichen Anforderung "Ja" und "Amen" sagt und gerne Überstunden in Kauf nimmt um eine unrealistische, utopische Deadline, die er selber nicht mitbestimmen durfte einzuhalten. Das mag sehr überzogen klingen aber genau das ist die Grundlage dieses Buches die es Uncle Bob erlaubt anschaulich "falsche" und "richtige" Verhaltensweisen aufzuzeigen und verständlich zu machen.

Nachdem man dieses Buch gelesen hat will man es am liebsten allen in den Kopf prügeln. Wenn der Chef mal wieder ankommt und eine utopische Deadline vorgibt möchte man ihm am liebsten sagen "Hier lies dieses Buch danach reden wir weiter". Dieses Buch kann die Arbeitswelt (und zwar nicht nur in der Softwareentwicklung) verändern, wenn sich jeder danach richten würde wäre die Welt unkomplizierter und verständnisvoller.

Meine Empfehlung könnt ihr euch nun vermutlich schon denken: Dieses Buch ist ein MUST-READ für jedermann.

Leserlicher Code ist wichtig

Dass leserlicher Code wichtig ist wissen wir. Zumeist kommen, wenn man nach einer Begründung fragt, Argumente wie "Wenn der Code nicht leserlich ist fällt es einem schwer den Code zu warten" oder "Nicht leserlicher Code macht die Fehlersuche schwierig" und und und.

Ein Grund für leserlichen Code wird aber zumeist vernachlässigt: Er macht es schlicht und ergreifend einfacher den Code zu lesen! Nur wenn Code leserlich ist kann er einfach gelesen werden und nur wenn Code gelesen werden kann, kann er auch verstanden werden.

Das ist jetzt vermutlich auch nichts neues, also weshalb fand ich es wichtig darüber zu schreiben? Ganz einfach weil es mir gerade jetzt so richtig bewusst geworden ist. Ja gewusst habe ich das schon "immer", aber dennoch neigt man dazu Code eben nicht leserlich zu halten. Man implementiert ihn so wie es einem gerade passt. Gliedert Methoden aus oder eben nicht. Nennt diese wie es einem gerade sinnvoll erscheint. Erscheint.... eben das ist das Problem! Ist man in der Materie drin denk man sich vieles dazu und vieles scheint eben klar und nicht erklärungsbedürftig. Man kennt den Kontext und weiß worum es geht und genau das hindert uns daran immer leserlich zu schreiben. Es macht einem auch nicht nur selber das Leben schwer, sondern auch Anderen. Ja, unleserlicher Code ist schlecht wartbar, weil man ihn versteht. Ja, unleserlicher Code macht die Fehlersuche schwer, weil man ihn nicht versteht. Ja, unleserlicher Code macht es anderen schwer ins Projekt einzusteigen, weil man ihn nicht versteht. Es läuft also alles aufs gleiche hinaus. Unleserlicher Code ist unverständlich!

Deswegen mein Apell an alle: Geht Quellcode des öfteren durch und nicht nur wenn ihr etwas ändern müsst/wollt. Lest einen Tag später nochmal drüber und ändert die Namen wenn sie nicht eindeutig sind, gliedert Methoden aus, wenn das dem Verständnis hilft. Refaktoriert was das Zeug hält um euren Code vom Vortag "aufzuhübschen". Ich jedenfalls werde mir genau dies angewöhnen. Morgens als erstes ein Selbsreview durchzuführen. Natürlich wird der Code so nicht perfekt aber besser und das ist mein Ziel: Besser zu werden.

Donnerstag, 10. Januar 2013

Meine Tomaten, oder die Pomodoro-Technik

Viele kennen das Problem vermutlich. Man hat sich einen Plan gemacht was man über den Tag erledigen will und immer kommt irgendwas dazwischen: Kollegen die etwas wissen wollen, Chefs die etwas erledigt haben wollen etc. pp. Ein paar mal habe ich es erlebt, dass ich gar nichts von dem erledigt bekommen habe was ich ursprünglich geplant hatte. Doch wie ändert man dies?

In dem Buch "The Clean Coder" von Robert C. Martin habe ich von der Pomodoro-Technik (http://www.pomodorotechnique.com/) gelesen und diese ausprobiert. Die Pomodoro-Technik eignet sich zum Zeitmanagement für geistige Aufgaben. Angewandt ist sie einfach. To-Do-Liste schreiben, Aufgabe (aus der To-Do-Liste) bestimmen die man bearbeiten will, Küchenuhr (Pomodoro) auf 25 Minuten drehen und los gehts. Das besondere dieser Thechnik sind meines Erachtens die festgelegten Zeiteinheiten und Pausen. Eine Zeiteinheit beträgt wie erwähnt 25 Minuten. Diese 25 Minuten werden als Pomodoro oder Tomate bezeichnet[1]. Nach jeder Pomodoro werden 5 Minuten Pause eingelegt, in denen NICHT an der während der Tomate bearbeiteten Aufgabe weitergemacht oder auch nur drüber nachgedacht werden soll. Diese Pause dient dazu Abstand zu gewinnen, sein Mana (wie Martin es in "The Clean Coder" bezeichnet) wieder aufzufüllen und erfrischt in die nächste Tomate zu starten. Daraus resultiert, dass man sich am Ende nicht ausgelaugt fühlt. Während einer Tomate soll man alle Ablenkung und Unterbrechung vermeiden und unterbinden. Kollegen die stören vertröstet man auf nach die Tomate Telefonate werden danach erledigt etc. Man arbeitet also 25 Minuten konzentriert an EINER Aufgabe. Zu Statistik-Zwecken kann/soll man die Anzahl der für eine Aufgabe benötigten Tomaten notieren. Dies sind nur ein Paar Aspekte der Technik, der Rest ist auf der angegebenen Seite nachzulesen wenn bedarf besteht.

Soweit, so gut. Kurzes googlen führte mich zur Pomodoro-App (http://www.pomodoroapp.com/) da ich verständlicherweise in einen Büro, welches ich nicht alleine bewohne keine Küchenuhr klingeln lassen wollte, und das alle 25 Minuten... Also App runtergeladen und los gings. Die App ist denkbar simpel. Aufgaben eintragen die für heute markieren und auf der Aufgabe die man bearbeiten will auf "start" klicken.

Die App wird zu einem kleinen süßen Widget was man auf dem Desktop an eine beliebige Stelle schieben kann und stört so nicht mehr. Sind die 25 Minuten abgelaufen wird die App wieder groß und die Pause fängt an. Auch hier möchte ich auf die weiteren Funktionen nicht eingehen.

Ich habe nun also meine Aufgaben die ich noch auf dem Zettel hatte in die App übertragen und mit einer beliebigen angefangen. Zu beginn ist es furchtbar schwierig in den 25 Minuten keine Störungen zuzulassen aber das wird mit der Zeit einfacher. Nun kan ich irgendwann an den Punkt, dass ich zeitaufändige Tests durchführen musste, die allerdings nicht beobachtet werden mussten. Solche Aufgaben eignen sich nicht für die Pomodoro-Technik, da die Technik voraussetzt, dass man während der 25 Minuten aktiv arbeitet. Ich habe hier also eine andere Aufgabe begonnen und erst nach Ablauf einer Tomate nach dem Teststand geschaut. Konnte ich auf den Test reagieren habe ich dies wieder mit der Pomodoro-Technik getan. Hierbei fiel mir eine andere Schwachstelle auf. Eine Pomodoro MUSS ablaufen und komplett bearbeitet werden. Hat man nun eine Aufgabe, welche lediglich 5 Minuten in Anspruch nimmt und die man nicht erweitern kann, durch andere Teilaufgaben beispielsweise, lohnt es sich eigentlich nicht dafür die Technik zu verwenden. Ich will ja nicht, dass die Zeitstatistiken für 2 unterschiedliche Projekte vermischt werden.

Fazit

Die Technik ist für große/lange Aufgabe sehr gut geeignet. Sie verhindert, dass man sich zu sehr reinsteigert und dadurch seine ganze Energie veräußert. Für die Abschließende Phase einer Entwicklung wo zumeinst nur kleinere Buxfixes und Tests anstehen kann man sie jedoch getrost vergessen. Hier lohnt es sich einfach weiter so zu arbeiten wie immer. Eine gute Sache kann man jedoch auch auf kleine Aufgaben mitnehmen. Lass dich nicht stören bis du fertig bist. So wird eine Aufgabe effizient erledigt.

Montag, 26. November 2012

Was man erwartet und was man bekommt...

Als ich das erste Mal mit der Aufgabe in Berührung kam Dateien und Verzeichnisse aus einem gegebenen Verzeichnis zu ermitteln stieß ich auf die Möglichkeit das mit der statischen Klasse Directory und den entsprechenden Methoden GetFiles und GetDirectories zu tun. Diese Methoden bekommen das zu durchsuchende Verzeichnis, evtl. einen Suchstring und auch optional eine SearchOption. Die Dokumentation besagt, dass alle Dateien (bzw. Verzeichnisse) innerhalb des angegebenen Pfads ermittelt und als string[] zurückgegeben werden. Das habe ich geglaubt und es hat auch bis zu einem Verhängnisvollen Tag problemlos funktioniert. An diesem sehr ernüchternden Tag war ich dabei zu erforschen warum ein, von mir entwickeltes Modul zum Löschen von Dateien und Verzeichnissen nicht ordnungsgemäß funktionierte. Als ich so fröhlich debuggte und in alle möglichen und unmöglichen else- und case-Zweige beine Breakpoints setzte lief ich tatsächlich in einen solchen hinein. Allerdings war die Meldung der Exception höchst verwunderlich, denn dort hieß es "Die Datei kann nicht gelöscht werden, da es sich um ein Verzeichnis handelt". Mit diesem Verzeichnis versuchte ich nämlich File.Delete aufzurufen. Zuvor hatte ich aber alle Dateien mithilfe von Directory.GetFiles aus dem Verzeichnis geholt. Also konnte es der Logik entsprechend nicht sein, dass es sich bei der Datei um ein Verzeichnis handelte.

Dies bedurfte weiterer Forschung. Es handelte sich tatsächlich um ein Verzeichnis in dessen Namen ein Punkt enthalten war. Nun stellte sich die Frage, wenn Verzeichnisse mit Punkt nun als Dateien interpretiert werden, was ist mit Dateien ohne Dateiendung? Die Überprüfung dessen zeigte, dass eben diese Dateien als Verzeichnisse interpretiert wurden. Verlässt man sich nun also darauf, dass die Methoden Directory.GetFiles und Dierectory.GetDirectories die erwarteten Daten (nämlich nur Dateien oder nur Verzeichnisse) zurück geben kann man, so wie ich, Probleme bekommen. Ob dieses Verhalten nun richtig oder falsch ist möchte ich hir nicht beurteilen, allerdings ist dieses Verhalten nicht das von mir erwartete.

Braucht man nun also alle Dateien oder Unterverzeichnisse sollte man hier auf die Klasse DirectoryInfo zurückgreifen. Dies hat zwei Schwächen, zum ersten handelt es sich nicht um eine statische Klasse (im Gegenteil zu Directory), was bedeutet, dass immer eine Instanz erstellt werden muss. Zum zweiten bekommt man hier ein FileInfo-Array (bei GetFiles) und ein DirectoryInfo-Array (bei GetDirectories). Mithilfe der Eigenschaft FullName kann dann der Pfad mit Datei-/Verzeichnis-Namen ermittelt werden.

Fazit: Wenn man fremden Code verwendet kann man sich nicht drauf verlassen, dass was man bekommt auch das ist, was man erwartet.

Montag, 8. Oktober 2012

Wieso gutes Softwaredesign so schwierig ist

Ein Grundsatz von dem ich absolut überzeugt bin ist: Software steht und fällt mit ihrem Design!. Die Oberfläche mag für den Benutzer das wichtigste sein, und eine schlechte Oberfläche sorgt auch dafür, dass Software nicht verwendet wird. Nun kommt das dicke ABER, denn eine gute Benutzeroberfläche lässt sich in einem guten Design auch leichter realisieren. Was für Vorteile bringt ein gutes Softwaredesign noch?
  • Leichtere Fehlerbehebung, da Fehler einfacher gefunden werden können und ihre Beseitigung keine (im Optimalfall) weiteren Fehler verursacht.
  • Leichtere Erweiterbarkeit, die Struktur flexibel ist und neue Anforderung einfach integriert werden können.
  • Leichtere Änderbarkeit von detaillierten Modulen durch wenig Abhängigkeiten.
  • Gute Wiederverwendbarkeit, da die Komponenten klar getrennt sind.
Man sieht also: gutes Design hat eigentlich nur Vorteile. Warum ist es dann so schwer dieses Umzusetzen? Die Antwort ist denkbar einfach und typisch Mensch: Die Faulheit des Entwicklers. Und ich möchte mich hier weiß Gott nicht ausschließen :) Ganz zu Beginn eines Projektes ist noch alles gut. Man hat sich ein tolles, simples, den Anforderungen entsprechendes Design überlegt und ist auch schon fleißig dabei dieses umzusetzen, da kommt der Auftraggeber und will auf einmal noch zusätzlich dies und jenes. Und achja wenn diese Funktion doch ein bisschen anders wäre.... Und das Unheil beginnt! Da man ja schon mitten in der Implementation ist versucht man die Änderungen irgendwie mit rein zu wursteln. Da wird hier halt noch auf diese Klasse zugegriffen und dort noch ausnahmsweise eine zusätzliche Abfrage implementiert. "Halt noch" und "ausnahmsweise" sind hier allerdings fatal, denn dies wird kein Einzelfall bleiben und eigentlich weiß man das auch, aber es ist nunmal jetzt gerade so viel komfortabler zu entwickeln. Dieser Prozess wir in eine endlose Schleife laufen und das wissen wir alle und je öfter dies passiert um so mehr verkümmert und erodiert das Design und die Software. (Hier spricht man auch von Softwareerosion)

Es gibt natürlich Regeln an die man sich halten kann um gutes Design zu gewährleisten, aber das größte Problem liegt hier tatsächlich an der Gewohnheit des Entwicklers. Zunächst muss man sich die richtige Einstellung aneignen um anschließend mit den richtigen Vorgehensweisen auch effektiv arbeiten zu können. Nehmen wir hier als Verbildlichung eine Küche. Die Küche ist unser Programm. Ist die Küche ordentlich, hat unser Programm eine ordentliche Architektur, eine unordentliche Küche repräsentiert hingegen ein schlechtes Design. Das Kochen ist die Implementierung. Beim Kochen wird die Küche nun unordentlich, das lässt sich nicht vermeiden. Was tun wir also? Wir räumen auf! Oftmals fehlt aber die Lust aufzuräumen und man lässt es bleiben. Dadurch vermehrt sich das Chaos bis es fast unbezwingbar ist. Wir als Entwickler müssen uns also angewöhnen die Küche immer sofort aufzuräumen statt irgendwann später. Ebenso müssen wir versuchen beim Kochen so wenig Unordnung wie möglich zu verursachen. Eine Anforderung eben schnell schmutzig implementieren, weil man ja später Aufräumen kann erhöht den Aufwand fürs Aufräumen und verringert die Motivation die Aufräumarbeiten durchzuführen.

Zusammenfassend kann man sagen: gutes Softwaredesign ist so schwierig weil wir es und schwer machen. Mit Disziplin und der richtigen Einstellung ist gutes Design einfach umzusetzen und spart Nerven und Arbeit.

Donnerstag, 27. September 2012

NDepend - THE Static Analysis-Tool for C#/.NET

For my bachlorthesis at the university of applied sciences in Bremen I was looking for a tool, which can calculate metrics from a given sourcecode. Therefore I went to Google and searched for "static analysis tool C#". A lot of results were given to me and Wikipedia holds a long list of such tools, for example FxCop, ReSharper, CodeRush, JustCode and NDepend. I downloaded all free tools for testing.
Result: only one tool was able to calculate the metrics I needed. NDepend! The rest were nice tools and Visual Studio plugins for easier refactoring.

For my bachelorthesis I primary used the analysis results from NDepend. In this article I want to give a short overview of my work with NDepend and talk about what I like about NDepend.

NDepend originally offers a great choice of metrics (http://www.ndepend.com/Metrics.aspx). There are many different kinds of metrics available at NDepend.


(big version)
Additionally - if the standard metrics don’t suffice - there is the possibility to create and calculate your own metrics with querys. The rules for the standard metrics can also be modified. Therefore these querys are included (for example you can edit the range of the metrics). With this unbounded alternatives to get relevant information about the sourcecode are given.

Beside the calculation of metrics, NDepend supports the visualisation of dependencies with graphes and matrices. I’m not able to evaluate this feature because I didn’t need it. A quick
overview allows me to say, that the dependencies between classes, assamblies and methods can be shown.


(big version)
NDepend is a very complex tool but with the right handling it offers lots of possabilities to help at the developing of big softwareprojects. The given design-goals can, espacialy in big developer groups, easily be verified and necessary adjustments can be initiated quickly. You can also implement rules for codeconventions but there are other tools, like CodeRush and ReSharper, which are better qualified to do this job. NDepend shows the rule violation not before a code analysis is done. Nevertheless I can recommend NDepend as a professional developing tool for any teamsize.

Mittwoch, 26. September 2012

NDepend - DAS Statische Analyse-Tool für C#/.NET


Im Rahmen meiner Bachelorthesis an der Hochschule Bremen im Studiengang "Dualer Studiengang Informatik" bin ich auf die Suche nach einem Tool gegangen, welches mir von einem existierenden Quellcode diverse Metriken berechnen kann. Was macht man also? Man geht auf Google und gibt dort in die Suchzeile "Statische Analyse Tool C#" ein. Nun erhält man nach dieser Suche auch diverse Treffer. Wikipedia bietet sogar eine ganze Liste solcher Tools an, darunter FxCop, ReSharper, CodeRush, JustCode und NDepend. Alle diese Tools wurden (sofern kostenfrei verfügbar) heruntergeladen und ausprobiert.
Fazit: Nur ein einziges bot Metrikermittlung so wie ich es mir vorstellte. NDepend! Der Rest waren nette Tools und VisualStudio Plugins zur verbesserten Refakturierung.

Für meine Bachelorthesis stützte ich mich also hauptsächlich auf die Analysen von NDepend. Hier möchte ich kurz meine Arbeit mit NDepend beschreiben und berichten, was mir an diesem Tool so gut gefällt.

NDepend bietet eine ziemlich beachtliche Auswahl an Metriken von Hause aus an (http://www.ndepend.com/Metrics.aspx). Von Größen- über Komplexitäts- bis hin zu Strukturmetriken ist hier alles möglich.

(Große Version)
Als zusätzliche Option - sollten die Standardmetriken nicht ausreichen - können mit Hilfe von Querys eigene Regeln definiert und ermittelt werden. Die Regeln der Standardmetriken sind zudem mitgeliefert und können nach Bedarf angepasst werden (beispielsweise können die Grenzen verändert werden). Dies bietet schier unendliche Möglichkeiten relevante Informationen über den Quelltext zu ermitteln.

Neben der Metrikermittlung bietet NDepend zudem die Möglichkeit Abhängigkeitsgraphen und -matritzen anzeigen zu lassen. Zu diesem Thema kann ich leider jedoch nichts sagen, da ich dieses Feature nicht verwendet habe. Ein grober Überblick zeigte mir jedoch, dass hier sowohl die Beziehungen zwischen Assemblies, wie auch Klassen und Methoden visualisiert werden können.

(Große Version)
NDepend ist ein sehr umfangreiches Tool und ist der richtige Umgang mit diesem einmal erlernt, so bietet es zahlreiche Möglichkeiten bei der Entwicklung von großen Softwareprojekten hilfreich eingesetzt zu werden. Die gesetzten Designziele können gerade in größeren Entwicklergruppen leicht verfolgt werden und nötige Korrekturmaßnahmen so schnell eingeleitet werden. Auch lassen sich Regeln zu Entwicklungsrichtlinien hinterlegen. Hier bieten sich aber die bereits oben erwähnten Tools wie CodeRush und ReSharper besser an. Diese zeigen direkt beim Entwickeln Verstöße der Richtlinien an, wohingegen NDepend diese erst bei der Analyse des Projektes bemängelt. Nichts desto trotz kann ich NDepend als professionelles Entwicklungswerkzeug für jede Projektgröße empfehlen.