Slide 1

Slide 1 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev The technical Debt Trap

Slide 2

Slide 2 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Doc Norton, CEO [email protected] @DocOnDev

Slide 3

Slide 3 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev what is technical debt?

Slide 4

Slide 4 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev – Ward Cunningham OOPSLA ‘92 Shipping first time code is like going into debt.

Slide 5

Slide 5 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite. – Ward Cunningham OOPSLA ‘92

Slide 6

Slide 6 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite. The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. – Ward Cunningham OOPSLA ‘92

Slide 7

Slide 7 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev The danger occurs when the debt is not repaid. Every minute spent on not-quite- right code counts as interest on that debt. – Ward Cunningham OOPSLA ‘92

Slide 8

Slide 8 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev The danger occurs when the debt is not repaid. Every minute spent on not-quite- right code counts as interest on that debt. – Ward Cunningham OOPSLA ‘92

Slide 9

Slide 9 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Technical debt is

Slide 10

Slide 10 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Technical debt is good

Slide 11

Slide 11 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Technical debt is good

Slide 12

Slide 12 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Technical debt is good

Slide 13

Slide 13 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Technical debt is a strategic decision

Slide 14

Slide 14 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Technical debt is a strategic decision • Allow for Rapid Delivery • To Elicit Quick Feedback • And Correct Design

Slide 15

Slide 15 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt is an indication of learning

Slide 16

Slide 16 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt is an indication of learning • Now know what you need • Implementation doesn’t match

Slide 17

Slide 17 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt is a metaphor

Slide 18

Slide 18 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev metaphors rock we reason by analogy Building on a weak foundation Puts pressure on our design Can’t keep running at this pace It’s raining men (hallelujah)

Slide 19

Slide 19 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev metaphorphosis when metaphors go wrong Credit Card SHORT-TERM Long-Term Return on Investment OPERATIONAL HOME LOAN Loan Shark PRAGMATIC LEVERAGE Intentional AUTO LOAN FRAUDULENT VOLUNTARY PYRAMID SCHEME Prudent Student Loan HIGH INTEREST INADVERTENT RECKLESS DEBT IN THE THIRD QUADRANT

Slide 20

Slide 20 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev metaphorphosis when metaphors go wrong “quick and dirty” - Martin Fowler “sloppy” - David Laribee “just hack it in” - Steve McConnell “CUT A LOT OF CORNERS” - James Shore

Slide 21

Slide 21 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt quadrant Reckless Inadvertent Prudent Deliberate “We don’t have time for design” “We must ship now and deal with consequences” “Now we know how we should have done it” “What’s Layering?”

Slide 22

Slide 22 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev – Ward Cunningham Youtube ‘09 [Many] have explained the debt metaphor and confused it with the idea that you could write code poorly with the intention of doing a good job later.

Slide 23

Slide 23 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev – Ward Cunningham Youtube ‘09 confused the debt metaphor with the idea that you could write code poorly

Slide 24

Slide 24 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev – Ward Cunningham Youtube ‘09 The ability to pay back debt [...] depends upon you writing code that is clean enough to be able to refactor as you come to understand your problem.

Slide 25

Slide 25 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev – Ward Cunningham Youtube ‘09 The ability to pay back debt [...] depends upon you writing code that is clean enough to be able to refactor as you come to understand your problem.

Slide 26

Slide 26 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev – Ward Cunningham twitter ‘09 Dirty code is to technical debt as the pawn broker is to financial debt.

Slide 27

Slide 27 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev – Ward Cunningham twitter ‘09 Dirty code is to technical debt as the pawn broker is to financial debt. Don’t think you are ever going to get your code back.

Slide 28

Slide 28 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt? Ask yourself…

Slide 29

Slide 29 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt? Ask yourself… • Is the code clean? • Is the code tested? • Is there a learning objective or event? • Is there a plan for payback? • Is the business truly informed?

Slide 30

Slide 30 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt? If you say no to even one… • Is the code clean? • Is the code tested? • Is there a learning objective or event? • Is there a plan for payback? • Is the business truly informed?

Slide 31

Slide 31 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt? If you say no to even one… • Is the code clean? • Is the code tested? • Is there a learning objective or event? • Is there a plan for payback? • Is the business truly informed? ... then you don’t have Technical Debt

Slide 32

Slide 32 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev mess (noun)

Slide 33

Slide 33 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev mess (noun) • Disorderly accumulation, heap, or jumble • A state of embarrassing confusion • An unpleasant or difficult situation

Slide 34

Slide 34 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev cruft (noun)

