Our ideal code is short, easy to read, has good tests and no compile warnings. New code should be written to conform to those standards, but existing code may not already meet that standard. In that case we should aim to improve that code over time.
A function should do one thing, if a function clause is more than 5 lines of code it is probably too long. Extract part of the code into its own function (Wrangler will do that automaticly for you). Similarly if a module is more than 100 lines of code consider if it is possible to split out some of the functions into their own module.
If a function has more that 4 arguments it is probably also too complex. (Note that we are not talking about the arity of the function here, but how many things it depends on).
If you are working on a feature and find an unrelated bug, stash your code (or switch to a new branch) fix the bug and send a Pull request for that issue, then go back to your code. But don’t mix the two.
Erlang has some conventions, for example Let it Crash, in general in Erlang you don’t want to write defensive code. If you are using a try/catch block you probably are doing something wrong.
In addition tagged types can aid debugging and understandability. For example instead of passing a binary as a user id, pass a tuple of the form {userid, UserId}. You can use pattern matching to make sure that types do not cross contaminate, and it is much easier to debug if something goes wrong.
Similarly when returning an optional value tag it as something like {ok, Value}|not_found.
Erlang’s type system is optional, but that does not mean it is not useful. Dialyzer can often provide useful information on possible problems, and if you use specs it can often find more problems, and if you add in pattern matching it will often cause code to fail fast and reveal errors quickly.
TDD is used in the industry for a good reason, it works. By writing a unit test, or better yet a QuickCheck property first we can ensure that our code can handle a wide range of inputs and be robust.
In cases where dialyzer can be used to find problems in the code then use that as well.
If you see a warning from the compiler, fix it. In some cases it may represent a real problem, in cases not, but it would be good to fix it.
If you need to do something that is a standard operation there is probably an open source package that will do what you need. Don’t write your own JSON decoder, use jsx (or one of the other open source tools).
Common Libraries * JSON: jsx, mochijson * Logging: lager * ORM: boss_db * templates: erlydtl * Build: rebar, erlang.mk * Mocking: meck * Property Based Testing: proper, quickcheck
In general we want to check for errors at the edge of the system. That is to say that the first time we see data from the user we should validate it, from there on out we should be able to assume that the data conforms to the model.
These are guidelines that have been created by others, they generally assume a language that is not Erlang, so they may not apply to us in all cases, but provide a basis to talk about codeing standards.
Nice, especially the links at the end.
My comments: