-
Notifications
You must be signed in to change notification settings - Fork 127
Style Guide
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.
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.
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.
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.
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 -> ()Don’t use very generic get and set as verbs for impure function names. Make an emphasis with verbs like load, send.