Slide 35

Slide 35 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev cruft (noun) • An unpleasant substance • The result of shoddy construction • Redundant, old or improperly written code

Slide 36

Slide 36 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev But, It’s Just semantics

Slide 37

Slide 37 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev It’s not Just semantics

Slide 38

Slide 38 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev It’s not Just semantics Technical Debt is Good

Slide 39

Slide 39 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev It’s not Just semantics Technical Debt is Good Quick and Dirty is Technical Debt

Slide 40

Slide 40 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev It’s not Just semantics Quick and Dirty is Good

Slide 41

Slide 41 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev It’s not Just semantics Quick and Dirty is Good

Slide 42

Slide 42 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt quadrant Reckless Inadvertent Prudent Deliberate “We don’t have time for design” “We must ship now and deal with consequences” “Now we know how we should have done it” “What’s Layering?”

Slide 43

Slide 43 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt quadrant Reckless Inadvertent Prudent Deliberate “We don’t have time for design” “Let’s deploy and gather more information” “Now we know how we should have done it” “What’s Layering?”

Slide 44

Slide 44 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt in other fields

Slide 45

Slide 45 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt in other fields

Slide 46

Slide 46 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Technical Debt in other fields

Slide 47

Slide 47 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Technical Debt in other fields

Slide 48

Slide 48 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt in other fields

Slide 49

Slide 49 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev RECKLESS AND DELIBERATE technical debt in other fields

Slide 50

Slide 50 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev RECKLESS AND DELIBERATE RECKLESS AND DELIBERATE technical debt in other fields

Slide 51

Slide 51 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev RECKLESS AND DELIBERATE RECKLESS AND DELIBERATE RECKLESS AND INADVERTENT technical debt in other fields

Slide 52

Slide 52 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt quadrant Reckless Inadvertent Prudent Deliberate “We don’t have time for design” “Let’s deploy and gather more information” “Now we know how we should have done it” “What’s Layering?”

Slide 53

Slide 53 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt quadrant Reckless Inadvertent Prudent Deliberate “We don’t have time for design” “Let’s deploy and gather more information” “Now we know how we should have done it” “What’s Layering?” IRRESPONSIBLE

Slide 54

Slide 54 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt quadrant Reckless Inadvertent Prudent Deliberate “We don’t have time for design” “Let’s deploy and gather more information” “Now we know how we should have done it” “What’s Layering?” IRRESPONSIBLE INCOMPETENT

Slide 55

Slide 55 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev technical debt quadrant Reckless Inadvertent Prudent Deliberate “We don’t have time for design” “Let’s deploy and gather more information” “Now we know how we should have done it” “What’s Layering?” IRRESPONSIBLE INCOMPETENT TECHNICAL DEBT

Slide 56

Slide 56 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev cruft or debt?

Slide 57

