Why Erlang suggest avoiding defensive programming( Joe Armstrong )

"defensive programming" (Was: Re: How nice should I be on exit?)


Joe Armstrong <> 
Wed Mar 5 12:25:08 CET 2003
Previous message: "defensive programming" (Was: Re: How nice should I be on exit?)
Next message: "defensive programming" (Was: Re: How nice should I be on exit?)
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 5 Mar 2003, Luke Gorrie wrote:


... cut ...


> Hope that clears things up for someone else who learned the other
> definition than the Erlang guys :-)


Yes :-)


I have two "thumb rules"


Check inputs where they are "untrusted" 


- at a human interface
- a foreign language program


Or when you want a better error diagnostic that the default one -
in this case just exit with the better diagnostic.


For example if I'm parsing an integer I'd write


I = list_to_integer(L)


or


case (catch list_to_integer(L)) of
   {'EXIT', _} ->
exit(["Most honored user I regrettably have to inform you
     that your input on line", Ln, "was not an integer
     in fact it was ",L, "which IMHO is wrong
     have a nice day Mr. C. Computer"]);
   I ->I
end.


The latter is "an industrial quality" error message :-)


Note (important) the semantics of both are to raise an exception in the
event of an error. 

Aside: I once saw code like this:


x(a) -> 1;
x(b) -> 2;
x(X) -> io:format("expecting a or b").
%% what do I do now


The programmer had actually added a comment (What do I do now) -
of course they had done the wrong thing.


The program:


x(a) -> 1;
x(b) -> 2.


Is correct.


Evaluating x(c) generates an exception as required.


In their modified program x(c) evaluates to the atom 'ok' (i.e. the return
value of io:format) - which is incorrect.


If they had wanted a better diagnostic they should have written:


x(a) -> 1;
x(b) -> 2;
x(X) -> exit({x,expects,argument,'a or b'}).


If you do *nothing* to your code you get a good diagnostic anyway:


If x in in the module m and you call this in the shell
you'd get:


(catch m:x(c)).
{'EXIT',{function_clause,[{m,x,[c]},
                          {erl_eval,expr,3},
                          {erl_eval,exprs,4},
                          {shell,eval_loop,2}]}}


function_clause means you couldn't match a function head.


[{m,x,[c]}, ...


means you were calling function x with argument c


So in this case NOT programming the error case  results in


1) shorted code
2) clearer code
3) no chance of accidentally violating the spec by introducing ad hock "out of spec" code to correct the error
4) perfectly acceptable error diagnostic


  IMHO 3)  is a  big gain -  specifications always  say what to  do if
everything works  - but never what  to do if the  input conditions are
not met - the usual answer is something sensible - but what you're the
programmer - In C etc. you  have to write *something* if you detect an
error -  in Erlang it's  easy - don't  even bother to write  code that
checks for errors - "just let it crash".


  Then  write a  *independent* process  that observes  the  crashes (a
linked process) -  the independent process should try  to correct the
error, if it can't correct  the error it should crash (same principle)
- each monitor  should try a  simpler error recovery strategy  - until
finally the  error is  fixed (this is  the principle behind  the error
recovery tree behaviour).


  Why was error handling designed like this?


  Easy - to make fault-tolerant  systems you need TWO processors.  You
can never ever make a fault tolerant system using just one processor -
because if that processor crashes you are scomblonked.


  One  physical processor does  the job  - another  separated physical
processor  watches  the first  processor  fixes  errors  if the  first
processor  crashes - this  is the  simplest possible  was of  making a
fault-tolerant system.


  This principle is mirrored exactly in the Erlang process structure -
this is because we want to have "location transparency" of processes -
in other  words at a  certain level of  abstraction we do not  wish to
know which physical processor an individual Erlang process runs on.


  This is  the fundamental reason  why we use "remote  error recovery"
(i.e. handling  the error  in a different  process, to the  process in
which  the error occurred)  - it  turns out  that this  has beneficial
implications for  the design  of a system;  mainly because there  is a
clean separation  between doing a job,  observing if the  job was done
and fixing an error if an error has occurred.


  This   organization  corresponds   nicely  to   a   idealized  human
organization of  bosses and workers -  bosses say what is  to be done,
workers do stuff.  Bosses do quality control and check that things get
done, if not they fire people  re-organize and tell other people to do
the stuff.  If  they fail (the bosses) they get  sacked etc.  <<note I
said, idealized organization, usually  if projects fail the bosses get
promoted and given more workers for their next project>>


  /Joe


##博客仅作个人记录##



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Erlang是一种功能性编程语言,最初是为了电话交换系统而设计的,具有并发、容错和分布式计算的能力。在功能性编程中,我们将程序视为一系列函数的集合,而不是一系列指令的序列。这种思维方式使得编写可靠、可扩展和可维护的软件变得更加容易。 要开始学习Erlang,我们首先需要安装它。Erlang可在多个操作系统上运行,包括Windows、Linux和Mac OS。我们可以从Erlang官方网站下载适合自己操作系统的安装程序,并按照提示进行安装。 安装完Erlang后,我们可以在命令行界面(或终端)中启动Erlang Shell(也称为Erlang交互式环境)。在Shell中,我们可以输入并执行Erlang代码。 Erlang的基本语法与其他编程语言有些不同。在Erlang中,函数定义使用"fun"关键字,比如:Add = fun(X, Y) -> X + Y end. 这将定义一个名为Add的函数,它接受两个参数X和Y,并返回它们的和。 在Erlang中,我们可以使用模式匹配来处理不同的情况。例如,我们可以编写一个函数来计算一个列表中所有元素的和,如下所示: sum([]) -> 0; sum([H|T]) -> H + sum(T). 当我们传递一个空列表[ ]给sum函数时,它将返回0。而当我们传递一个非空列表[H|T]时,它将把列表的头部元素H与剩余部分T的和相加。 在学习Erlang时,重要的是要尝试编写简单的程序和函数,以便熟悉基本的语法和概念。您可以使用Erlang Shell来交互式地测试和执行您的代码。 除了基本的语法和概念之外,Erlang还具有许多强大的特性,例如并发编程、消息传递和模式匹配。这些功能使Erlang成为开发可靠、高可扩展性的分布式系统的理想选择。 总之,Erlang是一种功能强大的功能性编程语言,它具有并发、容错和分布式计算的能力。我们可以通过安装Erlang并在Erlang Shell中尝试编写简单的程序,来快速上手Erlang。在学习过程中,我们将逐步掌握Erlang的基本语法和概念,为开发可靠和高可扩展的系统打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值