Javascript meta-programming of Annotation

Freedom of language

The concept of freedom has different definitions in different areas, we can learn from the dimension of mathematics constitute a space to practice their freedom of expression, this means: the same problem not related to each other in the number of design methodology.

For example, solve problems such as a merchandise discount, how to design order, extract function, there may be many specific ideas, but it may have been from the process (OP) oriented perspective, the same solution to this problem, if another language also supports object-oriented (OO) design methods, we believe the latter to be more freedom, because OO provides the ability to almost completely solve the problem from another angle.

Since the degree of freedom can learn from the definition of "dimension", we try to analyze the "dimension" computer language, before that, we need to analyze the language is simple step by step how to become complicated.

Focus of this article is a command-style computer language.

The first step, the basic aspects of the structure occurred (data structure), constants, variables, operators, sequence, branching, which reflects the circulation "order";

The second step, there routine, including functions, procedures, etc.;

The third step, the macro appear, including macros, templates, generics;

The fourth step, the objective world abstraction appeared on the structured, including OO and so on;

A fifth step, there membered programming capabilities, such as comments, reflection and the like;
...

From computer language Historically, these steps are not necessarily in chronological order to expand, we are more concerned about the ability to enhance the meaning of language brings. Among them, the second step is completed, marking the emergence of program structure design method for large software projects to provide better support, the third step is further abstracted to the second step, the meaning of the fourth step represents more significant where a very important point, which means you can finally support the achievement of "hierarchical", you can achieve the "core" and "periphery" to do the separation, the part is relatively stable with potential changes apart, that is, the content of the expression of a coding not only flat, and finally evolved a "class."

In essence, it reflects the evolution of rising above their own abstract language ability.

A very interesting phenomenon here is that abstraction on the rise, it will make the language dimension of up to a fractal - abstract nature is to provide some kind of recursive self-similarity mapping in space, thus reflecting the "fractal" the structure, the fractal structure exhibits increased fractal in the original space, but to give a new dimension is difficult integer, i.e., such a dimension can be up to 1.5-dimensional, two-dimensional but can not reach.

Therefore, the current dimensions of the vast majority of high-level computer language is 1.X.

The fifth step, however, means that the language began to really move towards a higher dimension.

In fact, there are many ways to achieve meta-programming, from the language itself is concerned, can be divided into two categories: Enhanced API and new syntax to achieve, on behalf of the former is reflected, on behalf of the latter for the Annotation.

Let's look at an example:

public class TestCase{
    @Before
    public void setUp() throws Exception{}
    @After
    public void tearDown() throws Exception{}
    @Test
    public void add() {}
}

The above is the use of the Java language Annotation type defines a unit test three stages, where:
@ the Before, the After @, @ the Test defined "variable" a "variable", and defines the order of execution, here is "Yes re-encoding process of encoding ", is a typical implementation of meta-programming.

We can of course also be addressed through enhanced API (reflection or by design constraints (such as touching version method)), but no matter what kind, is not the way to be as simple and straightforward Annotation.

The fundamental reason is that there is implementation of the existing code with enhanced API logical expression of these two dimensions too many "relevance", which 1.X-dimensional, but Annotation on the way to greatly reduce the correlation between the two decoupling more dimensions, so that a higher degree of freedom of the latter.

Based on the following JS Mocha unittests:

describe('测试过程1', function() {
    it('1+1', function() {
        expect(fn_add(1, 1)).to.be.equal(2);
    });
});

We expect the following programming style:

'@test(step=测试过程1,name=1+1,expect=2';
var step0 = function(){
    return fn_add(1, 1);
}

JS achieve the annotation-based meta-programming

We will try to introduce a mechanism Annotation JS, as follows:

'@Log(level=info,dateFormat=YYYY-MM-DD HH:mm)’;
var logInfo = function(_msg){
    console.log(_msg);
} 

Complex scenes, consider the relevance of a plurality of annotations:

'@Start';
var serverStart = function(){}

'@Rule(fileType=.(html|htm))';
var proHtml = function(_req,_res){}

'@Rule(fileType=.(jpg|gif|webp))';
var proPic = function(_req,_res){}

'@Finish';
var serverFinish = function(){}

At-js framework

Based on the above ideas, we realized the At-js framework and open source, the realization of ideas At-js is very simple, in the end Node.js, run by overwriting when JS file is loaded mechanism to achieve recognition of the judgment and Annotation types of native files Enhance processing, for performance reasons, At-js embodiment uses regular scans over the AST.

At-js use method comprising: defining and annotations using the annotation.

Definition Comment:

require('at-js').define('helloworld',{//annotation's name
    scope: 'var', build: function () {//the scope of it's effected
        return "return function(_msg)    {console.log('[helloworld]'+_msg);};"//the real script
    }
})

Use comments:

'@helloworld';
var sayHello = function(){}

sayHello('here')

running result:

[Helloworld]here

The following code describes a test unit ( HTTPS: //github.com/CheMingjun ... ):

'@test.start';
var start = function () {
    ds = {};
}

'@test.step(timeout=2000)';
var test0 = function* () {
    ds.test0 = 'finish';
    var rtn = yield (function(){
        return function(_next){
            setTimeout(function(){
                _next(null,3);
        },2000)
        }
    })();
    assert.equal(rtn,3);
}

'@test.step';
var test1 = function () {
    ds.test1 = 'finish';
    return ds;
}

'@test.finish';
var fh = function () {
    ds = null;
}

At-js Var defined annotation support different levels and stages of File, the embodiment is a complex of defined File Notes level, both the API as follows:

Var type defined Notes:

    {
        scope:'var',
        build:function(_ctx, _argAry){
            //_ctx
            {
                filePath,//应该该注释的文件位置
                name,//注释名称
                desc,//注释中的变量表(key-value)
                refName,//被注释的变量名称
                refType//被注释的变量类型(undefined|function|generator|object)
            }
            //_aryAry 被注释变量签名中的参数列表
        
            return //返回该变量被替换之后的代码
        }
    }

File type annotation defined:

    {
        return {
            which: {//针对改组annotation中的每一项做处理
                'test.start': function (_ctx, _argAry) {
                    //_ctx 与 _argAry 同上定义
                    //处理逻辑
                }
            }, script: function () {
                return //返回该文件追加的代码
            }
        }
    }

In the actual production process, the following set of annotations ORM:

    '@dao.column';
    var id;

    '@dao.column(name=name)';
    var name;

    '@dao.column(name=status)';
    var status;

    '@dao.column(name=creator_id)';
    var creatorId;

    '@dao.column(name=creator_name)';
    var creatorName;

    '@dao.column(name=gmt_create)';
    var createTime = function (_time) {
            var mm = require('moment');
            return mm(_time).format("YYYY-MM-DD HH:mm:ss");
    }

    '@dao.column(name=gmt_update)';
    var updateTime = function (_time) {
            var mm = require('moment');
            return mm(_time).format("YYYY-MM-DD HH:mm:ss");
    }

    '@dao.column(name=type)';
    var type;

to sum up

This article gives a brief definition of freedom of language, and discusses the different complexities presented in the language development process on this basis, and discusses how to increase the degree of freedom of meta-programming language is fundamental. In the second part, we try to increase the JS meta-programming language based on the ability of native and introduced the realization of the idea: At-js framework.

Guess you like

Origin www.cnblogs.com/baimeishaoxia/p/12039883.html