首先优化简单性

2022-02-25 17:32:42

在开发软件时,我们不可能对所有东西都进行优化,所以我们需要从一些东西开始,这些东西应该是简单的代码和简单的体系结构。例如,为了在JavaScript中过度优化速度,我们可能会向后编写For循环,从而损害可读性。

我认为我们应该首先优化简单性,只在必要时对复杂的内存、速度和抽象进行更改。

如果它速度慢但可读性好,我可以把它写得快。如果它坏了但可读,我可以让它工作。如果这是不可能理解的,那么我必须花几个小时试图理解这个讨厌的东西首先应该做什么。

工作、可读的软件应该是代码的“MVP”。在易于理解的代码中发现瓶颈是很容易的。如果必要的话,这段缓慢的代码可以优化速度。

在某些情况下,事先认真对待速度是有道理的。例如,选择项目使用哪种语言或框架是一个不能轻易撤销或更改的决定。如果您选择了错误的语言或框架,即使在当时看来这是一个简单的选择,我可以向您保证,将所有功能重写到一个新的堆栈中绝不简单。

例如,试图用Ruby on Rails编写一个现代PC游戏是一件蠢事。

你需要Redis吗?你真的需要Redis吗?可能不会。对于web API,在第一次迭代时省略缓存。大多数服务器不需要内存缓存来有效地为用户服务。当速度开始成为问题时,如果可能的话,在服务器本身上实现内存缓存。就整体系统复杂性而言,唯一比代码依赖性更糟糕的是基础设施依赖性。

只有在没有更简单的选项时,才能添加新的数据库、缓存系统、队列服务器或NPM模块。

编写可重用函数没有错,大多数编写良好的函数都是可重用的,不会增加任何不必要的复杂性。然而,我经常看到开发人员过度概括问题,损害可读性。

如果应用程序中目前只有一个地方调用函数,那么不要担心让该函数成为其自身最通用的版本。例如,假设我的Go API中有一些验证中间件:

输入apiParams struct{OrgID string UserID string}func validateParams(参数apiParams)error{if params.OrgID==";";{返回错误。新建(";需要OrgID";)}如果参数为。UserID=="" {返回错误。新建(";需要用户ID";)}返回零}

这确实是一个有用的功能,但我对干燥的渴望可能会促使我做以下事情:

键入apiParams struct{OrgID string UserID string}func validateParams(参数接口{})error{dat,:=json.Marshal(参数)mapParams:=map[string]string{}json。对k,v:=范围映射参数{if v=";";{返回fmt.Errorf(";%s未找到";,k)}返回nil}

我们已经成功地使代码更加抽象,现在任何函数都可以传入任何结构来检查公共字段是否存在!问题是,我还添加了新的边缘案例,这些案例在各种情况下肯定会产生bug。例如,如果一个整数被传递到我的函数中呢?

代码就这么简单,我们没有理由推广它。当我们最终被迫创建一个更广泛的抽象时,我们将有更多关于如何构建一个好的抽象的信息。

亲吻>;干的如果使用得当,干代码将比以前更简单,我不认为这些经验法则存在直接竞争。