SlideShare ist ein Scribd-Unternehmen logo
Clean Code
by example (Teil 1)
Auf den Punkt gebracht
Gregor Biswanger & Robert Walter
02/2021
Robert C. Martin (* 1952) ist ein US-
amerikanischer Softwareentwickler, IT-
Berater und Autor. Robert C. Martin, auch
bekannt als „Uncle Bob“, arbeitet seit den
1970er Jahren in diversen
Softwareentwicklungsprojekten, seit 1990 als
international anerkannter IT-Berater. 2001
initiierte er die Entwicklung des Agilen Manifests
(Manifest für Agile Softwareentwicklung, The
Agile Manifesto), das Fundament agiler
Softwareentwicklung. Er ist auch führendes
Mitglied der Bewegung Software Craftsmanship,
die sich der Clean Code Softwareentwicklung
verschrieben hat.
Der Buchautor
Inhalt (Teil 1)
Einführung
Bausteine
Gute Benennung
Funktionen
Kommentare
Formatierung
Objekte und Datenstrukturen
Fehlerbehandlung
Einführung
Warum Clean Code?
Brauchen wir das überhaupt?
Was macht Clean Code aus?
Woran erkennt man Clean Code?
Der gute Clean Code Ratschlag
„Programmiere immer so, als ob dein
Nachfolger, der deinen Code anpassen muss, ein
Psychopath ist, der weiß wo du wohnst!“
Uncle Bob
Eine Geschichte aus dem Leben…
Super Application v1.0 *
Release: 1980
* programmiert von Super Codern
Glücklicher User mit Geldüberschuss
Super Coder im Einsatz!
v1.0 v2.0 v3.0
v3.1
v4.0
v4.01
v4.02
Zeit
Release Bug #17
Bug #35
Bug #52 Bug #101
Bug #119
Bug #210
Bug #347
Auslieferung zur Weltmesse Bug #404
Bug #1296
Bugfix
Super Coder programmiert fleißig
Release für Release…
Was ist da los?
0%
20%
40%
60%
80%
100%
120%
1980 1981 1982 1983 1984
Produktivität
Zeit
Super Coder frustrierter User
Das Schicksal mit den Kunden!
B*
B*
B* (Produkt von anderer Firma)
Zeit
Glücklicher User mit Geldüberschuss Frustrierter User mit Sorgen Glücklicher User
(leider ab jetzt bei der Konkurrenz)
…und der Super Coder?
Super Coder Armer Bettler*
* sein Unternehmen war pleite
Zeit
Das Insider-Gespräch…
?!?
„Wir haben gecodet und programmiert wie die Helden – wir haben Features, Features,
und noch mal Features gebaut. Die Zeit war immer zu knapp. Wir haben einfach alles
immer schnell rein gehauen. Irgendwann haben uns die Bugs eingeholt. Wir haben nur
noch Bugs gefixt. Manche Bugfixes haben weitere Bugs hervorgerufen. Wir hatten keine
Zeit für Bugfixes. Der Code war richtig dreckig geworden. Es hat keinen Spaß mehr
gemacht. Wir haben nicht mehr durchgeblickt. Die Kunden waren sauer und sind
abgesprungen. Kollegen haben gekündigt. Wir sind den Bach runter gegangen!“
Ex-Super Coder
Uncle Bob
…und frägt nach:
„was war da
damals los?“
woraufhin Ex-Super
Coder einen
mehrzeiligen
Kommentar
abgibt:
Begriff für dieses Vorkommnis
=
Technische
Schulden
Bug #101
Bug #404
Bug #52
Feature #27 Feature #39 Feature #42
Feature #31
Der Lerneffekt
„Zeit darauf zu verwenden, den Code sauber zu
halten, ist nicht nur kosteneffektiv, sondern auch
eine Sache des professionellen Überlebens!“
Uncle Bob
Manager
Programmierer Programmierer
Wer ist also Schuld?
a) Die Programmierer
b) Die Manager
„Die Programmierer sind selbst Schuld,
wenn sie auf Clean Code zugunsten
schneller Ergebnisse verzichten.“
Welche
Eigenschaften
hat CleanCode?
+ lesbar wie ein Roman
+ stellt Design-Absichten dar
+ verständlich für andere
Entwickler
+ automatisiert getestet
+ minimale
Abhängigkeiten
+ minimiert
Duplizierungen
+ minimale Längen
+ einfach
+ wartbar
+ elegant
+ bedacht
Constantin öffnet die Klassendatei…
…er scrollt nach unten bis zur Methode, die geändert
werden muss
…er überlegt und geht die Möglichkeiten durch
…oh, er scrollt nach oben, an den Anfang des Klasse, um
eine Initialisierung der Instanzvariable zu prüfen
…jetzt scrollt er wieder zurück und beginnt zu tippen
…ups – er löscht, was er getippt hat
…er tippt wieder
…er löscht es wieder
…er tippt die Hälfte von etwas Anderem, aber er löscht es!
...Er scrollt nach unten zu einer anderen Methode, die eine
Methode aufruft, die er anpasst, um zu sehen, wie sie
aufgerufen wird
…er scrollt nach oben und tippt den selben Code, den er
gerade gelöscht hat
…er stoppt
…er löscht den Code schon wieder!
...er öffnet ein anderes Fenster, um sich eine abgeleitete
Klasse anzusehen: Ist diese Methode überschrieben?...
Code wird
viel öfter
gelesen als
geschrieben!
§ !!! §
§ !!! §
Ein Blick über die Schulter eines Programmierers…
Gute Benennung
anhand verschiedener Beispiele
int otd; //overtime
int overtimeInDays;
int overtimeForYear;
int overtimeSinceBegin;
int daysHavingOvertime;
// noch besser mit .NET
TimeSpan overtimeSinceBegin;
Gute Benennung
Anstatt: Besser:
public List<double[]> DoGet() {
List<double[]> arr =
new List<double[]>();
foreach (double[] it in coll)
if (it[0] == 2)
arr.Add(it[0]);
return arr;
}
public List<Cell> FilterBlackCells() {
List<Cell> blackCells =
new List<Cell>();
forech (Cell cell in chessboard)
if (cell.IsBlack())
blackCells.Add(cell);
return blackCells;
}
Gute Benennung
Anstatt: Besser:
Für was steht der
Rückgabewert?
Was macht die
Methode?
Was repräsentiert
die Collection?
Warum gerade 2? Was bedeutet das?
→ Antipattern: Magic Number
Was ist zum Schluss
in der Liste?
crtmjsms creationDateTime
Gute Benennung
Anstatt: Besser:
Hey, warum verwendest du hier die Variable
„CeErTeEmUndSoWeiter“?
Hey, warum verwendest du hier die
Variable „creationDateTime“?
Sprechbare Bezeichnungen verwenden, damit
eine Konversation möglich ist.
Sprechbare Bezeichnungen
CustomerObject
CustomerData
CustomerInfo
Customer
Gute Benennung
Anstatt: Besser:
Störung / „Rauschen“
Man sagt: a Customer
Nichts aussagende technische Begriffe
weglassen, wenn es keinen nennenswerten
Unterschied macht.
Ausschlaggebende Unterscheidungen
XlsxSheet
var data = new { Name = „Hans“ };
Sheet
var person =
new Person { Name = „Hans“ };
Gute Benennung
Anstatt: Besser:
Ohne Präfix
einfacher zu finden
Begriffe so wählen, damit sie intuitiv von vorne
schneller gefunden werden können.
Benutzer-suchbare Bezeichnungen
Weiter unten im Code ist nicht
mehr klar, was data eigentlich ist.
string strFullName;
string accountString;
// nach Refactoring passiert dann:
BankAccount accountString;
string fullName;
string account;
BankAccount account;
Gute Benennung
Anstatt: Besser:
Ungarische Notation (d.h. das hinten anstellen
des Typbezeichners an den Variablennamen)
ist wegen der guten Entwicklungsumgebung
nicht mehr hilfreich, sondern fehleranfällig.
Ungarische Notation
private string m_add; private string address;
Gute Benennung
Anstatt: Besser:
Präfixe für Membervariablen weglassen
Präfixe für Membervariablen
Sichtbarer Störfleck
Membervariable muss nicht
markiert werden, da Klassen
sowieso kurz genug sein sollten!
…Data
…Info
…Processor
…Manager
Article
ServiceAccount
Gute Benennung
Anstatt: Besser:
Nomen für Klassen verwenden und
mehrdeutige und nicht aussagekräftige
Namen vermeiden!
Klassenbezeichnungen
Nomen (Hauptwörter) verwenden
new Money(23.0)
CancelOrder
RemoveParagraph
Money.FromEuroCent(23.0)
Gute Benennung
Anstatt: Besser:
Verben für Methoden verwenden
Methodenbezeichnungen
Verben (Tunwörter) verwenden
GetProduct
FetchCatalog
RetrieveChecklist
FetchProduct
FetchCatalog
FetchChecklist
Gute Benennung
Anstatt: Besser:
Nur 1 Wort pro Konzept verwenden
→ Am besten Konsistenz-Lexikon anlegen
Konsistenz
Gleiche Funktionsweise,
unterschiedliche Benennungen
LogDynamicExtensionAnnotator
JobItemsInOrderRunner
LogVisitor
JobQueue
Gute Benennung
Anstatt: Besser:
Gängige Pattern-Benennung benutzen, statt
sie zu umschreiben
Pattern-Benennungen
Was soll das über die
Implementierung aussagen?
Visitor-Pattern
Queue-Collection
EPUSTargetAreaGlobalPositionAddress
//EPUS = Energy Power Ultra System
TargetArea
Gute Benennung
Anstatt: Besser:
Kein Solution-Präfix benutzen, da Name
sowieso bekannt und redundant ist.
Solution-Präfix
Zusammenfassung
Sprechbare Bezeichnungen
Ausschlaggebende Unterscheidungen
Benutzer-suchbare Bezeichnungen
Ungarische Notation
Präfixe für Membervariablen
Klassenbezeichnungen
Methodenbezeichnungen
Konsistenz
Pattern-Benennungen
Solution-Präfix
Gute Benennung
Funktionen
Wichtige Regeln und Eigenschaften
Wichtigste Regel für Funktionen
„Die erste Regel zu Funktionen ist, dass sie klein
sein sollen. Die zweite Regel für Funktionen ist,
sie sollen kleiner sein als das.“
Uncle Bob
„Und: Funktionen sollen nur eine einzige Sache
tun.“
if (count == 0) {
BreakProcessing();
} else if(count == 1) {
ProcessSingleItem();
} else {
ProcessMany(count);
}
Funktionen
Gut:
Bei if/then/else
→ 1 Zeile Methodenaufruf
Einrückungsebenen
Einrückungsebenen:
→ Maximal 2 Ebenen tief
„To…“-Paragraphen-Formulierung nutzen
To ShowReportWithHeadersAndFooters
we check to see if a site is a inclusion site and if so we
include the headers and footers. Otherwise we show it
as PDF.
Single
Responsibility
Principle
(SRP)
§ !!! §
§ !!! §
Wie findet man heraus, ob eine Funktion nur eine Sache tut?
Funktionen
Die Stepdown-Regel
Funktionen Stepdown-Regel
To include the headers and footers we include headers, then we include the
site report controls, then we include the footers.
To include the subreport header, we search the parent hierarchy for the
„subreport“ property and add an include statement for it.
To include the headers we include the subreport header if this is a supreport,
then we include the main header.
To search the parent…
ABSTRAKTIONSEBENEN
Show(true)
ShowMainReport()
// und
ShowSubReport()
//oder noch besser in .NET
Show(ReportType.Main)
// und
Show(ReportType.SubReport)
Anstatt: Besser:
boolean-Parameter
Was aktiviert der Parameter?
Methodendefinition:
Show(bool isSubReport)
Funktionen
funktioniert wegen Methodendefinition:
Show(ReportType reportType)
enum ReportType {
Main = 0,
SubReport = 1
}
boolean-Parameter durch zwei
Methodenaufrufe oder einen selbst
geschriebenen enum-Typen ersetzen.
consent = verify(user)
check(hasAgreedAll,
hasAgreedSpecialCase)
hasAgreed = verifyGDPRConsents(user)
checkAllOverridesOtherOption(
hasAgreedAll, hasAgreedSpecialCase)
// noch eleganter in .NET:
// Operation Overloading
hasOverride =
hasAgreedAll > hasAgreedSpecialCase
Anstatt: Besser:
Verben und Schlüsselwörter
Was genau wird geprüft?
Funktionen
Wie werden die Parameter verglichen?
Funktionen gegebenenfalls ausführlicher
benennen, damit Verhalten klar wird.
Parameteranzahl Empfehlung
1 am besten
2 gut
3
sollte vermieden
werden
Parameter-Anzahl
Funktionen
run(„a“, 1, true, false, „admin“,
new DefaultOptions(), true, null,
null, null, 1);
Anstatt: Besser:
Was wird alles übergeben? Hat
man hier noch den Überblick?
Was ist, wenn sich Parameter
ändern, oder noch welche
hinzukommen?
IsDbConnectionOpen() {
//…
httpSession.Start()
//…
}
IsDbConnectionOpen() {
//…
}
Anstatt: Besser:
Seiteneffekte
Status wird in Prüfungs-Methode
verändert – Der Seiteneffekt wird
von keinem Entwickler erwartet!
Funktionen
Keine Seiteneffekte (z.B. Schreibzugriffe in
Lese-Funktionen) einbauen
if (SaveField(„name“, „Hans“)) …
if (HasField(„name“)) {
SaveField(„name“, „Hans“)
…
}
Anstatt: Besser:
Command Query Separation
if-Abfrage
Lese-Zugriff
= Query
Funktionen
Query und Command Zugriffe müssen in zwei
separate Funktionen aufgetrennt werden.
Save-Methode
Schreib-Zugriff
= Command
Was gibt das SaveField für die Bedingung
zurück? Wann trifft es zu?
ExtendWithDefaultFooter(s)
void ExtendWithDefaultFooter(
StringBuilder report)
report.ExtendWithDefaultFooter();
class PlainTextReport : Report {
private StringBuilder content;
void ExtendWithDefaultFooter() { … }
}
Anstatt: Besser:
Ausgabeparameter
Der StringBuffer wird als Ein- und
Ausgabeparameter genutzt. Das ist
nicht so schön lesbar.
Funktionen
Ausgabeparameter können oft besser mit der
zugehörigen Methode in einer eigenen Klasse
gekapselt werden.
public void Remove(SubReport subReport) {
try {
DeleteControlsAndLinks(subReport);
} catch(Exception ex) {
LogError(ex);
}
}
private void
DeleteControlsAndLinks(page) { … }
private void
LogError(Exception ex) { … }
Funktionen
Gut:
Bei try/catch
→ 1 Zeile Methodenaufruf
try-catch-Blöcke extrahieren
„Clean Code ist lesbar wie ein Roman“
Zuerst kommt die Überschrift, dann die Details
Code zu kopieren!
Don‘t
repeat
yourself
(DRY)
§ !!! §
§ !!! §
Was ist die größte Todsünde beim Programmieren?
Funktionen
Code A
Code A-Kopie
mit Änderung
Code A-Kopie
mit
Änderung-
Kopie mit
Anpassung
aufrufender
Code
aufrufender
Code
aufrufender
Code
Änderung 1
Änderung 2
Änderung 2?
Änderung 2?
Änderung 3
Es entsteht ein
Vielfaches an Code
an verteilten Stellen
So entstehen
leichtsinnige Bugs
Änderung 1 ist bei
jedem Aufrufer
vorhanden
Änderung 2 nicht mehr, und
muss noch mal kopiert werden…
Produktive Vorgehensweise
Widerspricht es sich nicht, schnell und produktiv Funktionen zu schreiben,
die auch sauber sein müssen?
Nein, es gibt einen guten Kompromiss:
1) Code einfach mal quick & dirty „herunterschreiben“
2) Code refaktorisieren und verfeinern
Funktionen Refaktorisierung
Zusammenfassung
Kürze
Einrückungsebenen
Single Responsibility Principle
Stepdown-Regel
boolean-Parameter
Verben und Schlüsselwörter
Parameter-Anzahl
Seiteneffekte
Command Query Separation
Ausgabeparameter
try-catch-Blöcke extrahieren
Don‘t repeat yourself
Refactoring
Funktionen
Kommentare
Richtlinien und Arten
Kommentare und schlechter Code
„Kommentiere schlechten Code nicht einfach –
schreibe ihn neu!“
Brian W. Kernighan
& P. J. Plaugher
Veraltete Kommentare
„Kommentare lügen! Ein Programmierer kann
sie realistischerweise nie richtig instand halten.“
Uncle Bob
Auskommentierter alter Code muss immer
sofort gelöscht werden! Dafür gibt es nämlich
ein Quellcodeverwaltungssystem.
// check to see if the employee
// has earned super bonus
if ((employee.flags
& SUPER_FLAG)
&& (employee.Earning > 0))
…
if(employee.HasEarnedSuperBonus())
…
Anstatt: Besser:
Kommentare
+
Gute Arten von
Kommentaren
+ Gesetzliche Kommentare (Copyright Header)
+ Erklärung der Absicht
// Dies ist unser Versuch, einen Dead Lock zu
// erzwingen, mit einer brutal hohen Menge an
// Threads
+ Warnung vor Konsequenzen
// StateRepository ist nicht ThreadSafe
+ TODO-Kommentare
+ XML-Kommentare in public APIs oder
Javadocs
+ Begründung für leere catch-Blöcke
-
Schlechte Arten
von Kommentaren
− Code-erklärende Kommentare
// erhöhe i um 1
− Pflichtkommentare
///<summary>
/// Gets and sets the name
///</summary>
string Name { get; set;}
− Journal-Kommentare / Änderungshistorie
− Überflüssige Kommentare
/* Default Constructor */
− Positionsmarker
///// Methods /////////////////////////
− Klammerschluss-Kommentare
− Globale Informationen innerhalb von Funktionen
// Default User ist PowerAdmin aus Travolta
− Zu viele Informationen (z.B. komplexe
Spezifikationen)
− XML-Dokumentation/Javadocs in nicht-public-Code
Formatierung
Einheitliches Aussehen und Anordnung des Codes
Gemeinsamer Codestyle
Check_passwd() {
//…
}
Super Coder A Super Coder B Super Coder C
checkpassword ( )
{
//…
}
DoPasswordCheck
()
{
//…
}
CheckPassword()
{
//…
}
Formatierung
Am Anfang des
Projekts sollte man
sich im Team auf
einen gemeinsamen
Stil einigen. Team-
Regeln stehen dann
über individuellen
Regeln.
Empfohlene Anzahl an Codezeilen
Durchschnittlich [] Minimal [min.] Maximal [max.] Projekt
65 6 400 FitNesse
200 500
Große Systeme:
JUnit
testNG
JDepend
Ant
Tomcat
Formatierung
Zeitungs-Methapher
DIE NEUE ZEITUNG | GLOBALES
Obama will die Krankenversicherung einführen
Xxxxxxxxxx
Xxxxxxxxx
Xxxxxxxxxx
Xxxxxxx xxxx
xxx xxxxx xxxx xxxx
xxxxx xxxxxx xxxxx
xxxxxxxx xxxxxxxxx
xxxxxxxxxxxxxx xxxxx
xxxxxxxxxx xx xxx x x
xxxxxxxxxxx x xxxxxxx
xxxxxxx xxxxxxx x xxxx
xxxx xxxxx xxxxxx xxx
xxx xxxx xxxxxxx
xxxxxxxxxxxxxxxxxx
xxxxxxx xxxxxxxxxx
xxxxxxxxxxxxx
xxxxxxxxxxxx xxxxxxx
xxxxxxxxxx xxxxxx
xxxxxx xxxx
xxxxxxxxxx.
☺ Scherz am Rande - Kommentar eines Zeitungslesers:
„I only understand English and I can read only the first
three words!“
class ReportOutputGenerator {
public Report Render() {
// xxxxxxx
// xxxxxxx
// xxxxxxx
}
private void … {
// xxxxxxx
// xxxxxxx
}
private void …
}
Titel / Worum geht es? Wo bin ich?
Zusammenfassung
Details
Formatierung
class ReportOutputGenerator {
private Controls controls;
public Report Render() {
// xxxxxx
int i;
while(i < 0) { … }
// xxxxxx
}
private void … {
// xxxxxxx
// xxxxxxx
}
private void …
}
Eine Zeile Zeilenabstand zwischen Methoden zeigen
den Wechsel auch optisch und sind wichtig
Zusammenhängende Methoden sollten
vertikal nah beieinander stehen
Formatierung
Variablendeklarationen sollten immer so nah wie
möglich zu Ihrer Verwendung stehen.
Instanzvariablen sollten immer am Kopf der Klasse
gesammelt werden.
Zeichenlänge: Empfehlung max. 120 Zeichen
(es muss noch auf einen normalen Bildschirm
passen)
Objekte und
Datenstrukturen
Zugriff und Trennung
Objekt Datenstruktur
Objekte und Datenstrukturen
class Report {
public List<SubReport> SubReports
{ get; set; }
public string Title { get; set; }
…
}
class PageEditor {
void Remove(SubReport report) { … }
private void
DeleteControlsAndLinks(report)
{ … }
private void
LogError(Exception ex) { … }
}
Logik / Verhalten
Datenhaltung
vs.
Law of
Demeter
§ !!! §
§ !!! §
Objekte und Datenstrukturen
string outputPath =
dir.getBase()
.getReportsDir()
.getFullPath();
string outputPath =
dir.Base
.ReportsDir
.FullPath;
FileInfo
outputFileInfo = dir
.BuildReportsPath(
reportCategory);
Anstatt: Besser:
Uncle Bob hasst übrigens getter/setter
in Java, da sie sinnlos sind!
Verkettung von vielen Aufrufen, wie bei
einem Zug mit vielen Locks
Ein Modul darf nichts über das Innerste
eines Objekts wissen, das es manipuliert!
Das widerspricht dem Prinzip der Kapselung.
Fehlerbehandlung
Regeln und Tipps
void Remove(SubReport subReport) {
try {
DeleteControlsAndLinks(subReport);
} catch(Exception ex) {
LogError(ex);
}
}
private void
DeleteControlsAndLinks(subReport) { … }
private void
LogError(Exception ex) { … }
Fehlerbehandlung
Gut:
Bei try/catch
→ 1 Zeile Methodenaufruf
try-catch-Blöcke extrahieren
„Clean Code ist lesbar wie ein Roman“
Zuerst kommt die Überschrift, dann die Details
public int Activate(Person p) {
// …
if(p.Email == null) {
return ErrorCodes.Code47_NoMail;
}
// …
}
/// <exception
/// cref="Prog.MissingMailException">
/// Thrown when no mail address
/// is given, so that no activation
/// mail is possible. Activation
/// will be cancelled.
/// </exception>
public void Activate(Person p) {
// …
if(p.Email == null) {
throw new MissingMailException();
}
// …
}
Anstatt: Besser:
Exceptions statt return codes
Gut: Hier keine Magic Number
ABER: Magic Number kommt
trotzdem bei Anrufer an, und muss
sogar bekannt sein und erwartet
werden!
Fehlerbehandlung
Selbst geschriebene Exceptions statt return
Codes verwenden. So muss der Fehler
automatisch behandelt werden, oder wird
direkt für den Benutzer ausgegeben.
Damit Aufrufer über mögliche
Exceptions Bescheid weiß, sollte
man sie im XML Doc angeben.
try {
total += budgetRepo.LoadYearly();
} catch(
YearlyNotFoundException ex) {
total += LoadOutOfOrderBudget();
}
total += budgetRepo.LoadAll();
class OutOfOrderBudget
: YearlyBudget { … }
Anstatt: Besser:
Keine Exceptions für Kontrollfluss
Fehlerbehandlung
Exceptions nicht für normalen Kontrollfluss
verwenden. Besser ist es, z.B. das „Special
Case Pattern“ zu verwenden.
=„Special Case Pattern“
total kann dann mit Standardfall
und Sonderfall normal addiert
werden.
Häufig auftretender Sonderfall; ist ein
„Kontrollfluss“, da Aktion ausgelöst wird;
keine problematische unerwartete
„Ausnahme“. Exceptions zu werfen und zu
fangen ist nämlich „teuer“ (=frisst
Performance).
public IEnumerable<Customer> Load(
CustomerType type) {
if(type == null) throw new
IllegalArgumentException(„type“);
//…
return null;
}
public IEnumerable<Customer> Load(
CustomerType type) {
// Kein explizites null-Handling
//…
return Enumerables.Empty<Customer>();
}
Anstatt: Besser:
null-Handling
Team-Regel festlegen: null sollte am
besten nie als Parameter übergeben
werden!
Fehlerbehandlung
Team-Regel: Offensiv programmieren - nie null
als Parameter übergeben, und nie null als
Rückgabeparameter zurückgeben!
= „Null-Object-Pattern“
Aufrufer ist dadurch vor null-
Reference-Exception geschützt
Potentielle null-Reference-
Exception beim Aufrufer!
Code wird leider aufgebläht
= „Offensive Programmierung“
d.h. dafür sorgen, dass Fehler
beim Aufruf früh aufgedeckt
werden! Beim Debuggen gibt
es inzwischen gute Hinweise
zum null-Ursprung.
Wie es weiter geht…
Und jetzt folgt – die WERBUNG:
…seht ihr in Teil 2
beim nächsten Mal!
Eine klare Buchempfehlung
für alle Programmierer!

