Posts tagged: SEP

Seid stolz auf eure Fehler

Ja wirklich. Aber ich fürchte, das muss ich erklären.

Wir lernen meines Erachtens hauptsächlich aus Fehlern. Entweder aus eigenen oder aus denen von anderen. Deshalb sage ich meinen Studenten immer, sie sollen keine Angst haben, auch mal was Falsches zu sagen. Im Gegenteil: Wenn man eine falsche Antwort gibt, wird man sich viel leichter merken, was die richtige ist. Wenn man nur richtig geraten hat, hat man Pech, weil man sich dann schlechter daran erinnern wird, als wenn man die falsche Antwort gegeben hätte.

Fehler machen ist also gut. Weil man daraus lernt. Wenn man daraus lernt. Meistens ist das eher der komplizierte Schritt. Das ist etwas, das ich auch immer versuche, meinen Studenten bei zu bringen. Und heute bin ich mal an der Reihe, auf meinen eigenen Ratschlag zu hören. Ich habe einen Fehler gemacht. Die Seminararbeit, die ich geschrieben habe, ist nicht so gut angekommen. Sie war wohl u.a. nicht so gut verständlich. Und ich hab ein bisschen gebraucht, bis ich verstanden habe, warum. weiter lesen »

Von Eiswaffeln und Tests

Tests scheint irgendwie niemand gerne zu machen. Warum auch immer. Das sehe ich gerade jetzt wieder. Ich betreue ja wieder mal das Softwareentwicklungsprojekt und da soll im Team eine Software entwickelt werden. Und selbstverständlich muss man die auch testen (das schreiben wir sogar vor). Hier aber mal eine kurze Statistik, wie das aussieht:

  • Innerhalb von ca. 2 Wochen haben von den 17 Gruppen gerade mal 5 überhaupt angefangen, Tests zu schreiben.
  • Davon benutzen gerade mal zwei Stubs.
  • Dafür hat eine Gruppe ganz offensichtlich schon Probleme, das Prinzip von JUnit zu verstehen
  • Und eine hat bisher nur ein paar Fingerübungen gemacht.

