Skip to content
/ kdo Public

Easily organize functions or files, make the code clear, easy to read and maintain.

License

Notifications You must be signed in to change notification settings

hiowenluke/kdo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kdo logo

Kdo

Kdo easily organizes and executes small functions or files (as "NodeJS Best Practices" recommended), more better than plain functions (why), makes the code clear, easy to read and maintain. Kdo requires Node.js 7.6+ for async/await.

Kdo itself spreads the code into multiple small functions and files too. Noapi (a light API framework for Node.js, easily define, I/O and test) is a good usage of Kdo, it is recommended to read its source code.

Installation

npm i kdo --save

Test:

git clone https://github.com/hiowenluke/kdo
cd kdo
npm install
npm test

Examples

See examples to learn more.

Why kdo

There are many benefits to using kdo + flow (object or files) instead of plain functions.

1. Easily pass data

Left (not good)

The code in main function is complicated, pass the same parameters to multiple tasks, return new parameters from the task, and pass the new parameters to the next tasks, these make the code look uncomfortable and not easy to read.

And, the main problem is that the main function performs data dis-assembly and transfer. When we change the input and output parameters of the sub-function, we have to modify the related code in the main function at the same time, which means that the sub-function are not completely encapsulated.

Right (good)

Each of the functions is very concise and the logic is clear and easy to understand.

Examples

2. Clear process control

Left (not good)

The code that handles flag === 1 is spread across two places, f2 and main. When we change the condition of flag === 1, we need to modify these two places. If the code is long, or these functions spread across many files, then we may miss something.

And, the code in main function will not elegant (yes, writing elegant code is one of my goals).

Right (good)

The condition flag ===1 is met in f2, so the f3 will be ignored. We do not need to add redundant code in main function.

Examples

3. Flexible return value

Sometimes, in order to make the code structure clear, we classify the flow code into multiple files in a multi-level directory.

In the task flow, after a file is processed, if a non-undefined value is returned, kdo will terminate the subsequent processing and return it to the main function.

We do not need to write additional complex code. Yes, if we use plain functions instead of kdo, there must be a lot of redundant code to handle the same logic.

Examples

4. Require directory as an object

We can use kdo to easily organize small files in multi-levels directories, require them as an object, and access the functions or any other properties of it.

Examples

5. Require directory as a flow object

When we spread our business flows across multiple files in multi-levels directories, managing these flows is a big problem. This problem can be easily solved with kdo.

Kdo can easily requires the entire directory (including sub-directories) as flow object. So, we can split the long code into multiple files in multi-levels directories, without any restrictions.

// require the directory (including sub-directories) as a flow object
const flow = kdo('./01-flow');

const main = async () => {
    // execute all functions in flow object one by one
    // according to the order of the directory name and file name.
    const result = await kdo.do(flow);
    return result;
};

module.exports = main;

If our directories and files are as following:

/f1
    /f12
        f121.js
        f122.js
    f11.js
    f13.js

/f2   
    f21.js
    f22.js
    
f3.js

Then the order of execution will be like following (cool, right?):

f11, f121, f122, f21, f22, f3

See below examples to learn more.

Further more, we can specify the order of execution in index.js under directory, like below:

// index.js

const options = {
    first: 'f3', // execute these functions at first
    last: ['f7', 'f4'], // execute these functions at last
    exclude: 'f5', // do not execute these functions
};

module.exports = kdo.flow(options);

See below examples to learn more.

6. Require directory as an independent module

Kdo can easily requires the entire directory (including sub-directories) as a independent module, the main function does not needs to care about the details of it, just call it.

// index.js

const kdo = require('kdo');

// Kdo.flow() returns a function which does the following:
//     1. Requires the current directory (including sub-directories) as a flow object
//     2. Executes all functions in the flow object one by one
module.exports = kdo.flow();

Then require it in main function, and execute it.

// Require the sub-directory as a function which wrapped by kdo.
// Means, the sub-directory is a fully independent module, the main
// function does not needs to care about the details of it, just call it.
const flow = require('./01-flow');

const fn = async () => {
    const args = {a1: 1, a2: 2, a3: 3};

    // Execute the flow function, get the result.
    const result = await flow(args);
    return result;
};

module.exports = fn;

See below examples to learn more.

Why small functions

Why we should split long code into small functions or files?

The worst large applications pitfall is maintaining a huge code base with hundreds of dependencies - such a monolith slows down developers as they try to incorporate new features. Instead, partition your code into components, each gets its own folder or a dedicated codebase, and ensure that each unit is kept small and simple.

Otherwise: When developers who code new features struggle to realize the impact of their change and fear to break other dependent components - deployments become slower and riskier. It's also considered harder to scale-out when all the business units are not separated.

MURDER rule

Simply put, this can leads to MURDER which is a good thing (the answer comes from stackOverflow, by John Dibling):

  • M - Maintainability. Smaller, simpler functions are easier to maintain.
  • U - Understandability. Simpler functions are easier to understand.
  • R - Reuseability. Encourages code reuse by moving common operations to a separate function.
  • D - Debugability. It's easier to debug simple functions than complex ones.
  • E - Extensibility. Code reuse and maintainability lead to functions that are easier to refactor in 6 months.
  • R - Regression. Reuse and modularization lead to more effective regression testing.

More good articles

License

MIT

Copyright (c) 2019, Owen Luke

About

Easily organize functions or files, make the code clear, easy to read and maintain.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published