Velocity vs. Quality – How do developers and founders meet in the middle?

Code Quality

As developers we strive to write high-quality, well-tested code that works
correctly. It should be easy to extend and simple to understand, both for our
future selves and other developers. Within our field we constantly have
conversations about writing maintainable code and coming up with good
abstractions for the underlying business domain. Metaphors and rules-of-thumb
in this area are plentiful. There’s an oft-repeated saying along the lines of,
“Always write code as though it will be maintained by a homicidal, axe-wielding
maniac who knows where you live.” But is striving for perfection in the code we
write always the right decision?

At thoughtbot our lifeblood is client projects – the first text you see on our
homepage is “Let’s build something that your users will love.” Working with
clients, specifically product owners and founders, and making decisions
together about the direction of the product is a constant in our daily work.
Naturally, those product owners and founders are excited to move at a rapid
pace, delivering features to users as quickly as possible. So how do we balance
that desire with making the right decisions technically? Sometimes creating
software in a maintainable, scalable way can be slower than simply building
something which works, and the benefits might not be immediately obvious to a
non-technical founder or product owner.

A product owner and a developer working

Communication is Key

Like so many aspects of our work, at least part of the answer here is good
communication within the team. Having an open and honest conversation with the
product owner about the trade-offs on each side of a technical decision is
important. In my experience, these conversations tend to be longer and more
fleshed out the first few times they happen on a project. As a project
progresses, trust between developers and the product owner builds, and we tend
to implicitly understand each other’s judgements and motivations better. As
developers we have a responsibility to communicate clearly why we’d recommend a
particular technical decision – it could be for reasons of code
quality/maintainability, performance, or something else. What might the
repercussions be of not taking that route right now? As the product owner,
it’s important to communicate the context of a decision. Is there a specific
urgency around getting this feature shipped right now that makes taking a
technical shortcut worth it?

Conscious Technical Debt

An important part of the conversation is the concept of technical debt.
Technical debt brings a financial analogy to our project codebases. The idea is
that shortcuts or compromises we make while writing code and making code design
decisions result in debt. The debt can exist in the form of badly organized
code, poorer abstractions and worse code quality in general. Unless the debt is
paid off by addressing those compromises, we’ll pay interest on the debt through
changes and additions to the codebase taking longer. This ultimately results in
features being slower to ship. Furthermore, because concepts in the code are
less clear, it becomes easier to accidentally make the wrong change and ship
bugs to your users.

This description of technical debt makes it sounds like an inherently Bad Thing
which should be avoided at all costs. But, treated the right way, technical
debt can be a valid, useful option during a project. Martin Fowler has an
excellent blog post in which he describes a technical debt quadrant. I won’t
paraphrase that post too much (please go and read it though!) but the lesson I
try to keep in mind is that technical debt can be used positively if it’s
accumulated deliberately and prudently. So what does that mean? I think it
means that we have a responsibility to make sure such decisions are well-
considered and not made in isolation. Generally we work in small teams so
usually there are other developers or designers to have the conversation with,
as well as the product owner. Another important part is to have a plan in mind
for addressing the debt. What might a better solution look like? Are there
future features which touch on a similar area of the codebase which might
provide a good opportunity to tackle the debt when constraints are different?

In the context of a client project, an important part of the learning process
and feedback loop is to openly call out scenarios where technical debt is
slowing us down, and raise whether now is the right time to pay off the debt
through refactoring or revisiting past architecture decisions.

If you and your team would like help understanding and taming the technical
debt in your application, thoughtbot can help.

Maintaining Code Quality

Of course, consciously accumulating a small amount of technical debt doesn’t
give us a free pass to throw good software design out of the window! Two of the
tools which we regularly use to help maintain high standards are pair
programming and code reviews. One of the benefits of both of these is that they
force you to have a conversation about compromises made while writing code. The
important thing to remember is that even if we’re making trade-offs, we always
want to ship high quality code.

Wrapping Up

Honest conversations between developers and product owners are critical. Coming
to a good understanding of each other’s motivations is an import step in any
project. I’ve found that it’s useful to get into the habit of having these
conversations early in a project, to avoid having them for the first time when
a milestone is approaching and the pressure might be higher.

Source: Thoughtbot