SlideShare une entreprise Scribd logo
1  sur  93
Télécharger pour lire hors ligne
Refactoring C#

Legacy Code
Stefan Lieser
@StefanLieser
http://refactoring-legacy-code.net
Houston, we’ve had a problem.
http://er.jsc.nasa.gov/seh/13index.jpg
Wandelbarkeit
https://pixabay.com/de/chamäleon-hautnah-exotische-grün-1414084/
Investitionsschutz = Wandelbarkeit
Nicht-funktionale Anforderungen
Funktionale Anforderungen
Das Problem besteht aus drei Teilen:
• Lesbarkeit/Verständlichkeit ist nicht gegeben
• Automatisierte Tests fehlen
• Komplexe Refactorings sind notwendig
Das Dilemma:
• Um Tests zu ergänzen,

=> muss refactored werden.

• Um zu refactoren,

=> müssen Tests ergänzt werden.
KISS - Keep It Simple Stupid
• „Einfach“ in Bezug auf
• Schreiben / Erstellen?
• Lesen / Modifizieren !
Ein Sicherheitsnetz spannen:
• Versionskontrolle
• Continuous Integration
• Code Reviews
• Automatisierte Tests
Begründung für Refactorings:
• NICHT: Clean Code Developer, Prinzipien,

Werte, Craftsmen, …

• Sondern Kundennutzen:
• Neues Feature
• Bugfix
Es gibt zwei Arten

von Refactorings:



einfache und

komplexe.
Einfache Refactorings
Rename
Extract Method
Introduce Variable

