Kategorie: Software-Entwicklung

Summerschool “Agile Software Development”

Der FIT hat in diesem Jahr neben den schon mehrmals angebotenen — und im übrigen ebenfalls empfehlenswerten — Firmenexkursionen auch eine Veranstaltung zum Thema Agile Softwareentwicklung angeboten: Summerschool “Agile Software Development”.

Als ich die Ankündigung gelesen hatte, wusste ich sofort, dass ich da mitmachen wollte. Mit agiler Softwareentwicklung wollte ich mich sowieso mal beschäftigen. Außerdem sollte das Ganze auch sehr praxisnah sein. (Wenn man auf ner Uni studiert, sind wirklich praxisnahe Lehrveranstaltungen eher selten.) Und zum Dritten bot sich so mal wieder die Gelegenheit, mit ein paar Firmen in Kontakt zu kommen. weiter lesen »

Wollt ich nur mal gesagt haben…

  • Redundanzen sind doof.
  • Variablen, die eigentlich lokal deklariert sein könnten, aber als Attribut in der Klasse stehen, sind eklig.
  • Variablen, die als String deklariert werden, obwohl sie Integers, enums oder gar Objekte sein könnten, sind scheußlich.
  • Objekte, die erzeugt, aber nicht verwendet werden, sind sinnfrei.
  • Magic Values sind böse.
  • Konstanten sind nicht böse. Man darf sie ruhig verwenden.
  • Bezeichner, die nicht das kommunizieren, was sie bezeichnen, sind nervig.
  • Bezeichner, die absolut gar nichts aussagen, sind <hier stark negativ besetztes Adjektiv einsetzen>
  • Lange Parameterlisten sind schwer lesbar und zeugen von schlechtem Design.
  • Wenn ich bei Methoden Parameter abzählen muss, um zu gucken, ob ich einen vertauscht hab, ist da etwas faul.
  • Wenn ich Parameter mit Dummy-Werten füllen muss, läuft da was schief.
  • Magic Values sind böse.
  • Objektorientiert programmiert man nicht, wenn man irgendwie Objekte verwendet, sondern, indem man objektorientiert denkt.
  • Objekte sind etwas anderes als Tabellen. Ja, wirklich.
  • if (a == null) return null; else return a; ist das selbe wie return a;
  • REST ist jetzt nicht furchtbar kompliziert. Aber den Unterschied zwischen Ressourcen und Verben sollte man schon verstanden haben.
  • Passwörter speichert man nicht im Klartext.
  • SQL Injection kann man verhindern
  • Magic Values sind böse.
  • Eine Klasse mit über 800 LOC ist vermutlich eher weniger “simple”.
  • NullPointerExceptions sollte man nicht fangen, sondern verhindern.
  • Obsoleten Code kann man entfernen. Man benutzt dazu wahlweise [DEL] oder [Backspace].
  • Code einheitlich einzurücken, tut nicht weh. Zumal einem die IDE dabei helfen kann.
  • Fehlerbehandlung heißt nicht, im Fehlerfall nen Stacktrace auszugeben und dann einfach weiter zu machen, als wär nichts gewesen.
  • Hab ich schon erwähnt, dass Magic Values böse sind?
  • Meine Zehnägel tun weh.

Wollt ich nur mal loswerden…

SoftwareArchitekTOUR: Patterns in der Java-Welt

Gerade gehört: SoftwareArchitekTOUR: Patterns in der Java-Welt. Vor einiger Zeit hab ich die ersten beiden Episoden gehört. Jetzt hab ich mir mal diese angetan.

