/flowjs

Primary LanguageJavaScript

Flowjs

一个开放的,面向业务流程的,可灵活扩展和定制的前端业务开发框架。

本次0.5.x的更新相比之前版本有巨大的变化。

  • 极大的简化了《流程》和《步骤》的定义。
  • 简化输入输出数据的校验,不做深度校验,提高执行效率(看未来是否有需要加深度校验)
  • 内部通过context的传递来避免多次调用时,步骤数据会互相覆盖的情况。
  • 开始编写测试用例。

框架思路

互联网产品的特点就是快速的迭代更新,这就对前端的响应速度提出了挑战。flowjs的思路,就是通过抽象变化的产品形态背后相对稳定的业务流程,来以不变应万变!

框架由《流程》和《步骤》两个部分组成。《流程》负责定义一个业务逻辑的流程,《步骤》负责定义流程中一个步骤的实现。

开发同学可以将一个产品,定义为Flowjs的一个《流程》。当产品细节发生变化时,开发同学可以在基于流程不变的情况下,通过快速修改对应的步骤,来快速响应产品变化。

并且一个产品流程可以开放出来,类似的产品可以复用该《流程》,用自己的《步骤》实现来迅速完成自己产品的开发。

Flowjs还可以帮助开发者提高自己代码的逻辑性和可读性。《流程》代码与流程图有异曲同工之处。能够让其他开发者更容易的读懂和维护你的代码。

注意事项

每一个步骤需要明确的定义本步骤的输入与输出数据,否则会获取不到需要的流程数据,本步骤对数据做出的修改也无法提交到流程里。

允许一个步骤不经过定义,就直接使用。流程在执行时会自动跳过该步骤。便于先跑通主要流程,再实现具体步骤。

步骤与步骤之间尽可能的减少依赖

每一个步骤只能调用一次callback通知框架步骤完成

最佳实践

把Flowjs包到你的类中,提供默认的《步骤》实现。

function YouClass(options){
    this._flow = new Flow();
    var steps = {
        'step1':require('./step1'),
        'step2':require('./step2'),
        'step3':require('./step3')
    };
    if(options && options.steps){
        Object.extend(steps,options.steps);
    }
    var flow = this._flow;
    for(var stepName in steps){
        if(steps.hasOwnProperty(stepName)){
            flow.implement(stepName,steps[stepName]);
        }
    }
}

对《步骤》的重写,可以通过引用新的步骤文件实现。例如:

var steps = {
    'step1':require('./step1'),
    'step2':require('./step2'),
    'step3':require('./step3')
};

要重写step1,可以新创建一个step1文件newstep1,然后引用新文件

var steps = {
    'step1':require('./newstep1'),
    'step2':require('./step2'),
    'step3':require('./step3')
};

测试

nodejs环境下

npm install -g mocha
mocha test/

《流程》定义

var Flow = require('flowjs');

var flow = new Flow();

//《步骤》定义
flow.addStep('step1',{
    type:'step',  //《步骤》类型。step/condition/event。可选
    input:{ //输入数据
        param1:{
            empty:false //是否允许为空,默认为true
        }
    },
    output:{ //输出数据,如果param1未定义为输出数据,那么步骤内对param1做出的修改,不会保存的《流程》中
        param1:{
            empty:false //是否允许为空,默认为true
        }
    }
});
flow.addStep('step2'); //也可以仅仅这样来定义一个《步骤》。这将会定义一个type为step,没有输入输出数据的《步骤》
flow.addStep('step3',{ //这样可以定义一个condition类型的《步骤》
    type:'condition'
});
flow.addStep('step4',{ //这样可以定义一个event类型的《步骤》
    type:'event'
});

//《步骤》的实现
flow.implement('step1', {
    /**
     * 《步骤》的go方法,会作为《步骤》的入口,《流程》在执行到该《步骤》时,会执行go方法
     * @param  {[object]}   data    如果定义了input,那么会传入需要输入的数据
     * @param  {Function} callback  《步骤》执行完成后,需要调用callback通知《流程》
     */
    go: function(data, callback) {
        callback();
    }
});
flow.implement('step2', {
    go: function(data, callback) {
        callback();
    }
});
/**
 * 这是一个condition类型的《步骤》
 * @param  {Function} callback  这个回调的原型是function(data,condition){}
 * 其中condition表示步骤选择的分支。例子中表示,执行该步骤后,选择case1分支作为后续的步骤继续执行
 */
flow.implement('step3', {
    go: function(data, callback) {
        callback(data,'case1');
    }
});
/**
 * 这是一个event类型的《步骤》
 * @param  {function} callback 这个是步骤结束后的回调,同step类型的回调
 * @param  {function} trigger 这个是有事件发生时,用于通知《流程》的方法
 */
flow.implement('step4', {
    go: function(data, callback, trigger) {
        $(document).on('click',function(){
            trigger(data,'docclick');
        });
        callback(data,'case1');
    }
});

/**
 * begin的原型为function(data){}
 * 其中data为传入到流程中的初始数据
 */
flow.begin();
flow.go('step1');
flow.go('step2');
flow.go('step3',{
    cases:{
        //定义case1条件分支
        case1:function(){
            flow.go('step4',{
                events:{
                    //定义docclick事件发生时的处理
                    docclick:function(){
                        flow.go('step5');
                    }
                }
            });
        }
    }
});
//一个流程的所有除event类型的步骤都执行完毕后,会触发end事件。
flow.on('end',function(){
    
});

API

Flow

implement:function(stepName,options){}

    public

    实现《流程》中的一个《步骤》。

    stepName

        《步骤》名

    options

        实现《步骤》的相关参数

destroy:function(){}

    public

    销毁流程,会调用每一个执行过的步骤的destroy方法,让每个步骤有机会去释放资源。

go:function(step,options){}

    public

    用于定义《流程》

    step

        步骤名

    options.events

        定义传入event类型《步骤》的事件集

    options.cases

        定义传入condition类型《步骤》的分支集

addStep:function(name,options){}

    public

    向流程注册步骤

    name

        《步骤》名

    options

        定义《步骤》的相关参数

升级指导

0.5.0开始,《流程》和《步骤》的定义方式全部发生变化,请老版本代码按照0.5.0的方式重新定义