Erlang/Elixir鼓励 let it crash的编程哲学。此刻不是要记录什么是let it crash,而是写代码时想到了一个小细节。
这个小细节就是,函数调用时,尽量捕获到你希望获得的返回值。
例如你依赖的某个第三方库的api可能是这样:
@spec foo -> :ok | {:error, reason}
而如果你对代码过于自信、认为返回值肯定是:ok
的话,很可能就会这么调用:
def bar do
foo
end
上述代码是有危险的,它没有捕获函数的返回值。
假设foo/0
是个保存文件的函数,而保存文件一般情况下肯定会成功,所以代码编写者惯性思维地认为foo/0
一定会返回:ok
,但若是在磁盘顺坏、空间剩余不足等情况下也有可能使得该操作失败,也就是说,这个bar/0
实现有潜在危险!
我认为对bar/0
比较好的改写是:
def bar do
:ok = foo
end
仅仅是加了一个match。
加了这个match,若foo/0
返回了我们讨厌看到的{:error, reason}
,则该进程就会报异常,也就是let it crash。之后我们检查日志,就能发现一些潜在的危险,比如磁盘顺坏,就立刻修复磁盘或者迁移文件等。
再举个例子:
# 第三方库
@spec foo -> :ok
# 调用者代码
def bar do
foo
end
这次的调用总不会出问题了吧?你看foo/0
肯定会返回:ok
的,再去捕捉它的返回值,这不是多此一举吗?
那我想问,如果这个第三方库版本升级,foo/0
这个api也升级为如下形式了呢?这不是不可能吧~
@spec foo -> :ok | {:error, reason}
所以,更稳妥的写法还是加个match捕获期望的函数返回值吧。
// 其实上述例子都不怎么好,可我现在手头又没有比较好的例子,先凑活着这样吧