Und natürlich kann ich mich gewisser Kommentare nicht enthalten:

  • Double-Checked-Locking wird erklärt. Allerdings wird nicht darauf verwiesen, dass das Pattern kaputt ist. Zumindest wenn man kein volatile benutzt. Nähere Infos in der Wikipedia
  • Es wird davon gesprochen, dass das get/set-Idiom dazu verleitet, es überzuverwenden. Also man macht überall Getter und Setter und vergisst dabei, der Klasse sinnvolle Methoden zu verpassen. Die Problematik sehe ich auch. Ich frage mich nur momentan, ob Properties wie in Delphi/C#/Ruby/etc. hier einen Einfluss haben und wenn ja welchen. Positiv oder Negativ? Ich vermute einen positiven Einfluss, bin mir da aber nicht ganz sicher.
  • Immutability wird IMHO leider schlecht erklärt. Es geht natürlich nicht nur darum, dass Objekte mit gleichem Wert gleich sind, sondern auch, dass die Objekte (mehr oder weniger) zustandslos realisiert werden.
  • DependencyInjection hätte ich wahrscheinlich nicht verstanden, wenn ich nicht schon wüsste, was es ist. Generell scheint es mir so zu sein, dass der Podcast nur einen groben Überblick und ein paar Buzzwords liefert. Das hört sich jetzt wie vernichtende Kritik an, aber so ist es nicht gemeint. Überblick geben ist gut. Viel mehr kann man in ner dreiviertel Stunde auch nur schwer abhandeln. Man darf nur nicht mit falschen Erwartungen an den Podcast rangehen.
  • Zu Multiple Dispatch hab ich schonmal was geschrieben.

Enbugging — Wie wir Fehler machen und wie wir sie vermeiden

Wie im letzten Jahr, hab ich auch dieses Mal wieder einen Vortrag auf den Delphi-Tagen gehalten. Diesmal gings ums Fehler vermeiden. Man könnte auch sagen, um konstruktive QA-Maßnahmen. Egal. Jedenfalls gings um Bugs.

Abstract

“Wenn Debugging der Vorgang ist, Fehler aus einem Programm zu entfernen, dann ist Programmierung der Vorgang, Fehler in ein Programm einzubauen.” So liest man zuweilen im Netz und manchmal ist es nur zu wahr. Stunden verbringen wir damit, umständlich einen Fehler zu suchen, den wir zuvor noch ganz mühelos einbauen konnten. Wäre es da nicht praktischer, statt uns mit Debugging aufzuhalten, das Enbugging, das Einfügen von Fehlern gar nicht erst zu betreiben? Letztendlich sind wir ja eigentlich selbst schuld: Bugs entstehen nicht aus dem Nichts. Vielmehr erzeugen wir — meist unabsichtlich — Bedingungen, unter denen diese kleinen Krabbelviecher so prächtig gedeihen. Dieser Vortrag soll zeigen, wie Bugs entstehen und was wir dagegen tun können. Eine vollständige Betrachtung des Themas kann dabei natürlich nicht erfolgen. Stattdessen wird ein Überblick gegeben, um danach einzelne Aspekte zu vertiefen.

Folien

Wie versprochen gibts hier die Vortragsfolien: Download: Enbugging (Größe: 1.14 MB; bisher 198 mal heruntergeladen)

Ich hab wieder eine Gratwanderung zwischen vortragsunterstützenden Folien und Infos für alle, die den Vortrag nicht gesehen haben, versucht. Ob mir das gelungen ist, darf jeder selbst beurteilen (und mir am besten auch noch ein bisschen Feedback geben).

Hinweise

  • Eigentlich wollte ich noch erwähnen, dass Tony Hoare (der übrigens auch den QuickSort erfunden hat) auch dran schuld ist, dass in Pascal die geschweiften Klammern Kommentare sind. Hoare hat Vorbedingungen und Nachbedingungen in geschweiften Klammern vor bzw. hinter Code geschrieben (“Hoare-Tripel“) und damit formale Verifikation gemacht. Niklaus Wirth gefiel das Ganze so gut, dass er die geschweiften Klammern zu Kommentarzeichen machte.
  • Um die Beispiele zu verstehen, sollte man sich genau angucken, wie die Bezeichner (insbesondere die Klassen) heißen. Man sollte daraus erraten können, worum es geht. Meine Beispiele waren meist allgemein bekannte Datenstrukturen (List, Map, Set) oder standen in losem Zusammenhang mit Feedreadern, HTML-Parsern u.ä.
  • “Meine Fehlerliste” enthält viel zu wenige Daten, um hieraus schon etwas Sinnvolles ableiten zu können. Da muss ich noch mehr sammeln. Das hab ich beim Vortrag zwar schon dazu gesagt, aber es steht so explizit nicht in den Folien.
  • Was ich auch im Vortrag erwähnt hab, aber nicht auf den Folien steht: Bidirektionale Assoziationen sind starke Kopplungen. Also wenn sich zwei Module gegenseitig kennen, anstatt dass nur ein Modul das andere kennt, aber nicht umgekehrt. Man sollte deshalb zusehen, dass man möglichst nur einseitige Beziehungen hat.
  • Der Anhang enthält noch weitere Beispiele und Hinweise auf weiterführende Themen, die nicht angesprochen werden konnten.