Introduce Parameter
etc.
Vollständig
werkzeuggestützt
durchführbar
Komplexe Refactorings
Nicht mehr ausschließlich
werkzeuggestützt durchführbar
Einfache Refactorings
Lesbarkeit herstellen.
Erkenntnisse über den Code im Code sichern.
public	double	Endpreis(int	anzahl,	double	netto)	{

			var	nettoPreis	=	anzahl	*	netto;	
			return	nettoPreis	*	1.19;	
}
public	double	Endpreis(int	anzahl,	double	netto)	{

			return	(anzahl	*	netto)	*	1.19;	
}
public	double	Endpreis(int	anzahl,	double	netto)	{

			var	nettoPreis	=	anzahl	*	netto;	
			var	bruttoPreis	=	nettoPreis	*	1.19;	
			return	bruttoPreis;	
}
Introduce Variable
Introduce Variable
public	double	Endpreis(int	anzahl,	double	netto)	{	
			const	double	mwSt	=	0.19;	
				
			var	nettoPreis	=	anzahl	*	netto;	
			var	steuer	=	nettoPreis	*	mwSt;	
			var	bruttoPreis	=	nettoPreis	+	steuer;	
				
			return	bruttoPreis;	
}
public	double	Endpreis(int	anzahl,	double	netto)	{

			var	nettoPreis	=	anzahl	*	netto;	
			var	bruttoPreis	=	nettoPreis	*	1.19;	
			return	bruttoPreis;	
} Nicht mehr nur
toolgestützt!
public	IDictionary<string,	string>	ToDictionary(string	configuration)	{	
				var	settings	=	SplitIntoSettings(configuration);	
				var	pairs	=	SplitIntoKeyValuePairs(settings);	
				var	result	=	InsertIntoDictionary(pairs);	
				return	result;	
}
public	IDictionary<string,	string>	ToDictionary(string	configuration)	{	
				return	InsertIntoDictionary(SplitIntoKeyValuePairs(	
							SplitIntoSettings(configuration)));	
}
Introduce Variable
public	IDictionary<string,	string>	ToDictionary(string	configuration)	{	
				//	Split	configuration	into	settings	
				var	settings	=	configuration.Split(';');	
				//	Split	settings	into	key/value	pairs	
				var	pairs	=	new	List<KeyValuePair<string,	string>>();	
				foreach	(var	setting	in	settings)	{	
								var	keyAndValue	=	setting.Split('=');	
								pairs.Add(new	KeyValuePair<string,	string>(keyAndValue[0],	keyAndValue[1]));	
				}	
				//	Insert	pairs	into	dictionary	
				var	result	=	new	Dictionary<string,	string>();	
				foreach	(var	pair	in	pairs)	{	
								result.Add(pair.Key,	pair.Value);	
				}	
				return	result;	
}
Extract Method
public	IDictionary<string,	string>	ToDictionary(string	configuration)	{	
				var	settings	=	SplitIntoSettings(configuration);	
				var	pairs	=	SplitIntoPairs(settings);	
				var	result	=	InsertIntoDictionary(pairs);	
				return	result;	
}
foreach	(var	setting	in	settings)	{	
				var	key_and_value	=	setting.Split('=');	
				result.Add(key_and_value[0],	key_and_value[1]);	
}
Extract Method
foreach	(var	setting	in	settings)	{	
				AddSettingToResult(setting,	result);	
}	
private	static	void	AddSettingToResult(string	setting,		
								Dictionary<string,	string>	result)	{	
				var	key_and_value	=	setting.Split('=');	
				result.Add(key_and_value[0],	key_and_value[1]);	
}
if	(DateTime.Now	>=	weckZeit)	{	
				using	(var	soundPlayer	=	new	SoundPlayer(@"chimes.wav"))	{	
								soundPlayer.Play();	
				}	
				timer.Stopp();	
}
Extract Method
if	(WeckzeitErreicht())	{	
				using	(var	soundPlayer	=	new	SoundPlayer(@"chimes.wav"))	{	
								soundPlayer.Play();	
				}	
				timer.Stopp();	
}	
private	bool	WeckzeitErreicht()	{	
				return	DateTime.Now	>=	weckZeit;	
}
if	(WeckzeitErreicht())	{	
				using	(var	soundPlayer	=	new	SoundPlayer(@"chimes.wav"))	{	
								soundPlayer.Play();	
				}	
				timer.Stopp();	
}	
private	bool	WeckzeitErreicht()	{	
				return	DateTime.Now	>=	weckZeit;	
}
Extract Method
if	(WeckzeitErreicht())	{	
				Wecken();	
}
public	string	Format(string	vorname,	string	nachname,	
							string	strasse,	string	hn,	string	plz,	string	ort)	{	
				return	$"{vorname}	{nachname},	{strasse}	{hn},	{plz}	{ort}";	
}
public	string	Format(Adresse	adresse,	string	vorname,	string	nachname)	{	
				return	$"{vorname}	{nachname},	{adresse.Strasse}	{adresse.Hn},	
{adresse.Plz}	{adresse.Ort}";	
}
Extract Class from Parameters
public	class	Adresse	
{	
				private	string	strasse;	
				private	string	hn;	
				private	string	plz;	
				private	string	ort;	
				public	Adresse(string	strasse,	string	hn,	string	plz,	string	ort)	{	
								this.strasse	=	strasse;	
								this.hn	=	hn;	
								this.plz	=	plz;	
								this.ort	=	ort;	
				}	
				public	string	Strasse	{	
								get	{	return	strasse;	}	
				}	
				...	
}
public	string[]	CsvTabellieren(string[]	csvZeilen)	{	
				_csvZeilen	=	csvZeilen;	
				RecordsErstellen();	
				int[]	breiten	=	SpaltenbreitenErmitteln();	
				TabelleErstellen(breiten);	
				return	_tabelle;	
}
public	string[]	CsvTabellieren(string[]	csvZeilen)	{	
				var	records	=	RecordsErstellen(csvZeilen);	
				int[]	breiten	=	SpaltenbreitenErmitteln(records);	
				var	tabelle	=	TabelleErstellen(breiten,	records);	
				return	tabelle;	
}
Automatisierte Tests
ergänzen
Herausforderungen beim Ergänzen von Tests:
• Abhängigkeiten
• Aspekte nicht getrennt
• Ressourcenzugriffe
• Sichtbarkeit
• Globaler Zustand
Lösungen:
• Zunächst vermehrt Integrationstests,

