Mein Freund,
der Legacy-Code
    Mathias Meyer
    Peritor GmbH
self
• Chief Cloud Officer bei Peritor GmbH
• Rubyist
• Asynchronist
• Post-Relationalist
• @roidrage
• http://github.com/m...
Peritor

          Ruby on Rails
Deployment
               Performance-Tuning/-Reviews
Amazon Web Services
               ...
Peritor
Es war einmal


• Eine elegante Programmiersprache
• Ein wunderbar einfaches Web-Framework
Es war einmal



  +        =
Es war einmal


• Beide erreichten den Mainstream
• Beide wurden von vielen Entwicklern gefunden
• Beide sind keine Garant...
Es war einmal


    Ruby und Rails im Mainstream = Millionen LOLC*




*LOLC: Lines of Legacy Code
Es war einmal


• Millionen LOLC =

• Legacy-Code ist ein Markt
Legacy-Code?



• Code ohne Tests
Legacy-Code?


• Stuff that other people wrote.
  http://www.c2.com/cgi/wiki?LegacyCode
Legacy-Code?


• Technical Debt
  Niedrige Kosten/Aufwand am Anfang, im Laufe
  der Zeit steigend
Legacy-Code?


• Code der in Production ist.
  (Mathias Meyer, 2009)
Legacy-Code?


• Ergo:
  Code den ihr tagtäglich produziert.
Legacy-Code?

• Code den keiner gern anfässt.
• Code der schwer zu ändern ist.
• Code der fehleranfällig ist.
• Code der s...
Legacy-Code?

• Änderungen werden mit der Zeit exponentiell
  teurer
• Änderungen führen zu mehr Bugs
• Änderungen brechen...
Legacy-Code?

• Negativ vorbelastet
• Riesige Codewürste, unstrukturiert, ungetestet
• Sch***code
• Code-Smells ist noch g...
Legacy-Code?
                                          Legacy-Code in Ruby*
                         5000000
             ...
Warum?

• Mangelnde Erfahrung
• Entwickler bringen Java, C, PHP, Perl, etc. in
  ihren Ruby-Code ein
• Mangelndes Interess...
Warum?

   • Weil Leute immer noch
     keine Tests schreiben
   • Tests: Oftmals schon der
     halbe Weg zum Glück
   • ...
Eine Geschichte

• Ein Controller
• Er möchte unerkannt bleiben
• Er war die Ausgeburt aller Ängste vor Legacy-
  Code
Eine Geschichte

• ~1300 Zeilen
• Für mehrere Wochen auf Abspeckkur
  geschickt
• Auf 200 Zeilen, 3 neue Controller, und d...
Das will ich auch!

• Legacy-Code muss nichts schlechtes sein
• Auch wenn er so aussieht
• Legacy-Code kann schlimm ausseh...
Wie?
• Offensichtliches
 • Test all the fucking time, as much and as
   widely as you can
 • Refactor like a pr0n star
 • ...
Wie?


• Given enough eyeballs, all bugs are shallow.
• And all code will be awesome.
• Nicht immer!
Redmine


• app/controllers/issues_controller.rb:
  500 Zeilen, 23.5kb, “Nur” ~1000 Zeilen Tests
Wie?

• Wie gehe ich mit solchem Code um?
• Wie gehe ich ein Refactoring an?
• Wie ziehe ich eine Test-Suite auf?
• Wie re...
Wie?




© http://thisiswhyyourefat.com/
Halbwahrheiten

• Der große Wurf wird nicht auf einmal gelingen
• Ein großes Refactoring einplanen ist der Weg
  ins Verde...
Wie?
• Know your enemy, because knowing is half the battle
Tools?
Tools?


• Refactoring-Tools in Ruby? Nada
• Gesunder Menschenverstand
• Know when to stop
Wie?


• Code-Metriken
• Code Lesen
• Exploratives Testen
Code-Metriken

• Mit Statistiken stark riechende Stellen finden
• Hohe Signal-Noise-Ratio
• Zu einfach den Fokus zu verlier...
Code Lesen

