如何编写更清晰的函数。
命名约定:
这篇文章最初发表在我的博客上。请阅读文章《如何阅读更清晰的函数》。
我敢打赌,你肯定偶尔会仔细检查一小段代码,试图弄清楚为什么这个函数要这样写。几乎所有公司都提供这种服务,它运行正常,却没人愿意碰,大多数情况下,这是因为代码编写方式很糟糕。
在这篇文章中,我们将讨论如何编写干净的函数并最终减少技术开销。
几天前,我读了一本叫《代码整洁之道》的书。虽然没能读完整本书,但我还是浏览了其中几章,其中一章是:
如何编写干净的函数。
以下是本章的学习内容。
函数不应该太大。
函数代码不应超过几行。经验法则是,函数代码不应超过 100 行。通常,函数代码甚至应该少于 10 行。
创建块和适当的缩进非常有帮助。
在生产系统中进行编程时,正确的缩进和块的使用将起到至关重要的作用。虽然这部分在 Python 中是强制性的,但对于公司来说,制定一个代码风格指南是一个不错的选择。
const function = makeChanges() {
const a = 10;
const b = 20;
return a + b;
}
const function = makeChanges() {
const a = 10;
const b = 20;
return a + b;
}
您可以从上面的例子中感受到差异。
每个函数应该只做一件事。
一般来说,一个函数应该只做一件事,并且该函数的名称应该能够自解释。如果函数名能够自解释,那么你永远不应该阻止它写更长的名称。
我们不应该将功能划分为多个部分。
另一种说法是,一个函数通常应该只做一件事。
所有函数中都有一个抽象级别:循环或 if/switch 语句的单级。
很多人忽略了抽象层次。简单来说,抽象层次就是函数内部嵌套 if 语句/循环的数量。
该数字通常应保持在较低的值。
必须从上到下阅读代码。
我知道这对很多人来说很难。起初,就连我自己也遵循相反的规则。但读完这本书后,我终于能够理解这一点了。
在审查代码时,人们倾向于从顶部开始,慢慢地移到末尾。因此,从顶部开始,然后随着编写的进行向下移动是合理的。
应避免使用 Switch 语句。
switch
尽量避免使用语句。最好使用dict
(Python) 或Map
/ Object
(Javascript)。
const monthObj = {
jan: function_1,
feb: function_2,
mar: function_3
};
const month = 'jan';
monthObj[month]();
month_obj = {
'jan': function_1,
'feb': function_2,
'mar': function_3
};
month = 'jan';
monthObj[month]();
虽然有时很难将 switch 语句改成这样。如果速度差异不是很大,可读性总是比速度更重要。
使用描述性名称。
我们已经讨论过这一点了。我们应该始终为函数选择更合适的名称。描述性的名称比一些随机的函数文档字符串更有用。
函数参数的数量应该较少。
参数数量应该更少。如果你正在编写类方法,最好将其设置为实例变量。
注意:尽量避免使用标志参数。这意味着函数会执行多项操作。
一元函数
带有一个参数的函数。尽可能尝试编写单子函数。
二元函数
具有两个参数的函数
三合会
带有三个参数的函数。尽量少写。如果参数数量开始增加到给定值,最好将这些参数包装在各自的类中。
例如:
转换,
makeCircle(x, y, radius)
到
makeCircle(center, radius)
其中中心是中心类的对象,这很有意义。
命名约定:
对于单子:选择动词+名词的组合:
例如:writeField(name)
,说明名称被写入到某个字段。
另外,函数名称assertEquals(expected, actual)
可以更改为assertExpectedEqualsActual(expected, actual)
,这更有意义。
无副作用
副作用是指改变类参数/全局参数/传递参数的值。所有这些类型的改变都必须避免。
例如:假设你调用了一个函数checkUserPassword(userName, password)
,并在该函数中为用户初始化会话,那么该函数只能在特定情况下使用(例如用户尝试登录时,而不是用户想要更改密码时)。这种耦合也称为时间耦合。一个好主意是更改该函数的名称,并指明该函数具有时间耦合。
例子:checkPasswordAndInitializeSession(userName, Password)
函数应该要么做某事,要么回答某事,但不应该同时做这两者。
这称为命令查询分离。
更喜欢引发异常而不是返回错误代码。
将语句主体提取try-catch
到函数中。
例子:
try:
trythisfunc()
except:
logError() # this function do only error logging.
DRY:不要重复自己。
注意:一个好主意是先写一个又长又难的函数,然后为每一行代码编写测试。之后不断优化代码,确保测试不失败。
希望你喜欢这里的一些观点。另外,你可能有一些不认同的地方。请在本文的评论区分享。
鏂囩珷鏉ユ簮锛�https://dev.to/singh1114/how-to-write-cleaner-functions-j4m