Errata

  • Auf Folie 60 fehlt ein not. Es müsste also heißen if not FInnerList.Contains(item) then.

Bitte um Feedback

Das Feedback, das ich bisher bekommen hab, war durchweg positiv. Das freut mich. Ich will hier aber trotzdem nochmal nach Feedback und explizit auch Kritik fragen. Nur, wenn ich weiß, was ich besser machen kann, kann ich in Zukunft etwas weniger schlimme Vorträge machen… *g*

Insbesondere würde mich folgendes interessieren:

  • Hab ich verständlich geredet? War ich vielleicht zu schnell?
  • Waren die Beispiele verständlich? Nachvollziehbar? Praxistauglich?
  • Wie versteht man die Folien, wenn man sich den Vortrag nicht angehört hat?
  • Waren Thema und Inhalt angemessen? Zu theoretisch? Zu einfach? Zu schwer? Zu trivial?
  • Kann ich sonst etwas verbessern?

Enbugging — Was ich auf den Delphi-Tagen erzählen will

“Wenn Debugging der Vorgang ist, Fehler aus einem Programm zu entfernen, dann ist Programmierung der Vorgang, Fehler in ein Programm einzubauen.” Und ich fürchte das stimmt. Debugging ist manchmal nervig, auf jeden Fall aber zeitaufwändig. Und dabei sind wir doch eigentlich selbst schuld: Mühelos bauen wir Fehler in unseren Code ein, damit wir diese dann wieder mit viel Mühe erkennen, lokalisieren und beheben können.

Schön wäre es doch, wenn wir die Fehler gar nicht erst einbauen würden. Wir tun das nicht bewusst. Man könnte das jetzt einfach als Nachlässigkeit oder “Versehen” abtun, aber meistens ist es mehr: Wir erzeugen Bedingungen unter denen Bugs leicht entstehen. Wir tricksen und quasi selbst aus, indem wir unsere Programme so entwerfen, dass wir fast unausweichlich Bugs machen müssen, wenn wir nicht höllisch aufpassen. Uns ist das nicht immer bewusst, aber es ist so. Einige solche Bugschleudern hab ich selbst schon fabriziert.

Um dem zu begegnen gibt es IMHO drei Dinge, die wir tun können:

  1. Verstehen wie Code funktioniert, welche Probleme und Fallstricke existieren und welche Fehler man machen kann.
  2. Verstehen welche Fehler man persönlich macht.
  3. Bedingungen erzeugen, unter denen Bugs nicht so leicht entstehen oder zumindest schneller erkannt werden.

Das ist mehr oder weniger das, was ich auf den diesjährigen Delphi-Tagen in Köln erzählen will. Einen Vorgeschmack gibts schonmal hier: Download: Enbugging-preview (Größe: 383.76 kB; bisher 65 mal heruntergeladen)

Ich hab viel zu erzählen und weiß noch nicht ganz, ob ich davon noch etwas kürzen oder verändern muss. Deshalb erstmal nur das Kapitel zur Einführung. Den Rest gibts dann als finale Version nach oder kurz vor den Delphi-Tagen. Das, was ich hier zeige, ist zwar mit Abstand das langweiligste Kapitel, aber zumindest ist ein Inhaltsverzeichnis dabei, sodass man schonmal nen Eindruck gewinnen sollte, ob es sich lohnt, mir zu zu hören.

Alles in Allem werde ich nichts bahnbrechend Neues vorstellen. Das ist teilweise Erstsemester-Stoff [1], aber ich werde versuchen, aufzuzeigen, warum das wirklich praxisrelevant ist. Relevanter als ich das im ersten Semester erkannt hab. Es wird ne Menge Beispiele geben, die auch mit Abstand die meiste Arbeit gemacht haben und hoffentlich den ein oder anderen Aha-Effekt erzeugen. Mal sehen, ob mir das gelingt. Zumindest ist das mein Ziel.