• Use the source, Luke
• Notwendiges Übel
• Knowing!
• Con:Verlieren in Details immer zu einfach
Exploratives Testen

• Spezifische Teile des Codes mit Tests abdecken
• Zeile für Zeile, Feature für Feature
• Pro: Test-Su...
Subkategorie: Mocks/Stubs

 • Pro: Nützlich gegen unliebsame Abhängigkeiten
 • Con: Kann zur Sucht, zum Dauerzustand
   we...
Too. Many. Mocks.
before(:each)
do


@fanout
=
mock("fanout")


@binding
=
mock("binding",
:subscribe
=>
true)


@queue
=
...
Parallele Welten
• Notfallwaffe
• Code auseinandernehmen und parallel neu
  aufbauen (aus existierendem)
• Ja, zuerst auch...
Test-Suite Aufbauen

• Jetzt? Ja!
• Für die ganze Code-Basis? Nein!
• Klein anfangen,Vorher Hände waschen!
• Tests schreib...
Technik

• Sollbruchstellen finden
• Dependencies idenfizieren, wenn möglich
  aufbrechen
• Sollbruchstellen mit Tests abdec...
Technik in Rails
• RESTful als Guideline, nicht als Mantra
• Controller aufbrechen
• Zuviele Actions bedeuten zuviele pote...
Technik in Rails
• Tests von oben nach unten
 • Controller-Tests decken das wichtigste ab
 • Views nicht vergessen
 • Unit...
Technik in Rails


• Dependencies von Controllern nicht vergessen
 • Views
 • Helper
The Enterprise Way

• Versteck den Legacy-Code hinter noch mehr
 Legacy-Code
• ESB
• SOA
• EAI
SOAESBEAIOMGWTF!


• SOA: Legacy-Code as a Service
• Wenn schon, dann eine einfache REST-API
• Legacy-Code wird z.B. zum W...
SOAESBEAIOMGWTF!

• EAI: Enterprise Application Integration
• Versteckt Code hinter Messaging-Backends
• Dröger Name, groß...
SOAESBEAIOMGWTF!
• ESB: Enterprise Service Bus
• ESB = EAI + SOA + XML + OMG + Magic
• Unentdecktes Land unter Rubyists
Worauf fokussieren?
Refactoringchen

• Refactor as you go
• Code der angefasst wird, bekommt Tests
  verpasst und wird aufgeräumt
• Sollte sel...
Gezieltes Aufräumen
• Ein dunkle Stelle anpeilen
 • Analysieren
 • Testen
 • Refaktorieren,
 • Nochmals testen
• Sinnvoll ...
The Big Refactoring

• Sowas wie ein Big Refactoring existiert nicht
• Refactoring ist ein Prozess
• In jeder Iteration Ze...
The Big Rewrite
• Beliebt bei Entwicklern
• Unbeliebt beim Management, zu Recht
• Funktioniert so gut wie nie
• Oftmals vo...
Wie verkaufen?




Management     Entwickler
Wie verkaufen?

       • Management: Wir
         brauchen mehr
         Features
       • Entwickler: Wir
         brauch...
Wie verkaufen?
• Das klassische Vorurteil
• Es gibt auch einen Mittelweg
Wie verkaufen?

• Gar nicht, einfach machen
 • Skaliert nicht für große Umbauten
 • Hohes Business-Risiko
 • Sollte wohl d...
Wie verkaufen?
• Argumente sammeln
 • Code-Änderungen werden teurer
 • Neue Features fließen langsamer
 • Leidenschaftlich,...
Danach


Den Beweis antreten
Danach


• Bugs sind kein Weltuntergang, sie kommen vor
• Wenn man sie schneller fixen kann: Win!
Und dann?
Fin


mathias.meyer@peritor.com
Mein Freund Der Legacy Code
Mein Freund Der Legacy Code
Nächste SlideShare
Wird geladen in …5
×

Mein Freund Der Legacy Code

3.366 Aufrufe

Veröffentlicht am

Slides (in German) from my talk on legacy code at the German Rails-Konferenz.

