Im Doc Norton. CEO at CTO2 @DocOnDev @DocOnDev - - PowerPoint PPT Presentation

i m doc norton
SMART_READER_LITE
LIVE PREVIEW

Im Doc Norton. CEO at CTO2 @DocOnDev @DocOnDev - - PowerPoint PPT Presentation

The Technical Debt T RAP @DocOnDev Im Doc Norton. CEO at CTO2 @DocOnDev @DocOnDev http://leanpub.com/escapevelocity Im Doc Norton. CEO at CTO2 @DocOnDev @DocOnDev The Technical Debt T RAP @DocOnDev What is Technical Debt?


slide-1
SLIDE 1 The Technical Debt

TRAP

@DocOnDev
slide-2
SLIDE 2 @DocOnDev

I’m Doc Norton.

CEO at CTO2 @DocOnDev
slide-3
SLIDE 3 @DocOnDev

I’m Doc Norton.

CEO at CTO2 @DocOnDev http://leanpub.com/escapevelocity
slide-4
SLIDE 4 The Technical Debt

TRAP

@DocOnDev
slide-5
SLIDE 5 @DocOnDev What is Technical Debt?
slide-6
SLIDE 6 @DocOnDev

Shipping first time code is like going into debt.
  • Ward Cunningham, 1992
slide-7
SLIDE 7 @DocOnDev

Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back with a rewrite.
  • Ward Cunningham, 1992
slide-8
SLIDE 8 @DocOnDev

Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back with a rewrite. The danger
  • ccurs when the debt is
not repaid. Every minute spent on not-quite-right code counts as interest on that debt.
  • Ward Cunningham, 1992
slide-9
SLIDE 9

@DocOnDev

The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt.

slide-10
SLIDE 10

@DocOnDev

The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt.

slide-11
SLIDE 11

@DocOnDev

The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt.

slide-12
SLIDE 12

@DocOnDev

The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt.

slide-13
SLIDE 13 @DocOnDev

Technical Debt Is

slide-14
SLIDE 14 @DocOnDev

Technical Debt is

GOOD

slide-15
SLIDE 15 @DocOnDev Use captivating images Technical Debt is GOOD @DocOnDev
slide-16
SLIDE 16 @DocOnDev

Technical Debt is

GOOD

slide-17
SLIDE 17 @DocOnDev

Technical Debt is

A Strategic Design Decision 1 @DocOnDev
slide-18
SLIDE 18 @DocOnDev
  • Allow for Rapid Delivery
  • To Elicit Quick Feedback
  • And To Correct Design

Technical Debt is a Strategic Design Decision

@DocOnDev
slide-19
SLIDE 19 @DocOnDev

Technical Debt is

A Strategic Design Decision 1 2 An Indication of Learning @DocOnDev
slide-20
SLIDE 20 @DocOnDev
  • Now Know What You Need
  • And Implementation Doesn’t
Match

Technical Debt is an Indication of Learning

@DocOnDev
slide-21
SLIDE 21 @DocOnDev

Technical Debt is

A Strategic Design Decision 1 2 An Indication of Learning 3 A Metaphor @DocOnDev
slide-22
SLIDE 22 @DocOnDev
  • Here Be Danger

Technical Debt is a Metaphor

@DocOnDev
slide-23
SLIDE 23 @DocOnDev We Reason By Analogy

Metaphors Rock!

Building on a weak foundation

Puts pressure on our design

Can’t keep running at this pace

It’s raining men

(hallelujah)

slide-24
SLIDE 24 @DocOnDev When Metaphors Go Wrong!

Metaphorphosis

Technical Debt
slide-25
SLIDE 25 @DocOnDev When Metaphors Go Wrong!

Metaphorphosis

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

Technical Debt
slide-26
SLIDE 26 @DocOnDev When
 Metaphors Go Wrong @DocOnDev
slide-27
SLIDE 27 @DocOnDev

“quick and dirty”

  • Martin Fowler

“sloppy”

  • David Laribee

“just hack it in”

  • Steve McConnell

“cut a lot of corners”

  • James Shore
When
 Metaphors Go Wrong
slide-28
SLIDE 28 @DocOnDev 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?” Technical Debt Quadrant
  • Martin Fowler, 2009
@DocOnDev
slide-29
SLIDE 29 @DocOnDev