Weitere ähnliche Inhalte

Was ist angesagt?

digitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM Developer Day 2011: digitalSTROM-Server-AppsdigitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM.org
 
Node.js Security
Node.js SecurityNode.js Security
Node.js Security
Sebastian Springer
 
HTML5 und node.js Grundlagen
HTML5 und node.js GrundlagenHTML5 und node.js Grundlagen
HTML5 und node.js Grundlagen
Mayflower GmbH
 
Dockerize It - Mit apex in die amazon cloud
Dockerize It - Mit apex in die amazon cloudDockerize It - Mit apex in die amazon cloud
Dockerize It - Mit apex in die amazon cloud
OPITZ CONSULTING Deutschland
 
JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013
Oliver Zeigermann
 
Automatischer Build mit Maven
Automatischer Build mit MavenAutomatischer Build mit Maven
Automatischer Build mit Maven
Stefan Scheidt
 
Fr os con2010_devel_nytprof
Fr os con2010_devel_nytprofFr os con2010_devel_nytprof
Fr os con2010_devel_nytprof
Renee Baecker
 
Zend Framework 2 feat. MongoDB
Zend Framework 2 feat. MongoDBZend Framework 2 feat. MongoDB
Zend Framework 2 feat. MongoDB
Ralf Eggert
 
