Modular design of RIA projects

    Problems in developing large projects


    ninjaThe separation of data cutlets from performance, design, bikes ... the main thing is without fanaticism. What problem is often encountered when developing RIA applications. A team of strong programmers "falls in love" with a new project, and with the thoughts "now we will do something - the main thing is to do everything ourselves so that no one else’s bug gets inside" begin to abandon ready-made frameworks, libraries, solutions.
    True, there is one logical explanation for this trend, the fear of engaging in someone else’s product, it happens that during development it turns out that such an interface will be very difficult to develop on accessible tools, and crutches, edits of other people's frameworks, etc. are born. I would like to propose a solution to this problem. Creation of the manager of interfaces (modules). One module can use ExtJS, another dhtmlx, or maybe even pure Javascript

    Not stranger - but open


    What are the advantages of using ready-made solutions? It’s easier to find a new person for the project when you use a well-known third-party product. In a situation when you are the only one of the creators of the framework and decide to leave, then most likely the new team will rewrite everything from scratch. Plus, editing bugs and adding new features while you are working on business logic. If you want a powerful weapon in separating data from presentation - use ExtJS for example, why write your own framework !? You need to dynamically load dependencies - look towards YepNope. Work with dom, provide jQuery or any other well-known framework. Focus on the result. I understand that most programmers love to write everything from scratch - but that’s not because he wants to learn, to develop ... it’s from laziness ... yes, it’s from laziness. Learning someone else’s code, reading documentation is much more complicated than developing everything from scratch. When you write everything “from scratch” you don’t learn much, people learn mainly from others, while researching someone else’s work, you learn from experience (it's like eating your adversary’s liver ), and in conjunction with your experience you come up with something new ... more perfect. Creating stable applications in a short time will give you more recognition than digging into the edits of your next mega-framework after the release of the new browser IE6 , IE7 , IE8 , IE9.
    If your goal is to write your own framework, instead of developing an ERP for which you were given a period of 2 months, then start with the OS ... or with the processor architecture ... why not !?

    Modularity as a cure for many diseases


    Modularity is the principle of dividing a complex system into separate parts - modules. What benefit we get - we simplify the development, testing and maintenance of the system, minimize the number of connections between different parts of the system.
    The development of the kernel and modules can be carried out by different people in the team, and at all without interfering with each other. Refactoring the kernel or modules does not affect each other in any way and can be carried out in parallel and independently.

    The core is the head of everything


    The application core is a system part manager. Top manager of a company that acts as a supervisor. It controls access to resources and communication between company facilities. But there is no way to control the loading of goods into the warehouse, the issuance of provisions, etc. Let utilities and libraries to which tasks will be delegated do this.
    The core responsibilities include:
    • Delegation of loading modules and necessary dependencies to the library department (in our case, I chose YepNope).
    • The delegation of creating the canvas for the module interface.
    • Information transfer between modules.
    • Notification of any system events (closing the application, activating a new module, resizing the window, losing connection with the server, etc.).
    • Fulfilling module requests (e.g. loading another module)
    See the full project code on GitHub

    A simplified version of the kernel:
    /*=== core.js ===*/
    !function () {
        var listOfLibraries = {};
        $(window).resize(function() {
            $.each(listOfLibraries, function(){
                this.body.onResize($(window).width(), $(window).height());
            });
        });
        $("script[id=core]").bind('request', function (data) {
            switch (data.header) {
                case "attach":
                    var library = {
                        name: data.body.name,
                        body: new data.body.module()
                    };
                    listOfLibraries[library.name] = library;
                    $('
    ').appendTo('body'); var moduleContext = $('#'+library.name); library.body.main(moduleContext); break; } }); }();

    After loading, the kernel listens for the request message channel ; when a new module is connected, it adds it to the listOfLibraries collection . This collection stores all loaded modules.

    Give independence to the modules!


    Module example:
    /*=== HelloWorld.js ===*/
    !function () { 
        var Lib = function () {
            var context;
            this.main = function (moduleContext) { 
                context = moduleContext;
                context.html('Hello World');
            }
            this.onResize = function(width, height){
                context.width(width);
                context.height(height);
            }
        }
        $("script[id=core]").trigger({  
            type: "request",                
            header: "attach",
            body: {
                module: Lib, 
                name: "HelloWorld"
            }
        });
    } ();
    

    As can be seen from the example, the kernel communicates with external components by means of events, or rather one event “request” - a message pool.
    The body consists of a header ( header ) and a body ( old body ). In this case, the module tells the kernel that it wants to register in the system under the name “HelloWorld” and reports a link to the module body.
    Each module receives a context from the kernel with which it needs to work. Communication with the kernel, other modules or page elements should be through messages.
    Why then do we need a kernel if we could easily create a context in a module and work with it !?
    My answer is: to implement a multi-window interface, to load modules on demand, to be able to load module dependencies, to create a single communication system between modules, to simply maintain code ... and so on.
    As a result, we got a lightweight modular solution, in which even with a complete change in the kernel logic, the code of the modules does not change.
    All changes concern only the addition of new events. To unify the interface for communication between the kernel and modules, it is better to highlight an abstract class with a basic routine implementation and inherit all Lib classes of modules from it.

    window.Module = function () { 
        this.context;  
    }
    window.Module.prototype = {
        main: function (context) {
            this.context = context;
        },
        onResize: function (width, height) {
        }
    }
    

    When connecting a module to the kernel, you only need to make sure that the plug-in inherits the functionality of the abstract class Module, if successful, connect it to the system.
    See the full project code on GitHub

    Also popular now: