the technical debt trap - ndc oslo 2014

60
The Technical Debt Trap Doc Norton [email protected] @DocOnDev

Upload: michael-doc-norton

Post on 27-Aug-2014

1.046 views

Category:

Software


4 download

DESCRIPTION

Technical Debt has become a catch-all phrase for any code that needs to be re-worked. Much like Refactoring has become a catch-all phrase for any activity that involves changing code. These fundamental misunderstandings and comfortable yet mis-applied metaphors have resulted in a plethora of poor decisions. What is technical debt? What is not technical debt? Why should we care? What is the cost of misunderstanding? What do we do about it? Doc discusses the origins of the metaphor, what it means today, and how we properly identify and manage technical debt.

TRANSCRIPT

Page 1: The Technical Debt Trap - NDC Oslo 2014

The Technical Debt Trap

Doc Norton [email protected] @DocOnDev

Page 2: The Technical Debt Trap - NDC Oslo 2014

Doc Norton!Global Director of Engineering [email protected] | @DocOnDev

Husband Father

Page 3: The Technical Debt Trap - NDC Oslo 2014

Grandfather!

Page 4: The Technical Debt Trap - NDC Oslo 2014

What is Technical Debt?

Page 5: The Technical Debt Trap - NDC Oslo 2014

Shipping first time code is like going into debt.

OOPSLA ‘92

Ward Cunningham

Page 6: The Technical Debt Trap - NDC Oslo 2014

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.

OOPSLA ‘92

Ward Cunningham

Page 7: The Technical Debt Trap - NDC Oslo 2014

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

OOPSLA ‘92

Ward Cunningham

Page 8: The Technical Debt Trap - NDC Oslo 2014

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

OOPSLA ‘92

Ward Cunningham

Page 9: The Technical Debt Trap - NDC Oslo 2014

Technical Debt is Good

Page 10: The Technical Debt Trap - NDC Oslo 2014

WTF?Technical Debt is Good

Page 11: The Technical Debt Trap - NDC Oslo 2014

Technical Debt is Good

Strategic Design Decision

❖ Allow for Rapid Delivery!

❖ To Elicit Quick Feedback!

❖ And Correct Design

Page 12: The Technical Debt Trap - NDC Oslo 2014

Technical Debt is Good

Indication of Learning

❖ Now know what you need!

❖ Implementation doesn’t match!

Page 13: The Technical Debt Trap - NDC Oslo 2014

Technical Debt is a Metaphor

Here Be Danger

Page 14: The Technical Debt Trap - NDC Oslo 2014

Metaphor’s 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)

Page 15: The Technical Debt Trap - NDC Oslo 2014

Metaphorphosis

When Metaphors Go Wrong

SHORT-TERM

Long-Term

INADVERTENT RECKLESS DEBT IN THE THIRD

QUADRANTPrudent

Intentional

Credit CardFRAUDULENT

AUTO LOAN

Student Loan

HOME LOAN

Loan Shark

Return on Investment

PYRAMID SCHEME

VOLUNTARY

PRAGMATIC LEVERAGE

HIGH INTEREST

OPERATIONAL

Page 16: The Technical Debt Trap - NDC Oslo 2014

Metaphorphosis

When Metaphors Go Wrong

“QUICK AND DIRTY” MARTIN FOWLER HTTP://WWW.MARTINFOWLER.COM/BLIKI/TECHNICALDEBT.HTML

“SLOPPY” DAVID LARIBEE HTTP://MSDN.MICROSOFT.COM/EN-US/MAGAZINE/EE819135.ASPX

“JUST HACK IT IN” STEVE MCCONNELL HTTP://BLOGS.CONSTRUX.COM/BLOGS/STEVEMCC/ARCHIVE/2007/11/01/TECHNICAL-DEBT-2.ASPX

“CUT A LOT OF CORNERS” JAMES SHORE HTTP://JAMESSHORE.COM/BLOG/CARDMEETING/VOLUNTARY-TECHNICAL-DEBT.HTML

Page 17: The Technical Debt Trap - NDC Oslo 2014

The Technical Debt Quadrant

http://martinfowler.com/bliki/TechnicalDebtQuadrant.html

Page 18: The Technical Debt Trap - NDC Oslo 2014