Nagios Conference 2007 | Pluginprogrammierung in Perl by Wolfgang Barth
Nagios Conference 2007 |  Pluginprogrammierung in Perl by Wolfgang BarthNagios Conference 2007 |  Pluginprogrammierung in Perl by Wolfgang Barth
Nagios Conference 2007 | Pluginprogrammierung in Perl by Wolfgang Barth
NETWAYS
 
Javascript done right
Javascript done rightJavascript done right
Javascript done right
Dirk Ginader
 
Einfacher bauen
Einfacher bauenEinfacher bauen
Einfacher bauen
johofer
 
Vagrant, Puppet, Docker für Entwickler und Architekten
Vagrant, Puppet, Docker für Entwickler und ArchitektenVagrant, Puppet, Docker für Entwickler und Architekten
Vagrant, Puppet, Docker für Entwickler und Architekten
OPITZ CONSULTING Deutschland
 
Froscamp2010_padre
Froscamp2010_padreFroscamp2010_padre
Froscamp2010_padre
Renee Baecker
 
Eine Stunde was mit Api First!
Eine Stunde was mit Api First!Eine Stunde was mit Api First!
Eine Stunde was mit Api First!
JanWeinschenker
 
Große Applikationen mit AngularJS
Große Applikationen mit AngularJSGroße Applikationen mit AngularJS
Große Applikationen mit AngularJS
Sebastian Springer
 
Hendrik Jungnitsch: Software verpacken mit Docker
Hendrik Jungnitsch: Software verpacken mit DockerHendrik Jungnitsch: Software verpacken mit Docker
Hendrik Jungnitsch: Software verpacken mit Docker
gedoplan
 
Infrastructure as Code - BaselOne 17
Infrastructure as Code - BaselOne 17Infrastructure as Code - BaselOne 17
Infrastructure as Code - BaselOne 17
remigius-stalder
 
C / C++ Api for Beginners
C / C++ Api for BeginnersC / C++ Api for Beginners
C / C++ Api for Beginners
Ulrich Krause
 
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
gedoplan
 
digitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM Developer Day 2011: digitalSTROM-Server-AppsdigitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM.org
 

Was ist angesagt? (20)

digitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM Developer Day 2011: digitalSTROM-Server-AppsdigitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
 
Node.js Security
Node.js SecurityNode.js Security
Node.js Security
 
HTML5 und node.js Grundlagen
HTML5 und node.js GrundlagenHTML5 und node.js Grundlagen
HTML5 und node.js Grundlagen
 
Dockerize It - Mit apex in die amazon cloud
Dockerize It - Mit apex in die amazon cloudDockerize It - Mit apex in die amazon cloud
Dockerize It - Mit apex in die amazon cloud
 
JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013JavaScript für Java-Entwickler W-JAX 2013
JavaScript für Java-Entwickler W-JAX 2013
 
Automatischer Build mit Maven
Automatischer Build mit MavenAutomatischer Build mit Maven
Automatischer Build mit Maven
 
Fr os con2010_devel_nytprof
Fr os con2010_devel_nytprofFr os con2010_devel_nytprof
Fr os con2010_devel_nytprof
 
Zend Framework 2 feat. MongoDB
Zend Framework 2 feat. MongoDBZend Framework 2 feat. MongoDB
Zend Framework 2 feat. MongoDB
 
Nagios Conference 2007 | Pluginprogrammierung in Perl by Wolfgang Barth
Nagios Conference 2007 |  Pluginprogrammierung in Perl by Wolfgang BarthNagios Conference 2007 |  Pluginprogrammierung in Perl by Wolfgang Barth
Nagios Conference 2007 | Pluginprogrammierung in Perl by Wolfgang Barth
 
Javascript done right
Javascript done rightJavascript done right
Javascript done right
 
Einfacher bauen
Einfacher bauenEinfacher bauen
Einfacher bauen
 
Vagrant, Puppet, Docker für Entwickler und Architekten
Vagrant, Puppet, Docker für Entwickler und ArchitektenVagrant, Puppet, Docker für Entwickler und Architekten
Vagrant, Puppet, Docker für Entwickler und Architekten
 
Froscamp2010_padre
Froscamp2010_padreFroscamp2010_padre
Froscamp2010_padre
 
Eine Stunde was mit Api First!
Eine Stunde was mit Api First!Eine Stunde was mit Api First!
Eine Stunde was mit Api First!
 
Große Applikationen mit AngularJS
Große Applikationen mit AngularJSGroße Applikationen mit AngularJS
Große Applikationen mit AngularJS
 
Hendrik Jungnitsch: Software verpacken mit Docker
Hendrik Jungnitsch: Software verpacken mit DockerHendrik Jungnitsch: Software verpacken mit Docker
Hendrik Jungnitsch: Software verpacken mit Docker
 
Infrastructure as Code - BaselOne 17
Infrastructure as Code - BaselOne 17Infrastructure as Code - BaselOne 17
Infrastructure as Code - BaselOne 17
 
C / C++ Api for Beginners
C / C++ Api for BeginnersC / C++ Api for Beginners
C / C++ Api for Beginners
 
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
Das Runde muss in das Eckige - Java-Anwendungen für Kubernetes entwickeln und...
 
digitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM Developer Day 2011: digitalSTROM-Server-AppsdigitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
digitalSTROM Developer Day 2011: digitalSTROM-Server-Apps
 

Ähnlich wie Einführung in Clean Code mit .NET - Teil 1

Clean code in ABAP
Clean code in ABAPClean code in ABAP
Clean code in ABAP
Cadaxo GmbH
 
objectiF extrem
objectiF extremobjectiF extrem
objectiF extrem
Olaf Lewitz
 
C/ C++ for Notes & Domino Developers
C/ C++ for Notes & Domino DevelopersC/ C++ for Notes & Domino Developers
C/ C++ for Notes & Domino Developers
Ulrich Krause
 
23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten.
23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten.23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten.
23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten.
Stephan Schmidt
 
Clean Coding - Theorie und Praxis Guide.pptx
Clean Coding - Theorie und Praxis Guide.pptxClean Coding - Theorie und Praxis Guide.pptx
Clean Coding - Theorie und Praxis Guide.pptx
kaftanenko
 
Dnug35 ak-dev.071111-cookbook
Dnug35 ak-dev.071111-cookbookDnug35 ak-dev.071111-cookbook
Dnug35 ak-dev.071111-cookbook
Ulrich Krause
 
RoofTop Brains & BBQ: Ein Gästbuch für China
RoofTop Brains & BBQ: Ein Gästbuch für ChinaRoofTop Brains & BBQ: Ein Gästbuch für China
RoofTop Brains & BBQ: Ein Gästbuch für China
Johann-Peter Hartmann
 
PHP mit Paul Bocuse
PHP mit Paul BocusePHP mit Paul Bocuse
PHP mit Paul Bocuse
Stephan Schmidt
 
iks auf der gearconf 2012: Clean Code - Von der Lehre in den Alltag
iks auf der gearconf 2012: Clean Code - Von der Lehre in den Alltagiks auf der gearconf 2012: Clean Code - Von der Lehre in den Alltag
iks auf der gearconf 2012: Clean Code - Von der Lehre in den Alltag
IKS Gesellschaft für Informations- und Kommunikationssysteme mbH
 
C API for Lotus Notes & Domino
C API for Lotus Notes & DominoC API for Lotus Notes & Domino
C API for Lotus Notes & Domino
Ulrich Krause
 
Mehr Softwarequalität: Team Clean Coding
Mehr Softwarequalität: Team Clean CodingMehr Softwarequalität: Team Clean Coding
Stay calm & keep shipping - iOS DevCon 2013
Stay calm & keep shipping - iOS DevCon 2013Stay calm & keep shipping - iOS DevCon 2013
Stay calm & keep shipping - iOS DevCon 2013
superflomo
 
