Is Good Enough, Good Enough? (Part?1)

Is Good Enough, Good Enough? (Part?1)

“Perfect is the enemy of good.” - Voltaire

This is a two-part article, and this is the first part. You can find the second article here: Is Good Enough, Good Enough? (Part 2)

I used to be a perfectionist. I even thought that this was the only way to be. People who weren’t like me were obviously doing a lousy job. They just didn’t care.

Whenever I got involved in a new feature, I had very high expectations of myself and my work. I wanted to know all the details, cover all the edge cases, and make sure that the solution was scalable and extensible. I’ve spent a huge chunk of time outlining the perfect solutions that would cater to all current and future needs. It had to be perfect.

And then, when I started the actual implementation, I noticed I hadn’t thought of a legacy chunk of code that had a cardinal role in the feature. I missed a use case that affected my perfect plan to a non-negligible extent. I also realized that the library I was planning to use simply didn’t have a piece of functionality that I assumed was there.

I had to scrap my work and go back to the planning board to make a New Perfect Plan. This time I was even more diligent. But, obviously, something similar happened again.

That made me think: Am I chasing something that is not achievable? And more importantly, if it’s achievable, is it even preferable? Let’s explore this.

Why Perfection is a?Myth

But first, what is a perfect engineering solution?

  • It satisfies all functional and non-functional requirements.
  • It covers all edge cases.
  • It fits perfectly into the existing architecture.
  • It is 100% extensible and future-proof.

Sounds good and reassuring, right? It’s an engineering panacea. It gives us this nice, accomplished feeling.

However, the perfect solution falls apart when we consider TIME and REALITY.

Let me explain what I mean.

Customers Don’t Need Perfection

One of the most prevalent misconceptions is that customers are only satisfied by perfect systems. However, that’s not true:

  • First and foremost, if there are multiple customers, their definition of perfection might be different.
  • If a system serves customers properly in 9 out of 10 occasions, that is still a very valuable solution.
  • Customers can live with bugs and issues (given they are not making their main use case impossible to achieve).

Early Feedback is?King

Working relentlessly on the perfect solution robs us of early feedback. In my opinion, feedback is of key importance. Delivering something in a month has a clear benefit over delivering the perfect solution in a year.

  • An early prototype can facilitate discussions that could result in changes to the requirements.
  • Ideally, this could also result in decreasing the scope because we might realize that what we have right now is enough.
  • We might also discover that some of our initial assumptions were incorrect.
  • We might uncover a previously overlooked risk that could affect the scope or timeline of the project.

Better to figure these out early, right?

Requirements are not?Static

Contrary to popular belief, requirements are seldom static. Requirements serve as guidelines, but as more and more information becomes available, those requirements will very likely change.

I’m not implying that one should just ignore requirements. I’m just suggesting considering them as flexible constraints to development. And as Yoda once said, “Train yourself to let go of everything you fear to lose.”

I’ve seen my share of projects where we thought a set of requirements were paramount, but we ended up with something completely different. Something completely different that served our customers much better.

Some Requirements are More Important than?Others

Loosely connected to the previous point, in most cases, there’s a clear order of importance between the requirements. Some of them are must-haves, others are should-haves, and lastly, there’s a list of nice-to-haves.

The Pareto Principle (AKA the 80/20 rule) largely applies: Often, 80% of the value comes from 20% of the effort. Focusing on that crucial 20% can deliver significant value quickly.

And again, we might realize earlier that delivering the most important features is enough and makes the customers perfectly happy. No need to implement the rest.

Time to Market is Important

Often, there can be a competitive advantage gained from being early or even the first to market with a piece of functionality.

Creating the perfect solution with all the bells and whistles rarely allows us to be in that position.

Getting there early with limited functionality or a non-perfect user experience is often worth it because it could drive serious profit and could also come with a good deal of early feedback from actual users.

It’s OK to Fail (Sometimes)

Engineering types (myself included) have a hard time accepting that our amazing solutions could fail in production. We tend to program guardrails to handle all the error cases that we can think of. And yet, achieving perfection in error handling is hardly feasible. I’d argue that after a certain level, it becomes disproportionately harder and harder to handle possible error scenarios. I’d also argue that we shouldn’t?—?customers can tolerate an error from time to time unless it makes their main use case impossible. So we should be OK with living with a solution that can fail from time to time.

Of course, I’m talking about software that is not life- or mission-critical. In those cases, by all means, be as diligent with the error handling as humanely possible.

We Cannot (Always) Predict the?Future

Engineers often think they know what will happen in the future. They feel like they have a very good understanding of how the software will develop over time. They feel like they know in what ways they will need to extend the application.

However, in reality, this is rarely the case.

Amazingly architected, clever, extensible solutions can fall apart even from a single sentence of a new requirement. I’ve seen this several times.

Reality can hit hard, right?

The Psychological Toll of Chasing Perfection

If we step back a bit, chasing perfection also impacts our psyche. When I think about perfection, a huge and complex project comes to mind with many strict and complicated requirements. It might seem like a huge obstacle that is almost impossible to overcome. Perfectionists also often consider anything that is not perfect a failure. And with the high likelihood of not getting there, this can result in some subconscious anxiety and/or procrastination.

But What is “Good?Enough”?

I have avoided defining what “good enough” is so far. While I have an intuition of what it might be, I researched what the Internet thinks. So here’s a working definition that captures my thoughts perfectly.

“Good enough” software is software that:

  • Meets the core requirements: It effectively addresses the primary needs and use cases of its users. It may not have all the bells and whistles, but it delivers on its central promise.
  • Is reliable and stable: It functions consistently and predictably, with a manageable level of bugs and errors that don’t significantly hinder the user experience.
  • Is maintainable and adaptable: It’s built with a clear and understandable architecture, allowing for future modifications and extensions as needed. This doesn’t require predicting all future needs but having a solid foundation for adapting to reasonable changes.
  • Is delivered in a timely manner: It reaches users within a reasonable timeframe, allowing for early feedback and iteration. This may mean sacrificing some non-essential features to prioritize speed to market.
  • Provides a positive user experience: While not necessarily perfect, the user experience is intuitive and efficient enough to satisfy most users.

To preempt the critique, “Mark, are you suggesting that we should cut corners and ignore our engineering best practices?”, here’s what “good enough” software is NOT:

  • Sloppy or poorly designed: It still adheres to coding standards, best practices, and sound design principles.
  • Full of critical bugs: While some minor bugs may be acceptable, it doesn’t compromise on functionality or security.
  • Unmaintainable: It’s not a tangled mess of code that’s impossible to understand or modify.
  • Delivered excessively late: While prioritizing core features, it still aims for a reasonable delivery timeline.

Summary

In this article, I’ve talked about what I consider perfection from a software engineering perspective. I’ve also brought several examples to justify why I think perfection is neither achievable nor desirable. I’ve also given a definition of what I think “good enough” is in the software engineering domain. In the next article, I will talk about the actual engineering practices we can use to avoid chasing perfection while still delivering an awesome solution.

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

Márk Verebélyi的更多文章

  • Is Good Enough, Good Enough? (Part 2)

    Is Good Enough, Good Enough? (Part 2)

    In my previous article, I discussed what “Good Enough” software is, its common pitfalls when chasing perfection, and…

  • How to nail your software engineer interview?

    How to nail your software engineer interview?

    Over the past decade, I’ve conducted countless interviews for software engineering roles, meeting hundreds of engineers…

社区洞察

其他会员也浏览了