[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.

YouTube ‘09

Ummm… No.

http://www.youtube.com/watch?v=pqeJFYwnkjE&feature=player_embedded

Page 19: The Technical Debt Trap - NDC Oslo 2014

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

Page 20: The Technical Debt Trap - NDC Oslo 2014

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.

YouTube ‘09

Clean Code is Required

http://www.youtube.com/watch?v=pqeJFYwnkjE&feature=player_embedded

Page 21: The Technical Debt Trap - NDC Oslo 2014

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.

YouTube ‘09

Clean Code is Required

http://www.youtube.com/watch?v=pqeJFYwnkjE&feature=player_embedded

Page 22: The Technical Debt Trap - NDC Oslo 2014

Twitter ‘09

Dirty Code is a Bad Idea

Dirty code is to technical debt as the pawn broker is to financial debt.!

http://twitter.com/WardCunningham/status/3742903303

Don’t think you are ever going to get your code back.

Page 23: The Technical Debt Trap - NDC Oslo 2014

Is it 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?

Page 24: The Technical Debt Trap - NDC Oslo 2014

Is it 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

Page 25: The Technical Debt Trap - NDC Oslo 2014

You have a mess

Mess (noun)

❖ Disorderly accumulation, heap, or jumble!

❖ A state of embarrassing confusion!

❖ An unpleasant or difficult situation

Page 26: The Technical Debt Trap - NDC Oslo 2014

You have cruft

Cruft (noun)

❖ An unpleasant substance!

❖ The result of shoddy construction!

❖ Redundant, old or improperly written code

Page 27: The Technical Debt Trap - NDC Oslo 2014

Chill. It’s just semantics, man.

Just Semantics?

Technical Debt is Good

Page 28: The Technical Debt Trap - NDC Oslo 2014

Chill. It’s just semantics, man.

Just Semantics?

Technical Debt is GoodQuick and Dirty is Technical DebtQuick and Dirty is Good

Page 29: The Technical Debt Trap - NDC Oslo 2014

Chill. It’s just semantics, man.

Just Semantics?

Quick and Dirty is GoodQuick and Dirty is Good

Page 30: The Technical Debt Trap - NDC Oslo 2014

The Technical Debt Quadrant

http://martinfowler.com/bliki/TechnicalDebtQuadrant.html

Page 31: The Technical Debt Trap - NDC Oslo 2014

The Technical Debt Quadrant

http://martinfowler.com/bliki/TechnicalDebtQuadrant.html

“Let’s deploy and gather more information.”

Page 32: The Technical Debt Trap - NDC Oslo 2014

Technical Debt in Other Fields

Page 33: The Technical Debt Trap - NDC Oslo 2014

Technical Debt in Other Fields

Page 34: The Technical Debt Trap - NDC Oslo 2014

Technical Debt in Other Fields

Page 35: The Technical Debt Trap - NDC Oslo 2014

Technical Debt in Other Fields

RECKLESS AND DELIBERATE

RECKLESS AND DELIBERATERECKLESS AND INADVERTENT

Page 36: The Technical Debt Trap - NDC Oslo 2014

The Technical Debt Quadrant

http://martinfowler.com/bliki/TechnicalDebtQuadrant.html

IRRESPONSIBLE

INCOMPETENT

“Let’s deploy and gather more information.”

TECHNICAL

DEBT

Page 37: The Technical Debt Trap - NDC Oslo 2014

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

Page 38: The Technical Debt Trap - NDC Oslo 2014

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

Page 39: The Technical Debt Trap - NDC Oslo 2014

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

Page 40: The Technical Debt Trap - NDC Oslo 2014

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

Page 41: The Technical Debt Trap - NDC Oslo 2014

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)) { ... }

Page 42: The Technical Debt Trap - NDC Oslo 2014

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)) { ... }

Page 43: The Technical Debt Trap - NDC Oslo 2014

Cruft or Debt?

if (customer.isFederallyRegulated()) { ... }

Page 44: The Technical Debt Trap - NDC Oslo 2014

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");!}!

http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html

Page 45: The Technical Debt Trap - NDC Oslo 2014

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

Page 46: The Technical Debt Trap - NDC Oslo 2014

Cruft is a bad decision

Every Time

❖ You are a professional developer!

❖ You’re going to create unintentional cruft!

❖ You have to clean up the existing cruft

Page 47: The Technical Debt Trap - NDC Oslo 2014

The Trap

Cruft begets Cruft

❖ 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

Page 48: The Technical Debt Trap - NDC Oslo 2014

Avoid The Trap

Thresholds set false expectations

http://blog.castsoftware.com/wp-content/uploads/2011/04/Technical-Debt-Software-Quality1.jpg

Page 49: The Technical Debt Trap - NDC Oslo 2014

Avoid The Trap

Incremental fixes fail

http://www.jacoozi.com/blog/wp-content/uploads/2007/01/refactoring_coc_big.jpg

Page 50: The Technical Debt Trap - NDC Oslo 2014

http://www.jacoozi.com/blog/wp-content/uploads/2007/01/refactoring_coc_big.jpg

Page 51: The Technical Debt Trap - NDC Oslo 2014

Avoid The Trap

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

Page 52: The Technical Debt Trap - NDC Oslo 2014

Monitoring Cruft/Debt

A few key metrics

❖ Code Coverage!

❖ Code Complexity!

❖ Coupling!

❖ Maintainability

Page 53: The Technical Debt Trap - NDC Oslo 2014

Monitoring Cruft/Debt

Code Coverage

❖ Code exercised by automated tests!

❖ Monitor types of tests separately!

❖ Don’t set a coverage target!

❖ 100% coverage is a smell!

❖ Monitor Trends, Not Points

Page 54: The Technical Debt Trap - NDC Oslo 2014

Monitoring Cruft/Debt

Complexity

❖ Count of logical branches in code!

❖ Direct relationship with bugs!

❖ Typically high in concentrated areas!

❖ Reduce conditionals!

❖ Monitor Trends, Not Points

Page 55: The Technical Debt Trap - NDC Oslo 2014

Monitoring Cruft/Debt

Coupling

❖ Interconnectedness of systems!

❖ Highly coupled is difficult to change!

❖ Afferent (toward) and Efferent (away)!

❖ Dependency Injection!

❖ Monitor Trends, Not Points

Page 56: The Technical Debt Trap - NDC Oslo 2014

Monitoring Cruft/Debt

Make stories for cruft

❖ Velocity!

❖ Scalability!

❖ Availability!

❖ Maintainability

Page 57: The Technical Debt Trap - NDC Oslo 2014

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

Page 58: The Technical Debt Trap - NDC Oslo 2014

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 permiss

ion to do your job co

rrectly

Page 59: The Technical Debt Trap - NDC Oslo 2014

TheTechnical Debt Trap

Doc [email protected]!@DocOnDev

Comments / Questions?

Page 60: The Technical Debt Trap - NDC Oslo 2014

TheTechnical Debt Trap

Doc [email protected]!@DocOnDev

Thank You!