dann Refactoring und Unit Tests ergänzen.
• Mock Frameworks wie

TypeMock Isolator oder Telerik JustMock

einsetzen.
Wenige Integrationstests
Viele Unittests
Viele Integrationstests
Wenige Unittests
using	System.Collections.Generic;	
using	System.IO;	
namespace	ressourcen	
{	
				public	class	CsvReader	
				{	
								public	IEnumerable<string[]>	Read(string	filename)	{	
												var	lines	=	File.ReadAllLines(filename);	
												foreach	(var	line	in	lines)	{	
																var	fields	=	line.Split(';');	
																yield	return	fields;	
												}	
								}	
				}	
}
Integrierter
Ressourcenzugriff
[Test,	Isolated]	
public	void	Isolated_logic_test()	{	
				var	sut	=	new	CsvReader();	
				Isolate	
								.WhenCalled(()	=>	File.ReadAllLines(""))	
								.WillReturn(new[]	{	"a;b;c",	"1;2;3"	});	
				var	records	=	sut.Read("egal.csv").ToArray();	
				Assert.That(records[0],	Is.EqualTo(new[]	{	"a",	"b",	"c"	}));	
				Assert.That(records[1],	Is.EqualTo(new[]	{	"1",	"2",	"3"	}));	
}
Verhalten der
Attrappe beschreiben
public	class	PrivatesZeugs	
{	
				private	void	SaveToDatabase(string	data)	{	
								Console.WriteLine("Ressourcenzugriff..."	+	data);	
								throw	new	Exception();	
				}	
				public	void	DoSomething()	{	
								Console.WriteLine("DoSomething...");	
								SaveToDatabase("daten	daten	daten...");	
				}	
}
[TestFixture]	
public	class	PrivateMethoden	
{	
				[Test]	
				public	void	Private_Methode_nicht_ausführen()	{	
								var	sut	=	new	PrivatesZeugs();	
								Isolate.NonPublic.WhenCalled(sut,	"SaveToDatabase").IgnoreCall();	
								sut.DoSomething();	
				}	
}
Verhalten der
Attrappe beschreiben
Komplexe Refactorings
Mikado Methode
Change
Change
Change
Change
Change
Change
Change
Change
Change
Hm… ist das wirklich clever?
Change
Change
Cha
Change
Cha
Change
B
Cha
Revert!
Change
B
Cha
Change
B
Cha
Change
B
D
Cha
C
Revert!
Change
B
D
Cha
C
Change
B
D
Cha
C
Change
B
D
Cha
C
Change
B
D
Cha
C
E
Revert!
Change
B
D
Cha
C
E
Change
B
D
Cha
C
E
Change
B
D
Cha
C
E
Change
B
D
F
Cha
C
E
Revert!
Change
B
D
F
Cha
C
E
Change
B
D
F
Cha
C
E
Change
B
D
F
Cha
C
E
Change
B
D
F
A
Cha
C
E
Revert!
Change
B
D
F
A
Cha
C
E
Change
✓
Change
Change
✓
Change
Change
✓
Change
Change
✓
Change
Change
✓
Change
Change
Change
✓
✓Change
✓Change
Hurra!
B
D
F
A
Change
C
E
B
D
F
A
Change
C
E
A
n
a
l
y
s
e
R
e
f
a
c
t
o
r
i
n
g
Nach	Lösungen	suchen
Das	Mikado	Ziel	notieren
Das	Ziel	bzw.	die	aktuelle	Vorbedingung	
naiv	implementieren
Gibt	es	ein	
Problem?
Ist	das	Mikado	Ziel	
erreicht?
Nein Commit	der	Änderungen	in	die	
Versionskontrolle
Ja
Ergibt	die	Änderung	
Sinn?
Ja
Fertig!
Nein
Nein
Nächste	Vorbedingung	auswählen,	um	
damit	zu	arbeiten
Die	Lösungen	als	Vorbedingungen	im	
Mikado	Graph	notieren
Verwerfen	aller	Änderungen	mit	Hilfe	der	
Versionskontrolle
Start
Ja
• Änderung naiv ausführen.

