FORCÉN

a.k.a. el turista accidental

Módulos, teoría y praxis

Jueves
11.sep.14

Haciendo limpia en el disco duro encontré este documento escrito hace cinco años para explicar la base de la librería que se creó para una aplicación de gestión de proyectos altamente configurable. El backend era PHP orientado a objetos y en el frontend se usó Prototype.

Lo recupero aquí porque me sorprendió lo poco que he evolucionado en estos cinco años. La falta de necesidad, realmente; de aquella intentaba explicar a maquetadores web con algo de experiencia en Javascript como organizar un proyecto. Todo un cambio de mentalidad para ellos. Y dice así:

Una webapp puede tener de uno a N módulos. Cada módulo tiene su propio directorio. Los sistemas de permisos y acciones utilizarán el nombre de los directorios y de las vistas contenidas en los mismos para gestionar el acceso de los usuarios al contenido y acciones.

Usamos sformi [un pequeño proyecto privado hecho en PHP] para crear el código de los elementos principales de un Módulo: las clases y vistas, tanto principales como para cada objeto del módulo; y, por supuesto el dispatcher del módulo.

A continuación se describen los elementos del Módulo. Cada uno se corresponde con un archivo “.php”.

Vista Principal

Típicamente una lista de los objetos/entidades gestionados en el módulo. Un módulo puede tener más de una vista principal, por ejemplo “presupuestos.php” y “facturas.php”. El “index.php” de cada directorio sería siempre la vista principal por defecto.

Vista de Objeto/entidad

Una pantalla para editar los detalles de un tipo concreto de objeto/entidad. La vista contiene, típicamente, un formulario y las acciones necesarias para gestionar la vida del objeto. El generador permite crear el código para manejar Tabs dentro de la pantalla. Ejemplo “factura.php”.

Clase Principal

La clase que gestiona un módulo (ej: facturasClass). Desciende siempre de datosClass [una clase que encapsula el acceso a MySQL]. En su versión más simple tiene un método get[OBJETOS] utilizado desde la Vista Principal. En esta clase se incluyen también otros métodos comunes a todos los objetos del módulo, utilidades, etc.

Clase de Objeto

La clase para gestionar un objeto del sistema (ej: facturaClass). Desciende de la Clase Principal del Módulo al que pertenece. En su versión más simple tiene los cuatro métodos básicos de gestión de datos (get, insert, update, delete). Como regla obligatoria cada clase se corresponde con un archivo. No se define más de una clase por archivo, excepto en casos muy excepcionales.

Dispatcher

Este es el mecanismo preferido de comunicación via AJAX. Recibe, como mínimo, tres parámetros:

objeto: El ID de una clase del sistema. Este ID lo definimos en _config.php y en config.js

accion: El ID de la acción a ejecutar. Las cuatro básicas están definidas en _config.php y en config.js

id: El ID del objeto sobre el que aplicar la acción. Por ejemplo, el id de una factura o de un proyecto.

Algunas de las acciones requiere un cuarto parámetro, el payload, un objeto serializado con los datos a grabar.

Al llamar al dispatcher se instancia un objeto de la clase indicada en objeto, pasando el valor id como parámetro del constructor. A continuación ejecuta el método especificado por el la acción. Las cuatro básicas están creadas por defecto en el Dispatcher del Módulo.