Veröffentlicht in: Technologie
0 Kommentare
3 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe
Aufrufe insgesamt
3.366
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
86
Aktionen
Geteilt
0
Downloads
10
Kommentare
0
Gefällt mir
3
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Mein Freund Der Legacy Code

  1. 1. Mein Freund, der Legacy-Code Mathias Meyer Peritor GmbH
  2. 2. self • Chief Cloud Officer bei Peritor GmbH • Rubyist • Asynchronist • Post-Relationalist • @roidrage • http://github.com/mattmatt
  3. 3. Peritor Ruby on Rails Deployment Performance-Tuning/-Reviews Amazon Web Services Scaling http://dailyawswtf.com
  4. 4. Peritor
  5. 5. Es war einmal • Eine elegante Programmiersprache • Ein wunderbar einfaches Web-Framework
  6. 6. Es war einmal + =
  7. 7. Es war einmal • Beide erreichten den Mainstream • Beide wurden von vielen Entwicklern gefunden • Beide sind keine Garantie für guten Code
  8. 8. Es war einmal Ruby und Rails im Mainstream = Millionen LOLC* *LOLC: Lines of Legacy Code
  9. 9. Es war einmal • Millionen LOLC = • Legacy-Code ist ein Markt
  10. 10. Legacy-Code? • Code ohne Tests
  11. 11. Legacy-Code? • Stuff that other people wrote. http://www.c2.com/cgi/wiki?LegacyCode
  12. 12. Legacy-Code? • Technical Debt Niedrige Kosten/Aufwand am Anfang, im Laufe der Zeit steigend
  13. 13. Legacy-Code? • Code der in Production ist. (Mathias Meyer, 2009)
  14. 14. Legacy-Code? • Ergo: Code den ihr tagtäglich produziert.
  15. 15. Legacy-Code? • Code den keiner gern anfässt. • Code der schwer zu ändern ist. • Code der fehleranfällig ist. • Code der stetig verschlimmbessert wird.
  16. 16. Legacy-Code? • Änderungen werden mit der Zeit exponentiell teurer • Änderungen führen zu mehr Bugs • Änderungen brechen existierenden Code
  17. 17. Legacy-Code? • Negativ vorbelastet • Riesige Codewürste, unstrukturiert, ungetestet • Sch***code • Code-Smells ist noch gelinde ausgedrückt • Broken-Windows passt schon eher
  18. 18. Legacy-Code? Legacy-Code in Ruby* 5000000 LOLC LOTC 4500000 4000000 3500000 3000000 2500000 2000000 1500000 1000000 500000 0 1995 2000 2005 2010 * Zahlen frei erfunden
  19. 19. Warum? • Mangelnde Erfahrung • Entwickler bringen Java, C, PHP, Perl, etc. in ihren Ruby-Code ein • Mangelndes Interesse • “Keine Zeit” • “Feature-Druck”
  20. 20. Warum? • Weil Leute immer noch keine Tests schreiben • Tests: Oftmals schon der halbe Weg zum Glück • Refactoring ohne Tests: Die Welt des Schmerzes
  21. 21. Eine Geschichte • Ein Controller • Er möchte unerkannt bleiben • Er war die Ausgeburt aller Ängste vor Legacy- Code
  22. 22. Eine Geschichte • ~1300 Zeilen • Für mehrere Wochen auf Abspeckkur geschickt • Auf 200 Zeilen, 3 neue Controller, und den meisten Code ins Model abgeschoben
  23. 23. Das will ich auch! • Legacy-Code muss nichts schlechtes sein • Auch wenn er so aussieht • Legacy-Code kann schlimm aussehen, aber es liegt an euch wie ihr ihn hinterlasst • TODOs im Code vermeiden, lieber fixen
  24. 24. Wie? • Offensichtliches • Test all the fucking time, as much and as widely as you can • Refactor like a pr0n star • Pair a lot of the time • Agile, XP, Scrum, oh my! • Man kann es nicht oft genug sagen
  25. 25. Wie? • Given enough eyeballs, all bugs are shallow. • And all code will be awesome. • Nicht immer!
  26. 26. Redmine • app/controllers/issues_controller.rb: 500 Zeilen, 23.5kb, “Nur” ~1000 Zeilen Tests
  27. 27. Wie? • Wie gehe ich mit solchem Code um? • Wie gehe ich ein Refactoring an? • Wie ziehe ich eine Test-Suite auf? • Wie rechtfertige ich große Änderungen?
  28. 28. Wie? © http://thisiswhyyourefat.com/
  29. 29. Halbwahrheiten • Der große Wurf wird nicht auf einmal gelingen • Ein großes Refactoring einplanen ist der Weg ins Verderben • Stetige Verbesserung ist der Weg der Weisen
  30. 30. Wie? • Know your enemy, because knowing is half the battle
  31. 31. Tools?
  32. 32. Tools? • Refactoring-Tools in Ruby? Nada • Gesunder Menschenverstand • Know when to stop
  33. 33. Wie? • Code-Metriken • Code Lesen • Exploratives Testen
  34. 34. Code-Metriken • Mit Statistiken stark riechende Stellen finden • Hohe Signal-Noise-Ratio • Zu einfach den Fokus zu verlieren • Einzig nützlich: Test-Coverage als Peildaumen
  35. 35. Code Lesen • Use the source, Luke • Notwendiges Übel • Knowing! • Con:Verlieren in Details immer zu einfach
  36. 36. Exploratives Testen • Spezifische Teile des Codes mit Tests abdecken • Zeile für Zeile, Feature für Feature • Pro: Test-Suite wächst und ist bereit zum Refactoring • Sehr hoher Lerneffekt, viele Wtf-Momente garantiert
  37. 37. Subkategorie: Mocks/Stubs • Pro: Nützlich gegen unliebsame Abhängigkeiten • Con: Kann zur Sucht, zum Dauerzustand werden • Zuviele Mocks verstecken das Wesentliche • Fantasy Testing
  38. 38. Too. Many. Mocks. before(:each)