• Herausfinden, was kaputt gegangen ist.

Dies sind die Vorbedingungen für die Änderung.

• Visualisieren: zum Mikado Graph hinzufügen

• REVERT !!!

• Wiederholen, bis nichts mehr kaputt geht.
Demo
Uhrzeitwird
fortlaufendangezeigt
Uhrzeitwird
fortlaufendangezeigt
EigeneTimerklasse

erstellen
Uhrzeitwird
fortlaufendangezeigt
EigeneTimerklasse
integrieren
EigeneTimerklasse

erstellen
Uhrzeitwird
fortlaufendangezeigt
AnzeigenderUhrzeitauf
eigenemEvent
EigeneTimerklasse
integrieren
EigeneTimerklasse

erstellen
Uhrzeitwird
fortlaufendangezeigt
AnzeigenvonUhrzeit
undREstzeittrennen
AnzeigenderUhrzeitauf
eigenemEvent
EigeneTimerklasse
integrieren
EigeneTimerklasse

erstellen
Ziel
Unterziel
Unterziel
Unterziel
Unterziel
Unterziel
Unterziel
Unterziel
A
n
a
l
y
s
e
R
e
f
a
c
t
o
r
i
n
g
Vorteile der Mikado Methode
• Immer auslieferbar
• Nur auf dem Trunk, kein Branching
• Fokus auf das Ziel; nur das Nötigste tun
• Visualisierung
Fazit
• Einfache Refactorings: Lesbarkeit
• Automatisierte Tests: Korrektheit
• Komplexe Refactorings: Wandelbarkeit
Fragen?
http://refactoring-legacy-code.net
http://linkedin.com/in/stefanlieser
https://twitter.com/StefanLieser
http://xing.com/profile/stefan_lieser

Contenu connexe

En vedette

HGS Presentation / General Overview
HGS Presentation / General OverviewHGS Presentation / General Overview
HGS Presentation / General Overview
Amy_Anderson
 
Guia padres Encefalopatia hipóxico-isquémica_2014
Guia padres Encefalopatia hipóxico-isquémica_2014Guia padres Encefalopatia hipóxico-isquémica_2014
Guia padres Encefalopatia hipóxico-isquémica_2014
Javier González de Dios
 

En vedette (15)

My-CV1
My-CV1My-CV1
My-CV1
 
Lei Orgânica de Gravataí
Lei Orgânica de GravataíLei Orgânica de Gravataí
Lei Orgânica de Gravataí
 
Animators survival
Animators survivalAnimators survival
Animators survival
 
2010 09 21 AdminCamp News Tuesday
2010 09 21 AdminCamp News Tuesday2010 09 21 AdminCamp News Tuesday
2010 09 21 AdminCamp News Tuesday
 
Invertir en la bolsa de valores para incrementar el ahorro familiar
Invertir en la bolsa de valores para incrementar el ahorro familiarInvertir en la bolsa de valores para incrementar el ahorro familiar
Invertir en la bolsa de valores para incrementar el ahorro familiar
 
Ecotecnias: Arquitectura del futuro
Ecotecnias: Arquitectura del futuroEcotecnias: Arquitectura del futuro
Ecotecnias: Arquitectura del futuro
 
Ruta Ríos de Luz, fotografías de Luis Laforga
Ruta Ríos de Luz, fotografías de Luis LaforgaRuta Ríos de Luz, fotografías de Luis Laforga
Ruta Ríos de Luz, fotografías de Luis Laforga
 
HGS Presentation / General Overview
HGS Presentation / General OverviewHGS Presentation / General Overview
HGS Presentation / General Overview
 
