extreme coding: take control of your code exilesoft johannes brodwall exilesoft chief scientist...

93
Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Upload: amberlynn-claire-carroll

Post on 17-Dec-2015

218 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Extreme Coding:Take control of your code

ExilesoftJohannes Brodwall

Exilesoft Chief scientist

@jhannes

TODO:

Preparator refactoring of MyTime

Page 2: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Are you in control of the code?

Page 3: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Or is the code in control of

you?

Page 4: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Kata

New code

Old code

Page 5: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Part I

Page 6: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Practicing Test-Driven

Development

Page 7: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest { @Test public void oneHasNoFactors() { assertTrue(getPrimeFactors(1).isEmpty()); }

}Think of the simplest

test case

Page 8: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

@Test public void oneHasNoFactors() { assertTrue(getPrimeFactors(1).isEmpty()); }

private List<Integer> getPrimeFactors(int i) { // TODO Auto-generated method stub return null; }

}

Make the code compile=> Test runs red

Page 9: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

@Test public void oneHasNoFactors() { assertTrue(getPrimeFactors(1).isEmpty()); }

private List<Integer> getPrimeFactors(int i) { return new ArrayList<>(); }

}

The simplest thing to green

Page 10: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

@Test public void oneHasNoFactors() { assertTrue(getPrimeFactors(1).isEmpty()); }

private List<Integer> getPrimeFactors(int i) { List<Integer> factors = new ArrayList<>(); return factors; }

}

Refactor

Page 11: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

@Test public void oneHasNoFactors() { assertTrue(getPrimeFactors(1).isEmpty()); }

@Test public void factorsOfTwo() { assertEquals(Arrays.asList(2), getPrimeFactors(2)); }

private List<Integer> getPrimeFactors(int i) { List<Integer> factors = new ArrayList<>(); return factors; }

} The next simplest test=> Tests fail

Page 12: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

@Test public void oneHasNoFactors() { assertTrue(getPrimeFactors(1).isEmpty()); }

@Test public void factorsOfTwo() { assertEquals(Arrays.asList(2), getPrimeFactors(2)); }

private List<Integer> getPrimeFactors(int i) { List<Integer> factors = new ArrayList<>(); if (i == 2) factors.add(2); return factors; }

} Simplest possible thing: Special case it

Page 13: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

@Test public void oneHasNoFactors() { assertTrue(getPrimeFactors(1).isEmpty()); }

@Test public void factorsOfTwo() { assertEquals(Arrays.asList(2), getPrimeFactors(2)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); if (number == 2) factors.add(2); return factors; }

}Refactor – improve

naming

Page 14: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

// ... @Test public void factorsOfTwo() { assertEquals(Arrays.asList(2), getPrimeFactors(2)); }

@Test public void factorsOfThree() { assertEquals(Arrays.asList(3), getPrimeFactors(3)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); if (number == 2) factors.add(2); if (number == 3) factors.add(3); return factors; }}

Simplest next case + code

Page 15: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

// ... @Test public void factorsOfTwo() { assertEquals(Arrays.asList(2), getPrimeFactors(2)); }

@Test public void factorsOfThree() { assertEquals(Arrays.asList(3), getPrimeFactors(3)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); if (number > 1) factors.add(number); return factors; }}

Refactor away duplication

Page 16: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

// ... @Test public void factorsOfFour() { assertEquals(Arrays.asList(2,2), getPrimeFactors(4)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); if (number == 4) { factors.add(2); number /= 2; } if (number > 1) factors.add(number); return factors; }}

Next caseSpecial case result

Page 17: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

// ... @Test public void factorsOfSix() { assertEquals(Arrays.asList(2,3), getPrimeFactors(6)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); if (number == 6) { factors.add(2); number /= 2; } if (number == 4) { factors.add(2); number /= 2; } if (number > 1) factors.add(number); return factors; }} Next case – duplicate

special case

Page 18: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