Vorab kann ich schonmal sagen, dass ich den Titel geklaut hab. Und zwar von diesem sehr lesenswerten Artikel: The Art of Enbugging von Andy Hunt und Dave Thomas.

[1] OK, wirklich nur teilweise

Joshua Bloch über API Design

Joshua Bloch hatte vermutlich schon die ein oder andere schlechte Idee. Wahrscheinlich sogar ein paar richtig bescheuerte Ideen. Und genau deshalb hat er Ahnung.

In der Java API stecken ne ganze Menge blöde Ideen, aber auch sehr gute. Typischerweise kamen zuerst die blöden Ideen wie die ursprüngliche Implementierung der Date-Klasse oder die Idee Stack von Vector abzuleiten und dann die guten, die leider etwas spät dran sind, sodass die dann nur noch die Notsitze im Namensraum gekriegt haben.

Wie viel davon Joshua Bloch nun selbst verbrochen hat, weiß ich nicht. Jedenfalls gehört er deshalb zu den Leuten, die Ahnung vom API-Design haben. Meiner Meinung nach lernt man nur aus Fehlern wirklich gut. Entweder aus den eigenen oder aus denen von anderen. Wer lieber aus den Fehlern von anderen lernen will, sollte sich vielleicht mal seinen Vortrag “How To Design A Good API and Why it Matters” ansehen. Dort beschreibt er nämlich genau das: Was man so alles falsch gemacht hat, wie man es besser machen kann und warum das nicht nur für API-Designer relevant ist, sondern (in abgeschwächter Form) für jeden Entwickler. Sehr empfehlenswert.

Den Vortrag gibts in mehreren Varianten:

Besonders gut gefallen mir die Beispiele. Da ich gerade selbst für meinen Vortrag Beispiele hab finden müssen, weiß ich, dass das viel mehr Arbeit ist, als man vielleicht denkt.

Warum wir manchmal unterschiedlicher Meinung sind

Also nicht generell, sondern als Entwickler. Vielleicht hätte ich auch sagen sollen “Warum Software-Entwicklung nicht Mathe ist”. Aber auch das wäre missverständlich. Es geht mir um folgendes:

Bekanntlich sehe ich Softwareentwicklung als das ständige Ausbalancieren von Prinzipien oder Daumenregeln. So gern es wir uns auch vielleicht wünschen würden, es gibt kein allgemeines Patentrezept für gute Software. Es gibt kein allgemeines Kochrezept, keinen Algorithmus o.ä. nach dem wir uns richten könnten und der uns ein gutes Ergebnis garantieren würde.

Zumal “gut” auch wieder nur schwer fassbar ist. Einzelne Aspekte einer Software lassen sich messen. Manche ganz gut (Größe in LOC), manche mit Aufwand (z.B. Performance) andere nur mit Abstrichen (Kopplung, Usabiliy, Wartbarkeit, …). Wir sind also auf Heuristiken wie “Erfahrung”, “Bauchgefühl” und eben “Meinung” angewiesen. Natürlich kann man versuchen, alles irgendwie zu quantifizieren und auf Basis historischer Projektdaten eine Metrik für “Güte” zu definieren. Man kann das tun. Inwieweit das zielführend ist, ist jedoch wieder eine andere Frage [1].

Wie gesagt: Softwareentwicklung ist das Ausbalancieren von Daumenregeln, man könnte auch “Kräften” sagen. Diese Kräfte ziehen in verschiedene Richtungen und wir müssen ein Kräftegleichgewicht finden. Das Problem ist nur, dass wir nur sehr schwer sagen können, wie stark diese Kräfte nun sind.

Die folgenden Aussagen wird vermutlich kaum ein Entwickler ernsthaft anzweifeln:

  • Einfach ist besser als kompliziert (KISS)
  • Allgemeingültig/generisch ist besser als speziell
  • Goto ist böööse (goto statement considered harmful)
  • Globale variablen sind böööse (global variable considered harmful)
  • Starke Bindung, lose Kopplung

