Moving Quickly vs. Moving Nimbly

There are adherents to TDD who believe that the test is the document for the change.

There are also people who believe that valuable software happens if you just focus on the code.

I am not saying those overlap in a perfect circle, but you should draw your own conclusions.

For the rest of us, we want to document changes for others, without becoming a warehouse of documentation that no one reads.

There are many sources of documentation, and each has its purpose.

There’s PR/MR (Pull/Merge Request) documentation, that documents why you made the changes in your branch, what reviewers and testers should be concerned about, and areas you believe need extra attention.

There’s the documentation you put into a user story / ticket; where you want to capture the relevant details of why you’re doing this story; the ins and outs with other parts of the system; the high level details that this story encompasses; and the desired end state.

There’s the documentation you put into code: the code comments where you explain why you did what you did in an area where you couldn’t use proper naming to disclose your thinking. There’s also the tests you write, whether they’re characterization tests to detail how the component works and why it works that way, or the contract test that details what your APIs expect and how they work, or a end-to-end test that details the path the user takes through the system, that ties a user action to the actions the system takes to carry out that user request. There are also development driven by tests; that detail the particular ranges and expectations for each line of code.

But, none of these documents explain why a system is changing to a particular implementation, or new technology, or changing from an event-sourced system to a transactional system, or why angular was chosen over react (or vice versa), or how that affects the business, or how the business affects system changes.

Think about all the factors that go into any large change in a system:

  • Political context (there’s a possible re-org, and you want to show value before that happens so you don’t get re-organized right out the door)
  • Team context (the team doesn’t really understand the Reactive programming pattern, and so implementing RxJS or NGRX will take too much time, or the people on the team just don’t like to write unit tests)
  • Financial context (we have three weeks budgeted to fixing this part of the system)
  • Business context (there’s a sales deadline in two months, so whatever we have has to be done in one month so sales can meet their quotas with this new feature)
  • Technical context (We can’t upgrade to .NET Core because of legacy library X, so we have to remove/replace that library before we upgrade to .NET core, and that upgrade requires a new license agreement that has to go through procurement)
  • Architectural context (Our system is required to produce reports within 5 minutes of a transaction happening, so any solution needs to fit in to that architectural standard)

They may be uncomfortable to capture, but you need to capture them, because in 6 months you’re not going to remember why you made the decision you did, or all the ins-and-outs that caused that decision, but you need to, because if you don’t you might reverse course in 6 months only to lose both ground and faith from your business stakeholders.

You capture these decisions in what is known Architectural Decision Record; a document that contains all of those contexts I listed above; and for each record, you should fill out each section, even if it feels uncomfortable to do so. If you say, “well, this section is going to be blank so I’ll skip it”, then think hard about that context before skipping it. There’s always a business factor at play, or a social factor at play; it just may be uncomfortable to talk about; or it may be “because we want to maintain the status quo politically”, but it’s there.

They are also good to have listed because they give you areas to ask stakeholders about. Asking your boss, what political considerations are involved? is a necessary (albeit uncomfortable) question, because you want to do the right thing that gets the right result; and politics is how two or more people make decisions. Asking your manager about the financial considerations is just as crucial; because if you don’t ask, you’ll get surprised when you only have three weeks when you thought you had six (BTDT).

Besides those contexts that are each of their own sections, there are also other sections for the ADR:

1. Change desired
2. Reason for Change
3. Contexts (from above)
4. Approach A
– Pros
– Cons
– impacts on those contexts and considerations
5. Approach B
– Pros
– Impacts

6. Approach C
– Pros
– Cons
– Impacts
7. Approaches that didn’t make the top 3 but were discussed (you can bullet these, don’t need to go into detail)
8. Decision
9. Follow-up date on this decision and the follow-up recorded impact

This is the template I use; there are others, and you should mix and match your ADRs to fit your business. The most crucial part I’ve found is the actual context around the decision, because those are meant to capture the aura around a potential change; and that’s usually the first casualty of memory.

I pick three approaches because there’s research that says you should offer choice, but not too much; and if you can’t find yourself a third choice, remember: doing nothing is also an option.

These documents sometimes take weeks to fill out; that’s OK. The important part is that they take as long or as short as needed to capture the decision and receive alignment from others as to why the decision is being made. That will vary on the team and the change needed, but is one way to align the team to move nimbly, not just quickly.

The next Right thing

How many times have you been in a meeting where someone on the team says, “And we should make this configurable; just in case we need it”, or “this will scale better if we do x“.

Yea, that about sums it up.

As much as we hate to admit it, we can’t predict the future. Outside of the highly trained epidemiologists, the wider world didn’t anticipate that COVID-19 would have the effect its had. Almost none of us would have predicted we’d be at home for at least two weeks, or that schools would be shut down for the rest of the year, or that toilet paper would be the hottest commodity on the planet.

Let’s say you had some inside knowledge in January and your epidemiologist friend had told you that COVID-19 would be bad, and you trusted that person. Would you have stocked up on toilet paper? Would you have told your teachers and your schools that they needed to make sure their distance learning plans were set?

Probably not — even if we can see the first order effects well, it’s those second and third-order effects that get us, every time.

The mistake we make in building software is that we try to predict those second and third-order effects. We try to anticipate where events are heading, or the effect that each feature will have, and we suck at it.