// ... @Test public void factorsOfSix() { assertEquals(Arrays.asList(2,3), getPrimeFactors(6)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); int factor = 2; if (number % factor == 0) { factors.add(factor); number /= factor; } if (number > 1) factors.add(number); return factors; }} Refactor away

duplicationImportant design step!

Page 19: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

// ... @Test public void factorsOfEight() { assertEquals(Arrays.asList(2,2,2), getPrimeFactors(8)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); int factor = 2; if (number % factor == 0) { factors.add(factor); number /= factor; } if (number > 1) factors.add(number); return factors; }}

Next test – fails

Page 20: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

// ... @Test public void factorsOfEight() { assertEquals(Arrays.asList(2,2,2), getPrimeFactors(8)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); int factor = 2; while (number % factor == 0) { factors.add(factor); number /= factor; } if (number > 1) factors.add(number); return factors; }}

Simplest thing to make it work!

Page 21: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class PrimeFactorsTest {

// ... @Test public void factorsOfNine() { assertEquals(Arrays.asList(3,3), getPrimeFactors(9)); }

private List<Integer> getPrimeFactors(int number) { List<Integer> factors = new ArrayList<>(); for (int factor = 2; factor<number; factor++) { while (number % factor == 0) { factors.add(factor); number /= factor; } } if (number > 1) factors.add(number); return factors; }}

Next test and code

Page 22: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

TDD – the steps

Page 23: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Think of next tests

Write a test

Make it pass as simply as possible

Refactor: Add names, remove duplication

Page 24: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Think of next tests

Write a test

Make it pass as simply as possible

Refactor: Add names, remove duplication

Page 25: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Think of next tests

Write a test

Make it pass as simply as possible

Refactor: Add names, remove duplication

Page 26: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Think of next tests

Write a test

Make it pass as simply as possible

Refactor: Add names, remove duplication

Page 27: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

This is where the design comes:Refactor: Add names, remove duplication

Page 28: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

You think too much!

Page 29: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

You think too much!(about the wrong things)

Page 30: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Part II

Page 31: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Starting out with TDD

Page 32: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Problem domain:

Page 33: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Read measurement data

Page 34: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Given “some data” in the database

Page 35: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

When a client sends a “Read register

Modbus message”

Page 36: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Then we respond with the correct

data

Page 37: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Shallow acceptance test

Page 38: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

describe("Modbus data server", function() { it("should read saved data from correct register", function(done) { var measurements = [ sampleMeasurement({ cassette: 1, transponder: 1, thickness: 50.1 }), sampleMeasurement({ cassette: 1, transponder: 2, thickness: 50.2 }), ];

updateData(measurements, function() { readRegisters(cassette_start_pos(1), 4, function(err, data) { data.readFloatLE(0).should.be.approximately(50.1, 0.0001); data.readFloatLE(4).should.be.approximately(50.2, 0.0001); done(); }); }); });});

Page 39: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

describe("Modbus data server", function() { it("should read saved data from correct register", function(done) { var measurements = [ sampleMeasurement({ cassette: 1, transponder: 1, thickness: 50.1 }), sampleMeasurement({ cassette: 1, transponder: 2, thickness: 50.2 }), ];

updateData(measurements, function() { readRegisters(cassette_start_pos(1), 4, function(err, data) { data.readFloatLE(0).should.be.approximately(50.1, 0.0001); data.readFloatLE(4).should.be.approximately(50.2, 0.0001); done(); }); }); });});

Given

Page 40: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

describe("Modbus data server", function() { it("should read saved data from correct register", function(done) { var measurements = [ sampleMeasurement({ cassette: 1, transponder: 1, thickness: 50.1 }), sampleMeasurement({ cassette: 1, transponder: 2, thickness: 50.2 }), ];

updateData(measurements, function() { readRegisters(cassette_start_pos(1), 4, function(err, data) { data.readFloatLE(0).should.be.approximately(50.1, 0.0001); data.readFloatLE(4).should.be.approximately(50.2, 0.0001); done(); }); }); });});

