读书人

erlang的编程轨范

发布时间: 2013-03-28 10:20:24 作者: rapoo

erlang的编程规范
Programming Rules and Conventions
erlang的编程规范

erlang的基本体系:
从文件构造,进程,进程间联系,函数来说清楚整个构架。


The work in a system designed using Erlang is done by processes. A process is a job which can use functions in many modules. Processes communicate with each other by sendingmessages. Processes receive messages which are sent to them, a process can decide which messages it is prepared to receive. Other messages are queued until the receiving process is prepared to receive them.

A process can supervise the existence of another process by setting up a link to it. When a process terminates, it automatically sends exit signals to the process to which it is linked. The default behavior of a process receiving an exit signal is to terminate and to propagate the signal to its linked processes. A process can change this default behavior by trapping exits, this causes all exit signals sent to a process to be turned into messages.

A pure function is a function that returns the same value given the same arguments regardless of the context of the call of the function. This is what we normally expect from a mathematical function. A function that is not pure is said to have side effects.

Side effects typically occur if a function a) sends a message b) receives a message c) calls exit d) calls any BIF which changes a processes environment or mode of operation (e.g. get/1, put/2, erase/1, process_flag/2 etc).

3.1 Export as few functions as possible from a module
对外部来说接口不变,但是可以改变它的实现方式,且整个module对使用者来说简单。

3.2 Try to reduce intermodule dependencies
每一次调用外部的函数都会在代码目录下遍历去找这个module,减少不必要的外部调用是最有效的方法。PS

Note also that it is desirable that the inter-module calling dependencies form a tree and not a cyclic graph.
不要出现A调用B,B调用C,C又调用A的情况。

3.3 Put commonly used code into libraries

The libraries should be collections of related functions,典范如lists module .The best library functions have no side effects. Libraries with functions with side effects limit the re-usability. 不应该有lists_maths module混合功能是一个非常不好的习惯!

3.4 Isolate "tricky" or "dirty" code into separate modules
把所有的脏操作,看上去不合理的操作都用单独的modules分离开:如以下情况:
使用进程字典;
用erlang:process_info/1,(这个真是奇怪的需求,原因是什么?)
其它你不想做,但是又不得不做的情况。
对于这种代码一定要写好comment!

3.5 Don't make assumptions about what the caller will do with the results of a function
不要去假定使用者会在对的情况下怎样,错的情况下怎样。要让他们自己处理。比如:


3.7 Top-down
要使用从高层到低层的写法,要先明白这个函数是搞什么的,然后把结构定好,再去回头写那些细节。不要想一口气从头写完函数。

3.8 Don't optimize(优化) code
Don't optimize your code at the first stage. First make it right, then (if necessary) make it fast (while keeping it right).先做对,再做好。
3.9 Use the principle of "least astonishment"
不要写出让人惊讶的函数,模块,不然就是你的名字起错了!!!看上去整体风格都是一样的!
If you get astonished by what a function does, either your function solves the wrong problem or it has a wrong name.

3.10 Try to eliminate side effects.排除边界效应。
边界效应都是不可逆的,如改变环境变量,发消息 什么的。如果要写这样的函数,一定要独立且加注释啊!
Collect together the functions which have side effect and clearly document all the side effects.

