Principles Cut Both Ways

While I’ve become fully convinced Dave Ramsey is a fully-participating mechanism of the systemic class oppression he claims to help people escape, a line from “Total Money Makeover” has stuck with me.

“The good thing about principles is that they make life easy. I have heard it said that when someone bases his life on principle, 99 percent of his decisions are already made.”

Dave Ramsey

What’s not to love about that? You don’t need to decide if you’re going to deploy untested code — your department has principles around quality! I’d never starve the cat — I have principles against cruelty! I’d never allow sexual harassment in my workplace — that’s against my principles!

I don’t think it’s a hot take if I say that it’s not so easy. I also don’t have to think very hard to conjure up an example of conflicting principles. The issue, I think, is that how we rank our principles — their cascading priority — is what matters more than simply having principles.

This is normal — something is always going to be more important. The problem with that is much like implicit bias, we don’t really think about this ranking. Our brains just synthesize all the input can give us a snap decision that “Paying rent is more important than not abusing terms of service agreements.”

Managing Principles and Budgeting Money

I can’t tell you how many times I’ve gotten to the end of a month and wondered where the hell all my salary has gone. I’m usually pretty unhappy with what I find when I dig into the checkbook, too — impulse buys, random subscriptions, DoorDash orders several times a week. Absolutely none of it things I would have said is more important than paying down debt, yet that’s where my money went instead of the goal I supposedly value. This usually happens because I’m not actively deciding how to spend it, not holding up each decision to the light of my principles before keying in my card number.

Unless I make an active decision on each transaction (“I mean, yes, fish and chips would be nice for the third time this week, but each meal is also the cost of a minimum payment on the Discover card…”) then the money is essentially going to spend itself. And it’s going to do it in a way that has nothing to do with my stated principles.

It’s the same way with budgeting energy on a project. The number of times I’ve seen people get to the end of a card or sprint or even project and go “Oh yeah, I meant to fix that tech debt / try the new pattern / cross train that person and never got to it” is way bigger than zero. People (and yes, this means me too) tend to not even realize they’re letting their brain’s background processes make decisions like “We’re getting questions about how long this is taking so there’s no time to refactor that” or “Bob doesn’t even want to learn this part of the code so I won’t wait for him to be ready to pair.”

By the time we finish the card, we can see clearly how we did it in a way that we’re not proud of — the conscious thought reveals all the places we broke with principle. But by then it’s too late.

What to Do?

Decision making is like a muscle; it needs exercise. The implicit bias engine gives us a massive accelerator on decision making…but if we haven’t calibrated it correctly (and sometimes even when we have), then all it does is enable us to make the wrong decision faster. So we need to avoid relying on it, and that is a more difficult task than we realize.

It basically boils down to short-circuiting our ability to make snap decisions. We need to pause longer before picking a path.

Collaboration

One of the things I like (or hate, depending on the day) about pair programming is the extra step of discussing the next move with one’s partner. There’s a built-in slowdown that allows for things to move out of the background process and into the active cognitive thread. Plus, there’s a decent chance a partner hearing the solution is going to be more considering and critical of it — the number of times I’ve said to a pair partner (or had said to me) “But what about this” only to have them say “Oh, I didn’t think about it” is non-trivial.

Whether in a formal pair or a more informal “Let me run this by you” situation, the act of explaining your thoughts alone can provide clarity (rubber ducking, anyone?). Either you or a thoughtful teammate can remind you of goals that had been set or principles the team normed on, and point out what you just described doesn’t fit the bill.

Write it down

A line in a card about “Address tech debt around dependencies” is a pretty low-effort way to remember that little non-functional requirement. A big ol’ sticky note on the team wall or pinned in the Slack channel reminding everyone that we’re going to prioritize PR reviews is a good short term reminder.

This isn’t something that’s going to work indefinitely. There’s a famous parable in the Wendy’s world that advises us to “Clean the ketchup off the wall as soon as you see it, because next time you see it it’ll just look like part of the wall.” A sticky note in the “follow up” section of a team board has a shelf life of usefulness, and if you’re not actively engaging and refreshing them regularly then they’ll just become part of the decor.

A visual cue you’ll see somewhere long before the card or project is finished can be the nudge you need to review recent decisions and course correct before it’s too late.

Build a process

Whatever the details of it, you need to build a process for decision making that forces you to focus on the issue. It doesn’t need to be an hour long process, but if you can’t remember the last time you took 5 minutes to ponder something before reaching a verdict you might be letting your biases override your values.

