Code Monkey home page Code Monkey logo

erlang_guidelines's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

erlang_guidelines's Issues

Atom casing


snake_case for module names, function names, and atoms in general

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.


When making a library, make sure all API functions reside in one module

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

Project Structure

Use standard project structures

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.

Suggestion: Separate responsibilities in sumo_db.

rule

When using sumo_db you should separate the responsibilities clearly, creating for each entity:

  • one module (usually called MODELs) to describe the entity and allow administrating instances of the model in memory
  • one module (usually called MODEL_repo) to handle the various operations that require business logic relating to the entity
reasoning

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.

Create CONTRIBUTING.md

This file should describe how this repo is mantained, listing for isntance how to:

  • Suggest a new rule
  • Suggest a modification to an existing rule

RFC2119 compliance

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.

README.md structure

Add TOC and basically structure the rules to make it more easily readable/searchable

Prefer the git protocol over others when specifying dependency URLs


Prefer the git protocol over others when specifying dependency URLs

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"}}
}.
Reasoning

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.

Don't leave debugging calls in your source code

Don't leave debugging calls in your source code

Unless your project is meant to be run as an escript, there should be no io:format nor ct:pal calls in your production code (i.e. in the modules inside the src folder). Same rule applies for lager or error_logger calls used just for debugging purposes during test stages.

Suggestion: no if recommendation examples are missing or missleading


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.

Spaces per indentation

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.

How do you guys get your funs indented only 2 characters?

Here your fun body is only indented 2 characters:

My erlang-mode indents the bodies of funs 8 characters and when I'm looking at others' source online it usually is, too, like here:

https://github.com/cmullaparthi/ibrowse/blob/d2e369ff42666c3574b8b7ec26f69027895c4d94/test/ibrowse_test_server.erl#L18

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?

Variable name casing


PascalCase for variable names

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.


vim syntax plugin?

do you know any vim syntax plugin that handle all the guidelines? or how to configure vim-erlang?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.