19 Las aguas subterráneas y su protección en Francia - Agence Adour-Garonne
19 Las aguas subterráneas y su protección en Francia - Agence Adour-Garonne19 Las aguas subterráneas y su protección en Francia - Agence Adour-Garonne
19 Las aguas subterráneas y su protección en Francia - Agence Adour-Garonne
 
información Segura
información Segurainformación Segura
información Segura
 
Moving away from legacy code (AgileCymru)
Moving away from legacy code  (AgileCymru)Moving away from legacy code  (AgileCymru)
Moving away from legacy code (AgileCymru)
 
Incauca s.a.
Incauca s.a.Incauca s.a.
Incauca s.a.
 
Elisaul rojas ti
Elisaul rojas tiElisaul rojas ti
Elisaul rojas ti
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDD
 
Guia padres Encefalopatia hipóxico-isquémica_2014
Guia padres Encefalopatia hipóxico-isquémica_2014Guia padres Encefalopatia hipóxico-isquémica_2014
Guia padres Encefalopatia hipóxico-isquémica_2014
 

Similaire à Wandelbarkeit wieder herstellen - Refactoring C# Legacy Code

Einführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software EntwicklungEinführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software Entwicklung
Christian Baranowski
 
Bi testing media_factory_0.10
Bi testing media_factory_0.10Bi testing media_factory_0.10
Bi testing media_factory_0.10
inovex GmbH
 

Similaire à Wandelbarkeit wieder herstellen - Refactoring C# Legacy Code (20)

Hey, wie geht es dir?
Hey, wie geht es dir?Hey, wie geht es dir?
Hey, wie geht es dir?
 
Case Study: Automatisierte Code Reviews in einer gewachsenen SAP-Applikations...
Case Study: Automatisierte Code Reviews in einer gewachsenen SAP-Applikations...Case Study: Automatisierte Code Reviews in einer gewachsenen SAP-Applikations...
Case Study: Automatisierte Code Reviews in einer gewachsenen SAP-Applikations...
 
Automatisiertes Testen von Software in C++ (mit dem Test Framework Google Test)
Automatisiertes Testen von Software in C++ (mit dem Test Framework Google Test)Automatisiertes Testen von Software in C++ (mit dem Test Framework Google Test)
Automatisiertes Testen von Software in C++ (mit dem Test Framework Google Test)
 
Regulatorics: Offside is when the referee whistles - DOAG 2018
Regulatorics: Offside is when the referee whistles - DOAG 2018Regulatorics: Offside is when the referee whistles - DOAG 2018
Regulatorics: Offside is when the referee whistles - DOAG 2018
 
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
 
Rückwärts denken vorwärts handeln - Requirements Reverse Engineering bei Syst...
Rückwärts denken vorwärts handeln - Requirements Reverse Engineering bei Syst...Rückwärts denken vorwärts handeln - Requirements Reverse Engineering bei Syst...
Rückwärts denken vorwärts handeln - Requirements Reverse Engineering bei Syst...
 
Einführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software EntwicklungEinführung Vorgehensmodelle und Agile Software Entwicklung
Einführung Vorgehensmodelle und Agile Software Entwicklung
 
Bi testing media_factory_0.10
Bi testing media_factory_0.10Bi testing media_factory_0.10
Bi testing media_factory_0.10
 
KPI-driven Product Development - Lessons Learned (German)
KPI-driven Product Development - Lessons Learned (German)KPI-driven Product Development - Lessons Learned (German)
KPI-driven Product Development - Lessons Learned (German)
 
2005 - NRW Conf: Design, Entwicklung und Tests
2005 - NRW Conf: Design, Entwicklung und Tests2005 - NRW Conf: Design, Entwicklung und Tests
2005 - NRW Conf: Design, Entwicklung und Tests
 
Testgetriebene Softwareentwicklung
Testgetriebene SoftwareentwicklungTestgetriebene Softwareentwicklung
Testgetriebene Softwareentwicklung
 
Survivalkit für Codehausmeister
Survivalkit für CodehausmeisterSurvivalkit für Codehausmeister
Survivalkit für Codehausmeister
 
