Let's go back in time. A few years ago, I started a project and immediately reached for Bootstrap. I added it to my asset bundle and got to work.
I started writing HTML and sprinkling Bootstrap classes on every element. Before long, I had a handful of views tightly coupled to Bootstrap. I was dependent on it. Being dependent on something isn't necessarily a bad thing. After all, Bootstrap has helped push forward tens of thousands of applications on the internet.
However, there's a problem. I started using Bootstrap before I needed it. Did I need to pick a frontend framework immediately? No. Guess what? Now I'm stuck with it. Unless I want to carefully edit all of my templates or slowly reduce Bootstrap usage to zero, I'm basically stuck using Bootstrap until the end of this application's life.
Why wait to make decisions
Picking Bootstrap was one of a handful of decisions I made immediately upon the project starting. Worse yet, picking Bootstrap was a non-critical decision turned critical.
In other words, Bootstrap is not a core function of the application. It doesn't run business logic. It doesn't perform key functions of the critical work to be done. However, by making Bootstrap an early dependency, it's now key to the frontend. If I compulsively remove it, the frontend turns into a mess.
Questions like "Should I use React?" and "What CSS framework should I include?" can be left unanswered for awhile. Otherwise, you risk adopting a dependency before it's truly needed.
Benefits of delaying decisions
One way to help you skip decisions about the frontend is to write tests. Without tests, we're kind've forced to build a minimal frontend to verify our work. When you have to build a frontend, you're tempted to reach for dependencies you might not need.
Starting with tests for business logic can help us avoid the need of a frontend. Instead of using the frontend to verify work, we can run our test suite.
Let's say we're building the comment feature on dev.to. We want to notify the author when a new comment is posted. Without tests, we might create a new post, add a new comment, then check the author's notifications. That might require us to write a large amount of frontend code. It's possible we'd be making a number of decisions before we have a ton of knowledge about it.
If we jump the gun and use React for all of this, we might be stuck with it. We might realize later we didn't really need it, but who wants to go back and rebuild what's already built?
With tests, the story changes. We can ignore the frontend and save it for later. To get started, we'd write a test that creates a new comment. Then, we'd check to ensure the author has a new notification. Verifying our work is running a few tests. No frontend needed.
This isn't the only way
This is only an example. Delaying decisions about your frontend isn't something you always have to do. If your application is already based in React, it seems clear you'd continue using it. The same is true with Bootstrap. Once you're using it, the default is to continue using it.
However, the spirit of delaying decisions is something to adopt. We might be tempted to think a decision is easy and without consequence, but slowing down is a good idea. "Of course we need to use this library," you might say, only to realize later it's not as great as you thought.
The beauty of delaying decisions is that it can be applied to almost anything. Don't know what you want your backend to be? Build a minimal frontend as you work out the details. Not sure if you want to use Resque, Delayed Job, or Sidekiq? That's cool - you don't need to make that decision early in a project.
Delaying decisions saves you time
When you make a decision too early and want to change it later, the decision costs you time. If it wasn't a decision that needed to be made, it's a double whammy. Most decisions can be delayed.
If I would've waited to make a decision on Bootstrap, it would've been easy to adopt another framework. You can get away with building a frontend until you actually need a frontend. At the very least, your frontend can be basic until you need it to be fancy.
Try something. When you reach your next decision, don't come up with an answer right away. Let the answer simmer and stew in your head. Do I really need to make a decision on this right now? Can I wait until I know more?
You always have more information tomorrow. Take advantage of that fact.
Top comments (8)
Good ol' Last Responsible Moment (LRM). I remember when an old boss of mine tried to explain this concept to me; I certainly didn't grasp it's importance right away.
To Ben's point around convincing others, I think it all goes back to knowing that you don't know enough and being able to explain that uncertainty to others. This should hopefully help drive establishing better requirements early on so you can actually make the right decision. And if that cannot be answered, it could be a good sign to GTFO before everything falls apart or you have to deal with mountains of tech debt with little to show for it.
As to the problem of knowing when you don't know enough, that is a hard problem. Like you said in your post, one of the better method is to simply always be critical of your quick decisions. The cost of double checking your thinking early on is so minor compared to dealing with the fallout later on that it should really just become part of your own SOP.
That's a great way to put it. I find it's sometimes easy for me to get anxious taking a few days or a week to make what seems like a simple decision. It might feel simple at the time, but you're exactly right. There's a cost to double checking and a cost to living with that decision. Double checking is almost always cheaper. Oftentimes, what seems like a simple decision can spread rapidly throughout a code base to a point there's no turning back.
I was afraid this would be yet another misrepresentation of Last Responsible Moment as Last Possible Moment and abuse of YAGNI, but it was a practical, actionable solution to reaching for numerous front end dependencies before devising the business logic.
However ⚠️: What do you say to the following?
Is it really often that you correctly know what business logic you need without a UI in front of you? Is it not much more dangerous to get locked into wrong data architecture and process flows than into a simple CSS library?
You make a good point. I didn't mean to imply you should always defer your frontend decisions or that the frontend is much more dangerous to get locked into (apologies if that wasn't clear).
I agree with you also. It seems much more dangerous to get locked into a bad data architecture. However, it may be a moot point because once you get far enough down the road, most businesses are going to resist changing either one. Unless there's a big initiative, most people don't want to go back and make far reaching, risky changes.
In the end, it seems as though it's a balance (the life of a software engineer). I don't think you want to near completion of a frontend without thinking about the backend. Sketches, rough designs, and prototypes should be enough to start thinking about the business logic.
Instead of weaving Bootstrap into my frontend, I could've just started building out a UI with HTML and very limited CSS. It would've looked terrible, but it would've allowed me to start understanding use cases and how they're supported with business logic. By keeping it simple, it's cheap to throwaway if I realize we should build the frontend with React or something else.
What are your thoughts?
I think we should combat the sunk costs fallacy instead of engaging in it, but yeah, sketching can definitely give you some idea.
Still, what should you be showing to your friends/coworkers while hiding from those horrible business people? A prototype of an API server, or a mock of an interface, with the navigations but with static/random data and no backend calls at all?
To me, the latter is just a better version of design-mocking/wireframing software, focused less on the look and more on the specifics of the interaction (vs simple links from slide to slide)
But I totally get where you're coming from, it's easy to feel attached, and the business just doesn't get it and grabs on to the unoptimized prototype like it's their firstborn.
I co-sign all of this. It's possible to go too far and become stuck in holding patterns, but this is all very true.
The harder part sometimes is explaining the need to delay certain decisions if you're not working alone.
Agreed. When organizing my thoughts for the post, I had the same problem. It's not always easy to explain and sometimes can be a little hand wavy. Sometimes it feels like delaying is the right decision, but you can't come up with a great explanation as to why.
There's definitely a balance between delaying and just going for it. That's part of the beauty of building software. Learning when you've reached a crossroads can be a great skill to develop and only comes with experience. I highly doubt I've even come close to mastering it.
I think sometimes is hard to make decisions like the ones you talked about, but maybe a way of sorting this out it's by planning, if you have an idea of how are you going to approach every task, then you could say in which step the decision has to be made, and this is also important if you are working with other people.