Skip to content
Victor Nakoryakov edited this page Jul 3, 2017 · 4 revisions

This document describes common conventions that XOD source code follows.

Stylistic issues are handled automatically with ESLint and don’t deserve much attention. More fundamental principles can’t always be checked automatically, so they’re described in plain text.

Some aspects of the guide were introduced after many parts of XOD were already written so the code itself may not follow the principles 💯 but it should and would. You can help by making a PR.

Functional style programming

We’re very shifted toward functional programming style to an extent where JS allows to do it and what feels rational. We heavily rely on Ramda library to do it.

If you’re not familiar with FP concepts, the code could seem awkward to you. However, once you get it, you’ll find that such style leads to more explicit and reliable code, more reuse, easier testing, fewer surprises. Start with Thinking in Ramda and Professor Frisby’s Mostly Adequate Guide to Functional Programming.

Many sections below are direct consequences of functional programming style.

Prefer functions to classes

Classes are hard to extend and combine. They provide an implicit this object and in many cases encourage internal state mutation. Instead, use plain functions which operate on plain JS-objects. They are much easier to compose and test.

Use immutable state

Don’t mutate objects. To perform an update make a copy, change that copy, and return back the changed copy as a result. Ramda provides many functions to do it easily.

Minimize side effects

Side effects are viral. If a function has some side effect like FS or network access, and another function is composed with it, that new function would have side effects too. If it would get out of control the whole code base will be dirty, and loose all benefits of FP.

So the rule is:

  • Have as few impure functions as you can
  • Let other functions to take their results or themselves as argument

For example if you have some settings stored in a file instead of

loadSettings :: () -> Settings
loadDefaultBoard :: () -> String
loadDefaultPort :: () -> String
uploadDefault :: () -> ()

use:

loadSettings :: () -> Settings
getDefaultBoard :: Settings -> String
getDefaultPort :: Settings -> String
upload :: String -> String -> ()

Show side effects with name

Don’t use very generic get and set as verbs for impure function names. Make an emphasis with verbs like load, send.

Use Maybes and Eithers

Don’t catch exceptions

Don’t use complex monads just because

Don’t be point-free to be pointless

Clone this wiki locally