Wir kannten solche Probleme schon aus den letzten Jahren. Also hatten wir extra eine Saalübung zum Thema Testen gemacht. Wir hatten erklärt warum man testet, wie man das tut, wie und warum man Stubs verwendet und warum Test-First eine sinnvolle Strategie ist. Geholfen hat es offensichtlich wenig. :-(

Dabei könnten Unit-Tests helfen, Zeit zu sparen, weil man Bugs früher bemerkt. Ja genau: Richtig eingesetzt würden die Tests eigentlich Zeit sparen. Eigentlich…

Ich will jetzt aber wenigstens noch ein bisschen was zu Tests sagen. Nicht weil ich große Hoffnung hätte, dass das auf wundersame Weise 17-x SEP-Gruppen bekehrt (die meisten werden das hier wohl eh nicht lesen). Aber ich hab ein paar interessante Links, die vielleicht wenigstens *irgendwem* helfen könnten… weiter lesen »

Wie man Software entwirft

Wie schreibt man eigentlich Software?
– Nun, man tippt einfach den Code.
Und wie weiß man welchen Code man schreiben muss?
– Äh…

– Also, wenn man plangetrieben entwickelt, hat man ein Modell der Software, die man implementiert.
Und wie kommt man zu dem Modell?
– Man schreibt es auf, z.B. mit UML.
Und wie weiß man, was man aufschreiben muss?
– Äh…
– Also, wenn man agil entwickelt, entwickelt man i.d.R. testgetrieben, d.h. man schreibst zuerst Tests und aus den Tests kann man ersehen, welches Design man zu verwenden hat.
Und wie weiß man, wie man den Testcode schreibt?
– Man benutzt ein Unittest-Framework und testet damit die zukünftige Schnittstelle.
Und wie weiß man, wie die zu testende Schnittstelle aussehen muss?
– Äh…

OK, die Antwort auf diese Frage wird etwas länger. weiter lesen »

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 354 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?

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.

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 »

Softwareentwicklungs-Prinzipien: Eine Übersicht

Ich hatte ja schon angekündigt, dass ich mein Versprechen auf den letzten Delphi-Tagen in Raten erfüllen werde. Immer mal wieder landet etwas zu den Softwareentwicklungs-”Daumenregeln” oder -Prinzipien hier im Blog. Vielleicht werde ich die Artikelserie irgendwann in ein Tutorial packen oder auf andere Weise verarbeiten. Mal sehen.

Zuerst aber ist mal ein grober Überblick notwendig und diesen möchte ich hier geben.

Wie schon mehrfach erwähnt, sehe ich Softwareentwicklung als das ständige Ausbalancieren von “Daumenregeln” oder “Prinzipien”. Solche Daumenregeln gibt es eine ganze Menge. Ich hab bisher schon so an die hundert dieser Regeln zusammengetragen und werde die hoffentlich auch bald mal sortieren und hier posten. Diese Daumenregeln können sehr unterschiedlich sein. Manche sind sehr allgemein, andere hingegen auf ganz bestimmte Probleme spezialisiert. Viele dieser Daumenregeln, sind einfach nur Spezialisierungen oder Abwandlungen anderer, aber es ist auch nicht selten, dass sich einzelne Regeln widersprechen. Es ist dann jeweils ein geeigneter Mittelweg, ein Kompromiss zu suchen. Man kann diese Regeln auch als Kräfte betrachten, die in unterschiedliche Richtungen ziehen. So gesehen ist das Ziel ein Kräftegleichgewicht.

Das was ich hier schreibe, ist keine für alle Ewigkeiten gültige Wahrheit, an der nicht gerüttelt werden darf. Im Übrigen bin ich der Meinung, dass es so etwas gar nicht gibt. Aus nahe liegenden Gründen werde ich hier also meine persönliche Sichtweise auf die Softwareentwicklung darstellen. Man darf hier gerne anderer Meinung sein. Vieles ist Ansichtssache und auch wenn manche der Prinzipien (nicht aber alle) weithin anerkannte Lehrmeinung sind, sollte man trotzdem überlegen, ob man diese nachvollziehen kann. Im Übrigen wird man diese hier vorgestellten Daumenregeln nur dann wirklich anwenden können, wenn man die für zumindest einigermaßen sinnvoll erachtet.

Ich beziehe mich hier hauptsächlich auf objektorientierte Softwareentwicklung, prinzipiell gilt das meiste aber auch für andere Programmierparadigmen, bzw. sind leicht auf solche übertragbar. Jetzt will ich erstmal einen groben Überblick über die meiner Meinung nach wichtigsten Prinzipien geben. Genaueres folgt dann irgendwann mal in einzelnen Artikel zu den jeweiligen Prinzipien.

Die drei obersten Daumenregeln

“Die obersten drei Regeln der Softwareentwicklung”, wie ich sie hier mal nennen will, beschreiben, wie man mit den ganzen hier vorgestellten Regeln umgehen soll. weiter lesen »

The Tradeoff Game

Wie ich schon mehrfach erläutert habe, sehe ich Softwareentwicklung als das ständige Ausbalancieren von Prinzipien oder “Daumenregeln”. Es gibt eine ganze Menge solcher Daumenregeln (ich hab mal an die hundert solcher gesammelt) und ich hab vor, diese nach und nach hier mal vorzustellen.

Einige dieser Regeln ergänzen sich, manche sind spezieller als andere oder einfach nur eine andere Sichtweise auf eigentlich das selbe Prinzip. Viele aber widersprechen sich auch. Ein typisches Beispiel wären folgende beiden Prinzipien:

  1. mache deine Software generisch, damit sie auch leicht mit geänderten Anforderungen klar kommt; kurz: allgemeingültig ist besser als speziell
  2. mache deine Software einfach, damit sie leicht verständlich ist (KISS); kurz: einfach ist besser als kompliziert

Es wird wohl kaum jemand in Abrede stellen, dass beides wichtige Prinzipien der Softwareentwicklung sind. Wir alle wollen am liebsten einfachen Code der trotzdem sehr viel kann. In der Regel werden wir so etwas aber nicht haben können. Je generischer man versucht zu programmieren, desto komplexer wird der Code. Letztendlich streben beide Prinzipien also in unterschiedliche Richtungen. Es gilt dabei immer einen Mittelweg zu finden.

Man kann diese Daumenregeln auch als “Kräfte” bezeichnen. Dann wäre das, was wir suchen, eine Art Kräftegleichgewicht. Die Kräfte können unterschiedlich stark sein und so liegt das Gleichgewicht nicht immer in der Mitte. Außerdem gibt es meist mehr als zwei Kräfte, die es zu betrachten gilt.

Oft sind die Gewichtungen aber auch subjektiv. Manche Entwickler werden Einfachheit wichtiger finden, andere finden Generizität wichtiger. Es gibt dann mehrere “richtige” Lösungen. Aber alle werden darüber übereinstimmen, dass eine Lösung, die beide Prinzipien missachtet, eine schlechte ist. Komplizierte Software, die nur einen ganz bestimmten Spezialfall abdeckt und sich nicht auf andere Probleme anpassen lässt, wollen wir in der Regel nicht haben [1]. Wir suchen also eine Art Pareto-Optimum. Welche pareto-optimale Lösung jetzt für ein konkretes Problem gewählt werden sollte, hängt von vielen Faktoren ab. Zum einen von den konkreten Anforderungen für die zu entwickelnde Software, zum anderen aber auch projektabhängige Einflüsse wie Vorlieben, Kenntnisse und Fähigkeiten der Teammitglieder und sogar der Teamorganisation.

Dieses Ausbalancieren bezeichne ich gerne als “Tradeoff Game”. weiter lesen »

Magic Values

Letzte Woche hab ich ja schon etwas über Code Smells geschrieben. Einen weit verbreiteten Code Smell, nämlich die Magic Values, habe ich letztens mal wieder angetroffen und so nehme ich das mal zum Anlass, darüber etwas zu schreiben.

Der Begriff “Magic Value” oder “Magic Number” hat mehrere Bedeutungen. Hier geht es um den Code Smell der Magic Values, also insbesondere nicht um besondere Werte (d.h. Bytefolgen) als Erkennungszeichen in Dateiheadern o.ä.

Es geht also um Code, den man häufig vorfindet, der aber verbesserungswürdig ist. Hierzu sehen wir uns ein paar Beispiele an und werden unterschiedliche Arten von Magic Values ausmachen können:

Magic Values 1. Art: Unveränderliche Werte

1
... days * 1440 ...

Warum nun days mit 1440 multipliziert wird, wird aus dem Code nicht klar.

Besser:

1
2
3
4
5
6
7
// mit einer Funktion ist es klarer
function daysToMinutes(ADays: Integer): Integer;
begin
  return ADays * 1440;
end function;

... daysToMinutes(days) ...

Aber auch das geht besser:
weiter lesen »

Code Smells: Wenn Code anfängt zu stinken

Jeder, der schon eine Weile programmiert, wird die Situation kennen: Man liest Code (entweder fremden oder eigenen) und es läuft einem kalt den Rücken runter, die Zehnägel stellen sich auf und man will nur noch wegsehen. Wer das noch nie erlebt hat, sollte einfach mal seine ersten Programmierversuche wieder herauskramen.

Mancher Code scheint einfach zum Himmel zu stinken. Treffenderweise nennt man so etwas “Code Smell”. Letztens habe ich bei Nick Hodges von einem Stackoverflow-Thread über solche Code Smells gelesen.

Ich dachte mir, das passt wunderbar zu der an den Delphi-Tagen angekündigten (und leider immer noch nicht wirklich begonnenen) Artikelserie zu den Prinzipien der (objektorientierten) Softwareentwicklung. Wahrscheinlich werde ich zu jedem diskutierten Prinzip – wenn möglich – ein paar Code-Smells als abschreckendes Gegenbeispiel benennen. Hier aber erstmal ein paar allgemeine Gedanken zu Code Smells:
weiter lesen »

powered by WordPress | QuickLaTeX | WordPress Themes