c3d2-wiki/Themenabend%2FClean_Code.mw

170 lines
6.9 KiB
Plaintext
Raw Normal View History

2015-07-24 22:55:57 +02:00
{{historisch}}[[Kategorie:Themenabend]][[Kategorie:2015]]
{{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= |
2015-07-24 23:07:00 +02:00
SLIDES= [[ Themenabend/Clean_Code#Inhalt | Abschnitt Inhalt ]]|
2015-07-24 22:55:57 +02:00
}}
2015-07-24 23:07:00 +02:00
= Inhalt =
<pre>How to code
_______ _______ _______ __ _ _______ _____ ______ _______
| | |______ |_____| | \ | | | | | \ |______
|_____ |_____ |______ | | | \_| |_____ |_____| |_____/ |______</pre>
;name
:Nico Krebs
;blog
:www.mensch-und-maschine.de
;work
: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, daß 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? ===
==== Die 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 refactoriert werden, daß 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 Variablennnamen
* 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 (anm: also auch kein Script, das Kommandos verbindet. Als emergent könte 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*