Es “legal” utilizar otro mecanismo para comunicarse con el servidor, por ejemplo un “saveTask.php”, pero como norma general se utilizará el “dispatcher.php”.

  • Comentarios desactivados
  • What’s in an SPA?

    Martes
    09.sep.14

    Initially nothing. You can start from zero. Or have a landing page with a login, like in this case:

    <body>
    <div data-role="page" id="login">
    <div class="login">
            <label for="user">User</label><input id="user"/>      
            <label for="pwd">Password</label><input id="pwd" type="password" />
       <button>Login</button>
        </div>
    </div>
    </body>

    The header is equally frugal.

    <head>
        <meta charset="UTF-8" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="apple-touch-fullscreen" content="yes" />
       <meta name="viewport" content="user-scalable=no, width=device-width">
        <title>SPA</title>
    
    <link rel="stylesheet" href="css/jquery.mobile-1.4.3.min.css" />
    <link rel="stylesheet" href="css/base.css" />
    
    <script src="libs/jquery-2.1.1.min.js" type="application/javascript"></script>
    <script src="libs/jquery.mobile-1.4.3.min.js" type="application/javascript"></script>
    <script src="libs/can.custom.js" type="application/javascript"></script>
    <script src="libs/require.js" type="text/javascript"></script>
    
    <scipt>
    'use strict';
    
    var objApp;
    
    // a couple of functions that I’ll discuss below in the article
    
    </script>
    </head>

    I want to have jQueryMobile available from the beginning. Can.js is the basis of my MVC framework, so I have it loaded to. And Require.js, the tool that I’ll be using to load the code only when the user needs it. Forget about loading all of your JavaScript “just in case”.

    Now, you don’t really have to do nothing of until the user asks you to, so let’s wait for her to tap on the Login button and then start your app:

    $(function () {
        $('#login button').on('click', function(event) {
            event.preventDefault();
            if(!objApp) {
                require(['utils', 'app'],
                        function(utils, app) {
                                    objApp = app;
                                    login();
                                }
                        );
            } else {
                login();
            }
        });
    });

    I’m declaring the global objApp just to be a good citizen (and to pass my own strict jshint validations). Once the user decides to login I start loading code. Using Require.js I ask for utils.js and app.js files. You’ll notice that the callback receives two parameters, utils and app and I only use the second one. The reason is simple: in utils.js I have different objects, functions and some native functions overrides. I’m just declaring them as globals. In app.js I have something completely different: a couple of can.js based objects, ModulesHander and Application (what’s in those objects and what they do is irrelevant right now) and this magic block of code:

    define(
        function () {
            return new Application();
        }
    );

    This is the code that will tell to Require.js what is the result of loading app.js: a newly instantiated Application object. And that object is what Require.js passes to my callback: a brand new Application object that I assign to the objApp var. And then I attempt to login().

    function login() {
        objApp.authenticate(
                            $('#user').val().trim(),
                            $('#pwd').val().trim(),
                            function (boolOK) {
                              if(boolOK) {
                                    objApp.launch();
                                } else {
                                    alert(‘Wrong user or password.');
                                }
                            });
    }

    At this point of execution I know that objApp “contains an Application” so I can just call any of its methods, such as authenticate() to check if the user and password belong to a valid user and retrieve the configuration for that user. Or such as launch(), that is the method that put in action the rendering of any required pages and the loading of needed modules.

    Now, your app is ready to go. To continue…?

  • Comentarios desactivados
  • What do I do?

    Martes
    09.sep.14

    I code, I teach, I design, I sometimes take pictures. I’ve been coding for a very long time. Very long. By the time the people I was working at Apple with in the early nineties were phasing out into management I was still coding. I’m still coding now, twenty years later.

    Yeah, right. Very touching. What do I really do?

    I code nice Javascript applications. Not webpages, not sites. Applications. Single Page Applications, if you want to get technical. The kind of apps where the only HTML you write is hidden in a bunch of templates. That are, in turn, hidden into a bunch of modules. That communicate with other modules. All in object oriented Javascript. Ok, everything in Javascript is an object, but you got the point.

    Then I make that SPA talk to a back-end. I can code it in node.js (of course), or in OO-PHP, .NET (don’t tell anyone, but I hate C#) or, even better, I can avoid coding my own backend and link to an existing API. Plug into Twitter’s firehose, filter the messages you need and mix them with some other feed, show it beautifully to your user.

    Now, put the SPA into an Objective-C or Java “container” that makes it run as a native app in your tablet. You have an hybrid application. You know, this decade favorite flame war: hybrid or native. Everyone enjoys a nice flame war. Anyway, you get an app ready to distribute. And that applies too to the kind of app you need to acccess your CRM or your intranet while in the road.

    What else? All coders are lazy. It’s a requirement. We’re into coding to avoid repeating boring tasks. So you go and learn the joy of Grunt to handle and build your project. Oh, the things you can do with a tool like Grunt: generate the configuration for your modules, minimize and join the exact modules you need for a release… There’s a ton of things to do to have a perfect build: let a tool do it while you sip your coffee.

    So, what do I do? I design and code apps in Javascript. I don’t “make webs”.

  • Comentarios desactivados
  • El Diógenes digital

    Lunes
    08.sep.14

    Cientos de archivos temporales, otros tantos en directorios de entrada de un proceso, versiones antiguas punto zip (con una fecha para saber cuándo se olvidó eso ahí), archivos de código que ya no forman parte del proyecto…

    Bienvenidos al apasionante mundo del Síndrome de Diógenes digital. Una tara que es síntoma de ineptitud digital. Porque no tienes un sistema de versiones operativo (o lo tienes pero no lo usas “porque no me fío”). Porque no has montado en tu servidor una tarea que periódicamente limpia los archivos temporales que tu programa ha ido generando, por ejemplo, al subir los documentos de tus usuarios. Ineptitud digital. Especialmente grave si lo descrito en el primer párrafo lo encuentras en un servidor de producción.

    Por favor, que alguien le pase un pañito al server. Y, después, al proceso en general.

  • Comentarios desactivados
  • Apps simples

    Viernes
    27.jun.14

    Los tres gatos que me conocen me han oído repetir más de una vez un mini-mantra: una app hace una única cosa y la hace bien. Y cada vez hay menos excusas. La versión 8 de iOS incluye mecanismos de comunicación entre aplicaciones que superan la funcionalidad de los Intents en Android. Ya tiene las dos plataformas mayoritarias la capacidad de crear aplicaciones que ofrecen servicios a otras aplicaciones.

    Así que se acabó el hacer apps llenas de poyaques y de “por si alguien la necesita”. De hacer apps monolíticas con distintas “secciones” que intentan cubrir todo lo que un usuario pueda necesitar de un tema concreto. Si tu idea de producto cubre distintos aspectos crea una app por cada uno de ellos. Y, si esos aspectos/secciones/negociados necesitan intecomunicarse hazlo, pero usando el sistema. No creando una única mega app.

    El usuario que no necesita cargar con todo no se perderá o no dirá “buff, yo busco algo más simple”. El soporte y actualización de cada app será más simple. Sobre todo la actualización en cierta App Store que no se caracteriza por sus tiempos de reacción.

    Apps simples, que hagan una única cosa y la hagan bien. No mareeis a los usuarios.

  • Comentarios desactivados