Die Frage ist nur: Wie stark sind diese “Kräfte”? Und hierbei gehen die Meinungen auseinander. Wenn Entwickler also unterschiedlicher Meinung sind, dann hängt das selten daran, dass bestimmte Effekte/Prinzipien/Kräfte/Daumenregeln generell angezweifelt werden. Vielmehr streitet man sich um die Bewertung derselben. Ist in diesem konkreten Fall Allgemeingültigkeit oder Einfachheit wichtiger? Lieber eine technisch kompliziertere Lösung nehmen, die mehr kann oder besser eine einfache, die ihre Einschränkungen hat? Lieber ausnahmsweise mal ne globale Variable nehmen und dadurch den Code etwas einfacher machen oder darauf verzichten und damit die Kopplung reduzieren?

Es ist also meist nicht so, dass einer recht hat und der andere unrecht. Oft kann man guten Gewissens beide Positionen vertreten. Das macht entsprechende Diskussionen natürlich nicht immer einfach, weil man nicht wie in Mathe sagen kann “Da ist der Fehler, du hast unrecht”. Das kann anstrengend sein. Dennoch sind solche Diskussionen wichtig, denn sie helfen, eine passende Lösung für die gegebene Problematik zu finden und außerdem lernt man auch sie eine ganze Menge.

[1] IMHO sind Metriken in gewissem Umfang schon sinnvoll. Inwieweit ist aber wieder eine Bewertungsfrage.

Version Control by Example

Versionsverwaltungssysteme (engl. version control systems, VCS) sind ausgesprochen praktisch. Nein, ich denke eigentlich eher sie sind geradezu unabdingbar notwendig für jeden Entwickler. Jeder, der Code schreibt und diesen nicht versioniert, handelt IMHO fast schon fahrlässig. Und zwar unabhängig davon, ob man alleine entwickelt oder mit anderen im Team.

Bei mir befindet sich alles, von dem ich denke, dass es für mich in zwei Wochen immer noch relevant sein wird, in einem Repository. Angefangen hab ich mit Subversion, mittlerweile verwende ich aber eher git.

Mercurial und Bazaar hab ich mir ebenfalls angeguckt, bin aber letztendlich bei git geblieben. Der Unterschied zwischen diesen Systemen ist jedoch nicht allzu groß, auch, wenn es unter den jeweiligen Anhängern mitunter zu Grabenkämpfen kommt. Die üblichen Flames eben, nichts Besonderes. Jedes dieser drei Systeme hat seine Vor- und seine Nachteile und es gibt mitunter lustige Vergleiche. Zudem werden alle drei aktiv weiter entwickelt, was entsprechende Vergleiche, die man zuhauf im Netz findet, sehr schnell altern lässt.

Egal: Ich werde mich nicht groß an der Diskussion beteiligen. IMHO sind die Unterschiede im Detail zwar interessant, praktisch aber zweitrangig. Jedenfalls gefallen mir diese Verteilten Versionsverwaltungssysteme (DVCS) besser als die zentralen wie SVN. Einfach, weil ich wirklich unkompliziert für jeden Kleinkram schnell ein Repository anlegen kann.

Nun, warum schreib ich das alles? Ich habe eine wirklich tolle Einführung zu dem Thema gefunden: Version Control by Example. Das ist ein 210 Seiten kleines, unterhaltsam geschriebenes sehr anschauliches Buch, das in die Thematik einführt und an einem kleinen Fallbeispiel Subversion, Mercurial, git und eine Eigenentwicklung namens Veracity in Aktion zeigt und miteinander vergleicht. Bazaar wird leider nicht behandelt, aber auch so ist das Buch sehr empfehlenswert.

Ich hab das kostenlose PDF gelesen. Außerdem hab ich gerade gesehen, dass der Autor das Buch sozusagen als Marketing-Gag auch verschenkt. Hätte Eric Sink sein Buch ein halbes Jahr früher rausgebracht, so hätte ich es sicher meinen SEP-Studenten wärmstens empfohlen. Und das mach ich jetzt auch mal allgemein. Meine Empfehlung an alle die

  • Bisher immer noch kein VCS einsetzen (jetzt aber schnell!)
  • Sich über DVCS informieren wollen (das lohnt sich!)
  • Einen kurzen Praxisvergleich zwischen SVN, git, Mercurial (und Veracity) interessant finden

