Recent Bookmarks and Annotations
-
Coding Horror: Paying Down Your Technical Debt on 2009-11-20
-
We have to stop working on new features for a while and pay down some of our
technical debt.
-
accruing technical debt is unavoidable on any real software project.
-
-
All you can do is roll with the punches, and budget some time into the schedule
to periodically pay down your technical debt.
-
The time you take out of the schedule to make technical debt payments typically
doesn't result in anything the customers or users will see. This can sometimes
be hard to justify
-
One of the important implications of technical debt is that it must be
serviced, i.e., once you incur a debt there will be interest charges.
If the debt grows large enough, eventually the company will spend more on
servicing its debt than it invests in increasing the value of its other
assets
-
accumulated technical debt becomes a major disincentive to work on a
project. It's a collection of small but annoying things that you have to
deal with every time you sit down to write code.
-
-
Funny how it comes around and bites you in the ass a few months later
-
Unit testing, in this context, is irrelevant; you WILL make imperfect
architectural decisions early on
-
having a lot of unit tests makes it easier to make sweeping architectural
changes. That's true. But I also suspect if your changes are deep enough, you're
going to break some tests, too -- factor that time in as well
-
Lessons Learned: Embrace technical debt on 2009-11-20
-
The biggest source of waste in new product development is building something
that nobody wants
-
there is one silver lining when it does happen: we wind up
throwing
out working code, debt-riddled and elegantly designed alike
-
-
The failure of the feature had nothing to do with the quality of the code. As a
result, many technical debts were summarily cancelled. Had we taken longer to
get that feedback by insisting on writing cleaner code, the debt would have been
much deeper
-
-
Most of us think we know a good design when we see it. Unfortunately, no matter
how much up-front analysis we do, until the design is tested by actual practice,
we can't really know
-
it's more important to make continual progress than to build the ultimate
design
-
As in many scalability decisions, we’d have been much better off investing in
agility, so that we could change the architecture in response to actual customer
demand, rather than trying to predict the future.
-
In addition, third-party services and API’s enabled us to do more with less, but
at a cost: taking on the technical debt of products and teams outside our direct
control
-
Given the choice between incurring technical debt in a particular
end-user-visible feature and incurring the same level of debt in a core system,
I’d much prefer the former
-
There’s a chance that I’ll never have to pay for that particular debt, because
the feature may have no value for customers.
-
Technical debt manifests as rigidity or inflexibility. When modifying a part of
the product afflicted by debt, the work requires a lot of extra – and
unpredictable – clean up. But if a given feature is rarely modified, its debt is
much less expensive.
-
The opposite is true with debt in a core system; it’s much more likely that this
debt will slow down our ability to make changes later on
-
In the world of physical goods, the leaner a supply chain is, the less debt is
required to operate it
-
A similar relationship applies to technical debt. Teams that practice an agile
or lean development process are able to minimize the accumulation of technical
debt without sacrificing speed, because they work in smaller batches. They also
take better advantage of debt, because they find out sooner if a particular
investment has paid off
-
often build and deploy large systems before learning if their early choices
were sensible, and therefore wind up with a much larger debt to pay. In fact, by
the time they become aware of it, they’ve already started to pay significant
interest on that debt.
-
We can trade technical debt for process improvement, too. If that improvement
pays off (by reducing the batch size of our work, for example), it becomes
easier to address all technical debt in the future – including the debt
just incurred
-
it’s often worthwhile to write test coverage for legacy code even without taking
the time to refactor
-
This reverses the standard intuition about what engineering activities add
value, which usually concludes that test coverage is a form of necessary waste
but a refactoring is value-added work. However, a refactoring (by itself) might
go stale or introduce unintended side-effects. Adding test coverage will make it
easier to refactor in the future and also reduce our fear of making
changes elsewhere.
-
choose a disciplined approach to making proportional investments in prevention
and paying down debt,
-
They work by focusing our energy on making process and technical changes
in precisely those areas that are causing the biggest waste and slowdown.
-
the speed of just-in-time experimentation wedded to a discipline of rigorous
waste-reduction
-
our fundamental approach was flexible and resilient. At no point did we stop
everything and do a ground-up rewrite. Instead, we incrementally improved our
process, architecture, and infrastructure, always learning and adjusting
-
MF Bliki: TechnicalDebt on 2009-11-20
-
The tricky thing about technical debt, of course, is that unlike money it's
impossible to measure effectively. The interest payments hurt a team's
productivity, but since we
CannotMeasureProductivity, we can't
really see the true effect of our technical debt
-
One thing that is easily missed is that you only make money on your loan by
delivering
-
Technical Debt - 10x Software Development on 2009-11-20
-
the obligation that a software organization incurs when it chooses a design or construction approach that's expedient in the short term but that increases complexity and is more costly in the long term.
-
his commonly occurs when an organization makes a conscious decision to optimize for the present rather than for the future.
-
-
This kind of debt is like credit card debt. It's easy to incur unintentionally, it adds up faster than you think, and it's harder to track and manage after it has been incurred
-
One of the important implications of technical debt is that it must be serviced, i.e., once you incur a debt there will be interest charges.
-
If the debt grows large enough, eventually the company will spend more on servicing its debt than it invests in increasing the value of its other assets
-
business staff generally seems to have a higher tolerance for technical debt than technical staff does.
-
Business executives tend to want to understand the tradeoffs involved, whereas some technical staff seem to believe that the only correct amount of technical debt is zero
-
Everyone agrees that it's a good idea to incur debt late in a release cycle, but business staff can sometimes resist accounting for the time needed to pay off the debt on the next release cycle.
-
unlike financial debt, technical debt is much less visible, and so people have an easier time ignoring it.
-
maintains a debt list within its defect tracking system. Each time a debt is incurred, the tasks needed to pay off that debt are entered into the system along with an estimated effort and schedule. The debt backlog is then tracked, and any unresolved debt more than 90 days old is treated as critical.
-
If the shortcut you are considering taking is too minor to add to the debt-service defect list/product backlog, then it's too minor to make a difference; don't take that shortcut. We only want to take shortcuts that we can track and repair later."
-
One company tracks debt vs. team velocity. Once a team's velocity begins to drop as a result of servicing its technical debt, the team focuses on reducing its debt until its velocity recovers.
-
This is like a minimum payment--if your minimum payment is 3% of your balance, that's no problem. If the minimum payment is $1000 regardless of your balance, you'd think hard about taking on any debt at all.
-
Use an organization's maintenance budget as a rough proxy for it's technical debt service load.
-
Discuss debt in terms of money rather than in terms of features.
-
The only kinds that are really healthy are Types II.A.1 and II.B.
-
Analyzing Java Heap problems Part 2: Using Eclipse MAT « Schneide Blog on 2009-11-20
-
Analyzing Java Heap problems Part 1: Basic actions and tools « Schneide Blog on 2009-11-20
-
Explaining java.lang.OutOfMemoryError: PermGen space | Fresh Blurbs on 2009-11-19
-
Closures - Secrets of the JavaScript Ninja on 2009-11-18
-
It's not uncommon to find closures permeating JavaScript libraries, and other
advanced code bases, due to their ability to drastically simplify complex
operations.
-
there is a direct cost to storing and referencing your information in this
manner. It's important to remember that each function that accesses information
via a closure immediately has at "ball and chain," if you will, attached to them
carrying this information
-
-
Memoization is the process of building a function which is capable of
remembering its previously computed answers.
-
by adding a new .memoized() method we do have the ability to modify
and attach properties that are associated with the function itself. This allows
us to create a data store (._values) in which all of our
pre-computed values can be saved
-
Function wrapping is a means of encapsulating the functionality of a function,
and overwriting it, in a single step. It is best used when you wish to override
some previous behavior of a function, while still allowing certain use-cases to
still execute
-
a function can be safely overriden without any loss of functionality.
-
Their technique is interesting, as opposed to having a large if/else block
within their readAttribute function (debatably messy and not a good
separation of concerns) they, instead, opt to completely override the old
method, simply implementing this fix, and deferring the rest of the
functionality back to the original function
-
(function(){})(). This single piece of code is incredibly versatile
and ends up giving the JavaScript language a ton of unforeseen power
-
a code block which is instantly created, executed, and discarded. Additionally,
since we're dealing with a function that can have a closure, we also have access
to all outside variables
-
a common issue with closures and looping, namely that the variable that's being
enclosed (i) is being updated after the function is bound
-
This means that every bound function handler will always alert the last value
stored in i (in this case, '2'). This is due to the fact that
closures only remember references to variables - not their actual values at the
time at which they were called
-
Note that, in order to achieve this, we pass in the iterator value to the
anonymous function and then re-declare it in the arguments. This means that
within the scope of each step of the for loop the i variable is
defined anew, giving our click handler closure the value that it expects.
-
Keep as much of the library private as possible and only selectively introduce
variables into the global namespace
-
-
-
Overview - Secrets of the JavaScript Ninja on 2009-11-18
-
JScript Blog : Scope chain of JScript Functions on 2009-11-17
-
Scope chain refers to the chain of objects whose
properties are looked for when a variable is looked for its existence and its
value. Functions in JScript have their scope chain saved when they are
defined