mongoDB im Einsatz - Grundlagen
mongoDB im Einsatz - GrundlagenmongoDB im Einsatz - Grundlagen
mongoDB im Einsatz - Grundlagen
inovex GmbH
 
Vital und fit bis ins hohe Alter: Refactoring im Projekt
Vital und fit bis ins hohe Alter: Refactoring im ProjektVital und fit bis ins hohe Alter: Refactoring im Projekt
Vital und fit bis ins hohe Alter: Refactoring im Projekt
Benjamin Schmid
 
Kennen sie schon - Important tools for C# developers
Kennen sie schon - Important tools for C# developersKennen sie schon - Important tools for C# developers
Kennen sie schon - Important tools for C# developers
FDeitelhoff
 
GitLab: CI-Pipelines | PHP Usergroup Hamburg 20.03.2018
GitLab: CI-Pipelines | PHP Usergroup Hamburg 20.03.2018GitLab: CI-Pipelines | PHP Usergroup Hamburg 20.03.2018
GitLab: CI-Pipelines | PHP Usergroup Hamburg 20.03.2018
Christian Mücke
 
Gute Zeilen schlechte Zeilen, JUG Ostfalen 29.8.2013
Gute Zeilen schlechte Zeilen, JUG Ostfalen 29.8.2013Gute Zeilen schlechte Zeilen, JUG Ostfalen 29.8.2013
Gute Zeilen schlechte Zeilen, JUG Ostfalen 29.8.2013
gedoplan
 
The pain of choice - Important libs for C# developers
The pain of choice - Important libs for C# developersThe pain of choice - Important libs for C# developers
The pain of choice - Important libs for C# developers
FDeitelhoff
 
Day CQ 5.3 WCM - Was ist neu
Day CQ 5.3 WCM - Was ist neuDay CQ 5.3 WCM - Was ist neu
Day CQ 5.3 WCM - Was ist neu
Cédric Hüsler
 
Das funktionierte doch schon einmal! - JUnit Testing in XPages
Das funktionierte doch schon einmal! - JUnit Testing in XPagesDas funktionierte doch schon einmal! - JUnit Testing in XPages
Das funktionierte doch schon einmal! - JUnit Testing in XPages
Christian Güdemann
 

Ähnlich wie Einführung in Clean Code mit .NET - Teil 1 (20)

Clean code in ABAP
Clean code in ABAPClean code in ABAP
Clean code in ABAP
 
objectiF extrem
objectiF extremobjectiF extrem
objectiF extrem
 
C/ C++ for Notes & Domino Developers
C/ C++ for Notes & Domino DevelopersC/ C++ for Notes & Domino Developers
C/ C++ for Notes & Domino Developers
 
23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten.
23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten.23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten.
23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten.
 
Clean Coding - Theorie und Praxis Guide.pptx
Clean Coding - Theorie und Praxis Guide.pptxClean Coding - Theorie und Praxis Guide.pptx
Clean Coding - Theorie und Praxis Guide.pptx
 
Dnug35 ak-dev.071111-cookbook
Dnug35 ak-dev.071111-cookbookDnug35 ak-dev.071111-cookbook
Dnug35 ak-dev.071111-cookbook
 
RoofTop Brains & BBQ: Ein Gästbuch für China
RoofTop Brains & BBQ: Ein Gästbuch für ChinaRoofTop Brains & BBQ: Ein Gästbuch für China
RoofTop Brains & BBQ: Ein Gästbuch für China
 
PHP mit Paul Bocuse
PHP mit Paul BocusePHP mit Paul Bocuse
PHP mit Paul Bocuse
 
iks auf der gearconf 2012: Clean Code - Von der Lehre in den Alltag
iks auf der gearconf 2012: Clean Code - Von der Lehre in den Alltagiks auf der gearconf 2012: Clean Code - Von der Lehre in den Alltag
iks auf der gearconf 2012: Clean Code - Von der Lehre in den Alltag
 
C API for Lotus Notes & Domino
C API for Lotus Notes & DominoC API for Lotus Notes & Domino
C API for Lotus Notes & Domino
 
Mehr Softwarequalität: Team Clean Coding
Mehr Softwarequalität: Team Clean CodingMehr Softwarequalität: Team Clean Coding
Mehr Softwarequalität: Team Clean Coding
 
Stay calm & keep shipping - iOS DevCon 2013
Stay calm & keep shipping - iOS DevCon 2013Stay calm & keep shipping - iOS DevCon 2013
Stay calm & keep shipping - iOS DevCon 2013
 
mongoDB im Einsatz - Grundlagen
mongoDB im Einsatz - GrundlagenmongoDB im Einsatz - Grundlagen
mongoDB im Einsatz - Grundlagen
 
Vital und fit bis ins hohe Alter: Refactoring im Projekt
Vital und fit bis ins hohe Alter: Refactoring im ProjektVital und fit bis ins hohe Alter: Refactoring im Projekt
Vital und fit bis ins hohe Alter: Refactoring im Projekt
 
Kennen sie schon - Important tools for C# developers
Kennen sie schon - Important tools for C# developersKennen sie schon - Important tools for C# developers
Kennen sie schon - Important tools for C# developers
 
GitLab: CI-Pipelines | PHP Usergroup Hamburg 20.03.2018
GitLab: CI-Pipelines | PHP Usergroup Hamburg 20.03.2018GitLab: CI-Pipelines | PHP Usergroup Hamburg 20.03.2018
GitLab: CI-Pipelines | PHP Usergroup Hamburg 20.03.2018
 
Gute Zeilen schlechte Zeilen, JUG Ostfalen 29.8.2013
Gute Zeilen schlechte Zeilen, JUG Ostfalen 29.8.2013Gute Zeilen schlechte Zeilen, JUG Ostfalen 29.8.2013
Gute Zeilen schlechte Zeilen, JUG Ostfalen 29.8.2013
 
The pain of choice - Important libs for C# developers
The pain of choice - Important libs for C# developersThe pain of choice - Important libs for C# developers
The pain of choice - Important libs for C# developers
 
Day CQ 5.3 WCM - Was ist neu
Day CQ 5.3 WCM - Was ist neuDay CQ 5.3 WCM - Was ist neu
Day CQ 5.3 WCM - Was ist neu
 
Das funktionierte doch schon einmal! - JUnit Testing in XPages
Das funktionierte doch schon einmal! - JUnit Testing in XPagesDas funktionierte doch schon einmal! - JUnit Testing in XPages
Das funktionierte doch schon einmal! - JUnit Testing in XPages
 

Mehr von Gregor Biswanger

MongoDB: Entwurfsmuster für das NoSQL-Schema-Design
MongoDB: Entwurfsmuster für das NoSQL-Schema-DesignMongoDB: Entwurfsmuster für das NoSQL-Schema-Design
MongoDB: Entwurfsmuster für das NoSQL-Schema-Design
Gregor Biswanger
 
Fachmodell-First: Einstieg in das NoSQL-Schema-Design
Fachmodell-First: Einstieg in das NoSQL-Schema-DesignFachmodell-First: Einstieg in das NoSQL-Schema-Design
Fachmodell-First: Einstieg in das NoSQL-Schema-Design
Gregor Biswanger
 
Roadshow: Einstieg in die Hybrid-App Entwicklung mit dem Intel XDK und Apache...
Roadshow: Einstieg in die Hybrid-App Entwicklung mit dem Intel XDK und Apache...Roadshow: Einstieg in die Hybrid-App Entwicklung mit dem Intel XDK und Apache...
Roadshow: Einstieg in die Hybrid-App Entwicklung mit dem Intel XDK und Apache...
Gregor Biswanger
 
Clevere Tipps zum Thema Facebook Posts
Clevere Tipps zum Thema Facebook PostsClevere Tipps zum Thema Facebook Posts
Clevere Tipps zum Thema Facebook Posts
Gregor Biswanger
 
Responsive Webdesign mit Bootstrap
Responsive Webdesign mit BootstrapResponsive Webdesign mit Bootstrap
Responsive Webdesign mit Bootstrap
Gregor Biswanger
 
Intel XDK: Cross-Plattform Entwicklung – Apps Entwickeln für alle Plattformen...
Intel XDK: Cross-Plattform Entwicklung – Apps Entwickeln für alle Plattformen...Intel XDK: Cross-Plattform Entwicklung – Apps Entwickeln für alle Plattformen...
Intel XDK: Cross-Plattform Entwicklung – Apps Entwickeln für alle Plattformen...
Gregor Biswanger
 
Multi Touch.Prio.Conference 2009
Multi Touch.Prio.Conference 2009Multi Touch.Prio.Conference 2009
Multi Touch.Prio.Conference 2009
Gregor Biswanger
 

Mehr von Gregor Biswanger (7)