When

Page 41: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

describe("Modbus data server", function() { it("should read saved data from correct register", function(done) { var measurements = [ sampleMeasurement({ cassette: 1, transponder: 1, thickness: 50.1 }), sampleMeasurement({ cassette: 1, transponder: 2, thickness: 50.2 }), ];

updateData(measurements, function() { readRegisters(cassette_start_pos(1), 4, function(err, data) { data.readFloatLE(0).should.be.approximately(50.1, 0.0001); data.readFloatLE(4).should.be.approximately(50.2, 0.0001); done(); }); }); });});

Then

Page 42: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Shallow implementation

Page 43: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

var registers = new buffer.Buffer(10000);var cassette_start_register = function(cassette_id) { return 0;};var readRegisters = function(start_register, register_count, callback) { var message = registers.slice(start_register*2, start_register*2 + register_count*2); callback(null, message);};var updateData = function(objects, callback) { for (var i=0; i<objects.length; i++) { var measurement = objects[i]; var transducer_pos = 2*cassette_start_register(measurement.cassette_id) + 4*(measurement.transponder_id - 1); registers.writeFloatLE(measurement.thickness, transducer_pos); } callback();};

Page 44: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Extending it to the database

Page 45: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

var Sequelize = require("sequelize");var sequelize = new Sequelize('modbusfun', 'modbus', 'secret', { dialect: 'mysql', port: 3306, logging: false });

var Measurement = require('../lib/modbus-fun/measurement') .init(sequelize);var updateRegisters = function(callback) { Measurement.findMeasurements(function(err, objects) { for (var i=0; i<objects.length; i++) { var measurement = objects[i]; var transducer_pos = 2*cassette_start_register(measurement.cassette_id) + 4*(measurement.transponder_id - 1); registers.writeFloatLE(measurement.thickness, transducer_pos); } callback(); });};

Page 46: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Extending it to TCP

Page 47: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

var myRegisters = Registers.createRegisters(Measurement);var server = myRegisters.createSocket();var modbusClient;

var readRegisters = function(start, count, callback) { modbusClient.readRegisters(start, count, function(err, data) { callback(err, data); });};

Page 48: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

var readRegisters = function(offset, register_count, callback) { callbacks[++transactionId] = function(response_message) { callback(0, response_message.slice(10, 10 + register_count*2)); };

var fc = 0x04; var message = new buffer.Buffer(12); message.writeUInt16LE(transactionId, 0); message.writeUInt16LE(protocolId, 2); message.writeUInt16LE(6, 4); message.writeUInt8(unitId, 6); message.writeUInt8(fc, 7); message.writeUInt16LE(offset, 8); message.writeUInt16LE(register_count, 10);

client.write(message);};

Page 49: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Shallow – then deep

Page 50: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Part III

Page 51: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Getting in control of legacy code

Page 52: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime
Page 53: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime
Page 54: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime
Page 55: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public class HomeControllerTest{ [Test] public void GetEmployeeAvailabilityShouldXXX() { var homeController = new HomeController(); var result = homeController.GetEmployeeAvailability(); result.Should().BeNull(); }}

System.NullReferenceException : Object reference not set to an instance of an object. at Exilesoft.MyTime.Controllers.HomeController.GetEmployeeAvailability() in HomeController.cs: line 190 at HomeControllerTest.GetEmployeeAvailabilityShouldXXX() in HomeControllerTest.cs: line 11

