6. Quelle: Software Evolution, Tom Mens, Serge Demeyer
Initial
Development Phase Out Close DownEvolution
changes patches
Servicing
7.
8.
9. Big Bang
„Partialy New“
Maintenance
• Das Softwaresystem wird (nahezu)
komplett neu entwickelt.
• Das Altsystem muss während
dessen noch betreut werden.
• Es werden Teile neu entwickelt
oder hinzugefügt.
• Fokussierung auf Bugfixes und
Stabilisierung.
10. 1. It is hard to change because every change affects too many other parts
of the system. (Rigidity - Starr)
2. When you make a change, unexpected parts of the system break.
(Fragility - Zerbrechlich)
3. It is hard to reuse in another application because it cannot be
disentangled from the current application. (Immobility - Unbeweglich)
Quelle: http://www.objectmentor.com/resources/articles/dip.pdf
11. Quelle: Martin Fowler http://martinfowler.com/bliki/TechnicalDebtQuadrant.html
Ward Cunningham
rücksichtslos umsichtig
überlegt
versehentlich
„Wir haben keine
Zeit für ein
Design.“
„Wir müssen jetzt
liefern und uns später
um die Konsequenzen
kümmern.“
„Jetzt wissen wir wie
wir es hätten machen
müssen.“
„Layer? Was ist
das?“
14. Refactoring bezeichnet in der Software-Entwicklung die manuelle oder
automatisierte Strukturverbesserung von Quelltexten unter Beibehaltung des
beobachtbaren Programmverhaltens.
Dabei sollen die Lesbarkeit, Verständlichkeit, Wartbarkeit und Erweiterbarkeit
verbessert werden, mit dem Ziel, den jeweiligen Aufwand für Fehleranalyse und
funktionale Erweiterungen deutlich zu senken.
Quelle: https://de.wikipedia.org/wiki/Refactoring
15. Schreibe nur Code, der verlangt wird.
Entwickle schrittweise Deinen Code.
Wähle möglichst kleine Schritte.
Jeder Schritt muss den Code verbessern.
Test
Implementierung
Refaktorisierung
18. 1. Quellcode einchecken.
2. Einen Überblick darüber verschaffen was geändert werden soll.
3. Mindestens einen Test schreiben der das bestehende Verhalten
charakterisiert.
4. Refaktorisieren
5. Prüfen ob das Verhalten sich verändert hat.
19. Code without tests is bad code. It doesn't matter how
well written it is; it doesn't matter how pretty or object-
oriented or well-encapsulated it is.
With tests, we can change the behavior of our code
quickly and verifiably. Without them, we really don't
know if our code is getting better or worse.
28. Add Parameter Introduce Class Annotation Replace Conditional with Polymorphism
Change Bidirectional Association to Unidirectional Introduce Expression Builder Replace Constructor with Factory Method
Change Reference to Value Introduce Foreign Method Replace Data Value with Object
Change Unidirectional Association to Bidirectional Introduce Gateway Replace Delegation With Hierarchy
Change Value to Reference Introduce Local Extension Replace Delegation with Inheritance
Collapse Hierarchy Introduce Named Parameter Replace Dynamic Receptor with Dynamic Method Definition
Consolidate Conditional Expression Introduce Null Object Replace Error Code with Exception
Consolidate Duplicate Conditional Fragments Introduce Parameter Object Replace Exception with Test
Decompose Conditional Isolate Dynamic Receptor Replace Hash with Object
Duplicate Observed Data Lazily Initialized Attribute Replace Inheritance with Delegation
Dynamic Method Definition Move Eval from Runtime to Parse Time Replace Loop with Collection Closure Method
Eagerly Initialized Attribute Move Field Replace Magic Number with Symbolic Constant
Encapsulate Collection Move Method Replace Method with Method Object
Encapsulate Downcast Parameterize Method Replace Nested Conditional with Guard Clauses
Encapsulate Field Preserve Whole Object Replace Parameter with Explicit Methods
Extract Class Pull Up Constructor Body Replace Parameter with Method
Extract Interface Pull Up Field Replace Record with Data Class
Extract Method Pull Up Method Replace Subclass with Fields
Extract Module Push Down Field Replace Temp with Chain
Extract Subclass Push Down Method Replace Temp with Query
Extract Superclass Recompose Conditional Replace Type Code with Class
Extract Surrounding Method Remove Assignments to Parameters Replace Type Code with Module Extension
Extract Variable Remove Control Flag Replace Type Code With Polymorphism
Form Template Method Remove Middle Man Replace Type Code with State/Strategy
Hide Delegate Remove Named Parameter Replace Type Code with Subclasses
Hide Method Remove Parameter Self Encapsulate Field
Inline Class Remove Setting Method Separate Query from Modifier
Inline Method Remove Unused Default Parameter Split Temporary Variable
Inline Module Rename Method Substitute Algorithm
Inline Temp Replace Abstract Superclass with Module
Introduce Assertion Replace Array with Object
refactoring.com
29. Seam
A seam is a Place where you can alter behavior
in your program without editing in that Place.
Enabling Point
Every seam has an enabling point, a Place
where you can make the decision to use one
behavior or another.
34. public class PersonSelectionViewModel
{
List<Person> Persons { get; set; }
public void Initialize()
{
var query = "SELECT * FROM PEOPLE";
var connection = new DataBaseConnection();
var command = connection.CreateCommand(query);
var reader = command.Excute();
this.Persons = new List<Person>();
while(reader.Next())
{
var person = new Person();
person.Id = reader["ID"];
person.Name = reader["NAME"];
this.Persons.Add(person);
}
return;
}
. . .
35. [TestMethod]
public void ViewModelMustShowAllPersons ()
{
this.SetupDataBase();
var person = this.AddPersonToDataBase();
var sut = new PersonSelectionViewModel();
sut.Initialize();
this.AssertThatDataBaseContains(person);
}
36. public class PersonSelectionViewModel
{
List<Person> Persons { get; set; }
public void Initialize()
{
var repository = new PersonRepository();
this.Persons = repository.GetAllPersons();
return;
}
public void Save(Person person)
{
var repository = new PersonRepository();
repository.Save(person);
return;
}
. . .
}
38. [TestMethod]
public void ViewModelMustShowAllPersons ()
{
var person = new Person() { Name = "Meyer" };
var rep = Mock.Create<PersonRepository>();
Mock.Arrange(() => rep.Persons).IgnoreInstance()
.Returns(new List<Person> { person });
var sut = new PersonSelectionViewModel();
// Initializes the view model
sut.Initialize();
Assert.IsTrue(sut.Persons.Contains(person));
}
39. public class PersonSelectionViewModel
{
List<Person> Persons { get; set; }
private IPersonRepository repository;
private IPersonRepository Repository
{
get
{
return this.repository ?? (this.repository = new PersonRepository());
}
}
public void Initialize()
{
this.Persons = this.repository.GetAllPersons();
return;
}
. . .
}
40. [TestMethod]
public void ViewModelMustShowAllPersons()
{
var person = new Person() { Name = "Meyer" };
var repository = A.Fake<IPersonRepository>();
A.CallTo(repository.GetPersons()).Returns(new List<Person> {person});
var sut = new PersonSelectionViewModel();
var accessor = new PrivateObject(sut);
accessor.SetFieldOrProperty("repository", repository);
sut.Initialize();
Assert.IsTrue(sut.Persons.Contains(person));
}
44. SLOC
(in Mio.)
Windows NT 3.1 (1993) 4–5
Windows NT 3.5 (1994) 7–8
Windows NT 4.0 (1996) 11–12
Windows 2000 (2000) > 29
Windows XP (2001) 40
Windows Server 2003 (2003) 50
45. = 187 LoC
π •👍
Klasse < 500 LoC
Methode < 50 LoC ?
Fachlicher Druck, wenn der Auftraggeber auf die Projektbeteiligten Druck ausübt, neue Fachlichkeiten schnell und bevor technische Aufräumarbeiten abgeschlossen sind, geliefert zu bekommen.
Ungenügende qualitätssichernde Prozesse, wenn es in einem Projekt keine qualitätssichernden Prozesse gibt (oder diese nicht gelebt werden), welche die Technische Schuld laufend messen und Verbesserungsmaßnahmen einleiten.
Ungenügendes technisches Wissen, um technische Entscheidungen treffen zu können, welche die Technische Schuld nicht erhöhen und im Optimalfall reduzieren.
Ungenügende Kommunikation der gewählten technischen Lösungen und ihrer Hintergründe. Die Kommunikation kann auf vielerlei Arten erfolgen, beispielsweise durch selbsterklärenden Code, Dokumentation, Diagramme, Videos etc.
Parallele Entwicklung in eigenen Branches (beispielsweise Featurebranches) führt zu erhöhten Zusammenführungsaufwänden und somit Technischer Schuld.
Hintangestelltes Refactoring, wenn in Codeteilen, welche verbesserungswürdig sind, weiter Fachlichkeiten umgesetzt werden, ohne davor die Verbesserungen umzusetzen. Je mehr diese notwendigen Refactorings verzögert werden, desto aufwändiger werden sie bzw. die Umsetzung von Fachlichkeiten.
Lines of IL Code
Referenzgröße die erlaubt Dinge in ein Verhältnis zueinander zu setzen
- Die 9 wird von FX Cop als Maximal angesehen
Jede Ableitung (außer Interfaces) erhöht den Wert um 1
Klassen starten mit 1
Interfaces gelten nicht als Klassen und haben deshalb 0
Wenn man von Frameworkelementen erbt, hat man automatisch eine höhere Vererbungstiefe.
Die Zusammenfassung für die DLL/den Namensraum zeigt immer den höchsten Wert
1. The deeper a class in the hierarchy, the greater the number of methods it will probably inherit which makes it harder to predict its behavior.
2. Deeper trees involve greater design complexity since more classes and methods are involved.
3. Deeper classes in the tree have a greater potential for reusing inherited methods.
Assumptions 1 and 2 tell us that having a higher number for depth is bad. If that is where it ended we would be in good shape; however assumption 3 indicates that a higher number for depth is good for potential code reuse.
Spiegelt die Anzahl der Entscheidungen im Code wieder
Wie oft muss der Code durchlaufen werden um alle Codepfade abzudecken
Die Komplexität für Klassen und Namensräume wird kumuliert
Unit Tests sollten immer eine CC von 1 haben!
- Bei 25 gibt es eine Warnung von FX Cop
Wert zwischen 0 und 100
- Code Map hilft dabei sich einen Überblick über die Abhängigkeiten im Code zu verschaffen