MongoDB: Entwurfsmuster für das NoSQL-Schema-Design
MongoDB: Entwurfsmuster für das NoSQL-Schema-DesignMongoDB: Entwurfsmuster für das NoSQL-Schema-Design
MongoDB: Entwurfsmuster für das NoSQL-Schema-Design
 
Fachmodell-First: Einstieg in das NoSQL-Schema-Design
Fachmodell-First: Einstieg in das NoSQL-Schema-DesignFachmodell-First: Einstieg in das NoSQL-Schema-Design
Fachmodell-First: Einstieg in das NoSQL-Schema-Design
 
Roadshow: Einstieg in die Hybrid-App Entwicklung mit dem Intel XDK und Apache...
Roadshow: Einstieg in die Hybrid-App Entwicklung mit dem Intel XDK und Apache...Roadshow: Einstieg in die Hybrid-App Entwicklung mit dem Intel XDK und Apache...
Roadshow: Einstieg in die Hybrid-App Entwicklung mit dem Intel XDK und Apache...
 
Clevere Tipps zum Thema Facebook Posts
Clevere Tipps zum Thema Facebook PostsClevere Tipps zum Thema Facebook Posts
Clevere Tipps zum Thema Facebook Posts
 
Responsive Webdesign mit Bootstrap
Responsive Webdesign mit BootstrapResponsive Webdesign mit Bootstrap
Responsive Webdesign mit Bootstrap
 
Intel XDK: Cross-Plattform Entwicklung – Apps Entwickeln für alle Plattformen...
Intel XDK: Cross-Plattform Entwicklung – Apps Entwickeln für alle Plattformen...Intel XDK: Cross-Plattform Entwicklung – Apps Entwickeln für alle Plattformen...
Intel XDK: Cross-Plattform Entwicklung – Apps Entwickeln für alle Plattformen...
 
Multi Touch.Prio.Conference 2009
Multi Touch.Prio.Conference 2009Multi Touch.Prio.Conference 2009
Multi Touch.Prio.Conference 2009
 

