Skip to content

Arpple/code

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 

Repository files navigation

Code

Format/Styling

Tab > Spaces

Why?

tab = everyone can set it to how many space you are comfortable with

No semicolon

What?

just don’t use ; if you can

Why?

human don’t read semicolon if machine also don’t need it so what does it for?

if there are possibility for unexpected behavior, it may be worth to put it for safety but consider before if that is from bad writing format or from the language itself

Allow multiple empty line

What?

const groupOfLogic = () => {
  a
  a

  b
  b
}


otherBlock()

Why?

can provider better outline for seperation of code

Allow Any arguments per line

What?

when function have many arguments it should expand to multiple line but let’s the human decide how it should be written

Why?

new line can provide a grouping of arguments

const processEntityWithPosition = (
  entity, entityRelated,
  vectorX, vectorY, vectorZ,
  other
) => {}

Don’t enforce newline on multiple line arguments call

What?

when you want to call or construct something with multiple lines allow to put first or any number of arguments on same line

Why?

there are many cases that it will easier to read

// seperate data from logics
pipe(data,
  fn1,
  fn2
)

Length = Lifetime

What?

the longer the variable/function/class live the longer (descriptive) the name should be

// itemValidator.js
const filterItemOnlyInStock = (items) =>
  items.filter((item) => {
    stocks = Stock.getAllStocks(item)
    return stocks.filter((s) => s.quantity > 0)
  })

Dangling comma when multiline

Why?

additional 1 key right after you finish a line or maintaining the only last line to be without comma

acronym = word

What?

treat acronym same as single word, no matter what it is any character long in this way, the rule will be simple and the same in every case style

example word: HTML, IO

in camel case: html io htmlIo ioHtml

in pascal case: Html Io HtmlIo IoHtml

in snake case: html io html_io io_html

Code

Prefix > Infix

What?

infix

obj
  .something()
  .another()

prefix

pipe(obj,
  X.something(),
  Y.another()
)

Why?

easier to tap between pipeline by transforming function

pipe(obj,
  debug(log.info)(X.something),
  Y.another()
)

and you can still chain functions even they are not in the same class

Chain > Big Chunk Factory

What?

big chunk

const buildProduct = (params) => ({
  name: params.name,
  isActive: params.isActive || true,
  price: params.price || 0,
  brand: params.brandId
    ? BrandRepo.find(params.brandId)
    : null
})

chained

const buildProduct = (name) => ({
  name,
  isActive: true,
  price: 0,
})

const setActive = (isActive) => (product) => ({
  ...product, isActive
})

const setPrice = (price) => (product) => ({
  ...product, price
})

const setBrand = (brandId) => (product) => ({
  ...product,
  brand: BrandRepo.find(brandId)
})

product = pipe(buildProduct(),
  setActive(true),
  setPrice(100),
  setBrand(1)
)

Why?

don’t need to remember parameter key easier to seperate big building logic

Find vs Get

What?

my suggestion

find try to retrieve something but it may not found +so return type will be the thing or null

get just retrieve something and it should be exists so return type will be only the thing and may raise exception if not found

or you can use other words you want, but be consistent and explicit for example in Laravel there are find and findOrFail or in elixir you may use get and get!

Boolean parameter only for data

only use boolean parameter as a data, never use it for beheaviour

What?

// isActive is the boolean flag for data strucure
function setActive(isActive) {
  row.isActive = isActive
}

// isHungry is the boolean flag (maybe) read from data structure
// but use to define behavior
function eatFood(isHungry) {
  if (isHungry) {
    // eat
  } else {
    // not eat
  }
}

Why?

for readability and also understandability when calling the function

for setActive(true) you can know right away that true is mean for active

but for eatFood(true) it hard to know what true mean

Data structure for data

create data structure to model the data try not to create one for config behavior

What?

data strucutre for data is obvious, but data structure for behavior may look like this

type PurchaseParam {
  isIncludeTax: boolean,
  shippingFee: number | undefined,
}

function purchase(param: PurchaseParam) {
  if (param.isIncludeTax) {
  }

  if (param.shippingFee) {
  }
}

const param = {
  isIncludeTax: // some specific 'Shop'
  shippingFee: // total price of 'Item[]' over something
}

purchase(param)

Why?

making this kind of structure is a sign that you separate the decision logic and execution logic in different place

obviously the PurchaseParam isn’t represent any kind of data or model but just used do define the behavior of this specific purchase() function

you can see from example that the actual data is Shop and Item[] and it better to just use the actual data

function purchase(shop: Shop, items: Item[]) {
  if (shop) { // specific Shop
    // include tax
  }

  if (items) { // total price over something
    // add shipping fee
  }
}

No index file

What?

for language like js, you can use index file to be root file of directly so that you can write import with that directory name

- module
  - index.js
  - something.js
  - else.js

// when use
import 'module'

but you can do this instead

- module.js
- module
  - something.js
  - else.js

// when use
import 'module'

Why?

because with this you can start with just

- module.js

and when the module grow larger you don’t need any renaming and just create the directory with sub module

- module.js
- module
  - something.js
  - else.js

Testing

“Fail” test first

Why?

if the test fail, that means it actually is executed

Test by behaviour

What?

I have an article for this here

HTTP Api

define base path outside child route

What?

when defining route, don’t define prefix in subpath

// base.js
router.use(subRoute)

// subRoute.js
router.prefix('/sub')
router.get('/', controller.get)

instead define it in base path

// base.js
router.use('/sub', subRoute)

// subRoute.js
router.get('/', controller.get)

Why?

when you digging a code of some api it’s easier to start from top level which is base path by defining prefix in base you can see which file you need to go next without jumping to that file firsts

and if you start from sub route, you can still guess prefix from file/module name

About

note on coding preference

Resources

Stars

Watchers

Forks