Inspirel banner

Programming Distributed Systems with YAMI4

10.1 The Benefits Of Code Generation

As was already explained in the chapter devoted to YAMI4 data model, distributed systems should be treated as dynamically-typed due to the potentially independent evolution of communicating software modules. A single binary program that is inconsistent with regard to its own data type definitions indicates a severe compiler or linker bug or a serious deployment error - such problems are so disruptive that most programming languages do not even try to protect their run-time layers against them and a program crash is an accepted consequence of such a situation. Accepted, because the whole problem is under local control and a single program can be easily fixed and redeployed.

Things look a bit different when many programs in a distributed system are involved - an inconsistency between various modules is not only much more likely, it is also not acceptable for the server program to crash just because an older or newer version of the client has sent an unrecognized message. This means that data definition inconsistencies should be possible to handle, preferably at the application level, so that meaningful diagnostics can be created. This is achieved with the ``parameters'' API described earlier, which detects data definition inconsistency at run-time and reports errors to the application code.

As an example, consider the following C++ code:

{
    parameters params;
    // ...
    
    int a = params.get_integer("a");
    // ...
}

The code above works correctly if the parameters object indeed contains the integer entry with the given name - and gracefully reports an exception if this is not the case. This allows to deal with inconsistent remote modules without taking risk of falling into undefined behavior.

Still, even though completely type-safe, the above approach to data interchange might not be fully satisfying as there is an opportunity for simplification that is easy to spot. Consider an example program that receives a 3D point value from some other program:

struct point
{
    int x;
    int y;
    int z;
};
// ...

{
    parameters params;
    // ...
    
    point p;
    
    p.x = params.get_integer("x");
    p.y = params.get_integer("y");
    p.z = params.get_integer("z");
    // ...
}

The code above looks tedious, and could be simplified with appropriate helpers that can be generated automatically, so that the point value can be easily reconstructed from the incoming packet based on provided structure definition. It should be noted that whether the remote program uses the same code generator to simplify its own code is irrelevant as long as it can deliver expected data fields in the message.

The code generation that allows to simplify the application code on both client and server side is supported in YAMI4 in the form of YAMI4 Definition Language or, in short, YDL. It is a declarative language that allows to describe both data types and the set of supported messages and then generate appropriate code stubs that are easy to integrate with the program code.

One important property of such automatically generated code stubs is that they are imperative and synchronous, meaning that they do not allow the flexibility in meassage management that is natural with the regular YAMI4 agent API. Whether this property is an acceptable price for the added code clarity is to be judged by the application designer.

The YAMI4 Definition Language, the yami4idl compiler and generator and the language mappings are described in the following sections.