Slack is currently rolling out their new UI. This is a platform that’s seen a skyrocketing increase in usage due to the Stay-at-home orders; and they’re also in the middle of a (prior planned) UI change. My experience tells me this is a bad idea and will result in lots of pain and an ultimate partial or full reversal, but should you want to believe me, see my last paragraph.

As I said, it’s easy for us to make predictions, but it’s hard to see the future.

So why do we do it?

For one thing, it feels good to feel like you ‘got it right’. It’s proof that you are smart. Now it’s utterly silly for us to hang our hats on this notion, but we do it, all the time, with all the attendant pains it brings.

Contrast this with building software through Test Driven Development, where you never try to predict the future. You just do the next right thing, and the next right thing, and so on, until you have gotten to the point where you can attempt larger changes, because you know there are tests protecting you from making an oops.

It’s a completely different way of thinking about software; and while it doesn’t forgo designing up front; it does minimize the dangers of trying to future proof before you have a clear understanding of what that means, and what the effects are.

In your next design meeting, even if you aren’t practicing TDD, try this out. Try to focus on the next right thing. Or as Einstein once said, “I never think of the future. It comes soon enough.”

It’s hard to focus right now..

It’s really hard to focus right now.

In addition to trying to help others adopt TDD, I also work with clients to produce software for them. I’m notionally supposed to be writing features for that client right now; but much like everyone else, I’m running at about 20% efficiency.

This culture and this team I am working with has never adopted TDD, and few people on the team understand unit tests.

This is normal for our industry, and from experience, I know it’s contributing to the lack of concentration for me and for others.

With the kids at home, we (my spouse and I) get interrupted often, and that leaves us pockets of work time, and if you’re a developer, you know how hard it is to stay in ‘the zone’. I refer to that ‘zone’ in How to Destroy Programmer Productivityand if you could use a little baseball bat humor right now, I hope that link helps.

For the course I’m building, it’s easier to jump back into that every night than it is my daytime client work. The biggest reason is that because I have a failing test awaiting me when I go back to the course, I know exactly where I’m at. I don’t have to spend any time wondering what to do next; the failing test tells me what to do.

I only have to concentrate on the next right thing (sorry, Anna).

Contrast that with client work, where Unit tests and TDD approaches to building software vary among the team and culture. There, it’s harder to jump back into it. I don’t have an easily testable architecture and infrastructure waiting for me. I have my notes, and I have comments in the code; but I don’t have that part I rely on — the tests, which are especially useful during times like these. It’s a small thing, leaving a failed test to come back to, but when your attention is split among so many things, it’s extremely helpful to have.

How are you handling this? Hit reply and let me know. I’d love to hear from you. All we have is each other (especially since in most places — like where I live — we can’t even hang out with our IRL friends).

Intro to Hexagonal Architecture (video)

I’ve been setting up my home office to shoot the videos for my forthcoming course: Test Driven Development for .NET Project Teams. Besides writing scripts and assembling materials, I decided to shoot a short video to see the state of the set-up. Instead of something that couldn’t be useful to you (like me randomly talking for 15 minutes) I put together an intro to Hexagonal architecture (aka ports and adapters), which is a necessary component to ensuring you can build an application through Test Driven Development.

You can watch the video here: (At some point I might publish that link; but right now it’s a bit of a screen test, and may be re-shot later).

I would love your feedback on this, from small things like video aspect ratio, to the bigger things (like a concept was explained unclearly), and what you liked as well (and why!). Leave a comment below. I read every piece of feedback.

end note: This video was stream of consciousness (the slides were added after the fact to smooth out some of the rougher parts), so keep that in mind.

It’s a hack… but it works.

Last week I needed to finish the attic — I was putting down more insulation and creating a raised platform so we could store our many, many, possessions in the attic. I say this with a sense of ennui, as I feel like adding more space to store things encourages storing more things (kinda like expanding highways causes more traffic). But anyway, since my house was built in the 50s, there are quite a few gotchas in putting this platform down. Things like dealing with rafters that have faux headers (used to ensure the structure didn’t ‘shift’ during construction before the roof was put on), or random wooden beams that hang off into space.

So, at one point, it was either put a corner into a void or spend another hour working on the attic.

So I chose the hack.

The hack was that since this part of the attic would (at most) hold one box, and never a human, I could get away with letting the stud hang off the end of the ceiling beam.

This was a hack, and I can only imagine what someone who sees this in 40 years says.

I can’t really leave a note for them; so I guess they’ll think the previous owner was an unqualified hack.

They’d probably be right; but they’re also forgetting the context I was operating in — finishing the attic during a global pandemic so I could have my office back.

The good news is that with TDD and unit tests, you can explain your hacks to people who come after you. Comments work, though they often lie because they can’t be guaranteed to stay in sync with the code. That’s their chief problem. They lie.

The cool thing about your unit tests (and TDD is even better at this) is that they have to stay in sync with what the code does, otherwise they’d break. They can’t lie (though if poorly named or shaped, they can mislead).

The next time you need to make a hack in code; think about producing a characterization test that explains why the code does what it does; and indicates in what circumstances the code (and its tests) would be safe to remove. This may be a more brittle test; but given that it’s documenting a hack, that’s probably a good thing.

(If you’ve read the last post titled “Chesterton’s fence”, you’ll probably notice that this post is a corollary to that one. I’d like to think it’s worth your time if you haven’t already read it).