Slide 57 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev DataSet aDs, qDs; aDs = _dbConnector.UpdateAgentList(); qDs = _dbConnector.GetQueueList(); foreach (DataTable aTable in aDs.Tables) { foreach (DataRow aRow in aTable.Rows) { foreach (DataColumn aColumn in aTable.Columns) { DataSet asDs = _dbConnector.GetAgentSkills(aRow[aColumn].ToString());//AgentId foreach (DataTable asTable in asDs.Tables) { foreach (DataRow asRow in asTable.Rows) { foreach (DataColumn asColumn in asTable.Columns) { foreach (DataTable qTable in qDs.Tables) { foreach (DataRow qRow in qTable.Rows) { foreach (DataColumn qColumn in qTable.Columns) { DataSet sqDs = _dbConnector.GetSkillsForQueue(qRow[qColumn].ToString()); foreach (DataTable sqTable in sqDs.Tables) { foreach (DataRow sqRow in sqTable.Rows) { foreach (DataColumn sqColumn in sqTable.Columns) { foreach (string skill in sqRow[sqColumn].ToString().Split(paramDelimStr)) { if (skill == asRow[asColumn].ToString()) { try { _dbConnector.SetAgentQueueSkill(aRow[aColumn].ToString(), qRow[qColumn].ToString(), skill); } catch { continue; } } } } } } } } } } } } } } } cruft or debt?

Slide 58

Slide 58 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev DataSet aDs, qDs; aDs = _dbConnector.UpdateAgentList(); qDs = _dbConnector.GetQueueList(); foreach (DataTable aTable in aDs.Tables) { foreach (DataRow aRow in aTable.Rows) { foreach (DataColumn aColumn in aTable.Columns) { DataSet asDs = _dbConnector.GetAgentSkills(aRow[aColumn].ToString());//AgentId foreach (DataTable asTable in asDs.Tables) { foreach (DataRow asRow in asTable.Rows) { foreach (DataColumn asColumn in asTable.Columns) { foreach (DataTable qTable in qDs.Tables) { foreach (DataRow qRow in qTable.Rows) { foreach (DataColumn qColumn in qTable.Columns) { DataSet sqDs = _dbConnector.GetSkillsForQueue(qRow[qColumn].ToString()); foreach (DataTable sqTable in sqDs.Tables) { foreach (DataRow sqRow in sqTable.Rows) { foreach (DataColumn sqColumn in sqTable.Columns) { foreach (string skill in sqRow[sqColumn].ToString().Split(paramDelimStr)) { if (skill == asRow[asColumn].ToString()) { try { _dbConnector.SetAgentQueueSkill(aRow[aColumn].ToString(), qRow[qColumn].ToString(), skill); } catch { continue; } } } } } } } } } } } } } } }

Slide 59

Slide 59 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev DataSet aDs, qDs; aDs = _dbConnector.UpdateAgentList(); qDs = _dbConnector.GetQueueList(); foreach (DataTable aTable in aDs.Tables) { foreach (DataRow aRow in aTable.Rows) { foreach (DataColumn aColumn in aTable.Columns) { DataSet asDs = _dbConnector.GetAgentSkills(aRow[aColumn].ToString());//AgentId foreach (DataTable asTable in asDs.Tables) { foreach (DataRow asRow in asTable.Rows) { foreach (DataColumn asColumn in asTable.Columns) { foreach (DataTable qTable in qDs.Tables) { foreach (DataRow qRow in qTable.Rows) { foreach (DataColumn qColumn in qTable.Columns) { DataSet sqDs = _dbConnector.GetSkillsForQueue(qRow[qColumn].ToString()); foreach (DataTable sqTable in sqDs.Tables) { foreach (DataRow sqRow in sqTable.Rows) { foreach (DataColumn sqColumn in sqTable.Columns) { foreach (string skill in sqRow[sqColumn].ToString().Split(paramDelimStr)) { if (skill == asRow[asColumn].ToString()) { try { _dbConnector.SetAgentQueueSkill(aRow[aColumn].ToString(), qRow[qColumn].ToString(), skill); } catch { continue; } } } } } } } } } } } } } } }

Slide 60

Slide 60 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev DataSet aDs, qDs, asDs, sqDs; aDs = _dbConnector.UpdateAgentList(); qDs = _dbConnector.GetQueueList(); foreach (DataRow aRow in aDS.Tables[0].Rows) { String agentID = aRow[“AgentId”].ToString(); asDs = _dbConnector.GetAgentSkills(agentID); foreach (DataRow asRow in asDs.Tables[0].Rows) { String agentSkill = asRow[“Skill”].ToString(); foreach (DataRow qRow in qDs.Tables[0].Rows) { queueName = qRow[“QueueName”].ToString(); sqDs = _dbConnector.GetSkillsForQueue(queueName); foreach (DataRow sqRow in sqDs.Tables[0].Rows) { foreach (string skill in sqRow[“Skills”].ToString().Split(paramDelimStr)) { if (skill == agentSkill) { try { _dbConnector.SetAgentQueueSkill(agentID, queueName, skill); } catch { continue; } } } } } } }

Slide 61

Slide 61 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev AgentList agents = new AgentList(_dbConnector.UpdateAgentList()); QueueList queues = new QueueList(_dbConnector.GetQueueList()); foreach (Agent agent in agents) { foreach (Skill agentSkill in agent.skills) { foreach (Queue queue in queues) { foreach (Skill queueSkill in queue.skills.Where(x => x == agentSkill)) { try {_dbConnector.SetAgentQueueSkill(agent.agentID, queue.name, agentSkill); } catch { continue; } } } } }

Slide 62

Slide 62 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev

Slide 63

Slide 63 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev if ((customer.state == “AL” && customer.type == CustomerType.GENERAL_AGENT && customer.revenue > 100000) || (customer.type == CustomerType.RETRO_AGENT && (customer.state == “WI” || customer.state == “IL”)) || (customer.type == CustomerType.FED_MANAGEMENT && customer.revenue > 150000)) { ... } cruft or debt?

Slide 64

Slide 64 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev // If customer is Federally Regulated if ((customer.state == “AL” && customer.type == CustomerType.GENERAL_AGENT && customer.revenue > 100000) || (customer.type == CustomerType.RETRO_AGENT && (customer.state == “WI” || customer.state == “IL”)) || (customer.type == CustomerType.FED_MANAGEMENT && customer.revenue > 150000)) { ... }

Slide 65

Slide 65 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev if (customer.isFederallyRegulated()) { ... }

Slide 66

Slide 66 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev double getSpeed() { switch (_type) { case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts; case NORWEGIAN_BLUE: return (_isNailed) ? 0 : getBaseSpeed(_voltage); } throw new RuntimeException ("Should be unreachable"); } http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html cruft or debt?

Slide 67

Slide 67 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev class Swallow ... double getSpeed() { return getBaseSpeed(); } end class class EuropeanSwallow ... end class class AfricanSwallow ... double getSpeed() { return super.getSpeed - coconutLoad(); } double coconutLoad() { return getLoadFactor() * _numberOfCoconuts; } end class class NorwegianSwallow ... double getSpeed() { return (_isNailed) ? 0 : getBaseSpeed(_voltage); } end class

Slide 68

Slide 68 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev cruft is a bad decision

Slide 69

Slide 69 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev cruft is a bad decision • You are a professional developer • You’re going to create unintentional cruft • You have to clean up the existing cruft

Slide 70

Slide 70 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev The Trap

Slide 71

Slide 71 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev The Trap • Precedent for speed over quality • Expectation of increased velocity • Cruft slows you down • Must write more cruft to keep up • Ask permission to do your job correctly

Slide 72

Slide 72 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev failing strategies

Slide 73

Slide 73 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev failing strategies

Slide 74

Slide 74 text

No content

Slide 75

Slide 75 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev winning strategy Clean Constantly

Slide 76

Slide 76 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev winning strategy Clean Constantly • Never make an intentional mess • Monitor your “Technical Debt” • Follow the Boy Scout Rule • Remember quality is your responsibility

Slide 77

Slide 77 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev winning strategy Clean Constantly • Never make an intentional mess • Monitor your “Technical Debt” • Follow the Boy Scout Rule • Remember quality is your responsibility • NEVER ask permission to do your job correctly

Slide 78

Slide 78 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Monitor your cruft

Slide 79

Slide 79 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Monitor your cruft • Code Coverage • Code Complexity • Coupling • Maintainability • Monitor Trends, Not Points

Slide 80

Slide 80 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev review Technical Debt Cruft

Slide 81

Slide 81 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev review Technical Debt • A strategic design decision • Requires business to be informed • Includes a pay-back plan Cruft • Happens • Needs to be monitored and cleaned • Is NOT Technical Debt

Slide 82

Slide 82 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev review Technical Debt • A strategic design decision • Requires business to be informed • Includes a pay-back plan Cruft • Happens • Needs to be monitored and cleaned • Is NOT Technical Debt NEVER ask perm issio n to do yo ur jo b co rrectly

Slide 83

Slide 83 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev comments or questions? Doc Norton, CEO [email protected] @DocOnDev

Slide 84

Slide 84 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev Thank You! Doc Norton, CEO [email protected] @DocOnDev

Slide 85

Slide 85 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev The technical Debt Trap

Slide 86

Slide 86 text

#DevBootcamp / #TechnicalDebtTrap / @DocOnDev • OOPSLA 92 Paper - http://dl.acm.org/citation.cfm? id=157715, http://c2.com/doc/oopsla92.html • Ward Cunningham Technical Debt Video - http:// www.youtube.com/watch? v=pqeJFYwnkjE&feature=player_embedded • Ward Cunningham Twitter - http://twitter.com/ WardCunningham/status/3742903303 • Technical Debt Quadrant - http://martinfowler.com/ bliki/TechnicalDebtQuadrant.html • James Shore - http://jamesshore.com/Blog/ CardMeeting/Voluntary-Technical-Debt.html • Martin Fowler - http://www.martinfowler.com/bliki/ TechnicalDebt.html • David Larabee - http://msdn.microsoft.com/en-us/ magazine/ee819135.aspx • Steve McConnell - http://blogs.construx.com/blogs/ stevemcc/archive/2007/11/01/technical-debt-2.aspx • Jon Stewart - http://big.assets.huffingtonpost.com/ JonConfused.gif • Cruft Example 1 - http://thedailywtf.com/Series/ 2010/3/CodeSOD.aspx • Debt Threshold - http://blog.castsoftware.com/wp- content/uploads/2011/04/Technical-Debt-Software- Quality1.jpg • Hardening Sprints - http://blog.castsoftware.com/wp- content/uploads/2011/04/Technical-Debt-Software- Quality1.jpg