Blog de desarrolladores Abanq
Noticias y comentario de los desarrolladores. Bienvenido al blog

6/24/2011

AbanQ 2.4 : User y Developer

— Fede @ 11:00 am

A partir de la versión 2.4. AbanQ inicia un nuevo ciclo de vida de versiones. La idea es converger de forma transparente para el usuario a las nuevas tecnologías que hemos ido desarrollando en InfoSiAL en los últimos años, concretamente al motor AbanQ V3 y AbanQ Nebula. AbanQ 2.4 ya lleva la mayoría de los avances de AbanQ V3 en su motor, como son el sistema de informes para varios “backends” (Kugar, Jasper y SVG) y el sistema de scripts con ejecución de código en bytecode y que incluye los potentes AQSObjects que elevan la potencia de desarrollo de AbanQ a un nivel muy superior.

Con en el inicio de este nuevo ciclo de vida se crearán dos ediciones del motor; AbanQ User y AbanQ Developer. Las características de las versiones oficiales ofrecidas por InfoSiAL de cada una de estas ediciones son las siguientes:

AbanQ User

  • Orientado al usuario final sin necesidades de desarrollo.
  • Sólo ejecuta código en bytecode firmado digitalmente.
  • Sólo carga paquetes de módulos en ficheros con extensión .abanq (AbanQ Packages).
  • Puede exportar los módulos en el formato antiguo versión 2.3.
  • Se publicarán regularmente binarios, junto con su código fuente, que serán gratuitos y de dominio público.
  • En el caso de InfoSiAL se ofrecerá un servicio de certificación y firma de módulos, para que puedan ser ejecutados en los binarios correspondientes. Este servicio se detalla en la ficha del producto, concretamente en este enlace
  • AbanQ Developer

  • Orientado al desarrollador
  • Ejecuta tanto código en crudo como en bytecode
  • Incluye numerosas herramientas de desarrollo; empaquetador, compilador, entorno de desarrollo integrado con depurador y carga estática, etc..
  • Puede cargar, importar y exportar módulos de todas las versiones.
  • Esta versión estará disponible para los equipos de desarrollo de nuestras empresas; InfoSiAL S.L. y Grupo Empresarial para el Desarrollo del Open Source, S.A.
  • También estará disponible para nuestros clientes directos finales que lo soliciten y tengan en plantilla un departamento de desarrollo propio y permanente.
  • Se está estudiando ofrecer AbanQ Developer a todos los desarrolladores como SaaS en alquiler (Software como Servicio) mediante AbanQ Nebula. Los criterios que se van a seguir para decantarse por esta opción se explican en el apartado posterior.
  • CONSIDERACIONES PARA DESARROLLADORES

    En principio no es estrictamente necesario usar AbanQ 2.4 Developer para seguir desarrollando, todo lo que se desarrolle en la versión 2.3 se podrá ejecutar sin problemas en la 2.4 tras el proceso de firma. Cualquier desarrollador puede crear, probar y corregir su código en la versión 2.3 y sólo cuando esté totalmente acabado, firmarlo para ejecutarlo en la versión 2.4. Además la versión 2.3 y 2.4 pueden convivir perfectamente por lo que de cara al cliente se pueden instalar las dos versiones en dos directorios diferentes. Haciendo esto es posible iniciar procesos de desarrollo donde el cliente puede testear y validar todo en la versión 2.3 y sólo pasar a la 2.4 cuando el desarrollo se encuentre en fase estable y el cliente dé su visto bueno. Nosotros estimamos que siguiendo esta forma de trabajo, el coste del proceso de firma no debería ser determinante en el coste total del proyecto de desarrollo.

    Todo esto es suponiendo que se quieran usar los binarios oficiales de InfoSiAL de AbanQ User, y se quiera pagar el proceso de firma. Si no es esto lo que se quiere, cualquier desarrollador con los suficientes conocimientos, puede crear sus binarios no oficiales y adaptarlos a sus requerimientos para poder ejecutar código no certificado y firmado. Evidentemente a partir de ese punto InfoSiAL no dará ningún soporte ni mantenimiento sobre esos binarios extraoficiales ni sobre el código que ejecutan.

    Existe una tercera posibilidad, que hemos mencionado antes, y es la de ofrecer AbanQ Developer como SaaS mediante AbanQ Nebula. Esto está aún sin decidir y dependerá de la respuesta que obtengamos del conjunto de desarrolladores y usuarios sobre el nuevo sistema de certificación y firma. Hemos supuesto dos posibles escenarios, que nos llevarán a una decisión u otra:

  • Si hay cierta aceptación y se contrata regularmente este servicio de certificación y firma, entenderemos que se prefiere que InfoSiAL siga evolucionando el motor para estar lo mas al día posible y que se ofrezcan binarios regularmente. Y por lo tanto asumiríamos que los usuarios y desarrolladores están dispuestos a financiar ese esfuerzo de desarrollo mediante este servicio. En tal caso consideramos que sí sería necesario ofrecer AbanQ Developer como SaaS, ya que creemos que también se estaría dispuesto a contratarlo para seguir financiando el desarrollo.
  • Si no hay esta aceptación del servicio de certificación y firma, entenderemos que no hay interés en que InfoSIAL haga ese esfuerzo de desarrollo del motor y de ofrecer binarios regularmente. Asumiendo también que los usuarios y desarrolladores prefieren crear y usar sus propios binarios extraoficiales. En este caso, seguiríamos con la línea de desarrollo del motor pero de forma mas relajada y sobre todo muy ajustada a las necesidades de nuestras empresas y clientes directos. Por lo tanto en este supuesto creemos que no sería necesario ni rentable ofrecer AbanQ Developer como SaaS.
  • NOVEDADES EN LA VERSION 2.4

    Este sería un resumen de la novedades mas significativas de la versión 2.4:

  • Soporte para PostgreSQL 9.0
  • Soporte para Windows 7
  • Nuevo motor para JasperReports, totalmente integrado con Kugar y SVG
  • Sistema “multi-lenguaje”, que permite cargar dinámicamente y en tiempo de ejecución distintos idiomas para cualquier elemento del sistema. Esto permite, entre otras cosas, diseñar un único informe y tenerlo disponible en los distintos idiomas para los que se ha creado una traducción, siendo el usuario el que puede cambiar a un idioma u otro con un simple clic o cuadro de selección
  • Nueva interfaz de usuario experimental con el estilo de AbanQ V3
  • Nuevo motor de scripts proveniente de AbanQ V3, ejecuta código en bytecode con una significativa mejora en el rendimiento.
  • Tecnología AQSObjects, también proveniente de AbanQ V3, que permite un total control desde scripts de cualquier aspecto de la programación. Ahora ya es posible el filtrado de eventos, dibujar en cualquier elemento gráfico, arrastra y soltar, gestión completa de protocolos de red, manejo completo de XML, etc..
  • En AbanQ Developer, nuevo entorno integrado de programación (Workbench), que incluye un nuevo y potente depurador de Javascript, gestión de proyectos, analizador sintáctico en tiempo de desarrollo, autocomplementado y embellecedor de código, visor de variables, compilador en bytecode, certificación y firma y empaquetado de módulos en ficheros AbanQ Package.

  • AbanQ Developer
    AbanQ Developer

    AbanQ User
    AbanQ User

    11/10/2010

    Nos reinventamos: AbanQ Nebula

    — Fede @ 4:23 pm

    Imaginemos una aplicación totalmente independiente de plataforma y sistema, que el usuario puede utilizar sin notar ningun cambio en la forma de usarla y en su aspecto, en su pc de escritorio, en su movil, en su smartphone, en su pda, en su navegador, etc… Imaginemos tambien que los programadores pueden desarrollar y extender esa aplicación sólo una vez sin preocuparse del sistema destino, sus desarrollos futuros y pasados se podrán ejecutar en todo el universo electrónico conocido, sin ningun esfuerzo adicional.

    Pues dejemos de imaginar porque esto ya es posible con el motor gráfico que ha desarrollado InfoSiAL, al que llamamos Nebula. Nebula nace del desarrollo de AbanQ v3, y ha supuesto un grandísimo esfuerzo de investigación para dotar a AbanQ de total independencia de cualquier sistema gráfico y que permite entrar en la nube de una forma totalmente novedosa.

    Hasta ahora AbanQ trabajaba como todas la aplicaciones de escritorio, la interfaz de usuario se presentaba utilizando el sistema gráfico que ofrecia el sistema operativo subyacente, X11 en Linux, GDI en Windows, Carbon o Cocoa en MacOSX, etc.., esto limita mucho la universalidad de la aplicación, ya que para nuevas plataformas debes hacer un gran esfuerzo de adaptación a bajo nivel. En el desarrollo de AbanQ v3 decidimos romper con esta barrera diseñando un sistema universal sobre el que “pintara” AbanQ, y que nos permitiera salir a la web, a la nube, sin problemas. Afortunadamente tenemos el prometedor estándar HTML5 y su potente elemento Canvas, que puede ser utilizado como la ventana universal para la interfaz de usuario. Investigando, probando y dedicando muchísimo tiempo hemos conseguido desarrollar un motor que permite redirigir toda la salida gráfica de AbanQ a HTML5, e incluso de cualquier aplicación desarrollada bajo Qt.

    Una de las grandes ventajas de Nebula, es su facilidad para incluirlo en cualquier aplicación de Qt, y hacer que esta pueda ser presentada en cualquier plataforma que soporte HTML5 (casi todas actualmente). Esto nos ha permitido por ejemplo tener ya una versión de AbanQ 2.3 preparada para la nube, y nos va a permitir hacer una transición suave desde la versión 2.3 a la 3.0, traspasando gradualmente las tecnologías desarrolladas en la versión 3 a la versión 2, haciendo una evolución que será totalmente transparente para nuestros clientes y evitará cualquier trauma. ¿Para que dar un salto brusco y rompernos un tobillo si hemos descubierto como dar pequeños saltos hasta el objetivo?.

    El proyecto de evolución de la versión 2 a la versión 3, le hemos llamado Proyecto Nebula, y el resultado final será AbanQ Nebula, un sistema ERP/MRP/CRM totalmente universal y novedoso. Este mismo mes empezamos a instalar en algunos de nuestros clientes AbanQ Nebula 2.8, que es una evolución de la versión 2.3 con el motor Nebula y con varias tecnologías de la version 3.0 incluidas. A mediados del año que viene iniciaremos la migración de clientes a AbanQ Nebula 2.9 y a finales de ese mismo año a AbanQ Nebula 3.0.

    Si quereis ver a AbanQ Nebula en acción aquí teneis unos videos:

    VIDEO: AbanQ Nebula
    VIDEO: AbanQ Nebula II
    VIDEO: Nebula para cualquier aplicación Qt

    y algunas capturas:


    AbanQ Nebula en Firefox
    En Firefox

    AbanQ Nebula en Google Chrome
    En Chrome

    AbanQ Nebula en Opera
    En Opera

    AbanQ Nebula en Safari
    En Safari

    6/2/2009

    Por fin: Un editor gráfico de informes

    — Jesús @ 6:53 am

    Durante mucho tiempo AbanQ ha carecido de un editor gráfico de informes realmente usable. El editor de Kugar resulta demasiado básico y no responde a las mejoras que desde InfoSiAL hemos ido haciendo estos años al motor de informes de AbanQ. Así, para editar o crear informes había que hacerlo peleando directamente con los ficheros xml con formato kut en un editor de texto plano. Esta forma de trabajo es lenta y pesada, pero es lo que había hasta este momento.

    En InfoSiAL llevamos meses trabajando y probando un nuevo sistema de creación y edición de informes basado en el uso del editor de interfaces gráficos de QT en su versión 4: QT4 Designer. Este editor es la nueva versión del famoso editor de formularios de AbanQ (QT3 Designer) que hemos venido utilizando hasta el momento. QT4 Designer es mucho más completo e intuitivo que su predecesor, y tiene la potencia necesaria para ser el editor de informes que estábamos esperando.

    El procedimiento es:

    1. Se crea un infome en el formato nativo de QT4 Designer, al que daremos la extension ar (AbanQ Report). Este fichero se guarda en el directorio reports del módulo correspondiente, tal como se viene haciendo con los .kut

    2. Se carga el módulo de informes. AbanQ detecta que hay un fichero .ar nuevo o modificado, ya hace una conversión al vuelo del fichero .ar en .kut

    Internamente AbanQ sigue usando el formato kut, pero de cara al usuario o programador, sólo se ha de tocar el .ar desde el editor gráfico.

    Desde el editor de QT4 vamos a crear los campos y etiquetas del informe, y los vamos a agrupar en sus niveles correspondientes (encabezados, detalles y pies). Desde el panel de propiedades del editor establecemos:

    • Todas las propiedades de presentación del informe (posición, tamaños, colores, alineación, bordes, tipografía…)
    • Propiedades definidas en AbanQ (campo que se mostrará, decimales, formato de fecha, nivel de encabezados y detalles…)
    • Elementos gráficos: líneas o marcos y definición de su color y grosor, y bordes de campos y etiquetas.
    • Propiedades generales del informe (márgenes, formato y horientación de la hoja)

    Veámoslo en alguno pantallazos:

    Un informe en el editor QT4
    El editor. Vemos un informe de pedido de cliente en QT4 Designer. Las alturas de los niveles y detalles son las que tendrá el informe final. Usamos un fondo anaranjado para distinguir los niveles y la posición de las etiquetas y campos. Vemos a la derecha el panel de propiedades.

    Un informe en el editor QT4
    El informe en edición. El informe más de cerca. En los campos podemos poner textos de muestra para hacernos una idea del resultado final y establecer la apariencia con más facilidad.

    Un informe en el editor QT4
    Propiedades de un campo. En el panel propiedades además de las propiedades gráficas del elemento, indicamos qué campo vamos a mostrar y su formato. En este caso es una fecha.

    Un informe en el editor QT4
    El informe en AbanQ. Vemos la apariencia resultante, casi calcada de la que hemos creado en el editor.

    Es necesario resaltar que los informes actuales en formato .kut no se pueden convertir al formato .ar, es necesario rehacer todos los informes actuales para adecuarlos al nuevo formato.

    Publicaremos un documento de uso del editor más detallado en su momento.

    2/26/2009

    Sistema de detección temprana de bloqueos

    — Fede @ 5:42 pm

    En la versión 2.3 tenemos disponible un sistema experimental, sólo disponible para bases de datos PostgreSQL, que permite detectar bloqueos antes que se produzca, o de forma heurística estimar los posibles riesgos de bloqueo que pueden existir en un momento dado.

    El sistema avisa al usuario cuando se encuentra en una situación que puede derivar en un bloqueo o en un bloqueo potencial, permitiendo a este poder esperar o cancelar la transacción en curso y evitar así congelar la interfaz de usuario mientras exista el bloqueo.

    Por ejemplo, si dos usuarios están haciendo un albarán, y los dos intentan reservar un mismo artículo en un mismo almacén, se produce una situación de exclusión mutua sobre la cantidad de stock. Hasta ahora se producía un bloqueo que congelaba la aplicación de uno de los usuarios hasta que el otro acabara el albarán, pero con este nuevo sistema uno de los usuarios (el último en llegar ) será avisado de que si continua e intenta reservar stock en ese momento para ese artículo incurrirá en una situación de bloqueo, permitíendole así esperar, cancelar o si quiere definitivamente caer en el bloqueo.

    El sistema antibloqueos se puede controlar desde los scripts utilizando los nuevos métodos de la clase FLApplicationInteface y cuya documentación se puede encontrar en el fichero FLObjectFactory.h del código fuente de AbanQ.

    Generalmente la forma más sencilla de utilizar este sistema es cuando se llama al método commitBuffer de la clase FLSqlCursor. A partir de ahora este método se puede llamar con un parámetro booleano que indica que se realize una comprobación de bloqueos si es cierto ( true ):


    var cursor = new FLSqlCursor( “albaranaescli” );

    cursor.setModeAccess( cursor.Insert );
    cursor.refreshBuffer();
    …..
    …..
    cursor.commitBuffer( true ); // Con ‘true’ indicamos que se comprueben bloqueos antes de aceptar cambios

    2/17/2009

    Control de acceso sensible al contexto

    — Fede @ 8:10 pm

    En AbanQ v3 se han hecho muchas mejoras en seguridad y en el control de acceso, una de estas mejoras se puede probar en los últimas publicaciones de la versión 2.3; Control de acceso sensible al contexto.

    La mayoría de los sistemas de control de acceso son estáticos e invariantes con los datos, es decir insensibles al contexto, esto significa que nosotros definiremos reglas del tipo “El usuario Eladio no puede modificar los clientes y no puede ver las cantidades totales de las facturas”. Esta regla se aplica de forma sistemática para todos los clientes y para todas la facturas.

    Pero en muchos casos esas reglas de control de acceso necesitan ser aplicadas según el valor de ciertos datos, es decir queremos que sean sensibles al contexto, de tal manera que podamos definir reglas del tipo “El usuario Eladio no puede modificar los clientes de Albacete, y puede ver las cantidades totales de las facturas excepto las que corresponden a los tres meses anteriores”.

    Bien pues este tipo de reglas de control de acceso sensibles al contexto ya es posible usarlas en AbanQ, aún de forma limitada en la versión 2.3 y con toda su potencia en la nueva versión.

    Ahora cada FLSqlCursor tiene su control de acceso para tablas ( FLAccessControlTable ) que aplica al evaluar una condición cuando se carga un nuevo registro. Este control de acceso se puede definir mediante los scripts, las funciones que podemos usar son estas:


    /**
    Establece el acceso global para la tabla, ver FLSqlCursor::setAcosCondition().

    Este será el permiso a aplicar a todos los campos por defecto

    @param ac Permiso global; p.e.: “r-", “-w”
    */
    void setAcTable( const QString & ac ) ;


    /**
    Establece la lista de control de acceso (ACOs) para los campos de la tabla, , ver FLSqlCursor::setAcosCondition().

    Esta lista de textos deberá tener en sus componentes de orden par los nombres de los campos,
    y en los componentes de orden impar el permiso a aplicar a ese campo,
    p.e.: “nombre", “r-", “descripcion", “–", “telefono", “rw",…

    Los permisos definidos aqui sobreescriben al global.

    @param acos Lista de cadenas de texto con los nombre de campos y permisos.
    */
    void setAcosTable( const QStringList & acos );


    /**
    Establece la condicion que se debe cumplir para aplicar el control de acceso.

    Para cada registro se evalua esta condicion y si se cumple, aplica la regla
    de control de acceso establecida con FLSqlCursor::setAcTable y FLSqlCursor::setAcosTable.

    Ejemplos:

    setAcosCondition( “nombre", VALUE, “pepe” ); // valueBuffer( “nombre” ) == “pepe”
    setAcosCondition( “nombre", REGEXP, “pe*” ); // QRegExp( “pe*” ).exactMatch( valueBuffer( “nombre” ).toString() )
    setAcosCondition( “sys.checkAcos", FUNCTION, true ); // call( “sys.checkAcos” ) == true

    @param cond Tipo de evaluacion;
    VALUE compara con un valor fijo
    REGEXP compara con una expresion regular
    FUNCTION compara con el valor devuelto por una funcion de script

    @param condName Si es vacio no se evalua la condicion y la regla no se aplica nunca.
    Para VALUE y REGEXP nombre de un campo.
    Para FUNCTION nombre de una funcion de script. A la función se le pasa como
    argumento el objeto cursor.

    @param condVal Valor que hace que la condicion sea cierta
    */
    void setAcosCondition( const QString & condName, int cond, const QVariant & condVal );


    Con estas tres funciones podemos definir cualquier regla de control de acceso a nivel de tabla y que tengan en cuenta el valor de los datos de cada uno de los registros. Se puede establecer un permiso global para la tabla y luego permisos concretos para campos que sobreescriben el global. Por ejemplo este código en masterfacturascli.qs, permite editar el nombre y oculta el cif para registros bloqueados ( campo editable = false ).


    function interna_init()
    {
    var cur = this.cursor();

    // Permisos concretos para campos
    var acos = new Array( “nombrecliente", “rw", “cifnif", “–” );

    cur.setAcTable( “r-” ); // Permiso global sólo lectura
    cur.setAcosTable( acos ); // Lista permisos de campos

    // La condicion para aplicar la regla es que el campo editable tenga el
    // valor false
    cur.setAcosCondition( “editable", cur.Value, false );
    …….
    ……
    }

    Básicamente la definición de reglas sensibles al contexto se reduce en dar un permiso global, permisos concretos de campos y una condición que puede ser, comparar con un valor, con una expresión regular o el resultado que devuelve una funcion de script indicada, a esta función se le pasa el cursor, el contexto, actual de datos que condicionará el que se aplique o no una regla.

    2/14/2009

    Estilos SVG en informes de AbanQ

    — Fede @ 8:36 pm

    A partir del Build 14641 de la versión 2.3 vamos ir incluyendo algunas tecnologías extraídas de AbanQ V3 para que sean probadas a modo de prelanzamiento. Intentaremos ir poniendo en el blog algunas entradas comentando las más importantes.

    Y como el movimiento se demuestra andando empezamos ya mismo viendo una de esas funciones, Estilos SVG en informes, una pequeña pieza sacada de AbanQ V3 pero muy interesante y que seguro que será de mucha ayuda para mucha gente.

    EL CONCEPTO

    La idea es simplificar el diseño de informes utilizando estilos SVG fácilmente editables mediante herramientas existentes de diseño vectorial, aprovechando que los informes se pueden guardar en este formato y que ya tenemos un motor que puede interpretar y aplicar los atributos de ficheros SVG en el momento de la presentación.

    EJEMPLO BÁSICO

    Vamos a modificar el formato de la factura de cliente utilizando esta técnica, utilizando una versión del motor a partir del Build 14641 y la conocida herramienta Inkscape incluida en la mayoría de las distribuciones de Linux.

    Guardamos una factura cualquiera en formato SVG, para esto sólo debemos realizar la acción de imprimir y en el visor de informes pulsar el botón “Guarda como estilo SVG” de la barra de herramientas:


    El fichero SVG guardado lo editamos con Inkscape y hacemos una pocas modificaciones:



    Si volvemos al visor de informes y en el cuadro “Estilo” indicamos el fichero modificado obtenemos la nueva presentación del informe:



    Para hacer que este estilo fuera el predeterminado del informe bastaría modificar el fichero .kut e incluir la propiedad StyleName en la etiqueta raiz KugarTemplate:


    … kugartemplate BottomMargin=’50′ LeftMargin=’30′ PageOrientation=’0′ PageSize=’0′ RightMargin=’30′
    StyleName=’file:/home/falbujer/SVG/prueba.svg’ TopMargin=’50′ …

    Si la ruta empieza por file: se buscará el fichero en el sistema de ficheros de disco, si empieza por abanq: el fichero se buscará en la base de datos ( tabla flfiles ). En la base de datos se puede guardar un fichero en Administración, nuevo fichero y copiando y pegando el contenido XML del mismo. También existe el método FLReportViewer::setStyleName para establecer el estilo de un informe desde los scripts de forma dinámica.


    EJEMPLO MENOS BÁSICO

    En la mayoría de los casos es aconsejable que todo lo que no sean datos que vienen de la consulta que genera el informe sea “dibujado” en el estilo SVG, en vez de hacerlo editando el fichero .kut.

    Por eso cuando se utiliza esta técnica las etiquetas Label y Line del .kut deberían de dejar de usarse delegando el dibujo de esos objetos al estilo y al momento final de la presentación, reduciendo así drásticamente el tiempo necesario para diseñar un informe. Para esto podemos “Guardar SVG simplificado”, que sólo contiene los elementos del .kut que provienen de la consulta, es decir los campos de datos:

    Continua… (more…)

    9/25/2008

    ¿Qué pasa con AbanQ v3?

    — Fede @ 4:10 pm

    Mucha gente nos hace esta pregunta y siempre contestamos lo mismo, ya está listo lo que inicialmente teníamos previsto desarrollar, pero aún no lo vamos a liberar. Pero ¿por qué?, ¿sois unos desalmados que nos quereis hacer sufrir? ¿habeis abandonado el proyecto? ¿formais parte de una alianza conspiranoica mundial para nunca sacar el software en su fecha?.

    Pues no, la explicación es simple; Un día cuando ya teniamos nuestro AbanQ v3 listo, alguien dijo “bueno pues ya que estamos ¿por qué no hacemos una versión con interfaz Web totalmente compatible con la versión de escritorio?", y así empezó todo. Tenemos esto:

    AbanQ GUI V3 para Escritorio

    y ahora ya estamos consiguiendo tener además esto:

    AbanQ GUI V3 para Web

    Continua… (more…)

    12/20/2007

    Colaboración: Asientos predefinidos

    — Antonio @ 7:41 am

    Nuestro colaborador Guillermo Molleda, de la Universidad de Sevilla, está ultimando unas mejoras sustanciales en el apartado de Asientos Predefinidos del módulo de contabilidad. Estas mejoras estarán listas en la próxima versión 2.3

    Entre estas mejoras está un tratamiento más claro y eficiente de las variables en memoria, así como algunas modificaciones en la interfaz de usuario.

    Damos las gracias también a Mathias Behrle por su colaboración con Guillermo a la hora de testear su desarrollo. Danke Mathias!

    Plantilla de partidas

    11/23/2007

    AbanQ v3 : El motor de scripts, parte I

    — Fede @ 12:31 pm

    Hasta la versión 2 hemos venido usando el magnífico producto de Trolltech, QSA. La verdad es que ha funcionado muy bien y se ha portado como un campeón, pero a la hora de desarrollar AbanQ v3 y ver con detenimiento que podríamos mejorar, hemos visto algunas carencias del motor de script que queríamos solventar, así que hemos desarrollado un QSA con asteroides que trae algunas mejoras, veámoslas.

    Más rápido y Ahorra memoria = Menos cansino

    QSA incorpora su intérprete de ECMAScript (parecido a JavaScript ), no vamos a entrar en detalle de cómo funciona un intérprete, para el caso nos basta saber que existen una serie de reglas gramaticales que se aplican a un código fuente y que mediante reducciones se van creando los nodos de la gramática que almacenan la información necesaria para ejecutar ese código.

    La mayoría de la información que almacenan los nodos de la gramática son cadenas de texto, generalmente correspondientes a literales que se asignan a identificadores de variables, funciones, constantes, etc. Es fácil de prever que el número de cadenas de texto que puede llegar a contener un código medianamente grande es significativo y que una manera eficiente de crearlas y almacenarlas determinará la velocidad de ejecución y consumo de memoria. ¿ Cómo hace esto QSA ?, pues vamos a ver:

    Si nos fijamos por ejemplo en una regla de reducción de la declaración de una función:

    FunctionDeclaration:
    FUNCTION IDENT ‘(’ ‘)’ ResultSignature FunctionBody
    { $$ = new QSFuncDeclNode($2, 0L, $5, $6); delete $2; }

    IDENT, es efectivamente una cadena de texto ( el nombre de la función que elige el programador ), que se crea en el analizador léxico con este código:

    case Identifier:
    if ( (token = QSLookup::find( &mainTable, buffer16, pos16 )) < 0 ) {
    qsyylval.ustr = new QString( buffer16, pos16 );
    return IDENT;
    }

    Es decir se hace un new QString( buffer16, pos16 ) cada vez que se encuentra un identificador, ese puntero se pasa al nodo y se elimina; new QSFuncDeclNode($2, 0L, $5, $6); delete $2; ( el $2 hace referencia al parámetro 2 de la regla, es decir a IDENT ). Al crear el objeto nodo, este hace copia de la cadena y la almacena como un atributo suyo. Sólo hemos visto el nodo tipo función, pero es similar para muchos otros nodos que reducen identificadores; variables, vectores, constantes, clases, etc.. Por lo tanto resumiendo, cada vez que el intérprete encuentra un identificador, realiza estos pasos:

    • Crear una cadena de texto con new QString en la cabecera de la memoria
    • Pasarle el puntero de esa cadena al nodo que debe almacenarla
    • El nodo hace copia (profunda) de la cadena
    • Cuando el nodo ya ha copiado la cadena de texto, esta se elimina de memoria

    Podemos ver varios inconvenientes en esta manera de actuar, el que más llama la atención es el hecho de repetir sin cesar new’s seguidos de delete’s. Esto es muy ineficiente tanto en consumo de memoria (en el siguiente apartado se habla sobre otros inconvenientes que tiene esta manera de actuar con la memoria) como en velocidad de ejecución, sobre todo teniendo en cuenta que hay muchos identificadores que son literales exactamente iguales en distintas partes del código y es una pena que no nos acordemos de los creados con anterioridad, y así no tener que volver a crearlos, hacer copia y después destruirlos.

    En el caso del código de AbanQ, es especialmente interesante acordarse de los literales de los identificadores ya que debido a su estructura jerárquica y predefinida se reusan constantemente los nombres, por ejemplo ¿cuantos identificadores del tipo “internat_init”, “oficial_beforeCommit..”, “bufferChanged”, etc.. hay en los scripts de AbanQ?, efectivamente, un mogollón.

    Pues pensando, pensando, si tuviéramos algún contenedor donde almacenar las cadenas de texto de los identificadores, y cada una de ellas etiquetada con una clave unívoca, podríamos reutilizarlas ¿no?. Pero además si esa clave unívoca es un número, se la puedo pasar a los nodos que ya no tendrán que copiar la cadena, sólo almacenar esa clave y cuando se vaya a usar realmente la cadena de texto hacer una búsqueda por clave en el contenedor.

    Con esto conseguimos:

    • Ahorrar memoria ya que las cadenas repetidas sólo se almacenan una vez en el contenedor y los nodos sólo deben almacenar los números clave que hacen referencia a ellas.
    • Rapidez de ejecución ya que sólo creamos las cadenas nuevas y no se realizan copias profundas de las mismas en los nodos. Estas copias profundas son lentas, mucho más que el hecho de almacenar simplemente un número.

    Bien pues ahora sólo queda elegir que tipo de contenedor usamos y cómo generamos esas claves unívocas.

    Como contenedor nuestro planteamiento está pidiendo a gritos una tabla Hash ( QHash ) que almacena pares (Clave, Valor), este tipo de contenedor permite realizar búsquedas muy rápidas y optimiza bastante bien la memoria, el contenedor elegido es QHash(quint32,QString) , o lo que es lo mismo claves tipo entero sin signo de 32 bits que identifican a cadenas de texto.

    Para crear las claves unívocas lo ideal sería tener una función inyectiva, o uno a uno, que tomando como entrada una cadena de texto devolviera un numero de 32 bits único para ella. Bien, pues esto que parece tan fácil tiene tela si queremos que esa función sea lo suficientemente rápida cómo para que pase desapercibida. Realmente lo que estamos buscando es una función hash perfecta que garantice que no existan colisiones ( en este caso, una colisión se produce cuando para dos cadenas distintas se genera el mismo número de 32 bits ). La buena noticia es que la funciones hash perfectas existen, la mala es que son muy lentas. También tenemos la opción de usar una función hash no perfecta y asumir un mínimo riesgo de colisión. Calculando ese riesgo vemos que es perfectamente asumible con ciertas funciones hash rápidas y no perfectas, por lo que finalmente hemos decidido que merece la pena usar esta opción. La función elegida es esta:

    uint QSLexer::hashUstr( const QString & s )
    {
    int len = s.length();
    if ( !len )
    return 0;
    uint hash = 0;
    for ( int i = 0; i < len; ++i ) {
    hash += s[ i ].unicode();
    hash += ( hash << 10 );
    hash ^= ( hash >> 6 );
    }
    hash += ( hash < < 3 );
    hash ^= ( hash >> 11 );
    hash += ( hash < < 15 );
    return hash;
    }

    Esta función es muy rápida y la probabilidad media de colisión es de 1 entre 4.294.967.296 ( 2 elevado a 32 ), aunque realmente esa probabilidad de colisión es aún menor, ya que en la practica se maneja un diccionario bastante reducido de palabras. En resumidas cuentas casi podríamos decir que es más fácil que te toque la lotería del niño que tener una colisión de estas.

    Lo que hemos hecho al final es modificar QSA para tener una tabla Hash global a todos los nodos y generar claves para las cadenas de texto de los identificadores que van pasando por el analizador léxico. De esta forma los pasos que realiza el intérprete cuando encuentra un identificador son estos:

    • Calcula la clave unívoca de la cadena de texto mediante nuestra función hash.
    • Si la clave ya existe en la tabla Hash global no hace nada, de lo contrario la almacena en esta tabla.
    • Le pasa esta clave numérica al nodo que debe almacenarla

    El primer paso es muy rápido, y en el segundo para muchos casos sólo se realizará una búsqueda en la tabla, ya que hay muchas probabilidades de que la clave ya exista. El tercero también es muy rápido ya que sólo consiste en almacenar un valor numérico. Parece que hemos ganado algo, en el último apartado veremos si es verdad, ahora veamos lo que dejamos pendiente sobre otros problemas que tenía QSA con la memoria.

    Fragmentos de mi memoria

    Otro problema que solventa la nueva gestión de las cadenas de texto que acabamos de describir, merece mención especial. El problema es la fragmentación de la cabecera de memoria, también conocida como heap o memoria dinámica. En la implementación original de QSA hemos visto que se repiten hasta la saciedad la creación ( new’s ) y destrucción ( delete’s ) de cadenas de texto, tantas veces como identificadores encuentra el analizador léxico.

    Ya sabemos que un new reserva memoria y un delete la libera, en este caso las reservas de memoria en general son excesivamente pequeñas al referenciar en la mayoría de los casos a cadenas de texto cortas, unos pocos bytes. Estos trozos pequeños de memoria se crean en el heap de forma dinámica conforme se demandan y no de forma contigua, generalmente intercalados con otros trozos mas grandes que forzosamente se crean durante la ejecución, al liberarlos se marca como libre el trozo que ocupaban, por lo que al final tenemos muchos trozos pequeños libres dispersados por el heap. Tal y como lo hace la implementación original de QSA al realizar un análisis léxico de mucho código deja plagado el heap de mini-trozos no contiguos de memoria libre, en AbanQ se analiza muchísimo código constantemente por lo que en nuestro caso el problema aún es mas grave si cabe.

    El segmento heap aumenta su tamaño cuando se pide reservar un nuevo trozo de memoria que no cabe en un trozo liberado. Siempre que se pueda reubicar una reserva de memoria en un trozo de memoria liberado el heap no crecerá, ya que reusa memoria liberada. Cuando tenemos muchos trozos pequeños no contiguos, que en suma son mucha memoria libre pero que por separado son difíciles de reusar al no poder albergar nuevas reservas de memoria mayores, estamos ante un problema de fragmentación. Al crear trozos tan pequeños se obliga a crecer mucho al segmento heap ya que en la práctica aunque esos trozos están libres es como si estuvieran ocupados al no poder reusarse. Como la memoria no es infinita podemos llegar aun desbordamiento y hacer caer a la aplicación cuando en realidad no se necesita tanta memoria.

    En los sistemas Unix se soporta mejor este crecimiento de la memoria dinámica y rara vez se produce un desbordamiento, pero los sistemas Windows lo llevan peor, esta es una de la razones por la que Windows da calabazas cuando AbanQ le pide marcha.

    En la nueva implementación esto queda resuelto ya que todas las cadenas se crean una sola vez y se almacenan en una tabla hash que internamente compacta y agrupa sus elementos en memoria contigua, es decir, se usa mucha menos memoria y una vez que se libera es reutilizable.

    La prueba del algodón

    Ahora tenemos que ver si realmente todo esto ha servido para algo o no. La única manera que se me ocurre es ejecutar código y medir tiempos, tampoco vamos a ser muy exigentes, un par de scripts típicos, no sea que al final nos salgan resultados negativos y nos deprimamos.

    Probamos con Fibonacci:

    function fibonacci(n) {
    if (n == undefined)
    throw “Try calling the main function…";
    if (n == 0)
    return 0;
    else if (n == 1)
    return 1;
    return fibonacci(n-1) + fibonacci(n-2);
    }
    function oficial_fibo( n:Number ):String
    {
    var d1 = new Date();
    var fib;
    for (var x = 0; x < = n; ++x) {
    fib = fibonacci(x);
    print(’Fibonacci number: ‘ + x + ‘, is: ‘ + fib);
    }
    var d2 = new Date();
    var e = d2.getTime() - d1.getTime();
    print( ‘Total time : ‘ + e + ‘ms’ );
    }



    fibo( 22 ) - 22 términos

    QSA viejo

    QSA nuevo

    ejecución 1

    4725ms

    3456ms

    ejecución 2

    4687ms

    3511ms

    ejecución 3

    4737ms

    3456ms

    No está mal

    Ahora con un script genérico con consulta SQL:

    function prueba()
    {
    var d1 = new Date();
    var res:String = “Version ” + this.version();
    var cur:AQSqlCursor = new AQSqlCursor( “divisas” );
    cur.select();
    while( cur.next() )
    res += “n
    ” + cur.valueBuffer( “descripcion” );
    var qry:AQSqlQuery = new AQSqlQuery();
    qry.setTablesList( “clientes” );
    qry.setSelect( “nombre” );
    qry.setFrom( “clientes” );
    if ( qry.exec() )
    while( qry.next() )
    res += “n
    ” + qry.value( 0 );
    var bancos;
    bancos = [["0030″, “BANESTO"],["0112″, “BANCO URQUIJO"],
    ["2085″, “IBERCAJA"],["0093″, “BANCO DE VALENCIA"],
    ["2059″, “CAIXA SABADELL"],["2073″, “CAIXA TARRAGONA"],
    ["2038″, “CAJA MADRID"],["2091″, “CAIXA GALICIA"],
    ["0019″, “DEUTSCHE BANK"],["0081″, “BANCO DE SABADELL"],
    ["0049″, “BANCO SANTANDER CENTRAL HISPANO"],["0072″, “BANCO PASTOR"],
    ["0075″, “BANCO POPULAR"],["0182″,"BANCO BILBAO VIZCAYA ARGENTARIA"],
    ["0128″, “BANKINTER"],["2090″, “C.A.M."],["2100″, “LA CAIXA"],
    ["2077″, “BANCAJA"],["0008″, “BANCO ATLANTICO"],
    ["0061″, “BANCA MARCH"],["0065″, “BARCLAYS BANK"],
    ["0073″, “PATAGON INTERNET BANK"],["0103″, “BANCO ZARAGOZANO"],
    ["2013″, “CAIXA CATALUNYA"],["2043″,"CAJA MURCIA"],
    ["2103″, “UNICAJA"],["2105″, “CAJA DE CASTILLA LA MANCHA"],
    ["0042″, “BANCO GUIPUZCOANO"],["0138″, “BANKOA"],
    ["3056″, “CAJA RURAL DE ALBACETE"]];
    for (var i:Number = 0; i < bancos.length; i++)
    res += “
    ” + bancos[i][0] + ” ” + bancos[i][1];
    var d2 = new Date();
    var e = d2.getTime() - d1.getTime();
    print( ‘Total time : ‘ + e + ‘ms’ );
    return res;
    }


    QSA viejo (tiempo/memoria)

    QSA nuevo (tiempo/memoria)

    ejecución 1

    16ms / 51.4 Mb

    38ms / 8.7 Mb

    ejecución 2

    12ms / 51.4 Mb

    6ms / 8.7 Mb

    ejecución 3

    13ms / 51.6 Mb

    6ms / 8.8 Mb

    La primera vez es mas lento porque carga la tabla hash, luego es el doble de rápido. Con la memoria si que se nota de verdad.

    Al parecer si que hemos conseguido algo, pero aún se puede conseguir más, ya lo veremos más adelante.

    11/20/2007

    AbanQ v3 llama a las puertas de InfoSiAL

    — Fede @ 7:40 pm

    Pues sí, la versión 3 del motor de AbanQ está a punto de ver la luz después de varios meses de desarrollo. Hay avances muy significativos que recogen toda la experiencia que hemos adquirido durante estos años con AbanQ y del trabajo diario con nuestros clientes y usuarios. Estamos ante una pieza de software realmente avanzada y sofisticada que seguro gustará a los desarrolladores y usuarios.

    En esta entrada voy a resumir lo más interesante que traerá esta nueva evolución del motor, aunque mi intención es ir añadiendo nuevas entradas con explicaciones más detalladas sobre los detalles técnicos de los distintos subsistemas que componen el motor, así que si te interesa todo el galimatías técnico pásate por aquí de vez en cuando.

    AbanQ V3

    ¿Que hay de nuevo?

    - Totalmente reescrito en Qt4. Entre otras cosas esto significa mejor funcionamiento en todas las plataformas, incluida Windows.
    - Ya que lo hemos reescrito pues hemos mejorado la arquitectura creando distinto módulos de lo que antes era la librería flbase; AQCore, AQSql, AQNetwork, AQScript, etc..
    - Sistema de importación automática de módulos de la versión 2, totalmente transparente para el usuario. Pueden convivir perfectamente motores de la version 2 con los de la versión 3.
    - Posiblidad de conectar simultáneamente a varias bases de datos desde una misma instancia de aplicación.
    - Interfaz mejorada con formularios flotantes ( docks ), navegación en árbol con marcadores y recientes.
    - Diseño totalmente MVC, separando completament la lógica de la presentación. Hojas de estilos.
    - Sistema propio de ficheros basado en SQL ( AQSqlFileSystem )
    - Cada módulos ofrece una interfaz tipo shell (AQShell )
    - Consola de sistema para manejar el sistema de fichero SQL y con interfaz para manejar los módulos mediante comandos.
    - Drivers mas eficientes para MySQL y PosgreSQL
    - Nuevo motor de scripts, basado en QSA y WebKit
    - Compilación de scripts en bytecode. Interpretación rápida de bytecode

    AbanQ V3

    AbanQ V3

    6/26/2007

    Open Document como motor de informes alternativo

    — site admin @ 1:03 pm

    Hace poco publicamos una nueva extensión que permite generar un presupuesto con formato de Open Document (odt) a partir de una plantilla de referencia también en odt. La extensión crea el documento a partir de una serie de parámetros y de las propias líneas del presupuesto.

    A raíz de esto hemos estado investigando la posibilidad de utilizar Open Document como un sistema de generación de informes alternativo de forma genérica. Por lo pronto estamos preparando una pequeña extensión que permitirá definir formatos de factura en odt.

    Ejemplo de documento odt

    La principal ventaja de esto es que el usuario puede definir el formato de sus informes de modo totalmente libre mediante Open Office, NeoOffice, etc, ya que en Open Document el estilo y los datos están separados.

    El problema reside en que Kugar, a través de numerosas adaptaciones, nos permite realizar bastantes cosas que con odt habría que reprogramar: campos calculados, varios niveles de detalles, suma y sigue, etc.

    El cualquier caso para informes sencillos vemos que es una alternativa muy interesante.

    2/13/2007

    Estreno del Blog

    — site admin @ 12:33 pm

    Los programadores de InfoSiAL estrenamos este blog en el que iremos publicando nuestras ideas y proyectos a medida que se vayan desarrollando.

    InfoSiAL

    Powered by WordPress

    Categorías
    Histórico
    February 2012
    S M T W T F S
    « Jun    
     1234
    567891011
    12131415161718
    19202122232425
    26272829  
    Buscar