A thing I used to do while running a department in a distribution center was make myself as a follow up question when asked for a decision. It usually wound up being more — the “ask a question” rule was to force me to break out of the kneejerk response.

Processor: “I think we should move the supplies to the end of bay, it’d be quicker to reup.”

Bad: “We don’t have time to do that right now.” Also bad: “Yeah, that could be good.”

Good: “How often are you having to reload supplies?” Also good: “Alright, but where?”

At least for me, discussion of an idea forces my thinking out of the automatic and into the conscious.

Bring it All Back Home

Everywhere I’ve enjoyed working for an extended period of time had a codified set of principles I could align with. Every manager I’ve thrived with has had an identifiable (if not clearly defined) set of principles they operated under. Principles are wonderful things, that both make life easier by giving you a scaffold to navigate challenges and signal your values to others.

But they only help if you use them. If you or your organization is allowing decisions inconsistent with your principles, that’s possibly a major warning sign — but I think it’s more likely a sign decisions are being made too quickly, without a process that aims to properly assess options.

Don’t make decisions on autopilot. Principles are useless if you’re not actively holding them up as a litmus test to see which path actually serves you best.

Self-Organizing Teams Need a Gardener

The position of managing a self-organized team is a tricky one, and not many individuals promoted to management are suited for it. The traditional management candidate earns their stripes by being good at the technical task they are supposed to supervise, which does make a certain amount of sense. But the catch is a self-organizing team isn’t looking for a technical expert to tell them what to do; they’re looking for someone to block problems, provide insight, provide air cover, and maintain balance in the garden.

The manager on a team where there’s technically no need for one does what good managers on traditional teams have done for decades: they provide a vision of where to go, provide insight on how the journey is progressing, and remove problems as they appear in the path.

Teams as a Garden

The ol’ command-and-control model of teams and leadership is built on the idea that any butt in a seat, combined with enough other butts in other seats, can accomplish a task well. This thinking somehow survived into the 21st century, and is somehow getting a revival of sorts as the “return to the office” debate heats up. (It’s almost like a generation of decision makers has refused to either adapt with the times or get out of the way, but that will eventually resolve itself).

These days, it very much matters who is in what role, and how they interact with their other teammates. The GM of the Wendy’s I described in the last post described herself as a gardener: “I have to decide who to plant, where in the garden they’ll thrive, and do a little weeding and pruning to make sure everyone gets enough sunlight.” Jim Collins in Good To Great talked about getting the right people on the bus, and then finding the right seats for those people.

A team within a larger organization that has a budget, cannot be truly self-managing. The next best thing is a manager who views the team as a garden to be tended.

Maintaining Perspective

The manager’s role in a self-organized environment is largely about pointing things out.

  • “Was everyone aware there was a velocity drop last sprint?”
  • “The client had some specific notes from last demo…”
  • “Maybe this isn’t a fair conclusion, but it seems like pull requests are taking a long time to get reviewed.”
  • “I’m seeing a lot of work in progress that doesn’t seem to align with our sprint goals…”

When being trained to manage a Wendy’s in the mid 2000’s, the actual position assigned to the manager in charge was called the “Operations Leader.” (I have no idea if this approach survived the buyout that washed away so much of the Wendy’s Dave Thomas built). This was a change from the old way, where a manager worked in a position like sandwiches or fries and called the shots from there. It was like shifting from the player-manager arrangement baseball had early in the 20th century, to the modern “managing is a full time job” approach.

Not being tied to a position, being constantly on the move observing the restaurant operation, allowed the manager to see things like a slow moving front line. Or an over-full trash can. It allowed them to run to the back for more $1’s without hurting the flow of the team. I was taught that if I needed to step into a position, I needed to know how I was getting out of it — “I’m covering fries till Juan gets back from his break” or “I’m going to step in and help fill the grill with meat.”

The manager on a software team likewise isn’t heads-down writing code; they’re looking around, observing. They’re connecting with the client or the stakeholder. They’re digging into metrics. This gives them a wider perspective and more detailed context than most of the team who are writing code or similar tasks. From time to time, they dive in to pair with someone, or to take a quick look at some tricky problem. They’re uniquely positioned to reflect the performance of the team back to the team.

Maintaining Momentum

In a perfect world, this reflection should be enough to get the team started on either a solution or an explanation (as much as a senior leader might like an action plan when velocity dips, sometimes it can’t be helped). But we’ve all been in that meeting where everyone understands the problem but nothing seems to push the group towards decision mode.

This is where the manager needs to start asking some pointed questions.

  • “So I’m hearing this card isn’t needed — can we remove it?”
  • “Is the root cause of this bug in the data layer or the data itself?”
  • “I have to give George something…based on our velocity trend, can we do this in the current sprint?”
  • “Does this implementation work? Can we merge it now and add enhancements to the backlog?”

As the “ops leader,” keeping customers flowing through the lines is the primary goal. Sometimes a register operator is lingering a little too long chatting with a regular instead of getting the next order. Sometimes the grill operator is a little too focused on aligning the meat in perfect rows. Friendliness and attention to detail are excellent qualities we all want to see in people, but without the benefit of the wider perspective it can be hard to tell if we’re going overboard.

Even the most disciplined software creator will charge off into the weeds from time to time, and very few of them think deadlines or estimates are things intelligent folks deal in. By bringing their experience and perspective on the entire project to bear, and helping the team understand the big picture a skilled manager can be the difference between success and failure on a project.

The manager is also in a unique position to be the “first follower” of a suggested action, and thus break deadlocks or violent agreement. And if all else fails–and I mean, really fails–sometimes it’s the manager who needs to make the decision.

Maintaining Balance

Building teams out of individuals with different backgrounds and experience levels is challenging. Expecting them to just work together to accomplish common goals with limited direction is an extra layer on top of that. We can’t find a better example of this than the Wendy’s lunch team: high schoolers in an occupational intervention program, immigrants, retirees, college students, and occasionally a full adult training to be an assistant or general manager. One does not simply plop this group onto a restaurant floor and watch them work together in perfect harmony. This garden needed cultivating.

Management:

  • Hired for people who could play well with others
  • Got to know the team, and learned what different people valued
  • Observed interactions on the line and made note of good and bad matchups
  • Intervened with bad performance

Rather than thinking about the number of full-time equivalents they needed to hire, the folks at this Wendy’s thought about the skill and personality gaps. They were hiring for someone who could keep up with Janet, for someone who could be patient with Juan’s broken English. They were careful to not upset the harmony of their team by introducing someone who was obviously not going to be able to mesh with the rest.

This didn’t always lead to happily-ever-after, because people are people. So management learned that Janet and Teresa just didn’t get along, and it’d be silly to position them to work together. They discovered that Juan and Ricky apparently could read each others’ minds, and tried not to separate them.

They also took steps to support people who were really struggling, to eliminate an excessive burden on the rest of the team. A manager pairing with someone till they got the hang of things on fries, or giving direct feedback on how to improve saved resentful and friction among the team and let them just work.

In a worst case scenario, when we discovered that George had certain prejudices against immigrants he wasn’t willing to rethink…well, this is a capitalist society, and most teams (even self-organizing ones) can’t just eject people. That too fell to the manager to handle.

TL/DR:

The manager does the hard work of protecting the team. From outsiders, by way of handling senior management and careful selection of new additions, and from itself by way of monitoring and nudging members towards better performance. They also are charged with doing the hard work when someone is struggling to sync with the team and with being the bad guy in situations where someone won’t.

The manager on a team where there’s technically no need for one does what good managers on traditional teams have done for decades: they provide a vision of where to go, provide insight on how the journey is progressing, and remove problems as they appear in the path.

Self-Organizing Teams Are Teams of Leaders

I am a huge fan of a self-organizing team. I picked up this quirk long before I ever wrote a line of code — we’re talking at 17, working the lunch rush at a Wendy’s. The organized chaos of of the front counter is a thrilling thing to experience; two registers constantly loading up 2 orders each, a sandwich maker and grill cook working a choreographed dance to keep fresh beef and chicken flowing to warm buns, runners filling drinks as they call out for a Biggie fry. And…no manager.

The manager was there, obviously. Or more accurately, they were nearby. Observing the flow, looking for disruptions. Pulling the angry customer aside. Bringing up a sleeve of cups to make sure no one had to leave their post. Wendy’s went so far as to rename the position the manager had as the “operations leader” in order to rewire the company’s thinking. The manager didn’t direct the action, they weren’t a star player on the field — they were a coach, a strategist, a scout. You stayed on the sidelines, let the crew do their job, and jumped in to deal with problems as they arose.

