inaka / erlang_guidelines Goto Github PK
View Code? Open in Web Editor NEWInaka's Erlang Coding Guidelines
License: Apache License 2.0
Inaka's Erlang Coding Guidelines
License: Apache License 2.0
Use snake_case for module names, function names and atoms in general and avoid uppercase letters in them.
-module(good_module).
good_function_name(a_good_atom) ->
{ok, [is, a, reasonable_atom, to, use].
badFunctionName(a_Bad_Atom) ->
try tO:avoidTheUsage() of
pascalCase -> or_Bad_Snake_Case
catch
_ -> 'please!'
end.
Reasoning: This is the convention adopted by most open-source erlang projects (and by OTP itself, to some extent). Using it would make your code more clear and readable for everybody.
Take a look at Erlang.SE (i.e. the programming guidelines for Erlang at Ericsson) and extract as many guidelines as possible for this repo.
Header files should not include type definitions nor record definitions nor function definitions.
Header files could include macros definitions.
The goal is not to confuse people by assuming that's the version they should use.
The reasoning is simple, having all the API in one module makes it easier to use (as the end user just needs to see that module's list of exports to know what functionality is available) and also allows you to change the implementation in very deep ways without worrying about API retro-compatibility.
To see an example of this, you can check kafkerl.erl
Follow the OTP and community standards for project folder structure.
An individual Erlang application has the following structure when it is meant to conform to OTP conventions:
$APP_ROOT
|
-- ebin/ % Contains all generated .beam files.
-- include/ % Contains all public .hrl files.
-- priv/ % Contains all other artifacts.
-- src/ % Contains all .erl files and potentially private
| % .hrl files.
-- test/ % Contains all EUnit test files.
You should use this "flat" directory structure if your project is a simple Erlang application (e.g. a generic component which might be used in other projects) or a library application.
If your system consists of several applications working together, the umbrella project structure should be used, in which the system root contains a folder named apps
which will contain the individual application folders. Each application can then have its own ebin
, include
, src
and test
folders, and the entire project can share resources in the priv
folder, and dependencies can be downloaded and compiled once for the entire project.
$PROJECT_ROOT
|
-- $SYSTEM_ROOT/ % Main system directory.
|
-- config/ % Contains all system configuration
| % files and templates.
-- deps/ % Contains external applications which
| | % are used as part of the system.
| |
| -- some_dep_app/
-- apps/ % Contains all applications which are
| | % part of the system.
| |
| -- some_app/
| -- another_app/
-- patches/ % Contains all patches to Erlang/OTP
| % which are custom to this system.
-- priv/ % Contains all other artifacts.
Reasoning: All erlang tooling assumes these folder structures, and not following them will cause many errors, especially when working with releases.
An Erlang system consists of many applications and needs to follow various guidelines in order to be OTP-compliant. This ensures that it is compatible with various utility tools from OTP, e.g. for release generation. In the following lines the directory structure of a project is shown.
When using sumo_db you should separate the responsibilities clearly, creating for each entity:
By dividing the functions into two different modules we increase understandability of the functionality especially if these are called from external modules. It also allows us to better organize the code and have smaller modules.
This file should describe how this repo is mantained, listing for isntance how to:
A new file to specify rejected rules
This rule needs improvement
RFC 2119 specifies technical meanings for keywords to be used in other technical specifications and guidelines. Making the Inaka guideline documents compliant with this RFC would disambiguate and improve the wording of the guidelines.
If there is a consensus I will re-word the necessary guidelines.
Add TOC and basically structure the rules to make it more easily readable/searchable
Migrate to rebar3 as described here.
This is requested by esl/TODO#62
When specifying dependencies
%% bad
{deps,
[{lager, "2.*", {git, "[email protected]:basho/lager.git", "2.0.0"}},
{jiffy, "0.*", {git, "https://github.com:davisp/jiffy.git", "0.11.3"}}
}.
%% good
{deps,
{lager, "2.*", {git, "git://github.com/basho/lager.git", "2.0.0"}},
{jiffy, "0.*", {git, "git://github.com:davisp/jiffy.git", "0.11.3"}}
}.
SSH requires authentication.
https may require authentication (bitbucket does, github doesn't), but sometimes doesn't.
In addition, https is chatty compared to the git protocol, optimized for cloning repos.
The git protocol's main disadvantage is that it doesn't support authentication, which is a plus for CI systems.
Unless your project is meant to be run as an escript, there should be no
io:format
norct:pal
calls in your production code (i.e. in the modules inside thesrc
folder). Same rule applies forlager
orerror_logger
calls used just for debugging purposes during test stages.
Examples in no_if erl have different conditions betwen bad/1 and better/1, good/1. It needs to correct and extend.
bad(Connection) ->
{Transport, Version} = other_place:get_http_params(),
if
Transport =/= cowboy_spdy, Version =:= 'HTTP/1.1' ->
[{<<"connection">>, utils:atom_to_connection(Connection)}];
true ->
[]
end.
better(Connection) ->
{Transport, Version} = other_place:get_http_params(),
case {Transport, Version} of
{cowboy_spdy, 'HTTP/1.1'} ->
[{<<"connection">>, utils:atom_to_connection(Connection)}];
{_, _} ->
[]
end.
Altough bad/1 defines inequalty, the pattern matching in both of better/1 and good/1 defines equalty between Transport and cowboy_spdy. As this example has a logic to present the transformation, the better/1 and good/1 should be corrected while bad/1 still remains unchanged.
Furthermore arithmetic comparisons between more values (at least 3) and a variable, range checking examples should be even presented here to present the readability differences and to help the reasoning why do not use if's.
Hi,
I just want to make an observation about your suggested guidelines. I want to make clear that I am very well aware this repo only contains guidelines, and not rules. I also understand that inaka can develop code following whatever you guys consider the best. That said,
Aproximately 90% of the Erlang open source code out there is indented with 4 spaces (even Erlang itself):
... to name a few. The only trending project that I know of, using 2-space indentation is cowboy (and all ninenines
repos, of course).
There is a clear agreement when it comes to use spaces over tabs, but it would be ideal if we all agree on a number of spaces per indented line, to make our lifes easier when it comes to contributing to the open source community.
Some references:
My two cents.
Here your fun
body is only indented 2 characters:
erlang_guidelines/src/dyn_calls.erl
Line 10 in 2d6b364
My erlang-mode indents the bodies of fun
s 8 characters and when I'm looking at others' source online it usually is, too, like here:
I assume most people are using standard erlang-mode formatting.
I much prefer your style. Are you guys hand indenting or using a different IDE or have you hacked on your erlang-mode or something?
Of course it has perfectly valid uses, but those are rare, maybe using it could be discouraged? Specially since it's O(n)
Use PascalCase for variable names and don't include underscores in between words.
good(These, VariableNames) ->
TCPSocket = new_socket(),
[These | are(very, good, VariableNames)].
bad(THESE, Variable_Names) ->
Tcp_socket = new_socket(),
[THESE | are(very, bad, Variable_Names)].
Reasoning: This is the convention adopted by most open-source erlang projects (and by OTP itself, to some extent). Using it would make your code more clear and readable for everybody.
do you know any vim syntax plugin that handle all the guidelines? or how to configure vim-erlang?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.