SlideShare una empresa de Scribd logo
1 de 37
Legacy Code Kata
v3.0
William Munn, CGFWB
You Need This Stuff
• Seed Legacy Code
• https://github.com/KatasForLegacyCode/kCSharp/
archive/Step0.zip
• An IDE
• Visual Studio 2012+
• An nUnit test runner (I recommend nCrunch)
• OR Jetbrains Rider
Legacy Code
Read
This
Book
Dependency
Code Kata
• A code kata is an exercise in
programming which helps a us hone
our skills through practice and
repetition.
• The word kata is taken from
Japanese arts most traditionally
Martial Arts
• Why a code kata? Because we learn
by doing.
We Begin With Practice
Dependency Kata: Initial Structure
DoItAllTests.cs
Database.cs
DoItAll.cs
UserDetails.cs
ConsoleAdapter.cs
Program.cs
Logger.cs
Existing Files
We Will
Create
Test1 Test2 Test3 Test4 Build
Dependency Kata: Kata Barometer
Dependency Kata: First Things First
Let’s start by trying to get the existing test running.
• Currently, running the integration test times out. Why?
• DEPENDENCIES!
• Begin by abstracting and breaking the dependency on Console.Readline() DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: First Things First
We’ll use an adapter, but we could use the Console.SetIn method and a TextReader.
• Create an interface
public interface IConsoleAdapter
{
string GetInput();
}
• Create a class that implements the
interface & implement method to
handle our dependency
public class ConsoleAdapter : IConsoleAdapter
{
public string GetInput()
{
return Console.ReadLine();
}
}
ConsoleAdapter.cs
ConsoleAdapter.cs Did you know?
In software engineering, the adapter
pattern is a software design pattern
that allows the interface of an existing
class to be used as another interface.
Test1 Test2 Test3 Test4 Build
Dependency Kata: First Things First
• Create new constructor to accept IConsoleAdapter & set private variable
private readonly IConsoleAdapter _consoleAdapter;
public DoItAll(IConsoleAdapter consoleAdapter)
{
_consoleAdapter = consoleAdapter;
}
DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: First Things First
• Replace 4 calls to Console.ReadLine() WITH _consoleAdapter.GetInput()
• Replace 2 calls to Console.ReadKey() WITH _consoleAdapter.GetInput()
DoItAll.cs
DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: First Things First
We have broken instantiations of DoItAll
• Instantiate and pass in our new handler
var doItAll = new DoItAll(new ConsoleAdapter());Program.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: First Things First
Let’s update our integration test or it will also fail.
• Create a new implementation of IConsoleAdapter
public class DoItAllTests
{
[…]
var doItAll = new DoItAll(new FakeConsoleAdapter());
[…]
}
public class FakeConsoleAdapter : IConsoleAdapter
{
public string GetInput()
{
return string.Empty;
}
}
DoItAllTests.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: First Things First
• When the test is run we now get a meaningful exception. All of the dependencies that caused
the hang are gone.
• the test is now failing because the password is empty. This is a meaningful case but let’s just
update our fake for now.
public string GetInput()
{
return “someTestString”;
}
DoItAllTests.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: First Things First
• Following good testing practice,
let’s add an assert:
[Test, Category("Integration")]
public void DoItAll_Does_ItAll()
{
var doItAll = new DoItAll(new FakeConsoleAdapter());
Assert.That(() => doItAll.Do(), Throws.Nothing);
}
• Our test should still pass.
DoItAllTests.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Better Coverage
Some of our legacy code has no coverage and produces no quantifiable results
• Copy the existing test and rename it DoItAll_Fails_ToWriteToDB
[Test, Category("Integration")]
public void DoItAll_Does_ItAll()
{
[…]
}
[Test, Category("Integration")]
public void DoItAll_Fails_ToWriteToDB()
{
[…]
}
DoItAllTests.cs
Test1 Test2 Test3 Test4 BuildTest1 Test2 Test3 Test4 Build
Dependency Kata: Better Coverage
• Change the assert
Assert.That(doItAll.Do(),
Is.StringContaining("Database.SaveToLog Exception:”));
• Build will fail because our Do() method doesn’t return anything.
DoItAllTests.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Better Coverage
• Change Do()’s return type to string
public string Do()
• Add/update return statements in 3 locations:
public string Do()
{
[…]
if (_userDetails.PasswordEncrypted […])
{
[…]
return string.Empty;
}
[…]
{
[…]
using (var writer = new StreamWriter("log.txt", true))
{
[…]
return string.Empty;
}
}
[…]
return string.Empty;
}
DoItAll.cs
DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Better Coverage
Now create variables to hold the messages to return
public string Do()
{
[…]
if (_userDetails.PasswordEncrypted […])
{
var passwordsDontMatch = "The passwords don't match.";
[…]
}
[…]
{
[…]
using (var writer = new StreamWriter("log.txt", true))
{
var errorMessage = $"{message} - Database.SaveToLog Exception: rn{ex.Message}";
[…]
}
}
[…]
}
DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Better Coverage
Return the new values as appropriate
public string Do()
{
[…]
if (_userDetails.PasswordEncrypted […])
{
var passwordsDontMatch = "The passwords don't match.";
Console.WriteLine(passwordsDontMatch);
_consoleAdapter.GetInput();
return passwordsDontMatch;
}
[…]
{
[…]
using (var writer = new StreamWriter("log.txt", true))
{
var errorMessage = $"{message} - Database.SaveToLog Exception: rn{ex.Message}";
writer.WriteLine(errorMessage);
return errorMessage;
}
}
}
DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Better Abstraction
Abstract Console completely by adding the following code:
• Add a new IConsoleAdapter method
void SetOutput(string output);
• Update ConsoleAdapter implementation
public void SetOutput(string output)
{
Console.WriteLine(output);
}
ConsoleAdapter.cs
ConsoleAdapter.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: More Abstraction
Update FakeConsoleAdapter implementation
public void SetOutput(string output)
{}
DoItAllTests.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: More Abstraction
• Update DoItAll Implementation
• Replace 5 instances of Console.WriteLine
WITH _consoleAdapter.SetOutput
• Replace 1 instance of Console.Write
WITH _consoleAdapter.SetOutput
DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
DoItAll.Do() is trying to do too much. Let’s Refactor!
Write a TEST
Logger.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
DoItAll.Do() is trying to do too much. Let’s Refactor!
• Extract logging functionality by creating a new interface
public interface ILogger
{
string LogMessage(string message);
}
• Create a new class implementing ILogger
public class Logger : ILogger
{
public string LogMessage(string message)
{
throw new NotImplementedException();
}
}
Logger.cs
Logger.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
• Copy the entire try/catch block in DoItAll.Do()
into the implementation of Logger.LogMessage()
• Modify var errorMessage to be outputMessage
• Make sure all paths return a outputMessage
public string LogMessage(string message)
{
var outputMessage = message;
[…]
return outputMessage;
}
Logger.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
• Copy the entire try/catch block in DoItAll.Do()
into the implementation of Logger.LogMessage()
• Modify var errorMessage to be outputMessage
• Make sure all paths return a outputMessage
public string LogMessage(string message)
{
var outputMessage = message;
try
{
Database.SaveToLog(outputMessage);
}
catch (Exception ex)
{
// If database write fails, write to file
using (var writer = new StreamWriter("log.txt", true))
{
outputMessage = $"{message} - Database.SaveToLog Exception: rn{ex.Message}";
writer.WriteLine(message);
}
}
return outputMessage;
}
Logger.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
• Update the constructor of DoItAll with an ILogger
private readonly ILogger _logger;
public DoItAll(IConsoleAdapter consoleAdapter, ILogger logger)
{
_consoleAdapter = consoleAdapter;
_logger = logger;
}
[…]
DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
• Update the Do() method
public string Do()
{
[…]
_consoleAdapter.SetOutput(message);
message = _logger.LogMessage(message);
_consoleAdapter.GetInput();
return message;
}
DoItAll.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
We have broken instantiations of DoItAll
• Instantiate and pass in our new handler
var doItAll = new DoItAll(new ConsoleAdapter(), new Logger());
Program.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
Let’s update BOTH tests.
• Create a new implementation of ILogger
public class DoItAllTests
{
[…]
var doItAll = new DoItAll(new FakeConsoleAdapter(), new
FakeLogger());
[…]
}
[…]
public class FakeLogger : ILogger
{
public string LogMessage(
string message)
{
return string.Empty;
}
}
DoItAllTests.cs
Test1 Test2 Test3 Test4 Build
Dependency Kata: Refactor
• Create a third test by copying the second test and rename the copy
DoItAll_Succeeds_WithFakeLogging
• Update the copied assert
Assert.That(doItAll.Do(), Is.EqualTo(string.Empty));
• Now change the second test DoItAll_DoesItAll_FailsToWriteToDB to be an integration
test by depending on Logger and it will pass as well
var doItAll = new DoItAll(new FakeConsoleAdapter(), new Logger());
DoItAllTests.cs
DoItAllTests.cs
Test1 Test2 Test3 Test4 Build
DoItAllTests.cs
Dependency Kata: What’s Next?
Remove static keyword from the Database class and use an interface and DI.
New test file.
With fake and with concrete.
New interface for UserDetails.
Extract password validation to UserDetails method: HasValidPassword
Extract class UserRegistrationCommunication for Messages to users.
Add IoC Container?
Add Isolation Framework (ala Moq)?
Show ReSharper/Rider common refactorings?
Dependency Kata: What’s Next?
There is still plenty to refactor in this legacy code.
• What would you do next?
William Munn
twitter - @dubmun
Github – dubmun
BLOG – http://dubmun.com
Resources
Working Effectively with Legacy Code, Michael Feathers
The Art Of Unit Testing, Roy Osherove
Clean Code, Robert C. Martin
Pragmatic Programmer, Dave Thomas & Andy Hunt
Refactoring, Martin Fowler
Legacy Code Kata – V3.0

Más contenido relacionado

La actualidad más candente

Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureSalesforce Developers
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock FrameworkEugene Dvorkin
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and ProsperKen Kousen
 
Smarter Testing with Spock
Smarter Testing with SpockSmarter Testing with Spock
Smarter Testing with SpockDmitry Voloshko
 
Applying TDD to Legacy Code
Applying TDD to Legacy CodeApplying TDD to Legacy Code
Applying TDD to Legacy CodeAlexander Goida
 
Unit testing patterns for concurrent code
Unit testing patterns for concurrent codeUnit testing patterns for concurrent code
Unit testing patterns for concurrent codeDror Helper
 
Unit/Integration Testing using Spock
Unit/Integration Testing using SpockUnit/Integration Testing using Spock
Unit/Integration Testing using SpockAnuj Aneja
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctlyDror Helper
 
Smarter Testing With Spock
Smarter Testing With SpockSmarter Testing With Spock
Smarter Testing With SpockIT Weekend
 
Code Kata: String Calculator in Flex
Code Kata: String Calculator in FlexCode Kata: String Calculator in Flex
Code Kata: String Calculator in FlexChris Farrell
 
TDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleTDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleNoam Kfir
 
Rifartek Robot Training Course - How to use ClientRobot
Rifartek Robot Training Course - How to use ClientRobotRifartek Robot Training Course - How to use ClientRobot
Rifartek Robot Training Course - How to use ClientRobotTsai Tsung-Yi
 
JavaFX8 TestFX - CDI
JavaFX8   TestFX - CDIJavaFX8   TestFX - CDI
JavaFX8 TestFX - CDISven Ruppert
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureCRMScienceKirk
 
Creating Enterprise Web Applications with Node.js
Creating Enterprise Web Applications with Node.jsCreating Enterprise Web Applications with Node.js
Creating Enterprise Web Applications with Node.jsSebastian Springer
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxDavid Rodenas
 
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupAngular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupDavid Barreto
 

La actualidad más candente (20)

Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
 
Celery
CeleryCelery
Celery
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
 
Smarter Testing with Spock
Smarter Testing with SpockSmarter Testing with Spock
Smarter Testing with Spock
 
Applying TDD to Legacy Code
Applying TDD to Legacy CodeApplying TDD to Legacy Code
Applying TDD to Legacy Code
 
Bot builder v4 HOL
Bot builder v4 HOLBot builder v4 HOL
Bot builder v4 HOL
 
Unit testing patterns for concurrent code
Unit testing patterns for concurrent codeUnit testing patterns for concurrent code
Unit testing patterns for concurrent code
 
Unit/Integration Testing using Spock
Unit/Integration Testing using SpockUnit/Integration Testing using Spock
Unit/Integration Testing using Spock
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctly
 
Smarter Testing With Spock
Smarter Testing With SpockSmarter Testing With Spock
Smarter Testing With Spock
 
Code Kata: String Calculator in Flex
Code Kata: String Calculator in FlexCode Kata: String Calculator in Flex
Code Kata: String Calculator in Flex
 
Reactive Java (33rd Degree)
Reactive Java (33rd Degree)Reactive Java (33rd Degree)
Reactive Java (33rd Degree)
 
TDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleTDD and the Legacy Code Black Hole
TDD and the Legacy Code Black Hole
 
Rifartek Robot Training Course - How to use ClientRobot
Rifartek Robot Training Course - How to use ClientRobotRifartek Robot Training Course - How to use ClientRobot
Rifartek Robot Training Course - How to use ClientRobot
 
JavaFX8 TestFX - CDI
JavaFX8   TestFX - CDIJavaFX8   TestFX - CDI
JavaFX8 TestFX - CDI
 
Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
 
Creating Enterprise Web Applications with Node.js
Creating Enterprise Web Applications with Node.jsCreating Enterprise Web Applications with Node.js
Creating Enterprise Web Applications with Node.js
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
Angular Optimization Web Performance Meetup
Angular Optimization Web Performance MeetupAngular Optimization Web Performance Meetup
Angular Optimization Web Performance Meetup
 

Similar a Legacy Code Kata v3.0

New Features Of JDK 7
New Features Of JDK 7New Features Of JDK 7
New Features Of JDK 7Deniz Oguz
 
Legacy Dependency Killer - Utah Code Camp 2014
Legacy Dependency Killer - Utah Code Camp 2014Legacy Dependency Killer - Utah Code Camp 2014
Legacy Dependency Killer - Utah Code Camp 2014dubmun
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiRan Mizrahi
 
Why you should be using the shiny new C# 6.0 features now!
Why you should be using the shiny new C# 6.0 features now!Why you should be using the shiny new C# 6.0 features now!
Why you should be using the shiny new C# 6.0 features now!Eric Phan
 
Smalltalk in a .NET World
Smalltalk in a  .NET WorldSmalltalk in a  .NET World
Smalltalk in a .NET WorldESUG
 
Angularjs Test Driven Development (TDD)
Angularjs Test Driven Development (TDD)Angularjs Test Driven Development (TDD)
Angularjs Test Driven Development (TDD)Anis Bouhachem Djer
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test communityKerry Buckley
 
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMPInria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMPStéphanie Roger
 
Web technologies-course 12.pptx
Web technologies-course 12.pptxWeb technologies-course 12.pptx
Web technologies-course 12.pptxStefan Oprea
 
Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Gianluca Padovani
 
Chapter i c#(console application and programming)
Chapter i c#(console application and programming)Chapter i c#(console application and programming)
Chapter i c#(console application and programming)Chhom Karath
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Dror Helper
 
(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++Amazon Web Services
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchMats Bryntse
 
Maintaining Your Code Clint Eastwood Style
Maintaining Your Code Clint Eastwood StyleMaintaining Your Code Clint Eastwood Style
Maintaining Your Code Clint Eastwood StyleRebecca Wirfs-Brock
 
Java script unit testing
Java script unit testingJava script unit testing
Java script unit testingMats Bryntse
 

Similar a Legacy Code Kata v3.0 (20)

New Features Of JDK 7
New Features Of JDK 7New Features Of JDK 7
New Features Of JDK 7
 
Legacy Dependency Killer - Utah Code Camp 2014
Legacy Dependency Killer - Utah Code Camp 2014Legacy Dependency Killer - Utah Code Camp 2014
Legacy Dependency Killer - Utah Code Camp 2014
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
PostgreSQL and PL/Java
PostgreSQL and PL/JavaPostgreSQL and PL/Java
PostgreSQL and PL/Java
 
Why you should be using the shiny new C# 6.0 features now!
Why you should be using the shiny new C# 6.0 features now!Why you should be using the shiny new C# 6.0 features now!
Why you should be using the shiny new C# 6.0 features now!
 
Smalltalk in a .NET World
Smalltalk in a  .NET WorldSmalltalk in a  .NET World
Smalltalk in a .NET World
 
Angularjs Test Driven Development (TDD)
Angularjs Test Driven Development (TDD)Angularjs Test Driven Development (TDD)
Angularjs Test Driven Development (TDD)
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
 
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMPInria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
 
iOS testing
iOS testingiOS testing
iOS testing
 
Web technologies-course 12.pptx
Web technologies-course 12.pptxWeb technologies-course 12.pptx
Web technologies-course 12.pptx
 
Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)
 
Chapter i c#(console application and programming)
Chapter i c#(console application and programming)Chapter i c#(console application and programming)
Chapter i c#(console application and programming)
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013
 
(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++(DEV204) Building High-Performance Native Cloud Apps In C++
(DEV204) Building High-Performance Native Cloud Apps In C++
 
Java Performance Tuning
Java Performance TuningJava Performance Tuning
Java Performance Tuning
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha Touch
 
Design for Testability
Design for TestabilityDesign for Testability
Design for Testability
 
Maintaining Your Code Clint Eastwood Style
Maintaining Your Code Clint Eastwood StyleMaintaining Your Code Clint Eastwood Style
Maintaining Your Code Clint Eastwood Style
 
Java script unit testing
Java script unit testingJava script unit testing
Java script unit testing
 

Último

What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 

Último (20)

Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 

Legacy Code Kata v3.0

  • 2. You Need This Stuff • Seed Legacy Code • https://github.com/KatasForLegacyCode/kCSharp/ archive/Step0.zip • An IDE • Visual Studio 2012+ • An nUnit test runner (I recommend nCrunch) • OR Jetbrains Rider
  • 6.
  • 7. Code Kata • A code kata is an exercise in programming which helps a us hone our skills through practice and repetition. • The word kata is taken from Japanese arts most traditionally Martial Arts • Why a code kata? Because we learn by doing. We Begin With Practice
  • 8. Dependency Kata: Initial Structure DoItAllTests.cs Database.cs DoItAll.cs UserDetails.cs ConsoleAdapter.cs Program.cs Logger.cs Existing Files We Will Create
  • 9. Test1 Test2 Test3 Test4 Build Dependency Kata: Kata Barometer
  • 10. Dependency Kata: First Things First Let’s start by trying to get the existing test running. • Currently, running the integration test times out. Why? • DEPENDENCIES! • Begin by abstracting and breaking the dependency on Console.Readline() DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 11. Dependency Kata: First Things First We’ll use an adapter, but we could use the Console.SetIn method and a TextReader. • Create an interface public interface IConsoleAdapter { string GetInput(); } • Create a class that implements the interface & implement method to handle our dependency public class ConsoleAdapter : IConsoleAdapter { public string GetInput() { return Console.ReadLine(); } } ConsoleAdapter.cs ConsoleAdapter.cs Did you know? In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. Test1 Test2 Test3 Test4 Build
  • 12. Dependency Kata: First Things First • Create new constructor to accept IConsoleAdapter & set private variable private readonly IConsoleAdapter _consoleAdapter; public DoItAll(IConsoleAdapter consoleAdapter) { _consoleAdapter = consoleAdapter; } DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 13. Dependency Kata: First Things First • Replace 4 calls to Console.ReadLine() WITH _consoleAdapter.GetInput() • Replace 2 calls to Console.ReadKey() WITH _consoleAdapter.GetInput() DoItAll.cs DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 14. Dependency Kata: First Things First We have broken instantiations of DoItAll • Instantiate and pass in our new handler var doItAll = new DoItAll(new ConsoleAdapter());Program.cs Test1 Test2 Test3 Test4 Build
  • 15. Dependency Kata: First Things First Let’s update our integration test or it will also fail. • Create a new implementation of IConsoleAdapter public class DoItAllTests { […] var doItAll = new DoItAll(new FakeConsoleAdapter()); […] } public class FakeConsoleAdapter : IConsoleAdapter { public string GetInput() { return string.Empty; } } DoItAllTests.cs Test1 Test2 Test3 Test4 Build
  • 16. Dependency Kata: First Things First • When the test is run we now get a meaningful exception. All of the dependencies that caused the hang are gone. • the test is now failing because the password is empty. This is a meaningful case but let’s just update our fake for now. public string GetInput() { return “someTestString”; } DoItAllTests.cs Test1 Test2 Test3 Test4 Build
  • 17. Dependency Kata: First Things First • Following good testing practice, let’s add an assert: [Test, Category("Integration")] public void DoItAll_Does_ItAll() { var doItAll = new DoItAll(new FakeConsoleAdapter()); Assert.That(() => doItAll.Do(), Throws.Nothing); } • Our test should still pass. DoItAllTests.cs Test1 Test2 Test3 Test4 Build
  • 18. Dependency Kata: Better Coverage Some of our legacy code has no coverage and produces no quantifiable results • Copy the existing test and rename it DoItAll_Fails_ToWriteToDB [Test, Category("Integration")] public void DoItAll_Does_ItAll() { […] } [Test, Category("Integration")] public void DoItAll_Fails_ToWriteToDB() { […] } DoItAllTests.cs Test1 Test2 Test3 Test4 BuildTest1 Test2 Test3 Test4 Build
  • 19. Dependency Kata: Better Coverage • Change the assert Assert.That(doItAll.Do(), Is.StringContaining("Database.SaveToLog Exception:”)); • Build will fail because our Do() method doesn’t return anything. DoItAllTests.cs Test1 Test2 Test3 Test4 Build
  • 20. Dependency Kata: Better Coverage • Change Do()’s return type to string public string Do() • Add/update return statements in 3 locations: public string Do() { […] if (_userDetails.PasswordEncrypted […]) { […] return string.Empty; } […] { […] using (var writer = new StreamWriter("log.txt", true)) { […] return string.Empty; } } […] return string.Empty; } DoItAll.cs DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 21. Dependency Kata: Better Coverage Now create variables to hold the messages to return public string Do() { […] if (_userDetails.PasswordEncrypted […]) { var passwordsDontMatch = "The passwords don't match."; […] } […] { […] using (var writer = new StreamWriter("log.txt", true)) { var errorMessage = $"{message} - Database.SaveToLog Exception: rn{ex.Message}"; […] } } […] } DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 22. Dependency Kata: Better Coverage Return the new values as appropriate public string Do() { […] if (_userDetails.PasswordEncrypted […]) { var passwordsDontMatch = "The passwords don't match."; Console.WriteLine(passwordsDontMatch); _consoleAdapter.GetInput(); return passwordsDontMatch; } […] { […] using (var writer = new StreamWriter("log.txt", true)) { var errorMessage = $"{message} - Database.SaveToLog Exception: rn{ex.Message}"; writer.WriteLine(errorMessage); return errorMessage; } } } DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 23. Dependency Kata: Better Abstraction Abstract Console completely by adding the following code: • Add a new IConsoleAdapter method void SetOutput(string output); • Update ConsoleAdapter implementation public void SetOutput(string output) { Console.WriteLine(output); } ConsoleAdapter.cs ConsoleAdapter.cs Test1 Test2 Test3 Test4 Build
  • 24. Dependency Kata: More Abstraction Update FakeConsoleAdapter implementation public void SetOutput(string output) {} DoItAllTests.cs Test1 Test2 Test3 Test4 Build
  • 25. Dependency Kata: More Abstraction • Update DoItAll Implementation • Replace 5 instances of Console.WriteLine WITH _consoleAdapter.SetOutput • Replace 1 instance of Console.Write WITH _consoleAdapter.SetOutput DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 26. Dependency Kata: Refactor DoItAll.Do() is trying to do too much. Let’s Refactor! Write a TEST Logger.cs Test1 Test2 Test3 Test4 Build
  • 27. Dependency Kata: Refactor DoItAll.Do() is trying to do too much. Let’s Refactor! • Extract logging functionality by creating a new interface public interface ILogger { string LogMessage(string message); } • Create a new class implementing ILogger public class Logger : ILogger { public string LogMessage(string message) { throw new NotImplementedException(); } } Logger.cs Logger.cs Test1 Test2 Test3 Test4 Build
  • 28. Dependency Kata: Refactor • Copy the entire try/catch block in DoItAll.Do() into the implementation of Logger.LogMessage() • Modify var errorMessage to be outputMessage • Make sure all paths return a outputMessage public string LogMessage(string message) { var outputMessage = message; […] return outputMessage; } Logger.cs Test1 Test2 Test3 Test4 Build
  • 29. Dependency Kata: Refactor • Copy the entire try/catch block in DoItAll.Do() into the implementation of Logger.LogMessage() • Modify var errorMessage to be outputMessage • Make sure all paths return a outputMessage public string LogMessage(string message) { var outputMessage = message; try { Database.SaveToLog(outputMessage); } catch (Exception ex) { // If database write fails, write to file using (var writer = new StreamWriter("log.txt", true)) { outputMessage = $"{message} - Database.SaveToLog Exception: rn{ex.Message}"; writer.WriteLine(message); } } return outputMessage; } Logger.cs Test1 Test2 Test3 Test4 Build
  • 30. Dependency Kata: Refactor • Update the constructor of DoItAll with an ILogger private readonly ILogger _logger; public DoItAll(IConsoleAdapter consoleAdapter, ILogger logger) { _consoleAdapter = consoleAdapter; _logger = logger; } […] DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 31. Dependency Kata: Refactor • Update the Do() method public string Do() { […] _consoleAdapter.SetOutput(message); message = _logger.LogMessage(message); _consoleAdapter.GetInput(); return message; } DoItAll.cs Test1 Test2 Test3 Test4 Build
  • 32. Dependency Kata: Refactor We have broken instantiations of DoItAll • Instantiate and pass in our new handler var doItAll = new DoItAll(new ConsoleAdapter(), new Logger()); Program.cs Test1 Test2 Test3 Test4 Build
  • 33. Dependency Kata: Refactor Let’s update BOTH tests. • Create a new implementation of ILogger public class DoItAllTests { […] var doItAll = new DoItAll(new FakeConsoleAdapter(), new FakeLogger()); […] } […] public class FakeLogger : ILogger { public string LogMessage( string message) { return string.Empty; } } DoItAllTests.cs Test1 Test2 Test3 Test4 Build
  • 34. Dependency Kata: Refactor • Create a third test by copying the second test and rename the copy DoItAll_Succeeds_WithFakeLogging • Update the copied assert Assert.That(doItAll.Do(), Is.EqualTo(string.Empty)); • Now change the second test DoItAll_DoesItAll_FailsToWriteToDB to be an integration test by depending on Logger and it will pass as well var doItAll = new DoItAll(new FakeConsoleAdapter(), new Logger()); DoItAllTests.cs DoItAllTests.cs Test1 Test2 Test3 Test4 Build DoItAllTests.cs
  • 35. Dependency Kata: What’s Next? Remove static keyword from the Database class and use an interface and DI. New test file. With fake and with concrete. New interface for UserDetails. Extract password validation to UserDetails method: HasValidPassword Extract class UserRegistrationCommunication for Messages to users. Add IoC Container? Add Isolation Framework (ala Moq)? Show ReSharper/Rider common refactorings?
  • 36. Dependency Kata: What’s Next? There is still plenty to refactor in this legacy code. • What would you do next?
  • 37. William Munn twitter - @dubmun Github – dubmun BLOG – http://dubmun.com Resources Working Effectively with Legacy Code, Michael Feathers The Art Of Unit Testing, Roy Osherove Clean Code, Robert C. Martin Pragmatic Programmer, Dave Thomas & Andy Hunt Refactoring, Martin Fowler Legacy Code Kata – V3.0

Notas del editor

  1. Renamed for your pleasure.
  2. Mandatory Dilbert. Is legacy code, just code someone else wrote? Nah. So what IS legacy code? As I gained experience I came to think of legacy code as COBOL, Fortran, PHP… They seemed to fit the description my professors gave. Today have a much wider and scarier definition. According to Working Effectively with Legacy Code by Michael Feathers: legacy code is code without unit tests.
  3. SO… if you have code without unit tests, it is legacy code because you cannot modify, refactor, or fix it without the very real danger of breaking it. Unit tests add a layer of safety to enable these actions.
  4. The word “dependency” can refer to code that may be completely procedural and has little/no abstractions. This kind of dependent code can be addictive to write because it is often quicker and easier to write—at first. It doesn’t require as much thought, but the effects are disastrous to maintainability and extensibility. Not to mention the fact that it is usually impossible to unit test.
  5. Unfortunately, this isn’t likely to happen before lunch. Removing dependencies from existing code so that it can be unit tested is hard. 
  6. A kata is based on the martial arts kata or form. It is training through repetition and guidance. Go home and practice this kata once a and your brain will learn how to deal with legacy dependencies. You’ll get so good at it that is will seem like second nature.
  7. At first glance, the class structure may not seem too unreasonable. Data access has it’s own class and so do the UserDetails. Then we see the DoItAll class with the Do() method. Naming aside, this is unfortunately pretty common in several codebases I’ve seen. Someone who touched this code had good intentions. There is a unit test project with a single failing unit test. Probably because they weren’t sure how to deal with the dependency on the console.
  8. You’ll see this barometer throughout the kata. It will help you know what state your code should be in after each step.