164 lines
7.0 KiB
Plaintext
164 lines
7.0 KiB
Plaintext
{{historisch}}[[Kategorie:Themenabend]][[Kategorie:2015]]
|
|
<div style="float:right">
|
|
{{Themenabend
|
|
| TITEL= Clean Code
|
|
| UNTERTITEL=
|
|
| TERMIN= 23.07.2015
|
|
| ORT= HQ
|
|
| THEMA=
|
|
| REFERENTEN= Nico Krebs
|
|
| C3D2WEB= http://www.c3d2.de/news/ta-clean-code.html
|
|
| TOPIC=
|
|
| SLIDES= [[Themenabend/Clean Code]]
|
|
}}
|
|
</div>
|
|
|
|
__TOC__
|
|
|
|
<pre>
|
|
How to code
|
|
_______ _______ _______ __ _ _______ _____ ______ _______
|
|
| | |______ |_____| | \ | | | | | \ |______
|
|
|_____ |_____ |______ | | | \_| |_____ |_____| |_____/ |______
|
|
</pre>
|
|
|
|
; name: Nico Krebs
|
|
; blog: [http://www.mensch-und-maschine.de www.mensch-und-maschine.de]
|
|
; work:[http://www.projektmotor.de www.projektmotor.de]
|
|
; mail: nkoding@gmail.com
|
|
|
|
Alles, was im Folgenden beschrieben wird, ist eine Utopie, ein
|
|
nie erreichbares Ideal und keine dogmatische Handungsanweisung.
|
|
Doch ich versuche mich, so nah wie möglich da heran zu bringen -
|
|
immer pragmatisch auf den Anwendungsfall bezogen.
|
|
Jeder der folgenden Vorschläge kann für sich allein angewendet
|
|
werden, man muss nicht das ''Komplettpaket'' einbauen,
|
|
sondern man sollte sich heraussuchen, was praktikabel ist.
|
|
|
|
== Warum sind wir hier? ==
|
|
|
|
Wir alle haben das schon erlebt und wollen es in Zukunft vermeiden:
|
|
* Projekte werden mit der Zeit immer träger.
|
|
* Neue Features implementieren dauert länger, je mehr Features es gibt.
|
|
* Bugs fixt man nicht mehr in Minuten sondern in Wochen oder Monaten (z.b. wenn Architekturfehler erst spät sichtbar werden).
|
|
* Evtl. wird ein paralleles Projekt gestartet, das alles besser machen soll - aber dann dieselben Methoden verwendet.
|
|
* Beide Arbeitsgruppen konkurrieren, keine kommt wirklich voran.
|
|
* User sind unzufrieden.
|
|
* Das Projekt stirbt an seiner Größe und die Firma ggf. gleich mit.
|
|
* Es gibt sehr viele Sicherheitslücken im Projekt.
|
|
* Bekannteres Bsp.: flash. Vermutlich ist das Code mit ähnlichen Eigenschaften. Entsprechend anfällig ist das Ganze für Sicherheitslücken.
|
|
|
|
== Wie kommt man aus diesem Teufelskreis? ==
|
|
|
|
=== Analyse: Was ist schlechter Code und warum? ===
|
|
|
|
* große Funktionen und Klassen/Scriptfiles
|
|
* eine Funktion erledigt viele Aufgaben
|
|
* Abhängigkeiten sind hard coded
|
|
* Verschachtelte Schleifen und Konstrukte wie Branches ("switch" und "if/then/else") werden häufig genutzt.
|
|
* Logik befindet sich innerhalb von if-Blöcken.
|
|
* Klassen-/Funktions-/Variablennamen sind nicht aussagekräftig.
|
|
* Funktionen mit vielen Parametern
|
|
* Um den Code nachzuvollziehen, muss ständig zwischen Dateien gewechselt und darin über mehrere hundert/tausend Zeilen gescrollt werden.
|
|
* Funktionen sind schlecht oder gar nicht testbar, weil ein Testcase so komplex werden würden, dass sie selbst Tests bräuchten.
|
|
* im worst case GOTO-Anweisungen
|
|
* hohe Wahrscheinlichkeit von Sicherheitslücken<br>=> Spaghetti code
|
|
|
|
=== Im Umfeld schlechten Codes findet man häufig auch: ===
|
|
|
|
* keine automatischen Tests, weil untestbar (z.b. jUnit)
|
|
* keine Versionskontrolle (z.B. git)
|
|
* kein Ticketsystem (z.B. Redmine)
|
|
* kein CI-System (z.b. Jenkins/Hudson)
|
|
* keine Nutzung von IDEs (z.B. NetBeans)
|
|
* keine Dokumentation
|
|
* keine leistungsfähigen Kommunikationskanäle (twitter/foren/chat/...), sondern höchstens per E-Mail-/Telefonsupport
|
|
|
|
=== Was ist sauberer Code? ===
|
|
|
|
* verständlich im Hinblick auf Leistungsfähigkeit des Gehirns (drei bis sieben Elemente im Kurzzeitgedächtnis)
|
|
* lesbar wie ein Buch
|
|
* Eine Funktion hat genau eine Funktion.
|
|
* wenige Kontrollkonstrukte
|
|
* strikte Trennung von Logik und Fehlerprüfung
|
|
* testbare Funktionen und Klassen
|
|
* Nutzung von Test Driven Development, Ticketsystem, Buildsystem etc., um sich selbst zu organisieren und Überblick zu behalten
|
|
|
|
=== Wie schreibt man sauberen Code? ===
|
|
|
|
==== Leistungsfähigkeit des Gehirns als Grundlage ====
|
|
|
|
* möglichst drei bis sieben Packages pro Modul/Plugin
|
|
* möglichst drei bis sieben Klassen pro Package
|
|
* möglichst nicht mehr als sieben Funktionen pro Klasse -> besser drei
|
|
* möglichst drei bis sieben Zeilen Logik pro Funktion
|
|
* Klassen müssen so geplant oder refaktoriert werden, dass sie möglichst wenige hard coded Abhängigkeiten haben.
|
|
* Kommentare möglichst vermeiden, da sie meist sowieso nicht gepflegt werden. Besser sind selbsterklärende Funktions- und Variablennamen.
|
|
* Ein doc-Block für API-Methoden muss jedoch sein (für die User der API).
|
|
|
|
==== Lesbar wie ein Buch ====
|
|
|
|
* Buch = Modul
|
|
* Packagenames = Kapitelüberschriften
|
|
* Kapitel = Sammlung von Klassen
|
|
* Buchseite = Klasse
|
|
* aufgerufene Funktionen immer im Code unter der aufrufenden schreiben
|
|
* sinnvolle Funktionsnamen verwenden
|
|
|
|
==== Eine Funktion hat genau eine Funktion. ====
|
|
|
|
* Parameter sparen, möglichst viel über Klassenproperties abdecken
|
|
* geschlossene Systeme mit Klassen schaffen
|
|
* keine Branches ("if/then/else" Verzweigungen) in der Logik
|
|
|
|
==== Kontrollkonstrukte eliminieren! ====
|
|
|
|
* Durch Branches (if-Konstrukte) in der Logik hat eine Funktion meist nicht mehr nur eine Funktion.
|
|
* Branches und Switches (switch/if-Konstrukte) aufteilen
|
|
** interface mit canRun()/run()-Methoden
|
|
** in einer Schleife alle Implementierungen des Interfaces durchlaufen, die erste die canRun() mit true beantwortet, deren run()-Methode wird aufrufen
|
|
|
|
==== Strikte Trennung von Logik und Fehlerprüfung ====
|
|
|
|
* Trennung von Fehlerbehandlung und Logik
|
|
** error checking standardisieren
|
|
*** immer am Anfang einer Methode
|
|
*** Logik ohne störende Kontrollkonstrukte am Ende
|
|
*** idealerweise in eine eigene Funktion abkapseln
|
|
|
|
=== Teile und herrsche ===
|
|
|
|
* monolithische Systeme immer weiter aufteilen
|
|
* Je kleiner die Teile eines Systems sind, desto beherrschbarar sind sie für Menschen.
|
|
* siehe Quicksort, Design Patterns, rekursive Funktionen allgemein
|
|
|
|
=== Emergenz ===
|
|
|
|
* Zusammenschluss vieler einfacher Komponenten
|
|
* Bsp.: Schwärme, neuronale Netze, Würfelhaufen/Flummis, Conway's Game of Life, genetische/evolutionäre Algorithmen
|
|
|
|
* Was passiert da?
|
|
** Kontrolle an die Einzelteile abgeben
|
|
** Jedes Element kennt selbst den besten Weg, eine Situation zu behandeln.
|
|
** Komponenten können miteinander kommunizieren.
|
|
** Durch die Verbindungen entstehen neue Eigenschaften des Gesamtsystems (leider nur schwer vorhersagbar, welche. siehe Bewusstsein und freier Wille).
|
|
** Einige Eigenschaften sind jedoch vorhersagbar - und das kann man nutzen!
|
|
** Es gibt keinen "master", der die Einzelteile kontrolliert (Anmerkung: also auch kein Script, das Kommandos verbindet. Als emergent könnte man es bezeichnen, wenn zwei oder mehr Scripte autonom agieren und Daten miteinander austauschen.)
|
|
** Insofern können auch autonome Module, Klassen und Funktionen emergentes Verhalten produzieren. -> siehe Multithreading
|
|
|
|
== Aktuelle Forschungsschwerpunkte ==
|
|
|
|
* Erhöhung der Systemsicherheit
|
|
* fehlertolerante Systeme
|
|
* fehlerbehebende Systeme
|
|
* cyber physical systems
|
|
* Standardisierung von Komponenten & model driven development (nutzbare Variante, nicht CASE)
|
|
** Vorbild: Automobilindustrie
|
|
*** Zuverlässigkeit
|
|
*** Vorhersagbarkeit der Kosten & Entwicklungszeit
|
|
*** standardisierte Tests
|
|
*** hochgradig wiederverwendbare Komponenten
|
|
*** standardisierte Schnittstellen
|
|
|
|
=> das Ziel: Software Design => Software *Engineering*
|