do 

@fanout
=
mock("fanout") 

@binding
=
mock("binding",
:subscribe
=>
true) 

@queue
=
mock("queue",
:bind
=>
@binding,
:publish
=>
true) 

@amq
=
mock("AMPQueue",
:queue
=>
@queue,
:fanout
=>
@fanout) 

@serializer
=
mock("Serializer",
:dump
=>
"dumped_value") 

@target
=
mock("Target
of
Request") 

@reaper
=
mock("Reaper") 

Nanite::Reaper.stub!(:new).and_return(@reaper) 

@request_without_target
=
mock("Request",
:target
=>
nil,
:token
=>
"Token", 


:reply_to
=>
"Reply
To",
:from
=>
"From",
:persistent
=>
true,
:identity
=>
"Identity") 

@request_with_target
=
mock("Request",
:target
=>
"Target",
:token
=>
"Token", 


:reply_to
=>
"Reply
To",
:from
=>
"From",
:persistent
=>
true) 

@mapper_with_target
=
mock("Mapper",
:identity
=>
"id") 

@mapper_without_target
=
mock("Mapper",
:request
=>
false,
:identity
=>
@request_without_target.identity) 

@cluster_with_target
=
Nanite::Cluster.new(@amq,
32,
"the_identity",
@serializer,
@mapper_with_target) 

@cluster_without_target
=
Nanite::Cluster.new(@amq,
32,
"the_identity",
@serializer,
@mapper_without_target) 

Nanite::Cluster.stub!(:mapper).and_return(@mapper) end it
"should
forward
requests
with
targets"
do 

@mapper_with_target.should_receive(:send_request).with(@request_with_target,
anything()) 

@cluster_with_target.__send__(:handle_request,
@request_with_target) end
  39. 39. Parallele Welten • Notfallwaffe • Code auseinandernehmen und parallel neu aufbauen (aus existierendem) • Ja, zuerst auch ohne Tests, wenn’s sein muss • Test-Suite aufbauen mit den verschobenen Code-Teilen • Eltern haften für ihre Kinder
  40. 40. Test-Suite Aufbauen • Jetzt? Ja! • Für die ganze Code-Basis? Nein! • Klein anfangen,Vorher Hände waschen! • Tests schreiben für Funktionalität die durch neue Features zerbrechen kann • Skaliert nicht bei großen Geschwüren
  41. 41. Technik • Sollbruchstellen finden • Dependencies idenfizieren, wenn möglich aufbrechen • Sollbruchstellen mit Tests abdecken • Refactor! • Rinse and repeat
  42. 42. Technik in Rails • RESTful als Guideline, nicht als Mantra • Controller aufbrechen • Zuviele Actions bedeuten zuviele potentielle Ressourcen • Code raus aus den Controllern, sie müssen dumm sein • resource_controller, make_resourceful, etc.
  43. 43. Technik in Rails • Tests von oben nach unten • Controller-Tests decken das wichtigste ab • Views nicht vergessen • Unit-Tests sollten daraus entstehen • Models != ActiveRecord • Neue Models braucht das Land
  44. 44. Technik in Rails • Dependencies von Controllern nicht vergessen • Views • Helper
  45. 45. The Enterprise Way • Versteck den Legacy-Code hinter noch mehr Legacy-Code • ESB • SOA • EAI
  46. 46. SOAESBEAIOMGWTF! • SOA: Legacy-Code as a Service • Wenn schon, dann eine einfache REST-API • Legacy-Code wird z.B. zum Web-Service
  47. 47. SOAESBEAIOMGWTF! • EAI: Enterprise Application Integration • Versteckt Code hinter Messaging-Backends • Dröger Name, großer Effekt • Entkoppelt alten von neuem Code • Erspart nicht das Refactoring, macht es aber potentiell einfacher
  48. 48. SOAESBEAIOMGWTF! • ESB: Enterprise Service Bus • ESB = EAI + SOA + XML + OMG + Magic • Unentdecktes Land unter Rubyists
  49. 49. Worauf fokussieren?
  50. 50. Refactoringchen • Refactor as you go • Code der angefasst wird, bekommt Tests verpasst und wird aufgeräumt • Sollte selbstverständlich sein
  51. 51. Gezieltes Aufräumen • Ein dunkle Stelle anpeilen • Analysieren • Testen • Refaktorieren, • Nochmals testen • Sinnvoll bei vielen größeren Code Smells
  52. 52. The Big Refactoring • Sowas wie ein Big Refactoring existiert nicht • Refactoring ist ein Prozess • In jeder Iteration Zeit einplanen zum Aufräumen alten Codes, mit spezifischem Ziel • Aber: Es ist eine Alternative
  53. 53. The Big Rewrite • Beliebt bei Entwicklern • Unbeliebt beim Management, zu Recht • Funktioniert so gut wie nie • Oftmals voller Stop der Entwicklung • Kulmuliert neuen Legacy-Code • Ergebnis bleibt meist weit hinter Erwartungen zurück
  54. 54. Wie verkaufen? Management Entwickler
  55. 55. Wie verkaufen? • Management: Wir brauchen mehr Features • Entwickler: Wir brauchen mehr Zeit zum aufräumen
  56. 56. Wie verkaufen? • Das klassische Vorurteil • Es gibt auch einen Mittelweg
  57. 57. Wie verkaufen? • Gar nicht, einfach machen • Skaliert nicht für große Umbauten • Hohes Business-Risiko • Sollte wohl durchdacht sein
  58. 58. Wie verkaufen? • Argumente sammeln • Code-Änderungen werden teurer • Neue Features fließen langsamer • Leidenschaftlich, aber nicht trotzig, Konsens ist trotzdem wichtig • Wenn gar nichts mehr geht, Notbremse ziehen
  59. 59. Danach Den Beweis antreten
  60. 60. Danach • Bugs sind kein Weltuntergang, sie kommen vor • Wenn man sie schneller fixen kann: Win!
  61. 61. Und dann?
  62. 62. Fin mathias.meyer@peritor.com

×