开源日报 每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,坚持阅读《开源日报》,保持每日学习的好习惯。
今日推荐开源项目:《遁入黑暗 halfmoon》
今日推荐英文原文:《When DRY Doesn’t Work, Go WET》
开源日报第865期:《遁入黑暗 halfmoon》
今日推荐开源项目:《遁入黑暗 halfmoon》传送门:项目链接
推荐理由:这是一个类似于 BootStrap 的框架项目——通过 CSS 提供了各种常用页面组件,同时提供 JS 库作为附赠品,甚至连类名这些都和 BootStrap 差不到哪去,如果有过 BootStrap 使用经验的话很快就能上手。这个项目最大的亮点在于提供了简便的黑暗模式,只需简单的调用附加 JS 库中的一个函数,就能使页面自动切换到黑暗模式,从而更满足夜晚熄灯之后的使用需要。
今日推荐英文原文:《When DRY Doesn’t Work, Go WET》作者:🔴 Nick Bull JS
原文链接:https://medium.com/better-programming/when-dry-doesnt-work-go-wet-6befda0444bf
推荐理由:重复不可耻而且有用

When DRY Doesn’t Work, Go WET

It’s okay if you repeat yourself

I’ve seen this mistake many times, and I’ve made it myself. When you first read about the DRY programming concept, you probably misunderstood it.

What was going on in your head was this:

Wikipedia: DRY stands for not repeating the same code twice.
You: Hmm, ok I’ll replace all my duplications with abstraction.

And it seems like a good solution, but it’s not. Your abstraction is often wrong.

Here is why:
  1. You see duplication.
  2. You extract duplication into a new abstraction (method, class).
  3. You replace the duplication with the new abstraction.
  4. You think your code is perfect.
  5. Time passes.
  6. The product manager has new requirements. Your abstraction is almost perfect for them.
  7. You start to implement the new requirements.
  8. And here’s the little but:
  9. Your abstraction is almost perfect. Why? The new requirements affect only 95% of the old code you extracted into abstraction. The other 5% is not affected. And instead of creating a new abstraction with 95% copied code from the current one, you decide to change the code of your abstraction.
  10. You add a conditional statement, if..else for example, and pass a parameter, so your abstraction can perform different actions for different decisions.
  11. Now your abstraction behaves differently for different cases.
  12. Another new requirement arrives. Another additional parameter. Another new conditional. (Loop until code becomes very difficult to understand and maintain.)
  13. Congrats, you’ve created a wrong abstraction.
The code no longer represents a single, common abstraction. It becomes a condition-laden procedure. It’s hard to understand and easy to break. Adding new features is incredibly hard and every new feature complicates the code even more.

It’s an infinite loop.

So what to do?

Write Everything Twice.

WET

WET (Write Everything Twice) is the opposite concept to DRY. When you start to develop a new system you don’t know all the future requirements. So don’t rush into abstractions.

You need to remember: Duplication is far cheaper than the wrong abstraction.

For example, you are building a web app and don’t have a UI design for all pages right now. But you also have many buttons, and they’re similar on every page. You decide to move them to a component called Button and reuse it on every page. Seems logical.

“Hey, hey!” the new page design came from the product manager. You look at it and find a new, fancy button at the bottom of the page.

It looks like the old buttons, but it has this “one little thing.” To implement it, you need to rewrite 10% of your Button component, and add conditional statements and new parameters.

Now you have a dilemma:
  • Change Button. Rewrite 10% of the abstraction code (add logical conditions to support new fancy button logic).
  • Create two abstractions: FancyButton and Button. Copy 90% code from Button to FancyButton.
I know you want to choose the first option. You think that you can handle it. You’re not going to build the wrong abstraction.

But the sad truth is, you will (except if you are an experienced programmer and know what you’re doing).

Copy that code. Don’t be afraid.

After a while, you will know what your buttons will look like in the future. Then you can analyze the current codebase, find duplicated code in the button components, and move them to the good abstraction.

If It’s Too Late

If you find that it’s too late to deal with a wrong abstraction, the fastest way to move forward is back.

Do the following:
  1. Move the abstracted code back.
  2. Delete the unused parameter that’s passed to the abstraction to perform different actions for different decisions.
  3. Delete unused logic.
This removes the abstraction and conditional statements for each caller.

In the End…

If you find yourself passing parameters and adding conditional statements through shared code, your abstraction is wrong.

Prefer duplication over the wrong abstraction.

Thanks for reading!
下载开源日报APP:https://openingsource.org/2579/
加入我们:https://openingsource.org/about/join/
关注我们:https://openingsource.org/about/love/