Einführung in Clean Code mit .NET - Teil 1

  • 1. Clean Code by example (Teil 1) Auf den Punkt gebracht Gregor Biswanger & Robert Walter 02/2021
  • 2. Robert C. Martin (* 1952) ist ein US- amerikanischer Softwareentwickler, IT- Berater und Autor. Robert C. Martin, auch bekannt als „Uncle Bob“, arbeitet seit den 1970er Jahren in diversen Softwareentwicklungsprojekten, seit 1990 als international anerkannter IT-Berater. 2001 initiierte er die Entwicklung des Agilen Manifests (Manifest für Agile Softwareentwicklung, The Agile Manifesto), das Fundament agiler Softwareentwicklung. Er ist auch führendes Mitglied der Bewegung Software Craftsmanship, die sich der Clean Code Softwareentwicklung verschrieben hat. Der Buchautor
  • 3. Inhalt (Teil 1) Einführung Bausteine Gute Benennung Funktionen Kommentare Formatierung Objekte und Datenstrukturen Fehlerbehandlung
  • 4. Einführung Warum Clean Code? Brauchen wir das überhaupt? Was macht Clean Code aus?
  • 5. Woran erkennt man Clean Code?
  • 6. Der gute Clean Code Ratschlag „Programmiere immer so, als ob dein Nachfolger, der deinen Code anpassen muss, ein Psychopath ist, der weiß wo du wohnst!“ Uncle Bob
  • 7. Eine Geschichte aus dem Leben… Super Application v1.0 * Release: 1980 * programmiert von Super Codern Glücklicher User mit Geldüberschuss
  • 8. Super Coder im Einsatz! v1.0 v2.0 v3.0 v3.1 v4.0 v4.01 v4.02 Zeit Release Bug #17 Bug #35 Bug #52 Bug #101 Bug #119 Bug #210 Bug #347 Auslieferung zur Weltmesse Bug #404 Bug #1296 Bugfix Super Coder programmiert fleißig Release für Release…
  • 9. Was ist da los? 0% 20% 40% 60% 80% 100% 120% 1980 1981 1982 1983 1984 Produktivität Zeit Super Coder frustrierter User
  • 10. Das Schicksal mit den Kunden! B* B* B* (Produkt von anderer Firma) Zeit Glücklicher User mit Geldüberschuss Frustrierter User mit Sorgen Glücklicher User (leider ab jetzt bei der Konkurrenz)
  • 11. …und der Super Coder? Super Coder Armer Bettler* * sein Unternehmen war pleite Zeit
  • 12. Das Insider-Gespräch… ?!? „Wir haben gecodet und programmiert wie die Helden – wir haben Features, Features, und noch mal Features gebaut. Die Zeit war immer zu knapp. Wir haben einfach alles immer schnell rein gehauen. Irgendwann haben uns die Bugs eingeholt. Wir haben nur noch Bugs gefixt. Manche Bugfixes haben weitere Bugs hervorgerufen. Wir hatten keine Zeit für Bugfixes. Der Code war richtig dreckig geworden. Es hat keinen Spaß mehr gemacht. Wir haben nicht mehr durchgeblickt. Die Kunden waren sauer und sind abgesprungen. Kollegen haben gekündigt. Wir sind den Bach runter gegangen!“ Ex-Super Coder Uncle Bob …und frägt nach: „was war da damals los?“ woraufhin Ex-Super Coder einen mehrzeiligen Kommentar abgibt:
  • 13. Begriff für dieses Vorkommnis = Technische Schulden Bug #101 Bug #404 Bug #52 Feature #27 Feature #39 Feature #42 Feature #31
  • 14. Der Lerneffekt „Zeit darauf zu verwenden, den Code sauber zu halten, ist nicht nur kosteneffektiv, sondern auch eine Sache des professionellen Überlebens!“ Uncle Bob Manager Programmierer Programmierer Wer ist also Schuld? a) Die Programmierer b) Die Manager „Die Programmierer sind selbst Schuld, wenn sie auf Clean Code zugunsten schneller Ergebnisse verzichten.“
  • 15. Welche Eigenschaften hat CleanCode? + lesbar wie ein Roman + stellt Design-Absichten dar + verständlich für andere Entwickler + automatisiert getestet + minimale Abhängigkeiten + minimiert Duplizierungen + minimale Längen + einfach + wartbar + elegant + bedacht
  • 16. Constantin öffnet die Klassendatei… …er scrollt nach unten bis zur Methode, die geändert werden muss …er überlegt und geht die Möglichkeiten durch …oh, er scrollt nach oben, an den Anfang des Klasse, um eine Initialisierung der Instanzvariable zu prüfen …jetzt scrollt er wieder zurück und beginnt zu tippen …ups – er löscht, was er getippt hat …er tippt wieder …er löscht es wieder …er tippt die Hälfte von etwas Anderem, aber er löscht es! ...Er scrollt nach unten zu einer anderen Methode, die eine Methode aufruft, die er anpasst, um zu sehen, wie sie aufgerufen wird …er scrollt nach oben und tippt den selben Code, den er gerade gelöscht hat …er stoppt …er löscht den Code schon wieder! ...er öffnet ein anderes Fenster, um sich eine abgeleitete Klasse anzusehen: Ist diese Methode überschrieben?... Code wird viel öfter gelesen als geschrieben! § !!! § § !!! § Ein Blick über die Schulter eines Programmierers…
  • 18. int otd; //overtime int overtimeInDays; int overtimeForYear; int overtimeSinceBegin; int daysHavingOvertime; // noch besser mit .NET TimeSpan overtimeSinceBegin; Gute Benennung Anstatt: Besser:
  • 19. public List<double[]> DoGet() { List<double[]> arr = new List<double[]>(); foreach (double[] it in coll) if (it[0] == 2) arr.Add(it[0]); return arr; } public List<Cell> FilterBlackCells() { List<Cell> blackCells = new List<Cell>(); forech (Cell cell in chessboard) if (cell.IsBlack()) blackCells.Add(cell); return blackCells; } Gute Benennung Anstatt: Besser: Für was steht der Rückgabewert? Was macht die Methode? Was repräsentiert die Collection? Warum gerade 2? Was bedeutet das? → Antipattern: Magic Number Was ist zum Schluss in der Liste?
  • 20. crtmjsms creationDateTime Gute Benennung Anstatt: Besser: Hey, warum verwendest du hier die Variable „CeErTeEmUndSoWeiter“? Hey, warum verwendest du hier die Variable „creationDateTime“? Sprechbare Bezeichnungen verwenden, damit eine Konversation möglich ist. Sprechbare Bezeichnungen
  • 21. CustomerObject CustomerData CustomerInfo Customer Gute Benennung Anstatt: Besser: Störung / „Rauschen“ Man sagt: a Customer Nichts aussagende technische Begriffe weglassen, wenn es keinen nennenswerten Unterschied macht. Ausschlaggebende Unterscheidungen
  • 22. XlsxSheet var data = new { Name = „Hans“ }; Sheet var person = new Person { Name = „Hans“ }; Gute Benennung Anstatt: Besser: Ohne Präfix einfacher zu finden Begriffe so wählen, damit sie intuitiv von vorne schneller gefunden werden können. Benutzer-suchbare Bezeichnungen Weiter unten im Code ist nicht mehr klar, was data eigentlich ist.
  • 23. string strFullName; string accountString; // nach Refactoring passiert dann: BankAccount accountString; string fullName; string account; BankAccount account; Gute Benennung Anstatt: Besser: Ungarische Notation (d.h. das hinten anstellen des Typbezeichners an den Variablennamen) ist wegen der guten Entwicklungsumgebung nicht mehr hilfreich, sondern fehleranfällig. Ungarische Notation
  • 24. private string m_add; private string address; Gute Benennung Anstatt: Besser: Präfixe für Membervariablen weglassen Präfixe für Membervariablen Sichtbarer Störfleck Membervariable muss nicht markiert werden, da Klassen sowieso kurz genug sein sollten!
  • 25. …Data …Info …Processor …Manager Article ServiceAccount Gute Benennung Anstatt: Besser: Nomen für Klassen verwenden und mehrdeutige und nicht aussagekräftige Namen vermeiden! Klassenbezeichnungen Nomen (Hauptwörter) verwenden
  • 26. new Money(23.0) CancelOrder RemoveParagraph Money.FromEuroCent(23.0) Gute Benennung Anstatt: Besser: Verben für Methoden verwenden Methodenbezeichnungen Verben (Tunwörter) verwenden
  • 27. GetProduct FetchCatalog RetrieveChecklist FetchProduct FetchCatalog FetchChecklist Gute Benennung Anstatt: Besser: Nur 1 Wort pro Konzept verwenden → Am besten Konsistenz-Lexikon anlegen Konsistenz Gleiche Funktionsweise, unterschiedliche Benennungen
  • 28. LogDynamicExtensionAnnotator JobItemsInOrderRunner LogVisitor JobQueue Gute Benennung Anstatt: Besser: Gängige Pattern-Benennung benutzen, statt sie zu umschreiben Pattern-Benennungen Was soll das über die Implementierung aussagen? Visitor-Pattern Queue-Collection
  • 29. EPUSTargetAreaGlobalPositionAddress //EPUS = Energy Power Ultra System TargetArea Gute Benennung Anstatt: Besser: Kein Solution-Präfix benutzen, da Name sowieso bekannt und redundant ist. Solution-Präfix
  • 30. Zusammenfassung Sprechbare Bezeichnungen Ausschlaggebende Unterscheidungen Benutzer-suchbare Bezeichnungen Ungarische Notation Präfixe für Membervariablen Klassenbezeichnungen Methodenbezeichnungen Konsistenz Pattern-Benennungen Solution-Präfix Gute Benennung
  • 32. Wichtigste Regel für Funktionen „Die erste Regel zu Funktionen ist, dass sie klein sein sollen. Die zweite Regel für Funktionen ist, sie sollen kleiner sein als das.“ Uncle Bob „Und: Funktionen sollen nur eine einzige Sache tun.“
  • 33. if (count == 0) { BreakProcessing(); } else if(count == 1) { ProcessSingleItem(); } else { ProcessMany(count); } Funktionen Gut: Bei if/then/else → 1 Zeile Methodenaufruf Einrückungsebenen Einrückungsebenen: → Maximal 2 Ebenen tief
  • 34. „To…“-Paragraphen-Formulierung nutzen To ShowReportWithHeadersAndFooters we check to see if a site is a inclusion site and if so we include the headers and footers. Otherwise we show it as PDF. Single Responsibility Principle (SRP) § !!! § § !!! § Wie findet man heraus, ob eine Funktion nur eine Sache tut? Funktionen
  • 35. Die Stepdown-Regel Funktionen Stepdown-Regel To include the headers and footers we include headers, then we include the site report controls, then we include the footers. To include the subreport header, we search the parent hierarchy for the „subreport“ property and add an include statement for it. To include the headers we include the subreport header if this is a supreport, then we include the main header. To search the parent… ABSTRAKTIONSEBENEN
  • 36. Show(true) ShowMainReport() // und ShowSubReport() //oder noch besser in .NET Show(ReportType.Main) // und Show(ReportType.SubReport) Anstatt: Besser: boolean-Parameter Was aktiviert der Parameter? Methodendefinition: Show(bool isSubReport) Funktionen funktioniert wegen Methodendefinition: Show(ReportType reportType) enum ReportType { Main = 0, SubReport = 1 } boolean-Parameter durch zwei Methodenaufrufe oder einen selbst geschriebenen enum-Typen ersetzen.
  • 37. consent = verify(user) check(hasAgreedAll, hasAgreedSpecialCase) hasAgreed = verifyGDPRConsents(user) checkAllOverridesOtherOption( hasAgreedAll, hasAgreedSpecialCase) // noch eleganter in .NET: // Operation Overloading hasOverride = hasAgreedAll > hasAgreedSpecialCase Anstatt: Besser: Verben und Schlüsselwörter Was genau wird geprüft? Funktionen Wie werden die Parameter verglichen? Funktionen gegebenenfalls ausführlicher benennen, damit Verhalten klar wird.
  • 38. Parameteranzahl Empfehlung 1 am besten 2 gut 3 sollte vermieden werden Parameter-Anzahl Funktionen run(„a“, 1, true, false, „admin“, new DefaultOptions(), true, null, null, null, 1); Anstatt: Besser: Was wird alles übergeben? Hat man hier noch den Überblick? Was ist, wenn sich Parameter ändern, oder noch welche hinzukommen?
  • 39. IsDbConnectionOpen() { //… httpSession.Start() //… } IsDbConnectionOpen() { //… } Anstatt: Besser: Seiteneffekte Status wird in Prüfungs-Methode verändert – Der Seiteneffekt wird von keinem Entwickler erwartet! Funktionen Keine Seiteneffekte (z.B. Schreibzugriffe in Lese-Funktionen) einbauen
  • 40. if (SaveField(„name“, „Hans“)) … if (HasField(„name“)) { SaveField(„name“, „Hans“) … } Anstatt: Besser: Command Query Separation if-Abfrage Lese-Zugriff = Query Funktionen Query und Command Zugriffe müssen in zwei separate Funktionen aufgetrennt werden. Save-Methode Schreib-Zugriff = Command Was gibt das SaveField für die Bedingung zurück? Wann trifft es zu?
  • 41. ExtendWithDefaultFooter(s) void ExtendWithDefaultFooter( StringBuilder report) report.ExtendWithDefaultFooter(); class PlainTextReport : Report { private StringBuilder content; void ExtendWithDefaultFooter() { … } } Anstatt: Besser: Ausgabeparameter Der StringBuffer wird als Ein- und Ausgabeparameter genutzt. Das ist nicht so schön lesbar. Funktionen Ausgabeparameter können oft besser mit der zugehörigen Methode in einer eigenen Klasse gekapselt werden.
  • 42. public void Remove(SubReport subReport) { try { DeleteControlsAndLinks(subReport); } catch(Exception ex) { LogError(ex); } } private void DeleteControlsAndLinks(page) { … } private void LogError(Exception ex) { … } Funktionen Gut: Bei try/catch → 1 Zeile Methodenaufruf try-catch-Blöcke extrahieren „Clean Code ist lesbar wie ein Roman“ Zuerst kommt die Überschrift, dann die Details
  • 43. Code zu kopieren! Don‘t repeat yourself (DRY) § !!! § § !!! § Was ist die größte Todsünde beim Programmieren? Funktionen Code A Code A-Kopie mit Änderung Code A-Kopie mit Änderung- Kopie mit Anpassung aufrufender Code aufrufender Code aufrufender Code Änderung 1 Änderung 2 Änderung 2? Änderung 2? Änderung 3 Es entsteht ein Vielfaches an Code an verteilten Stellen So entstehen leichtsinnige Bugs Änderung 1 ist bei jedem Aufrufer vorhanden Änderung 2 nicht mehr, und muss noch mal kopiert werden…
  • 44. Produktive Vorgehensweise Widerspricht es sich nicht, schnell und produktiv Funktionen zu schreiben, die auch sauber sein müssen? Nein, es gibt einen guten Kompromiss: 1) Code einfach mal quick & dirty „herunterschreiben“ 2) Code refaktorisieren und verfeinern Funktionen Refaktorisierung
  • 45. Zusammenfassung Kürze Einrückungsebenen Single Responsibility Principle Stepdown-Regel boolean-Parameter Verben und Schlüsselwörter Parameter-Anzahl Seiteneffekte Command Query Separation Ausgabeparameter try-catch-Blöcke extrahieren Don‘t repeat yourself Refactoring Funktionen
  • 47. Kommentare und schlechter Code „Kommentiere schlechten Code nicht einfach – schreibe ihn neu!“ Brian W. Kernighan & P. J. Plaugher
  • 48. Veraltete Kommentare „Kommentare lügen! Ein Programmierer kann sie realistischerweise nie richtig instand halten.“ Uncle Bob Auskommentierter alter Code muss immer sofort gelöscht werden! Dafür gibt es nämlich ein Quellcodeverwaltungssystem.
  • 49. // check to see if the employee // has earned super bonus if ((employee.flags & SUPER_FLAG) && (employee.Earning > 0)) … if(employee.HasEarnedSuperBonus()) … Anstatt: Besser: Kommentare
  • 50. + Gute Arten von Kommentaren + Gesetzliche Kommentare (Copyright Header) + Erklärung der Absicht // Dies ist unser Versuch, einen Dead Lock zu // erzwingen, mit einer brutal hohen Menge an // Threads + Warnung vor Konsequenzen // StateRepository ist nicht ThreadSafe + TODO-Kommentare + XML-Kommentare in public APIs oder Javadocs + Begründung für leere catch-Blöcke
  • 51. - Schlechte Arten von Kommentaren − Code-erklärende Kommentare // erhöhe i um 1 − Pflichtkommentare ///<summary> /// Gets and sets the name ///</summary> string Name { get; set;} − Journal-Kommentare / Änderungshistorie − Überflüssige Kommentare /* Default Constructor */ − Positionsmarker ///// Methods ///////////////////////// − Klammerschluss-Kommentare − Globale Informationen innerhalb von Funktionen // Default User ist PowerAdmin aus Travolta − Zu viele Informationen (z.B. komplexe Spezifikationen) − XML-Dokumentation/Javadocs in nicht-public-Code
  • 53. Gemeinsamer Codestyle Check_passwd() { //… } Super Coder A Super Coder B Super Coder C checkpassword ( ) { //… } DoPasswordCheck () { //… } CheckPassword() { //… } Formatierung Am Anfang des Projekts sollte man sich im Team auf einen gemeinsamen Stil einigen. Team- Regeln stehen dann über individuellen Regeln.
  • 54. Empfohlene Anzahl an Codezeilen Durchschnittlich [] Minimal [min.] Maximal [max.] Projekt 65 6 400 FitNesse 200 500 Große Systeme: JUnit testNG JDepend Ant Tomcat Formatierung
  • 55. Zeitungs-Methapher DIE NEUE ZEITUNG | GLOBALES Obama will die Krankenversicherung einführen Xxxxxxxxxx Xxxxxxxxx Xxxxxxxxxx Xxxxxxx xxxx xxx xxxxx xxxx xxxx xxxxx xxxxxx xxxxx xxxxxxxx xxxxxxxxx xxxxxxxxxxxxxx xxxxx xxxxxxxxxx xx xxx x x xxxxxxxxxxx x xxxxxxx xxxxxxx xxxxxxx x xxxx xxxx xxxxx xxxxxx xxx xxx xxxx xxxxxxx xxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxxx xxxxxxxxxxxxx xxxxxxxxxxxx xxxxxxx xxxxxxxxxx xxxxxx xxxxxx xxxx xxxxxxxxxx. ☺ Scherz am Rande - Kommentar eines Zeitungslesers: „I only understand English and I can read only the first three words!“ class ReportOutputGenerator { public Report Render() { // xxxxxxx // xxxxxxx // xxxxxxx } private void … { // xxxxxxx // xxxxxxx } private void … } Titel / Worum geht es? Wo bin ich? Zusammenfassung Details Formatierung
  • 56. class ReportOutputGenerator { private Controls controls; public Report Render() { // xxxxxx int i; while(i < 0) { … } // xxxxxx } private void … { // xxxxxxx // xxxxxxx } private void … } Eine Zeile Zeilenabstand zwischen Methoden zeigen den Wechsel auch optisch und sind wichtig Zusammenhängende Methoden sollten vertikal nah beieinander stehen Formatierung Variablendeklarationen sollten immer so nah wie möglich zu Ihrer Verwendung stehen. Instanzvariablen sollten immer am Kopf der Klasse gesammelt werden. Zeichenlänge: Empfehlung max. 120 Zeichen (es muss noch auf einen normalen Bildschirm passen)
  • 58. Objekt Datenstruktur Objekte und Datenstrukturen class Report { public List<SubReport> SubReports { get; set; } public string Title { get; set; } … } class PageEditor { void Remove(SubReport report) { … } private void DeleteControlsAndLinks(report) { … } private void LogError(Exception ex) { … } } Logik / Verhalten Datenhaltung vs.
  • 59. Law of Demeter § !!! § § !!! § Objekte und Datenstrukturen string outputPath = dir.getBase() .getReportsDir() .getFullPath(); string outputPath = dir.Base .ReportsDir .FullPath; FileInfo outputFileInfo = dir .BuildReportsPath( reportCategory); Anstatt: Besser: Uncle Bob hasst übrigens getter/setter in Java, da sie sinnlos sind! Verkettung von vielen Aufrufen, wie bei einem Zug mit vielen Locks Ein Modul darf nichts über das Innerste eines Objekts wissen, das es manipuliert! Das widerspricht dem Prinzip der Kapselung.
  • 61. void Remove(SubReport subReport) { try { DeleteControlsAndLinks(subReport); } catch(Exception ex) { LogError(ex); } } private void DeleteControlsAndLinks(subReport) { … } private void LogError(Exception ex) { … } Fehlerbehandlung Gut: Bei try/catch → 1 Zeile Methodenaufruf try-catch-Blöcke extrahieren „Clean Code ist lesbar wie ein Roman“ Zuerst kommt die Überschrift, dann die Details
  • 62. public int Activate(Person p) { // … if(p.Email == null) { return ErrorCodes.Code47_NoMail; } // … } /// <exception /// cref="Prog.MissingMailException"> /// Thrown when no mail address /// is given, so that no activation /// mail is possible. Activation /// will be cancelled. /// </exception> public void Activate(Person p) { // … if(p.Email == null) { throw new MissingMailException(); } // … } Anstatt: Besser: Exceptions statt return codes Gut: Hier keine Magic Number ABER: Magic Number kommt trotzdem bei Anrufer an, und muss sogar bekannt sein und erwartet werden! Fehlerbehandlung Selbst geschriebene Exceptions statt return Codes verwenden. So muss der Fehler automatisch behandelt werden, oder wird direkt für den Benutzer ausgegeben. Damit Aufrufer über mögliche Exceptions Bescheid weiß, sollte man sie im XML Doc angeben.
  • 63. try { total += budgetRepo.LoadYearly(); } catch( YearlyNotFoundException ex) { total += LoadOutOfOrderBudget(); } total += budgetRepo.LoadAll(); class OutOfOrderBudget : YearlyBudget { … } Anstatt: Besser: Keine Exceptions für Kontrollfluss Fehlerbehandlung Exceptions nicht für normalen Kontrollfluss verwenden. Besser ist es, z.B. das „Special Case Pattern“ zu verwenden. =„Special Case Pattern“ total kann dann mit Standardfall und Sonderfall normal addiert werden. Häufig auftretender Sonderfall; ist ein „Kontrollfluss“, da Aktion ausgelöst wird; keine problematische unerwartete „Ausnahme“. Exceptions zu werfen und zu fangen ist nämlich „teuer“ (=frisst Performance).
  • 64. public IEnumerable<Customer> Load( CustomerType type) { if(type == null) throw new IllegalArgumentException(„type“); //… return null; } public IEnumerable<Customer> Load( CustomerType type) { // Kein explizites null-Handling //… return Enumerables.Empty<Customer>(); } Anstatt: Besser: null-Handling Team-Regel festlegen: null sollte am besten nie als Parameter übergeben werden! Fehlerbehandlung Team-Regel: Offensiv programmieren - nie null als Parameter übergeben, und nie null als Rückgabeparameter zurückgeben! = „Null-Object-Pattern“ Aufrufer ist dadurch vor null- Reference-Exception geschützt Potentielle null-Reference- Exception beim Aufrufer! Code wird leider aufgebläht = „Offensive Programmierung“ d.h. dafür sorgen, dass Fehler beim Aufruf früh aufgedeckt werden! Beim Debuggen gibt es inzwischen gute Hinweise zum null-Ursprung.
  • 65. Wie es weiter geht… Und jetzt folgt – die WERBUNG: …seht ihr in Teil 2 beim nächsten Mal! Eine klare Buchempfehlung für alle Programmierer!