Eiffel: Das Esperanto unter den Programmiersprachen

Ich gehöre zu denjenigen, die sich gerne immer mal wieder eine neue Programmiersprache ansehen. Nicht um in jeder dieser Programmiersprachen letztendlich auch produktiv zu arbeiten, aber um mal “übern Tellerrand zu gucken”.

Das Ganze ist nicht nur interessant, sondern hat auch den Vorteil, dass man sehr viel über unterschiedliche Herangehensweisen und Programmierkulturen erfährt. Die einzelnen Sprachen unterscheiden sich nicht nur in der Syntax, sondern auch in der Denkweise, wie Probleme gelöst bzw. Code geschrieben wird. Sowas ist manchmal augenöffnend und kann auch mal helfen, kreative Lösungen für schwierige Probleme zu finden, die man in “seiner” Programmiersprache hat.

Das heißt natürlich nicht, dass man anfangen sollte, die eigene Sprachkur zu missachten. Im Gegenteil: Manchmal ist es sinnvoller, eine schlechte, aber allseits bekannte Lösung zu verwenden, als eine elegante, die für andere Entwickler “fremdartig” wirkt. Code schreibt man i.d.R. ja nicht nur für sich selbst, sondern auch für die anderen Entwickler im Team, etc.

Aber für schwierige, nicht-alltägliche Probleme kann man auch mal eine kreative Lösung gebrauchen. Und dafür ist es ganz gut, wenn man mit anderen Sprachen und Programmierkulturen in Kontakt kommt. Außerdem ist es mit Programmiersprachkulturen ähnlich wie mit natürlichen Sprachen: Sie verändern und beeinflussen sich gegenseitig und das ist eine Bereicherung. [1]

Ich bin nicht der einzige, der so denkt. In “The Pragmatic Programmer” [2] geben Andy Hunt und Dave Thomas den Rat: “Learn at least one new language every year.” Und da komm ich sogar in etwa hin. Die meisten davon kann ich nicht (mehr) wirklich gut. Wirklich produktiv einsetzen kann ich momentan davon nur ne Hand voll. Aber darum gehts ja auch nicht.

Nun, ich hab mich jetzt ein bisschen mit Eiffel beschäftigt. Aus Zeitgründen leider nur oberflächlich. So hab ich praktisch keinen echten Code geschrieben sondern nur Tutorials und Code gelesen. Das bedeutet natürlich, dass viel von der Syntax bald wieder verflogen sein wird. Aber wie gesagt: Darum gehts mir gar nicht.

Ich hab also einen Eindruck von Eiffel bekommen. Um jetzt mehr als ein Bauchgefühl vermitteln zu können, müsste ich wohl wirklich mal ein paar hundert Zeilen Code schreiben. Aber dafür hab ich momentan keine Zeit. Hier also nur mal ein erster Eindruck. weiter lesen »

Patterns

Überblick


Motivation

Es soll vorkommen, dass man in der Softwareentwicklung Probleme lösen muss. Und es soll vorkommen, dass man ein Problem, dass man schonmal gelöst hatte, nochmal lösen muss. Und es soll vorkommen, dass sich manche Probleme ähneln. Typischerweise versucht man, wenn man ein Problem zum zweiten Mal lösen muss, schneller zu sein als beim ersten Mal. Das nennt sich “lernen”.

Aber es gibt noch eine weitere Möglichkeit, beim zweitem Mal Arbeit zu sparen: Wiederverwendung. Besteht die Lösung eines Problems in einem Stück Code, dann kann man diesen verallgemeinern (parametrisieren) und beim zweiten Mal einfach hernehmen und benutzen. Das Ergebnis ist dann eine Prozedur, eine Klasse oder allgemein: ein Modul.

Aber auch, wenn die Lösung nicht in einem Stück Code besteht, sondern in einer bestimmten Herangehensweise, einer bestimmten Strukturierung oder Idee, so kann man sie wiederverwenden. Das Gegenstück zum Modul, dem wiederverwendeten Code, ist das Pattern bzw. Muster, sozusagen die wiederverwendete Idee. weiter lesen »

powered by WordPress | QuickLaTeX | WordPress Themes