On the internet, any discussion involving preferences inevitably leads to arguments.

Preference is a very personal thing, but if the choice affects not just oneself but also collaborative team members, the company’s interests, or user experience, then more considerations are needed.

Whatever the choice, it should follow a certain principle. Different people have different principles; for me, it is "Worse is Better."

Worse is Better: The Victory of Simplicity

"Worse is Better" is a philosophy proposed by Richard P. Gabriel. It expresses that a system’s design should be simple. If other aspects of the design make the system more complex, they should be sacrificed.

He compares Lisp/Lisp Machine with contemporary C/Unix, and I’ve listed the comparison below:

Simplicity

  • Lisp believes that the design must be simple, especially the interface. If a simple interface requires complex implementation, it’s acceptable.
  • Unix believes that the design must be simple. Simple implementation is more important than a simple interface.

Correctness

  • Lisp believes that the design should be correct in all aspects, with no errors allowed.
  • Unix believes that the design should be correct in all aspects, but some errors are permissible if it keeps the design simple.

Consistency

  • Lisp believes that the design should be consistent in all aspects.
  • Unix believes that the design shouldn’t be overly inconsistent. Sometimes, to maintain simplicity, consistency can be sacrificed, but it’s better to abandon designs dealing with uncommon cases rather than introducing implementation complexity or inconsistency.

Completeness

  • Lisp believes that the design should cover all important cases as much as possible and must cover all reasonable expected cases.
  • Unix believes that the design should cover all important cases as much as possible. However, completeness can be sacrificed if it keeps the design simple.

In short, the core concept of Worse is Better is to appropriately sacrifice other aspects for simplicity.

After reading these comparisons, most people might think Lisp's design is superior, but Unix turned out to be more successful. Let’s take a look at what exactly happened:

  1. Because Unix and C are simple, they could run on cheaper hardware, extending their reach to places Lisp could not.
  2. Because Unix and C were incomplete, complex monolithic systems couldn’t be built all at once, so large projects had to be broken down into reusable modules. Thus, the concept of software engineering was born, and the pace of program improvement accelerated.

As a result, the "worse" Unix and C achieved victory.

Vue vs React: Trade-offs and Choices

Six months ago, I was chatting with an engineer from a client’s team, and he asked me why I often use Vue instead of React. I said that using Vue imposes less mental burden; for example, you can directly include Vue in an HTML file and treat Vue as a better version of jQuery.

Thus, using Vue, you can go big by starting a modern web project with Nuxt.js, or keep it simple by writing vanilla JavaScript and use Vue to enhance the development experience.

This flexibility is very appealing to me because, often, a complete web app isn’t needed, which means no need to maintain dependencies or handle complexity.

Golang: A Balance of Simplicity and Efficiency

Before version 1.2, Go was a very boring language (and it still is).

For example, checking if a list contains an element: other languages can use if item in list, but in Go, for a long time, you had to write a complete loop:

for _, v := range list {
  if v == item {
      return true
  }
}

Go’s much-criticized error handling also clearly inherits from C.

But this dullness is one of Go’s strengths. For example, it’s easier for team members to unify their coding styles, improving readability and maintainability (checking if a list contains an element is not a good example, so now we have slices.Contains).

Go finds a good balance between simplicity and functionality. It might not be the most flexible or elegant language, but its philosophy makes it excel at building efficient and reliable systems.

Markdown: A Balance of Simplicity and Functionality

Since its inception, Markdown has always been controversial.

Some argue that as a markup language, Markdown’s syntax is too simple to meet complex needs; the lack of standards leads to differences between implementations; overall, it’s inferior to ReStructuredText and Asciidoc.

Others argue that as a markup language, its limitations are too many compared to more complete WYSIWYG HTML editors.

However, Markdown is positioned just right, and its popularity proves that it has struck a good balance between simplicity and functionality.

Because Markdown's capabilities are limited, it’s the easiest markup language to learn, allowing non-tech-savvy users to get started quickly and write intuitively, meeting 90% of needs with the most basic syntax. This has made it the "de facto standard" outside of WYSIWYG editors, achieving what ReStructuredText and Asciidoc did not.

Of course, Markdown isn’t suitable for scenarios requiring precise control over layout or documents with complex tables and charts, where WYSIWYG editors are a better choice. But for most writing needs, Markdown provides a great balance.

Biological Evolution: Simplicity Brings Possibility

Beyond the tech industry, biological evolution is also an excellent example of Worse is Better.

From Simple to Complex

Life initially began with simple single-celled organisms. These "crude" forms of life weren’t perfect, but they could survive and reproduce, laying the foundation for complex life forms.

Similarly, in software development, it’s common to start with a simple but usable version and then iterate to refine it.

Highly Adapted, Highly Risky

In biological populations, genetic diversity may seem mediocre, but it actually provides room for future evolution. In contrast, organisms that are highly adapted and highly specialized, like large predators, are more prone to extinction when the environment changes.

When designing systems, be aware that overdesign and overadaptation can reduce adaptability. For example, if a system is locked into Amazon Web Services, it won’t function if AWS encounters issues.

The same goes for product decisions. Relying on a big platform, like the WeChat ecosystem, may allow rapid growth by leveraging the platform’s advantages, but it also entails uncontrollable risks within the ecosystem, which could lead to total loss.

Strength in Flaws

Interestingly, some seemingly flawed genes can be advantageous in specific environments. For example, the sickle cell anemia gene, while causing anemia, provides greater resistance to malaria.

Some choices and decisions may have shortcomings, but in specific contexts, they can yield unexpected advantages. For instance:

  • Instagram initially allowed only square photos, which was seen as a drawback. However, this "flaw" became a defining feature of Instagram, prompting users to focus more on composition and creating a unique visual style.
  • Early Twitter limited each tweet to 140 characters, initially viewed as a limitation. Yet this "flaw" encouraged users to express themselves more concisely and creatively, speeding up information dissemination. This trait later became a hallmark of Twitter, shaping a unique social media culture.

Therefore, being imperfect doesn’t necessarily mean failure. On the contrary, it can offer more possibilities for adaptability and long-term survival. In technology choices and product design, a simple yet flexible solution might have more vitality than a perfect but rigid one.

The best designs are often those that users don’t notice; the most practical tools are often the least conspicuous. "The best way is no way, the greatest vessel takes shape from the void, the greatest sound has no voice, the greatest image has no form."


A few days ago, my product manager asked me, "You once said that when creating a solution, you should consider it comprehensively and fully, but why do you also emphasize that the solution should be simple enough?"

Well, I did say these two things at different times without immediately realizing the contradiction between them.

A few years ago, I emphasized the completeness of a solution because, back then, I was working in large companies (especially influenced by WeChat and Apple), doing insignificant tasks but with access to ample resources—enough to create comprehensive solutions without worrying about costs; the top-level strategy was persistent enough to be prepared to bear sunk costs from the outset.

At that time, my designs were either for "large and complex system scenarios"—which had to be huge and fully functional—or for "diamond-like gem scenarios"—which had to be exquisitely designed, elegant, and as perfect as possible.

But in small companies with limited resources and facing changes, more trade-offs and sacrifices are needed. At this point, the Worse is Better design philosophy is a better motto: simple but usable, gradually improving.

Therefore, in my career, I have experienced a shift from pursuing perfection to recognizing the value of "good enough." It’s not about compromise and trade-offs; it's about doing the right thing at the right time, continuously accumulating the right results, and maintaining room for maneuver.