WHAT: this is a blog where i collect news about the usage of javascript a serious programming language on the client side and server side. WHY: because it seams to be the most ubiquitous language and has functions as first class objects, and closures and ....

Sunday, June 29, 2008

Declaring Object Structures

There are different ways of creating object structure.
One is declaring a structure:

Declerative programming emphasises on the principle of concentrating on WHAT is the result and not HOW it that result achieved.

SQL is for example a declerative query language. As a consequence there are lots of implementation variations and they can be improved without the changing the user code.

There is a good language for everything, look how we can declare object structures for example a HTML DOM structure:



  • Computational Construction

    This involves calling an API, and create instances directly with function calls. It is thus not delerative at all:


    var body = document.getElementByTag('body')[0];
    var div = document.createElement('div'); body.appendChild(div); div.setAttribute("class","c1 c2");
    var p = document.createElement('p'); div.appendChild(p);
    var bla = document.createTextNode("bla bla"); p.appendChild(bla);


    This a very verbose way to build object structures.
    We are using functions to declare a structure by 'computing' it, altough there is not much computing going on, more wiring structures together over and over again.
    Each each library of functions creates a sort of new 'language'. But as it are functions the emphasis is still on computation. The disadvantage is that there is so much freedom in ordering and verbose calling going on, that we can not capture the relevant information at once: What is really going on? Compare this to the next code resulting in the same structure:


    var bla = document.createTextNode("bla bla");
    var body = document.getElementByTag('body')[0], div = document.createElement('div');
    var p = document.createElement('p'); p.appendChild(bla);
    body.appendChild(div);div.appendChild(p);
    div.setAttribute("class","c1 c2");

    The focus on HOW we build it, hides the knowledge about WHAT we build.


  • Representive Data Declaration

    In this case we define the final oject structure, what we want, by using representive data structure:


    var html = [{ body : [{}, {div:[{ class: "c1 c2" }, {p: [{},"bla bla"]} ]} ]}
    }]


    We then need extra functional code wich translates the object structure into the final object structure: funtion get_node(description,document){ .... return 'the node';}, which can hide all sort of implementation details.

    With this pure data based approach, we are forced to use the elements and semantics provided by the base language. Here we use for eample javascript object literals to express html literals. As javascript has other semantics then html mark up it is not so good at it. It makes it more verbose. See how we have to express that importance of ordering of html child nodes by using arrays, and how we allow multiple object with the same name by using objects with a single attribute. That is why we get these repeating ':[{' ']}' and kind of brackets.

    A small advantage is that the parser checks some of the brackets, but as the correctnes depends on a certain combination, the correct 'html' syntax can be checked only at runtime.

    Another advantage is that you only need to learn javascript to be able to 'read' html, and not an extra language. On the other side to 'understand' it, you still have to learn the html concepts. And the verbose non suitable notation is not very helpfull.

    Ext uses this approach combined with the computational construction.

    Other examples of this approach and its limits can be seen when using XML based template languages or even XSLT. Very often XSLT contains computational elements like 'if' 'then' 'else'.
    Expressing this in a declerative language that was not designed to be computational becomes very verbose and besides it then is a sort of 'XML' it does not provide any advantage. We use a lanaguage for what it was not designed, and therefore is not good at. The interpunctation is not optimized. For example XML only knows nested brackets, we can not express directly an expression with 3 elements 'if C then A else B' directly, but have to encode it: 'AB' or simular. To make it simple we then put functional code like javascript in the string attributes or text nodes.
    That is mostly often exactly what template languages do.


  • Decleration with Function Language

    Here we use function calls with objects as parameters in a mixed way, as builders to create the object structure:

    var body_node = body()
    .div({class:"c1 c2"})
    .p("bla bla").end()
    .end()
    .end().toString(document);


    This allows a short flexible notation mixing calls and parameter objects.

    Note how this approach goes step further in using functions as interpunctation elements. The meaning changes depending on the context. Here a own block/bracket structuring language is developed by using javascript function names.
    Because we are allowed to introduce new function names with n paramters we can change the set of available language elements.

    The syntactical correctnes is not controlled by the language parser, but could be at runtime. Throwing a missing end() call exception for example.

    This is thus creating a new language using a an other language. We thus can use the programmatic API calls mixed with object strcuters as function parameters as an implementation of the function language deceleration.

    jQuery also uses this approach.





  • Dedicated Language


    This seams to be the shortest and clearest way to declare a structure. Use a dedicated optimzed language, suited to the purpose.


    var body = '<body><div class="c1 c2"><p>bla bla</p></div></body>';


    Note how the function language decleration approach may serve as an implementationof a parser/compiler/runtime system for such a language.

    In a first attemp, a pre processor could translate the above code in a appropiate function calls:


    var body_node = body().div({class:"c1 c2"}).p("bla bla").end().end().end().toString(document);


    While many people resist when developers want to define a new language, because things become 'complicated' then this is just part of the truth. Above examples show that without a dedicated language, things do not get clearer. While not learning something 'new', that standard code is very 'hard' to understand so what costs more? The problem is that it is not easy to design a good language and often you would need to extend it, adapt it to changes. You must spreak a fashionable language, you need to find enough developers. You need good debugging capabilities etc. This makes it as hard just like the framework programming where you start depending completly on the framework/compiler developer.

    A big part of the problem is that the dedicated language gives you the feeling of being locked in the 'every thing must be expressed in this language/framework' trap. And things start to become even more problematic if in an attempt to 'escape' these limits complete external languages are mixed in with there own different semantics but then need to communicate with each other using API calls, then all sort of adapters libraries, translations are needed and then at the interfaces all sorts of conversion errors and mismatches occur. You are in a trap.
    Just see what happend to the HTML Javascript, java, flash mixing.

    A requirement to make a language work is to be able really to hide the implementation for 95% of the cases to developers and allow a simple debugging. This 'all or nothing' requirement is what makes a dedicated language not suitable for single projects. There are how ever some things that can done to embed a dedicated language, and not suprisingly they are the same as for developing a library:


    • Take a primary full supported language with debugger libraries as starting point. And embed your stuff in it. Not the other way round.
      First design a good library of you add ons.


    • Make the use of the language extension optional. The old framework idea don't call us, we call you approach is causing the locked in the trap. It makes you reacting like a fool, never knowing when you are getting called and why. Debugging is a pain. The developer of the user code must be in control when he calls what. Most developers even SQL programmers simply think in HOW things are done and must be able to programm, test and debug that way.


    • Keep the language small and simple. If you can not hide the inner working 100% make them obvious, provide source and allow debugging. C++ startet as a simple preprocessor. The resulting C code could still be debugged and was understandable. Lateron when it became popular debuggers/compilers made it an own language.


    • If you are not able to put it a good concise library then you are not able to make it a good language.





No comments: