The Roads Approach

The Roads Approach

It’s normal for engineers to think of the best solution possible when we think of solutions. A bad engineer would deliver as fast as possible without even considering whether his work is good enough or right. A “good” engineer would think a lot about how to do it and be very slow. A great engineer does both things. So, how can you be fast and slow at the same time? When we are working on a pretty small problem, or in a green field(a new project where you can do whatever you want), and/or a small company or startup with very little software. We all want to have success, and we want companies to thrive; success means more software, and more software often means more technical debt, and it becomes impossible to change everything all the time.

Missing the point: Quality

If, as an engineer, you get a task and get rid of it as fast as possible(you get it done), how can that be bad? Well, it depends, but it could easily be shallow work, because when we are doing it fast without quality in mind, we can easily be missing several aspects of proper quality, for instance:

  • Are we doing the right thing? Is this what the business needs? Is this really useful for the users? Is this the right solution? As engineers, we often assume “Discovery” was done right, but is it really the case at all times? Even if discovery is right and the need is real, how do we know we actually doing the best thing possible?
  • Are we doing things right? By doing it right, I mean, did we perform proper research? Did we read about the problem space? Did we read the papers? Did we research the problem space? Did we figure out what the industry is doing? Do we know the patterns and anti-patterns? Do we have proper architecture, design, testing, configuration, automation, observability, and all aspects of a proper deep solution? Are we?
  • Do we understand the context? We are always delivering software, but do we deliver the same software at all times? Even on the same projects, some tasks have different natures. Kanban captures this very well, but Scrum is not so well (to be nice). There are many categories, but let’s just consider two for now. Let’s say in one kind of task the software is already know and will be used for many years, in that case we do the best we can do add as much quality as possible. Now imagine something else, what if we don’t know if it will be used for years? What if we only know if we put in prod. How much quality should we put in this case? Many engineers think that this only happens if we consider startups vs big tech companies or enterprises. However even in a big company is possible to have “startup moments” where you are building a new project and you don’t fully know what you are doing. In that case, should you go all in with quality day 1?

The bottom line is that we can fail by doing under-quality work or doing a poor job for something that should have much more quality. However, we also can fail by over-quality and adding too much quality for something that might die soon, or we might pivot in a very different direction.

Do not be cynical. Do not use this as an excuse to always do a poor-quality job and do less because you are “discovery optimized.” Instead, do better, understand the context, and ask questions. Have better awareness.

Missing the point: Timing

Timing is interesting. IF you don’t deliver, you are dead. Engineers often get fired for lack of delivery. Not delivering is fatal. There is no option; delivery always needs to happen. The more senior you are, the more you make, and the more expectations there are under you to deliver. Do not fool yourself you need to deliver. Frequently.

Timing is essential for companies because there is competition; those who can figureout things fast learn faster and deliver better solutions for users win. So speed is a competitive factor. However, delivering crap solutions fast has the opposite effect; it might destroy your brand.

The thing with timing is that you must know how to “master” it. You need to have a balance between quality and delivery. Usually, people think they have quality or speed but need both. You need to learn how to master multiple timings because there is nothing as just “one time.” For instance:

  • Personal Time: You manage yourself and how fast or slow you will take to deliver something. IF you are slow, did you accept your speed, or are you trying to improve it? Do you measure your time? Do you know expectations under you?
  • Dependencies Time:When engineers do tasks, they often just think about their work. However we always have dependencies, did you consider: Other downstream dependencies time? Infrastructure or security dependencies time? Approvals time? All the technology you want to use can be used?
  • Traps Time: Do you know all the traps you have in place up to front? Do you know all the things that will slow you down? Do you know if what you need to do is possible? Do you know if you will struggle with technical debt? Do you know if you will be blocked by binary coupling?

The best approach is to figure out this before starting the work. That way, you master time and have a lot more chance to be correct in your predictions. What you do not want to do is get stuck in a low delivery or no delivery cycle, which will lead to bad things like losing your task, being sent to another engineer, or you will lose credit, people will stop believing in you, or worse, you will be fired for lack of delivery.

When changing jobs or starting in a new company, people underestimate the time they will need to learn about the latest “environment” and new “systems” and where the “tech debt is” and how to be effective with it.

Often engineers don’t know how critical things are for the business, holding suck critical things without delivery is a very bad idea. All these incentives might make you think it’s impossible to have proper quality, but that is not true, we can have quality. Because I explain how fix this, let’s understand the next dimension: Scale.

Missing the point: Scale

IF your plus one, ask you to go to the supermarket and buy potatoes. How many potatoes do you bring home? Here are some options:

  • None = Bad Idea
  • 1..10 = Reasonable right?
  • 1k? too much?
  • 1M potatoes? Crazy?

Well, I think you got the idea already; probably, for your plus one, 1.10 is fine, but when we do something in companies, we always need to ask this question: what is the scale we are dealing with. Because doing a full scan in a 10-row table is one thing, doing a full scam on a 100-TB table is very different. What scale do we assume?

Scale has another interesting aspect: when it will happen. Do you have 10 million users now, or will you have them in 6 months or 1 year? Some businesses are very wild, and you cannot control how fast or slow they grow; others are much more predictable. The non-obvious thing here is that building software for one user is one thing; you might vibe code it(LOL), but building for 100M is very different. So, the scale influences the quality a great deal. Do not be cynical and build the worst solution possible. However, also, do not assume you need all things right now.

Boiling the Ocean

You probably heard the phrase: “Don’t try to boil the ocean”. I had to confess something. I listened to this phrase as an execution to do hard things, but because when it is used as a poor excuse, I think there is an important point behind it.

If your company is successful, you have a lot of software. At scale, there is usually a lot of software, and there is technical debt. It’s normal. However, having problems is not an excuse not to improve. We should always be able to work to improve. Now, with a lot of software, it is impossible to re-write all the software all the time. It’s possible to refactor a lot all the time, but not re-architecture and re-write all at all the time. It’s impossible to boil the entire ocean, but we can boil water all the time. The hidden truth here is that we need delivery. We can think, diagram, and debate, but we need to deliver. To deliver, you need to make some compromises; changes need to be phased.

What If is not an ocean?

This is the equivalent of “Don’t be cynical.” Yes, we can’t boil the ocean. However, refactoring still needs to happen every day. We do refactor every day, but we don’t refactor ALL the code every day. Unless you are working on something very well.

The Roads Approach

In the 2000s, an XP group in Italy developed this concept, which I’ve been using for a long time. The idea is that quality is dimensional. Another way to see it is that we don’t build the ocean; we eat the cake, and we have the cake.

We can think and even diagram a “asphalt highway” solution but we do not deliver that. We deliver a dirty road. A dirty road sucks. It is full of dirt, and very few cars can pass that. Eventually, they will get stuck, but the chances of you not delivering that are very low.

After delivery of the dirty road, if you need, we can evolve to the “cobblestone road,” which is much better and has limitations; it’s very wobbly and can’t host F1 cars there. But depending on the volume of vehicles passing there yearly, you might be fine and stop there.

Now, if still required, we would evolve to the highway. Remeber, Facebook started with PHP and Twitter with Ruby. Later on with need Twitter migrated to Scala but was not on day 1. So the roads are a way to reduce risk, deploy in production fast, learn and improve the quality, and always do refactoring but in phases, in waves like in the ocean where waves come in groups of 3 weaves.

Using the road approach, we can eat the cake and have the cake; we can be FAST and SLOW simultaneously. We are fast because we always deliver and improve quality via refactorings and better architecture evolution. We are slow because we have time to think about the highway while delivering inferior roads. I’ve been using Roads Approaches for decades, and I teach it to many customers. I can vouch that it is very effective and works well. Give it a try.

How to do Better?

OK. In case I used too many metaphors, here is a list of practical things you can do to make it better, deliver more, think better, and do more sophisticated and dirty solutions.

  • Always delivery, do PRs every week.
  • 2 weeks without delivery is BAD; anything more than that is RED FLAG.
  • Limit how much you think at once; think for 2 days and a max of 1 week.
  • Get things done, and think about how you can get into production faster and what you can simplify?
  • Write ideas in the wiki and use diagrams.
  • Document the problem, and focus more on the problem space.
  • Write 2–5 different solutions in diagrams.
  • Do not deliver all modernization at once, break it into phase, 3–5 phases is great.
  • Ask questions to know the Scale, do math to simulate impact.
  • Ask questions to understand the “moment,” how much you discovered, and how much you have yet to discover (37 Signals uphill charts are great for that).
  • Socialize and ask other engineers and architects for opinions.
  • Think, Deliver, Deliver, Think, Deliver, Think, Deliver, Deliver.
  • Avoid Analysis paralysis of “just” thinking and no delivery.
  • Start with the contracts so you can unblock the upstream teams.
  • Make sure you know the traps; sometimes, it could be tech debt you are not aware of; other times, it could be security you don’t understand; and other times, it could be tech debt blocking refactorings.
  • Use more experienced architects, ask questions, and do not be alone.
  • Do small POCs to figure out things.
  • Think outside of the box. Sometimes, the problem is the solution.
  • Deliver value continuously, do refactoring continuously, and always deliver.
  • Work in phases, and don’t boil the ocean.
  • Don’t be cynical. Do not accept the status quo; change it little by little.

Principles of Software Architecture Modernization is full of examples, principles, and techniques on how to deal with monoliths and distributed monoliths at Scale. Continuous Modernization covers the mindset, practices, and shift to better work data with teams dealing with such systems.

Originally published at https://diego-pacheco.blogspot.com on March 23, 2025.

Leandro Iglezias

Software Engineer at LNAIX

2 天前

The roads approach it's very good example to think we can delivery and improvement constantly?

要查看或添加评论,请登录

Diego Pacheco的更多文章

  • The Dark Side of LLMs: part 2

    The Dark Side of LLMs: part 2

    July 2024: I wrote the first blog post about The Dark Side of LLMs. During these 7 months, many things have changed;…

  • The Monk and The Rockstar

    The Monk and The Rockstar

    I have been doing practical and real software architecture for more than 20+ years. Software architecture is a great…

    4 条评论
  • The Issue with Feedbacks

    The Issue with Feedbacks

    I love feedback. I believe in feedback a lot.

  • Quality Needs to be Managed

    Quality Needs to be Managed

    Quality often means something different to each person. My definition of quality revolves around technical excellence.

  • State

    State

    If you look up on dictionary.com the first two definitions of state are: 1.

  • Leaky Contracts

    Leaky Contracts

    Service contract design is hard. People do it all the time, but it is not always correct.

    2 条评论
  • Services

    Services

    We are in the holiday season. You walk into any Starbucks and see the Christmas decorations.

  • Proprietary Systems and Distributed Monoliths

    Proprietary Systems and Distributed Monoliths

    Distributed Monoliths are the predominant form of modern legacy systems. Sometimes distributed monoliths are created by…

  • Functional Programming

    Functional Programming

    There are many programming languages. Most of them are based on C.

    1 条评论
  • Proper Error Handling

    Proper Error Handling

    No matter what programming languages you use. Engineers need to make dozens to hundreds of small decisions every day.