3.11 Don't allow private data structure to "leak" out of a module
时刻想着如果要重写这个模块(里面的数据结构变化了,便是要求外部的调用不用变!

Clean separation of error recovery code and normal case code should greatly simplify the overall system design.

The error logs which are generated when a software or hardware error is detected will be used at a later stage to diagnose and correct the error. A permanent record of any information that will be helpful in this process should be kept.

4.2 Identify the error kernel(分清哪一些是可以出错的,哪一些核心是不可出错的?)
One of the basic elements of system design is identifying which part of the system has to be correct and which part of the system does not have to be correct.

In conventional operating system design the kernel of the system is assumed to be, and must be, correct, whereas all user application programs do not necessarily have to be correct. If a user application program fails this will only concern the application where the failure occurred but should not affect the integrity of the system as a whole.

The first part of the system design must be to identify that part of the system which must be correct; we call this the error kernel. Often the error kernel has some kind of real-time memory resident data base which stores the state of the hardware.

5 Processes, Servers and Messages

5.1 Implement a process in one module
The code for the top loop of a process should not be split into several modules - this would make the flow of control extremely difficult to understand. This does not mean that one should not make use of generic server libraries, these are for helping structuring the control flow.

5.2 Use processes for structuring the system
Processes are the basic system structuring elements. But don't use processes and message passing when a function call can be used instead.
能用函数代码发消息的就不要用发消息+进程来计算东西了。

5.3 Registered processes
进程要注册!才能好理解。

5.4 Assign exactly one parallel process to each true concurrent activity in the system
"Use one parallel process to model each truly concurrent activity in the real world"
决定用并行的进程来描述需求的准则是,使代码看上去和真实世界一样吧。
If there is a one-to-one mapping between the number of parallel processes and the number of truly parallel activities in the real world, the program will be easy to understand.

5.5 Each process should only have one "role"
每个进程只负责自己的责任,不用管别人的。
Supervisor: watches other processes and restarts them if they fail.
Worker: a normal work process (can have errors).
Trusted Worker: not allowed to have errors.

5.6 Use generic functions for servers and protocol handlers wherever possible
尽量使用系统自带的OTP gen_server gen_fsm。。。。

5.7 Tag messages
发消息时一定要在头标记一个atom的tuple来标记消息 ,PID !{for_fun,Test,1,2}.

5.8 Flush unknown messages

5.12 Trapping exits
As few processes as possible should trap exit signals. Processes should either trap exits or they should not. It is usually very bad practice for a process to "toggle"(栓牢套住) trapping exits.

6 Various Erlang Specific Conventions
6.1 Use records as the principle data structure
The record features of Erlang can be used to ensure cross module consistency of data structures and should therefore be used by interface functions when passing data structures between modules.

6.2 Use selectors and constructors
选择器和构造器。
demo() ->
P = #person{name = "Joe", age = 29},
#person{name = Name1} = P,% Use matching, or...
Name2 = P#person.name. % use the selector like this.

6.3 Use tagged return values
just like 5.7 Tag message

6.4 Use catch and throw with extreme care
不要用catch throw
Catch and throw can be useful when the program handles complicated and unreliable input (from the outside world, not from your own reliable program) that may cause errors in many places deeply within the code. One example is a compiler.

6.5 Use the process dictionary with extreme care
不要用进程字典:The use of get and put will cause a function to behave differently when called with the same input at different occasions. This makes the code hard to read since it is non-deterministic.

6.6 Don't use import
Hard to understand.

6.7 Exporting functions
It is a user interface to the module.
It is an interface function for other modules.
It is called from apply, spawn etc. but only from within its module.

7 Specific Lexical and Stylistic Conventions
7.1 Don't write deeply nested code嵌套要少一点。

7.2 Don't write very large modules
400 lines是极限

7.3 Don't write very long functions
Don't write functions with more than 15 to 20 lines of code.

7.4 Don't write very long lines
Don't write very long lines. A line should not have more than 80 characters.

7.5 Variable names
Choose meaningful variable names - this is very difficult.

7.6 Function names
The function name must agree exactly with what the function does.

7.7 Module names
Erlang has a flat module structure (i.e. there are not modules within modules).

7.8 Format programs in a consistent manner
统一风格 {1,2,3} VS { 1 , 2 , 3 }


8 Documenting Code
8.1 Attribute code
You must always correctly attribute all code in the module header. Say where all ideas contributing to the module came from - if your code was derived from some other code say where you got this code from and who wrote it.
Never steal code - stealing code is taking code from some other module editing it and forgetting to say who wrote the original.

Examples of useful attributes are:

读书人网 >编程

热点推荐