Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
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.576 Aufrufe

Veröffentlicht am

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

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

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

×