Your SlideShare is downloading. ×
The Technical Debt Trap - AgileIndy 2013
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

The Technical Debt Trap - AgileIndy 2013

1,672
views

Published on

A visually updated version of the slide deck.

A visually updated version of the slide deck.


0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,672
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
29
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • Design decisions that allow for more rapid delivery / illicit quick feedback / gather data necessary to correct design
  • - Plan to sell several different products. Starting with just one. Don’t extract interface yet.
  • Allows us to establish a simple understanding of a complex problem in common representational terms
  • "We incurred structural debt in order to meet your deadline. We should discuss that debt and set a plan for paying it back later."
  • "We incurred mechanical debt to stay in budget. We should get metrics around that and make sure we pay the debt down in the future."
  • "We incurred health debt during the surgery. You see, it is like we paid for the surgery with a credit card instead of a home equity loan..."
  • First, let’s get rid of the curlies for readability
  • Now, let’s assume we don’t have multiple tables in our DataSets nor do we need to iterate through multiple columns in cases where we’re looking for an AgentID or queueName
  • Now let’s introduce some abstraction. We’ll create some classes that receive DataSets and return collections of objects. We’re not showing these here. Our ORM could do this for us. And let’s not make the same series of calls for queue data for every agent.
  • Now we can see what this does. We get a list of skills for an agent, compare them to a list of skills for a queue and call SetAgentQueueSkill for all matches. Seems to me, this code shouldn’t exist. The AgentQueueSkill table should be a view in the dB.
  • Is this where this evaluation belongs? Probably not. What are we checking for here? Perhaps a comment will help us.
  • Better? Not really. But what if that comment was code?
  • What about this one?
  • Why is this NOT cruft? We clearly have more code.
  • 1. Gartner Report in 2009 :: Includes Hardware 2. CAST Study in 2009 :: No correlation between size and debt; more modular == less debt
  • Ruby - churn => volume of changes git - gitswarm => visual history of changes Java - Cobertura or Sonar
  • Ruby - churn => volume of changes git - gitswarm => visual history of changes Java - Cobertura or Sonar
  • Java - Cobertura, Clover, EMMA .NET - NCover Ruby - rcov / metric_fu
  • Java - Cobertura, Clover, EMMA .NET - NCover Ruby - rcov / metric_fu
  • NDepend JDepend
  • Transcript

    • 1. The Technical Debt TrapMichael “Doc” Norton@DocOnDev
    • 2. Michael “Doc” NortonGrouponDirector ofTechnologydoc@groupon.com@DocOnDevHusband Father
    • 3. GrandFatherHe’s SOOO Cute!!
    • 4. What is Technical Debt?
    • 5. WardCunninghamShipping first time code islike going into debt. OOPSLA ’92
    • 6. WardCunninghamShipping first time code islike going into debt. A little debt speedsdevelopment so long as it ispaid back promptly with arewrite. OOPSLA ’92
    • 7. WardCunninghamThe danger occurs whenthe debt is not repaid.Every minute spent on not-quite-right code counts asinterest on that debt. OOPSLA ’92
    • 8. WardCunninghamThe danger occurs whenthe debt is not repaid.Every minute spent on not-quite-right code counts asinterest on that debt. OOPSLA ’92
    • 9. Technical Debt is a Good Idea
    • 10. Technical Debt is a Good IdeaWTF?
    • 11. Technical Debt is a Good IdeaStrategic Design Decision Allow for Rapid Delivery To Elicit Quick Feedback And Correct Design
    • 12. Technical Debt is a MetaphorHere Be Danger
    • 13. Metaphors Rock We Reason By Analogy Can’t keep running at thisBUILDING ON pace A WEAK FOUNDATIONIT’S RAINING MEN (HALLELUJAH) Puts pressure on our design
    • 14. Metaphorphosis When Metaphors Go Wrong Return on InvestmentSHORT-TERM Fraudulent Credit Card Inadvertent Reckless AUTO LOAN Debt in the Third PYRAMID SCHEMEHIGH INTEREST Intentional Quadrant Long-Term HOME LOAN Loan Shark VOLUNTARY PrudentPragmatic Leverage Student Loan OPERATIONAL
    • 15. Metaphorphosis When Metaphors Go Wrong “CUT A LOT OF CORNERS” JAMES SHORE HTTP://JAMESSHORE.COM/BLOG/CARDMEETING/VOLUNTARY-TECHNICAL-DEBT.HTML “QUICK AND DIRTY” MARTIN FOWLER “SLOPPY” HTTP://WWW.MARTINFOWLER.COM/BLIKI/TECHNICALDEBT.HTML DAVID LARIBEE “JUST HACK IT IN”HTTP://MSDN.MICROSOFT.COM/EN-US/MAGAZINE/EE819135.ASPX STEVE MCCONNELL HTTP://BLOGS.CONSTRUX.COM/BLOGS/STEVEMCC/ARCHIVE/2007/11/01/TECHNICAL-DEBT-2.A
    • 16. The Technical Debt Quadrant http://martinfowler.com/bliki/TechnicalDebtQuadrant.html
    • 17. Ummm... no.[Many] have explained thedebt metaphor andconfused it with the ideathat you could write codepoorly with the intention ofdoing a good job later. http://www.youtube.com/watch?v=pqeJFYwnkjE&feature=player_embedded YouTube.com ’09
    • 18. Ummm... no.[Many] have explained thedebt metaphor andconfused it with the ideathat you could write codepoorly with the intention ofdoing a good job later. http://www.youtube.com/watch?v=pqeJFYwnkjE&feature=player_embedded YouTube.com ’09
    • 19. [Many] have explained thedebt metaphor andconfused it with the ideathat you could write codepoorly with the intention ofdoing a good job later.
    • 20. ... confused itwith the idea thatyou could writecode poorly ....
    • 21. Clean Codeis RequiredThe ability to pay back debt[...] depends upon youwriting code that is cleanenough to be able torefactor as you come tounderstand your problem. http://www.youtube.com/watch?v=pqeJFYwnkjE&feature=player_embedded YouTube.com ’09
    • 22. Clean Codeis RequiredThe ability to pay back debt[...] depends upon youwriting code that is cleanenough to be able torefactor as you come tounderstand your problem. http://www.youtube.com/watch?v=pqeJFYwnkjE&feature=player_embedded YouTube.com ’09
    • 23. Dirty Code isa BAD IdeaDirty code is to technicaldebt as the pawn broker isto financial debt.Don’t think you are evergoing to get your code back. http://twitter.com/WardCunningham/status/3742903303 twitter ’09
    • 24. Is It Technical Debt?Ask yourself ... Is the code clean? Is the code tested? Is there a learning objective? Is there a plan for payback? Is the business truly informed?
    • 25. Is It Technical Debt?If you say no to even one... Is the code clean? Is the code tested? Is there a learning objective? Is there a plan for payback? Is the business truly informed? ... then you don’t have Technical Debt
    • 26. You have a messMess (noun)Disorderly accumulation, heap, or jumbleA state of embarrassing confusionAn unpleasant or difficult situation
    • 27. You have cruftCruft (noun)An unpleasant substanceThe result of shoddy constructionRedundant, old or improperly written code
    • 28. Chill. It’s just semantics,man.Just Semantics?Technical Debt is Good
    • 29. Chill. It’s just semantics,man.Just Semantics?Quick and Dirty is Technical Debtis Good Technical Debt is Good
    • 30. Chill. It’s just semantics,man.Just Semantics?Quick and Dirtyis Good Dirty is Good
    • 31. The Technical Debt Quadrant http://martinfowler.com/bliki/TechnicalDebtQuadrant.html
    • 32. The Technical Debt Quadrant “Let’s deploy and gather more information.” http://martinfowler.com/bliki/TechnicalDebtQuadrant.html
    • 33. Technical Debt in otherfieldsConstruction TE R A IB E E L D D AN S S LE CK RE
    • 34. Technical Debt in otherfieldsAutomotive TE R A IB E E L D D AN S S LE CK RE
    • 35. Technical Debt in otherfieldsMedical NT TE E R D V IN A N D S A ES K L EC R
    • 36. The Technical Debt Quadrant LE CA L SI B N I “Let’s deploy and N H T E C EB PO gather more ES T information.” IRR D N T PE TE M INCO http://martinfowler.com/bliki/TechnicalDebtQuadrant.html
    • 37. DataSet aDs, qDs;aDs = _dbConnector.UpdateAgentList();qDs = _dbConnector.GetQueueList();foreach (DataTable aTable in aDs.Tables) { Cruft or Debt? 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; } } } } } } } } } } } } } }} http://thedailywtf.com/Series/2010/3/CodeSOD.aspx
    • 38. 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; } }} } } } } } } } } } } } } http://thedailywtf.com/Series/2010/3/CodeSOD.aspx
    • 39. 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; } } } } } }} http://thedailywtf.com/Series/2010/3/CodeSOD.aspx
    • 40. 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; } } } }} http://thedailywtf.com/Series/2010/3/CodeSOD.aspx
    • 41. 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)) { ... }
    • 42. Cruft or Debt?// If customer is Federally Regulatedif ((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)) { ... }
    • 43. Cruft or Debt?if (customer.isFederallyRegulated()) { ... }
    • 44. 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 newRuntimeException ("Should be unreachable");} http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html
    • 45. Cruft or Debt?class Swallow ... double getSpeed() { return getBaseSpeed(); }endclassclass EuropeanSwallow ...end classclass AfricanSwallow ... doublegetSpeed() { return super.getSpeed - coconutLoad(); } doublecoconutLoad() { return getLoadFactor() * _numberOfCoconuts; }endclassclass NorwegianSwallow ... double getSpeed() { return(_isNailed) ? 0 : getBaseSpeed(_voltage); }end class
    • 46. Cruft is a bad decisionEvery TimeYOU ARE A PROFESSIONAL DEVELOPER (Professionals behave ethically)YOU ARE GOING TO CREATE UNINTENTIONAL CRUFT (You can’t help it. It’s unintentional.)YOU HAVE TO CLEAN UP THE EXISTING CRUFT (Intent doesn’t alter Responsibility)
    • 47. The Cost of “Technical Debt”We did thisWORLD-WIDE TECHNICAL DEBT (INCLUDES HARDWARE) $1 Trillion (by 2015)PER BUSINESS APPLICATION $1 Million
    • 48. GrammyDoesn’tLoveMe!Me!Me!It’s all about expectations
    • 49. The TrapCruft begets cruftPrecedent for speed over qualityExpectation of increased velocityCruft slows you downMust write more cruft to keep up Ask Permission to do your job correctly
    • 50. Avoid The TrapThresholds set falseexpectations http://blog.castsoftware.com/wp-content/uploads/2011/04/Technical-Debt-Software-Quality1.jpg
    • 51. Avoid The TrapIncremental fixes fail http://www.jacoozi.com/blog/wp-content/uploads/2007/01/refactoring_coc_big.jpg
    • 52. Avoid The TrapIncremental fixes fail http://www.jacoozi.com/blog/wp-content/uploads/2007/01/refactoring_coc_big.jpg
    • 53. Avoid The TrapClean ConstantlyNever make an intentional messMonitor your “Technical Debt”Follow the Boy Scout RuleRemember quality is your responsibility NEVER Ask Permission to do your job correctly
    • 54. Monitoring Cruft/DebtA few key metricsCode CoverageCyclomatic ComplexityCouplingMaintainability
    • 55. Monitoring Cruft/DebtCode CoverageCode exercised by automated testsMonitor test types separatelyDon’t set a coverage target100% coverage is a smellMonitor trends, not points
    • 56. Monitoring Cruft/DebtCyclomatic ComplexityNumber of logical branches in codeDirect relationship with bugsTypically high in concentrated areasReduce conditionalsMonitor trends, not points
    • 57. Monitoring Cruft/DebtCouplingInterconnectedness of systemsHighly coupled is difficult to changeAfferent (Toward) and Efferent (Away)Dependency InjectionMonitor trends, not points
    • 58. Cruft/Debt CardsTie it to Business ValueVelocityScalabilityAvailabilityMaintainability
    • 59. ReviewTechnical DebtIs a strategic design decisionRequires the business to be informedIncludes a pay-back planCruftHappensNeeds to be monitored andcleanedIs NOT Technical Debt
    • 60. ReviewTechnical DebtIs a strategic design decisionRequires the business to be informedIncludes a pay-back planCruftHappensNeeds to be monitored andcleanedIs (probably) NOT Technical Debt
    • 61. Thank You! The Technical Debt Trap Michael “Doc” Norton @DocOnDev