Sure, if a register operator wasn’t asking anyone to “Biggie-size” their combo, the manager over-hearing this would remind them of procedure. But they weren’t sitting in the middle of the kitchen, directing everyone’s movement. Each member of that team understood their job and just did it. They would react to the feedback provided by the manager — “We have another 10 cars in the drive thru line” or “The void percent is getting high.”

Non-Manager Leadership

Looking back, the lunch crew wasn’t just a collection of A+ professionals executing as some amazing hive-mind. When I was started on being a runner, I theoretically knew everything I needed to do–how to fill the cups with ice, what the codes on the screen meant, where to stage trays, how to pack a to-go bag. But Jackie had been doing this job, with and without runners, for five years. She had a mindboggling wealth of experience, and fortunately was willing to share it.

“Don’t wait to get the chili on this order — it’s the only thing you need till the sandwich comes up, and you can use that time to make the drinks for this couple on the next order.”

“Okay, see those four construction workers that just walked in? Just call out the four Biggie fries now so Juan knows he needs to drop more.”

“Didn’t you see we just refilled that iced tea? It’s too hot–see if drive thru will get you one so it won’t water down as much.”

The same thing happened with everyone else — sandwich makers who would tell me how I could help them go faster, or suggest things I can do to finish the order while they were running behind. The folks on the fry station who would direct me to scoop my own fries while they dropped more into the fryer. A hundred or more little suggestions or directions in the course of a two and a half hour rush shift. Almost none of them coming from a manager.

Gradually, I began to be the person giving those directions. “Just set up a new tray every time, don’t bother waiting till they tell you it’s to-go or not.” “Hey Juan, I see about 8 people heading inside!” “Janet, the group that loves grilled chicken is here, do we have enough up?”

There wasn’t a diminished leadership presence because of the manager being removed to a more strategic role, there was an increased in localized leadership. People who understood the immediate needs spurred their peers in the right direction, helped to avoid mistakes, and provided praise for the little-but-crucial things done well that would never warrant attention from management with their eyes on the big picture.

The Software Tie-In

There’s really not much difference between a software team and a fast food team. In fact, I’d say the primary success metric is the same for both teams: how often can you deliver customized, completed work to the customer?

In-before-derisive-comments-about-“burgerflippers:” All jobs boil down to a series of steps to be followed. Mastery of a role boils down to understanding how those steps can and should be adapted in the face of rare or new situations. Is mastery in running a fry station an easier goal than mastery in writing data layer logic? Based on my experience, it’s impossible to tell — both roles have plenty of people who want to achieve mastery, and both have plenty who just phone it in.

An incorrect order (a burger instead of a chicken sandwich, for instance) is a lot like a bug. And just like a bad software team that treats bugs as part of the process, a bad Wendy’s has adapted to remaking orders after the customer complains. A good Wendy’s (or software) team is horrified every time they make a mistake that reaches the customer — and works together to avoid the mistake in the first place. They aren’t just winging it, assuming “If I’m doing this incorrectly the manager will stop me.” And they aren’t letting their peers do that either.

A self-organizing software team is a group of professionals who are comfortable enough in their own skills and their place on the team to provide leadership when it is appropriate. If Jane sees a security gap in some code Bob worked on, she’s able to constructively point it out and help resolve it. If there’s a pipeline problem creating a bottleneck, no one waits for management to authorize fixing it — Mia just pops open the YAML file and fixes it. If there’s missing test coverage around a critical flow, Linda doesn’t need to get management’s permission to address it with Tyler before it gets merged. If all of these interactions had to flow through a single point of authority they’d just outsource the whole team within 6 months.

So what IS the manager’s role if everyone’s a leader? Let me get into that next time, since I’m willing to bet not many of you read even this far.

The Code, the Acceptance Criteria, and Does Anything Else Really Matter?

Somewhere along the line, I think software creators got a reputation for being insanely smart. This is valid, largely accurate, and totally okay.

Also somewhere along that journey, some organizations decided that since software creators are so smart, software creators didn’t need specific instructions. General goals for a user story would suffice.

Also also somewhere along the way, some other organizations realized that smart people get their own ideas. Often, those ideas often weren’t what management or the client wanted, so those organizations use all the character limits and fields included in the card program to define user stories. Down to the method names to be created.

Two extremes, staring desperately at each other across a gulch. A gulch full of software creators from both sides who have hurled themselves into the abyss after realizing they can never actually deliver what’s required because of terrible systems.

Definition of Done