Page 56: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public JsonResult GetEmployeeAvailability(){ string specialEventFullText = string.Empty; DateTime? selectedDate = (DateTime)Session[selectedDateKey]; if (selectedDate == null) selectedDate = DateTime.Now;

private DateTime SelectedDate{ get { if (Session == null) return DateTime.Now; return ((DateTime?) Session[selectedDateKey]) ?? DateTime.Now; }}

Ctrl-r, ctrl-m

Page 57: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Test goes reeeely slow and bombs:

System.Data.SqlClient.SqlException : A network-related or instance-specific

error occurred while establishing a connection to SQL Server.

Page 58: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

private string DisplaySpecialEvent(string specialEventFullText){ List<SpecialEvent> specilEventList = dbContext.SpecialEvents.Where(c => c.EventFromDate <= DateTime.Today && DateTime.Today <= c.EventToDate).ToList();

Ctrl-r, ctrl-m

private IEnumerable<SpecialEvent> SpecialEvents{ get { return dbContext.SpecialEvents; }}

Page 59: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public HomeController(){ dbContext = new Context(); SpecialEvents = dbContext.SpecialEvents;}

public HomeController(IEnumerable<SpecialEvent> specialEvents){ SpecialEvents = specialEvents;}

Page 60: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

[Test]public void GetEmployeeAvailabilityShouldXXX(){ var homeController = new HomeController(new List<SpecialEvent>()); var result = homeController.GetEmployeeAvailability(); result.Should().BeNull();}

Page 61: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Test now runs fast, but encounters

EntityFramework issues

Page 62: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public JsonResult GetEmployeeAvailability(){ string specialEventFullText = string.Empty; var selectedDate = SelectedDate;

//SpecialEvent specilEvent = dbContext.SpecialEvents.Where(c => c.EventFromDate.Value.Year == selectedDate.Value.Year && // c.EventFromDate.Value.Month == selectedDate.Value.Month && c.EventFromDate.Value.Day == selectedDate.Value.Day).SingleOrDefault();

specialEventFullText = this.DisplaySpecialEvent(specialEventFullText);

var allAttendanceForDay = dbContext.Attendances.Where(a => a.Employee.IsEnable == true && a.Year == selectedDate.Year && a.Month == selectedDate.Month && a.Day == selectedDate.Day);

Page 63: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public JsonResult GetEmployeeAvailability(){ string specialEventFullText = string.Empty; var selectedDate = SelectedDate;

specialEventFullText = this.DisplaySpecialEvent(specialEventFullText);

var allAttendanceForDay = dbContext.Attendances.Where(a => a.Employee.IsEnable == true && a.Year == selectedDate.Year && a.Month == selectedDate.Month && a.Day == selectedDate.Day);

Page 64: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public JsonResult GetEmployeeAvailability(){ var selectedDate = SelectedDate; string specialEventFullText = DisplaySpecialEvent(string.Empty);

var allAttendanceForDay = dbContext.Attendances.Where(a => a.Employee.IsEnable == true && a.Year == selectedDate.Year && a.Month == selectedDate.Month && a.Day == selectedDate.Day);

Page 65: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Session[attendanceListKey] = result.ToList();

if (Session != null) Session[attendanceListKey] = result.ToList();

Page 66: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public List<int> GetExitLocationMachins(){ string _exitLocationMachines = ConfigurationManager.AppSettings["ExitLocationMachines"].ToString(); List<int> _locationIDList = new List<int>(); foreach (string locationID in _exitLocationMachines.Split(',')) _locationIDList.Add(int.Parse(locationID));

return _locationIDList;}

Really!?

“Machins”?!

Page 67: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public List<int> GetExitLocationMachins(){ string _exitLocationMachines = ConfigurationManager.AppSettings["ExitLocationMachines"].ToString(); List<int> _locationIDList = new List<int>(); foreach (string locationID in _exitLocationMachines.Split(',')) _locationIDList.Add(int.Parse(locationID));

return _locationIDList;}

Ctrl-r, ctrl-r

public List<int> GetExitLocationMachines(){ string _exitLocationMachines = ConfigurationManager.AppSettings["ExitLocationMachines"].ToString(); List<int> _locationIDList = new List<int>(); foreach (string locationID in _exitLocationMachines.Split(',')) _locationIDList.Add(int.Parse(locationID));

return _locationIDList;}

Page 68: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

[Test]public void GetEmployeeAvailabilityShouldXXX(){ ConfigurationManager.AppSettings["ExitLocationMachines"] = "200,300"; var homeController = new HomeController(new List<SpecialEvent>(), new List<Attendance>()); var result = homeController.GetEmployeeAvailability(); result.Should().BeNull();}

Page 69: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

internal static List<EmployeeData> GetAllEmployees(){ //var tempValue = CasheEmployeeData(); string data = new WebClient().DownloadString(string.Format(ConfigurationManager.AppSettings["EmployeeWebApi"], "GetMyTimeEmployees")); JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();

cacheEmployeeDataList = (List<EmployeeData>)jsonSerializer.Deserialize(data, typeof(List<EmployeeData>));

List<int> employeeEnrollmentsIds = EmployeeEnrollmentRepository.GetEmployeeEnrollments().Select(s=>s.EmployeeId).ToList();

return cacheEmployeeDataList.Where(s => employeeEnrollmentsIds.Contains(s.Id)).ToList();}

Page 70: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public IEnumerable<EmployeeData> EmployeeWebList { get; set; }

public HomeController(){ dbContext = new Context(); SpecialEvents = dbContext.SpecialEvents; Attendances = dbContext.Attendances; EmployeeWebList = new EmployeeWebGateway();}

public HomeController(IEnumerable<SpecialEvent> specialEvents, IEnumerable<Attendance> attendances, IEnumerable<EmployeeData> employeeWebList){ Attendances = attendances; SpecialEvents = specialEvents; EmployeeWebList = employeeWebList;}

Page 71: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public JsonResult GetEmployeeAvailability(){ ... int onsiteEmployeeCount = EmployeeRepository.EmployeesOnSite(selectedDate);

Ctrl-r, ctrl-i

int onsiteEmployeeCount = dbContext.EmployeesOnSite.Count(a => a.FromDate <= (DateTime?) selectedDate && a.ToDate >= (DateTime?) selectedDate);

Page 72: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Expected object to be <null>, but found System.Web.Mvc.JsonResult{ ContentEncoding = <null> ContentType = <null> Data = { GraphData = Time,Count, PeopleIn = 0, PeopleOut = 0, absentEmployeeCount = 0, totalEmployeeCount = 0, onSiteCount = 0, specilEvent = } JsonRequestBehavior = DenyGet MaxJsonLength = <null> RecursionLimit = <null>}.

Hurrah!

Page 73: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

[Test]public void GetEmployeeAvailabilityShouldXXX(){ ConfigurationManager.AppSettings["ExitLocationMachines"] = "200,300"; var homeController = new HomeController( new List<SpecialEvent>(), new List<Attendance>(), new List<EmployeeData>(), new List<EmployeeOnSite>()); var result = homeController.GetEmployeeAvailability(); result.Should().BeNull();}

Page 74: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

public HomeController(){ dbContext = new Context(); SpecialEvents = dbContext.SpecialEvents; EmployeesOnSite = dbContext.EmployeesOnSite; Attendances = dbContext.Attendances; EmployeeWebList = new EmployeeWebGateway();}

public HomeController(IEnumerable<SpecialEvent> specialEvents, IEnumerable<Attendance> attendances, IEnumerable<EmployeeData> employeeWebList, IEnumerable<EmployeeOnSite> employeesOnSite){ EmployeesOnSite = employeesOnSite; Attendances = attendances; SpecialEvents = specialEvents; EmployeeWebList = employeeWebList;}

Page 75: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

[Test]public void GetEmployeeAvailabilityShouldTrackArrivedEmployees(){ ConfigurationManager.AppSettings["ExitLocationMachines"] = "200,300";

var today = DateTime.Today.AddDays(-1); var employee1 = new EmployeeEnrollment { IsEnable = true, EnrollNo = 1 }; var employee2 = new EmployeeEnrollment { IsEnable = true, EnrollNo = 2 }; _attendances.Add(SampleAttendance(today.AddHours(12), employee1)); _attendances.Add(SampleAttendance(today.AddHours(13).AddMinutes(30), employee2));

var homeController = new HomeController( new List<SpecialEvent>(), _attendances, new List<EmployeeData>(), new List<EmployeeOnSite>()); homeController.SelectedDate = today.AddHours(19).AddMinutes(23);

var result = homeController.GetEmployeeAvailability(); string graphData = GetProperty(result.Data, "GraphData").ToString(); graphData.Should().Contain("Time,Count\n"); graphData.Should().Contain("11:00:00,0"); graphData.Should().Contain("13:00:00,1"); graphData.Should().Contain("14:00:00,2"); graphData.Should().Contain("19:23:00,2"); graphData.Should().NotContain("20:20:00,");}

Page 76: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Testing legacy code

Page 77: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

New up a class and call a method

Page 78: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Replace dependencies with

Lists (!)

Page 79: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Get the test to run

Page 80: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Add logic to the test

Page 81: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

[Test]public void GetEmployeeAvailabilityShouldReduceEmployeesWhenExit(){ _attendances.Add(SampleAttendance(_today.AddHours(12).AddMinutes(30), _employee1)); _attendances.Add(SampleAttendance(_today.AddHours(13).AddMinutes(20), _employee1, "out", 200)); _homeController.SelectedDate = _today.AddHours(19).AddMinutes(23);

var result = _homeController.GetEmployeeAvailability(); string graphData = GetProperty(result.Data, "GraphData").ToString(); graphData.Should().Contain("12:00:00,0"); graphData.Should().Contain("13:00:00,1"); graphData.Should().Contain("14:00:00,0");}

Page 82: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

[Test]public void GetEmployeeAvailabilityShouldCountEmployeesInside(){ _attendances.Add(SampleAttendance(_today.AddHours(12).AddMinutes(30), _employee1)); _attendances.Add(SampleAttendance(_today.AddHours(13).AddMinutes(20), _employee1, "out", 200));

_homeController.SelectedDate = _today.AddHours(8).AddMinutes(31); GetProperty(_homeController.GetEmployeeAvailability().Data, "PeopleOut").Should().Be(0);

_homeController.SelectedDate = _today.AddHours(12).AddMinutes(31); GetProperty(_homeController.GetEmployeeAvailability().Data, "PeopleIn").Should().Be(1); GetProperty(_homeController.GetEmployeeAvailability().Data, "PeopleOut").Should().Be(0);

_homeController.SelectedDate = _today.AddHours(13).AddMinutes(21); GetProperty(_homeController.GetEmployeeAvailability().Data, "PeopleIn").Should().Be(0); GetProperty(_homeController.GetEmployeeAvailability().Data, "PeopleOut").Should().Be(1);}

Page 83: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

But: It’s not about the tests

Page 84: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

It’s about the refactorings

Page 85: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

• Rename• Extract method• Introduce variable• Introduce parameters• Inline method

Page 86: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

The Challenge

Page 87: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Do 100 refactorings per day

Page 88: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Do 100 refactorings per day

Print out a cheat sheet with resharper refactorings

Page 89: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Practice a coding kata

Page 90: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Create a test for a legacy class

Page 91: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Give me feedback:

How likely are you to recommend this session to a co-worker on a scale from 1 (lowest) to 10 (highest)?

Optional: What's the reason for your number?

Page 92: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

[email protected]

http://JohannesBrodwall.comhttp://exilesoft.com

http://twitter.com/jhannes

Thank you

Page 93: Extreme Coding: Take control of your code Exilesoft Johannes Brodwall Exilesoft Chief scientist @jhannes TODO: Preparator refactoring of MyTime

Give me feedback:

How likely are you to recommend this session to a co-worker on a scale from 1 (lowest) to 10 (highest)?

Optional: What's the reason for your number?