So much of our “ship fast” culture is based around end-user application development, where it’s a reasonable and defensible approach.
But the further away you go from end users toward libraries, then internal services, then even further toward infrastructure, the slower and more thoughtfully you should move. These things often have far less rapidly changing requirements, and getting it right pays dividends. Or more realistically, blasting something half-baked out results in drag on your organization that you end up having to support for forever.
On a slightly different axis, APIs should be built with more thought and care than internal implementations. Backward-incompatible API changes are hard. So start out by building an API that expresses the logic your consumers want to implement. README-driven development works great here: literally write the README that showcases how people would use your API to do a variety of tasks. Then you can iterate as many times as necessary on the code, while having to iterate on the exposed surface area far less than if you just exposed today’s internals as the API (which is sadly the norm).
This, exactly. Rapid iteration on user control surfaces is good; rapid iteration on public APIs is bad.
Edit to say — rapid iteration of UX is good as long as it’s goal-aligned and has an endpoint. Set a goal, iterate and measure until you achieve it, then leave it alone.
"Rapid iteration on user control surfaces is good; rapid iteration on public APIs is bad."
I think rapid UI iteration is bad once a product has reached a certain maturity. I absolutely hate it when a tool I use often, suddenly changes its interface without any discernible benefit. I am fine with yearly changes but the constant churn is really annoying. MS Teams is a big offender here. They constantly change stuff but nothing gets better, just different. And a lot of UX guys seem to feel it's best to take away features that only a few percent of users are using.
Compared to the progress we made in 1990s and 2000s, it feels like most companies are just moving buttons around and making UI elements more difficult to distinguish but otherwise they are out of ideas for actually useful stuff.
I can't think of a UI/UX iteration in the last 10+ years that felt like an upgrade.
Reddit, Gmail, Twitter, Windows, Android, touch screens replacing actual buttons, etc. they all used to be better but big companies seemingly can't help themselves from making their product worse.
Yes, please leave it alone. Nothing prompts me to leave a service I've been with for a long time than a UX "refresh" after I had years of experience and setting everything the way I liked it.
I think this is such an interesting issue. On one hand as a system developer, you want to keep existing customers happy with what they are used to. On the other- you want to grow and acquire new ones which requires upgrades to existing processes till you reach a limit - you need a new ui/ux. And what do you do? Maintain N versions?
The problem, as usual, stems from businesses prioritizing growth above all things (including the existing customers). There's absolutely nothing wrong with having a stable business that turns a respectable profit, but modern day American business culture is allergic to the idea.
> even further toward infrastructure, the slower and more thoughtfully you should move. These things often have far less rapidly changing requirements
I used to think that, until I worked on my first large scale system, infra heavy. It turns out it works both ways.
If changing infra is hard, slow, painful and risky, people will be less inclined to do so. If changing infra is fast, easy, and with low risk, people will be much more inclined to change things.
Even if you had very stable requirements (doubtful in this day and age), I see no reason why you wouldn't build your system in a way that is easy and safe to change, for the day when it's needed.
You should still ship early and ship off in with infrastructure projects, but the changes you're going to make are going to be a lot smaller, and the big ones are going to be planned far in advance. You will still need big changes, and even your small changes require subjectively "more" thought.
Both things are true: you should move slower and more thoughtfully on infrastructure projects, and "ship often" is still valuable advice and a worthwhile goal
I don’t disagree at all, but I want to be clear that my point is more about upfront thoughtfulness and less about continual ability to iterate.
Being careful upfront often increases your ability to iterate rapidly because you aren’t constantly dealing with the consequences of poor early decisionmaking that causes calcification.
Hard disagree. The system I'm talking about is the largest scale system I've worked with (millions of QPS, thousands of servers). We built it in such a way that we were able to rewrite entire parts of our stack easily and relatively safely. The techniques and tools to do it are widely available today.
Good for you. Modular programming goes a long way, of course, but I'd say that your changes were then those that could be foreseen, for example by drawing the right modular boundaries from the start.
Mjeah. It is our goal at work to enable our teams to deploy changes to their systems in production within minutes. And this works and the teams utilizing it get commended for it.
But I also need to plan and execute a major database upgrade with ~250 applications depending on it. I will be very happy if I can have a solid, generally accepted plan in a month or two. It will just take 1-2 person-days to eventually execute the updates, but it will take 6 - 12 months to get there. And from what I hear from colleagues and customers, that's fast.
Great, butmy end users don't live in fast internet range. every few months they spend some time in 2g cell range. upgrades mean mailing a usb drive. we have to get quality right as fixes cannot be rolled out fast.
TDD is trying to accomplish the same thing. Here’s the shape of the thing, now make it work. But maybe we should just be writing the manual first. Though I would say we need something akin to “code coverage” in that doc, even if it’s just QA changing the font color of every line that is now true from red to black, so you know where the gaps still are.
Sort of, but sometimes I feel like TDD approaches the forest by making each tree first one by one.
I really like writing a usage README first, since I don’t have to make anything work along any axis yet but I can play freely with the shape of things, figure out how to make the whole thing consistent, and experiment on what boundaries it makes sense to break components apart so they can be mixed and matched.
This does require a decent amount of engineering experience to both figure out what your consumers really need and also to design something that is actually implementable.
We are doing this weird zigzag of a gradient descent because we know that things are bad, but we don’t know exactly how they are bad. We don’t know exactly which direction is “downhill” and which is “uphill”, so we turn around and head somewhere in a 120° code of where we think is the opposite direction. But it’s not the right thing, it just has some of the opposite qualities of the wrong thing.
It’s better than post-disaster politics, where “something must be done, this is something, so we shall do it” but it has an aftertaste of that same sentiment, if that makes sense.
But the further away you go from end users toward libraries, then internal services, then even further toward infrastructure, the slower and more thoughtfully you should move. These things often have far less rapidly changing requirements, and getting it right pays dividends. Or more realistically, blasting something half-baked out results in drag on your organization that you end up having to support for forever.
On a slightly different axis, APIs should be built with more thought and care than internal implementations. Backward-incompatible API changes are hard. So start out by building an API that expresses the logic your consumers want to implement. README-driven development works great here: literally write the README that showcases how people would use your API to do a variety of tasks. Then you can iterate as many times as necessary on the code, while having to iterate on the exposed surface area far less than if you just exposed today’s internals as the API (which is sadly the norm).