I think part of the problem is the vocabulary, and how there’s somehow multiple sorta conflicting definitions of what a “requirement” is, and “acceptance criteria” similarly can mean different things to different groups at different parts of the cycle. What every piece of work actually needs is a definition of what “done” looks like — how do you know this goal is finished?

When I set out to hike a trail, I know when I’m done. Even on a interconnected set of trails in a national or state park, I know that when I get to the overlook, or loop back to the start, or reach the fork right before the bridge, that’s the end of the hike. It should be the same way with picking up a card — “Go for a hike” as a title with nothing else to go on is a terrible definition of done, and so is

  • Wear the Walmart boots, not the Bean boots
  • Drive your spouse’s car
  • Head East out of your neighborhood
  • Drive I-71 North to exit 183
  • Find the Notch Valley Trail Head parking lot
  • Park in the shade
    • etc etc…

Software creators are smart individuals who have been trained in the art of solving problems. If you give them a solution to implement, at best they will be bored and THAT is never a good thing. If you give them a poorly defined problem they’re going to fill in the blanks, which can lead to an implementation that isn’t actually useful in the wider roadmap.

Define the Problem in Sufficient Detail

The goal of a card should be to define the problem being solved. Be it a value story, a list of behaviors the software should have, a self explanatory wireframe showing what it should look like at the end, or ideally a combination of all that. If there are technical concerns — say, a specific database that needs to be involved or a security concerns to be considered — that should also live somewhere in the card.

You don’t want to be prescriptive on a solution before anyone’s started to pull back the curtain and started work on the card — what makes sense during a discussion with a product owner, backlog refinement or sprint planning might not make sense in practice. If the card is so specific one has to prove it wrong before they can do the work, that’s all bad.

But leaving it completely open ended is also a recipe for a terrible demo. Most software creators won’t have been in the meeting where the requirements were discussed with the client or product owner… meaning their solution to a minimalist prompt and it’s behavior might be absolutely inappropriate in the wider context.

TL/DR:

The goal in writing a card should be to put everything in it necessary for any member of the team to read it, maybe ask a couple clarifying questions, and come up with an implementation plan. The goal shouldn’t be to hand them an implementation plan. It should not be to create a cryptic post-it note reminder with a single sentence fragment. The card should resemble (in written form, obvi) that scene in “Apollo 13” after everything goes sideways: Gene Krantz first defining, and then telling the team to work the problem.

A Love Letter to Automated Testing — As a Tool for Quality

I think automated testing, particularly automated unit testing, is a misunderstood creature. Every time I run into a “Do we write tests or do we not?” discussion in the wild, the focus is around the confidence tests give one about the functionality of the code. People in favor of tests generally argue about how you gain higher confidence about how well the code functions, and people counter that with their existing approaches like QA or the fact that their management accepts bugs as part of the process.

For me, that confidence boost isn’t the point; it’s a nice result, a by-product of the real advantage. It’s like scallions on my baked potato, or the sauteed onions on my steak, or the whipped cream on my sundae. Yes, I relish those things and they give me the extra hit of dopamine that makes me feel I have to have them…but I don’t skip the potato because I only have sour cream, and I definitely don’t refuse ice cream because there’s no toppings. The garnish is just the obvious benefit to the dish, the same way the “Confidence it will work” is the crouton on the testing salad.

Valuable tests are more than logic validators. They enforce sane engineering practices, expose complexity, put a fan behind code smells, and provide documentation that will be up-to-date as long as people are running the test suite. In short, automated tests are a way to avoid poor Quality code.

Tests Help Avoid Poor Quality Code

Quick qualifier here -- working code is good code, but we all know Quality code when we're in it. Yes, I'm stealing applying concepts from Pirsig again.

Poor Quality code is difficult to test. Sometimes so difficult it’s not worth it, like an abandoned copper mine that still has plenty of ore… but it’d take an investment many times over market price to extract it safely. For me, I can use the ease of writing a test to tell me a lot about the architecture, patterns, and configuration of the codebase. It’s the quickest way to identify challenges I’m going to face.

  • “Oh. This method is new-ing up a dependency in-line. That’s…that’s going to be hard to mock.”
  • “So part of the constructor on this service class is… calling out to a 3rd party API for part of it’s configuration?”
  • “Wait. The controller is making a call directly to DatabaseA, so it can use the return to make a call to a service class that talks to DatabaseB?”