Softwerkskammer Chemnitz Special Pecha Kucha Night
Softwerkskammer Chemnitz Special Pecha Kucha NightSoftwerkskammer Chemnitz Special Pecha Kucha Night
Softwerkskammer Chemnitz Special Pecha Kucha Night
 
Mastering architecture, design- and code-quality
Mastering architecture, design- and code-qualityMastering architecture, design- and code-quality
Mastering architecture, design- and code-quality
 
Legacy-Software-Refactoring - Zielsetzungen für ein erfolgreiches Refactoring...
Legacy-Software-Refactoring - Zielsetzungen für ein erfolgreiches Refactoring...Legacy-Software-Refactoring - Zielsetzungen für ein erfolgreiches Refactoring...
Legacy-Software-Refactoring - Zielsetzungen für ein erfolgreiches Refactoring...
 
Build Patterns - Patterns und Best Practices für den Build Prozess
Build Patterns - Patterns und Best Practices für den Build ProzessBuild Patterns - Patterns und Best Practices für den Build Prozess
Build Patterns - Patterns und Best Practices für den Build Prozess
 
JavaScript und trotzdem Softwerker
JavaScript und trotzdem SoftwerkerJavaScript und trotzdem Softwerker
JavaScript und trotzdem Softwerker
 
Continous Deployment - Schneller entwickeln
Continous Deployment - Schneller entwickelnContinous Deployment - Schneller entwickeln
Continous Deployment - Schneller entwickeln
 
30. Treffen der .NET User Group Rhein-Neckar mit Constantin Klein - „Bekommen...
30. Treffen der .NET User Group Rhein-Neckar mit Constantin Klein - „Bekommen...30. Treffen der .NET User Group Rhein-Neckar mit Constantin Klein - „Bekommen...
30. Treffen der .NET User Group Rhein-Neckar mit Constantin Klein - „Bekommen...
 
Advanced Continuous Integration
Advanced Continuous IntegrationAdvanced Continuous Integration
Advanced Continuous Integration
 

Dernier

Dernier (6)

Chemie (B.Sc.) und Water Science (B.Sc.) uni DUE
Chemie (B.Sc.) und Water Science (B.Sc.) uni DUEChemie (B.Sc.) und Water Science (B.Sc.) uni DUE
Chemie (B.Sc.) und Water Science (B.Sc.) uni DUE
 
Wirtschaftsingenieurwesen an der Universität Duisburg-Essen
Wirtschaftsingenieurwesen an der Universität Duisburg-EssenWirtschaftsingenieurwesen an der Universität Duisburg-Essen
Wirtschaftsingenieurwesen an der Universität Duisburg-Essen
 
Religion_Unterrichtsstunde zum Kölner Dom.pdf
Religion_Unterrichtsstunde zum Kölner Dom.pdfReligion_Unterrichtsstunde zum Kölner Dom.pdf
Religion_Unterrichtsstunde zum Kölner Dom.pdf
 
Betriebswirtschaftslehre (B.Sc.) an der Universität Duisburg Essen
Betriebswirtschaftslehre (B.Sc.) an der Universität Duisburg EssenBetriebswirtschaftslehre (B.Sc.) an der Universität Duisburg Essen
Betriebswirtschaftslehre (B.Sc.) an der Universität Duisburg Essen
 
Angewandte Kognitions- und Medienwissenschaft an der Universität Duisburg_Essen
Angewandte Kognitions- und Medienwissenschaft an der Universität Duisburg_EssenAngewandte Kognitions- und Medienwissenschaft an der Universität Duisburg_Essen
Angewandte Kognitions- und Medienwissenschaft an der Universität Duisburg_Essen
 
Angewandte Philosophie an der Universität Duisburg-Essen.
Angewandte Philosophie an der Universität Duisburg-Essen.Angewandte Philosophie an der Universität Duisburg-Essen.
Angewandte Philosophie an der Universität Duisburg-Essen.
 

Wandelbarkeit wieder herstellen - Refactoring C# Legacy Code