[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.
  • Ward Cunningham, 2009
slide-30
SLIDE 30

@DocOnDev

…confused the debt metaphor with the idea that you could write code poorly…

slide-31
SLIDE 31 @DocOnDev

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.
  • Ward Cunningham, 2009
slide-32
SLIDE 32

@DocOnDev

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-33
SLIDE 33 @DocOnDev

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.

  • Ward Cunningham, 2009
slide-34
SLIDE 34 @DocOnDev Do I Have
 Technical
 Debt? Is the code clean? 4 5 Is the code tested? 1 Is there a learning opportunity? 2 Is there a plan for payback? 3 Is the business truly informed? @DocOnDev
slide-35
SLIDE 35 @DocOnDev Do I Have
 Technical
 Debt? Is the code clean? 4 5 Is the code tested? 1 Is there a learning opportunity? 2 Is there a plan for payback? 3 Is the business truly informed? @DocOnDev
slide-36
SLIDE 36 Mess (Noun)
  • Disorderly accumulation, heap,
  • r jumble
  • A state of embarrassing
confusion
  • An unpleasant or difficult
situation @DocOnDev
slide-37
SLIDE 37 Cruft (Noun)
  • An unpleasant substance
  • The result of shoddy
construction
  • Redundant, old or improperly
written code @DocOnDev
slide-38
SLIDE 38 Cruft (Noun)
  • An unpleasant substance
  • The result of shoddy
construction
  • Redundant, old or improperly
written code @DocOnDev
slide-39
SLIDE 39 @DocOnDev

But, It’s Just Semantics, Doc.

slide-40
SLIDE 40 @DocOnDev

It’s Not Just Semantics.

slide-41
SLIDE 41 @DocOnDev

It’s Not Just Semantics.

Technical Debt is
slide-42
SLIDE 42 @DocOnDev

It’s Not Just Semantics.

Quick and Dirty is Technical Technical Debt is Good
slide-43
SLIDE 43 @DocOnDev

It’s Not Just Semantics.

Quick and Dirty is
slide-44
SLIDE 44 @DocOnDev Reckless Inadvertent Prudent Deliberate “We don’t have time for design” “We must ship now and deal with consequences” “We must ship now and deal with consequences” “Now we know how we should have done it” “What’s Layering?” Technical Debt Quadrant
slide-45
SLIDE 45 @DocOnDev 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?” Technical Debt Quadrant
slide-46
SLIDE 46 @DocOnDev

“Technical Debt”

In Other Fields

slide-47
SLIDE 47 @DocOnDev “Technical Debt”
 in other fields Construction @DocOnDev
slide-48
SLIDE 48 @DocOnDev Use captivating images “Technical Debt”
 in other fields Automotive @DocOnDev
slide-49
SLIDE 49 @DocOnDev “Technical Debt”
 in other fields Medical @DocOnDev
slide-50
SLIDE 50 @DocOnDev R e c k l e s s a n d D e l i b e r a t e R e c k l e s s a n d I n a d v e r t e n t “Technical Debt”
 in other fields
slide-51
SLIDE 51 @DocOnDev 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?” Technical Debt Quadrant Reckless and Deliberate Reckless and Inadvertent
slide-52
SLIDE 52 @DocOnDev 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?” Technical Debt Quadrant Irresponsible Incompetent T e c h n i c a l 
 D e b t
slide-53
SLIDE 53 @DocOnDev

Cruft or Debt?

slide-54
SLIDE 54 @DocOnDev

1

Cruft or Debt?

@DocOnDev
slide-55
SLIDE 55 @DocOnDev Cruft or Debt? 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-56
SLIDE 56 @DocOnDev Cruft or Debt? 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-57
SLIDE 57 @DocOnDev Cruft or Debt? 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-58
SLIDE 58 @DocOnDev Cruft or Debt? 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-59
SLIDE 59 @DocOnDev Cruft or Debt? 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-60
SLIDE 60 @DocOnDev

2

Cruft or Debt?

@DocOnDev
slide-61
SLIDE 61 @DocOnDev Cruft or Debt? 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-62
SLIDE 62 @DocOnDev Cruft or Debt? 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-63
SLIDE 63 @DocOnDev Cruft or Debt? // 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-64
SLIDE 64 @DocOnDev Cruft or Debt? if (customer.isFederallyRegulated()) { ... }
slide-65
SLIDE 65 @DocOnDev

3

Cruft or Debt?

Bonus Points - Name The Movie @DocOnDev
slide-66
SLIDE 66 @DocOnDev Cruft or Debt? 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"); }
slide-67
SLIDE 67 @DocOnDev Cruft or Debt? 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"); }
slide-68
SLIDE 68 @DocOnDev Cruft or Debt? 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-69
SLIDE 69 @DocOnDev Don’t Do Cruft! 1 You’re a Professional Developer 2 You’re Going to Create Unintentional Cruft 3 You Have to Clean Up Existing Cruft CRUFT! @DocOnDev
slide-70
SLIDE 70 @DocOnDev The Trap! 1 Precedent for Speed over Quality 2 Expectation of Increased Velocity 3 Cruft Slows You Down 4 Must Write More Cruft to Keep Up 5 Ask Permission to do You Job Correctly
slide-71
SLIDE 71 @DocOnDev

Managing Cruft

slide-72
SLIDE 72 @DocOnDev

1

Failing Strategy

slide-73
SLIDE 73 @DocOnDev

Cleaning Iteration

  • Schedule Iterations for cleaning code
  • Defer quality to cleaning sprint
  • Focus on speed/velocity at all other times
slide-74
SLIDE 74 @DocOnDev Use captivating images Cleaning Iteration @DocOnDev
slide-75
SLIDE 75 @DocOnDev

1

Winning Strategy

slide-76
SLIDE 76 @DocOnDev

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-77
SLIDE 77 @DocOnDev

Monitor Your Cruft

  • Code Coverage
  • Code Complexity
  • Churn
  • Maintainability
  • Monitor Trends, Not Points
slide-78
SLIDE 78 Title Text

HERE 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
@DocOnDev
slide-79
SLIDE 79 Title Text

HERE 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 PERMISSION TO DO YOUR JOB CORRECTLY @DocOnDev
slide-80
SLIDE 80 @DocOnDev THANK YOU!
slide-81
SLIDE 81 @DocOnDev

For slides and research:
 Send a blank email to cto2@SendYourSlides.com with the subject line: TechnicalDebt

THANK YOU!