All things I’ve run into trying to write what I thought would be quick tests around legacy code, moving roughly from easiest to fix to most difficult. If you never write tests, and the app worked correctly right off the bat, and you never need to change the functionality, none of these things are problems, per se. But when was the last time you had an application go into prod without a problem? How many stakeholders have you met whose requirements are written in stone?

When I worked at a home improvement retailer, one of my jobs was to cut wood to size for customers. I was taught by a retired carpenter-turned-retailer to measure on the saw where the piece of wood would be once it was cut, then clamp scrap wood there. This gave me a guide to know when the 2×4 was cut correctly without too much conscience effort, and also prevented me from cutting too much.

For me, writing a test is a lot like clamping that scrap into place. The test is a fixed goal to hit, and you know without question and without thinking about it while you’re coding if you’ve hit it or not. If tests are failing (and that includes refusing to compile or build), the code isn’t right. Could I cut 2x4s by measuring each 18 inch length out individually? Yes, but it’s harder than just cutting till I can’t reach the scrap anymore. Could I write that class to cover all the use cases without a test for each one? Probably, but it’s definitely going to be harder.

I write tests because they force me to think about the problem, to break it down to testable pieces, and figure out how to keep it testable. I’m not trying to combine the “what” and “how” in the same thought. Tests also force me to implement that code in a way that is testable –and testable code is (typically) easy to change, easy to diagnose, easy to plug into different use cases.

Documentation

The beauty of arrange/act/assert, especially in an xUnit style test with a minimum of shared setup, is each test is explicit about how the system under test behaves under different conditions. If you’re confirming that a specific result happens based on configuration, you have to put that value in the test. If the data context has to return a specific value, you have to specify it in the test where it’s visible to anyone.

Which means that a year from now, when you need to update a switch statement — you already know what all the values correspond to, without looking up the requirements doc from two projects ago. You won’t need to spend as much time explaining the code to someone — the tests lay it all out, in all the variability. The dependencies are documented, the expected behavior of dependencies is laid out.

Recently (and this has happened more than a few times) I went to the tests as the first stop in a bug squash. I quickly realized that none of the tests covered the scenario where the main dependency throws a null reference exception; as a result, the code was just logging the exception and returning an inappropriate value. I was able to write a test that replicated the situation, and then put a bug fix in without ever actually debugging the app.

Having up-to-date tests is like having up-to-date documentation. You don’t need to debug the application to figure out what it’s doing under the hood, you already know by following the story told by the tests.

And When Coupled With Test Driving…

So all of that above is primarily based on experiences I’ve had trying to wrap legacy code, and it boils down to “Tests help me understand the code so I can improve it safely.”

But…what if you were able to avoid the whole “this needs redesigned before we can add the feature” part? What if I told you there was a way to build that same quality into your code, right from the start?

This is the obligatory TDD plug. I don’t want to harp on it — I love TDD, and even I can’t stand most of the TDD missionaries out there — but again, I view the tests the same way I view configuring the IDE, using git aliases, customizing my PowerShell profile, using Resharper. It’s a tool that allows me to work with the code in a way that drives Quality. Writing a test for an empty service class is going to keep the problem I’m trying to solve very small. And if I’m trying to solve a small problem by “using the the least amount of code to make the test pass,” I’m far less likely to over-engineer a situation. This keeps my code lightweight, flexible, and simple.

As the problems become more complicated, in the “Only update the database if these 3 conditions are true and also it’s Tuesday” vein, so does my code…but incrementally, and in a way that doesn’t break previous passing tests. I’m already avoiding regressions and we’ve never deployed this code. My code is only as complex as it needs to be (if I stay disciplined), and the fewer moving parts the fewer things that can spawn bugs.

Tests, whether before or after writing your prod code, are going to drive Quality. I just prefer to be efficient and find out I’m making a mess before I commit any changes.

Wrapping It All Up

I’ve worked in shops with no automated tests. I’ve worked in TDD shops. I’ve worked in shops that half-assed testing. I’ve learned you do not need tests to write and change working code, but that tests make the job infinitely easier. And when delivering software isn’t an absolute struggle, I write far better code.

Code that can’t be tested without a lot of work is smelly. Writing tests in that case is like opening the refridgerator door — without opening that door you never smell the fact that last week’s leftovers are ready for the trash. Tests, if nothing else, tell the story of how your code is supposed to function — far better than writing a README or walking someone through the entire application.

These two items are the things I’ve come to appreciate about automated tests far more than the pat “I know the code works because tests.”

Blog at WordPress.com.

Up ↑