Desarrollo en Dynamics AX 7: La nueva arquitectura

Mientras esperamos que se publique la versión definitiva de “El Nuevo” AX o Dynamics AX 7, podemos empezar a comprender las bases del sistema utilizando la información publicada y la Preview pública. Antes de entrar a analizar los detalles de la nueva versión, que son muchos y nos va a llevar bastante tiempo, hay que comprender las bases que han motivado todos esos cambios y que nos van a permitir comprender mejor la nueva forma de desarrollar, que aunque utiliza herramientas parecidas a las versiones anteriores, veremos como son totalmente diferentes.

Model Store vs Local Repository

En versiones anteriores el código y los metadatos se almacenaban en ficheros de capa (AX 2009) y después en bases de datos, ya sea una base de datos dedicada (AX 2012 R2+) o en la propia base de datos de negocio (AX 2012 RTM). Este simple hecho condicionada las herramientas que podíamos utilizar para trabajar con este código y metadatos. Esto es, programar, crear nuevos objetos, hacer pruebas, compilar, etc…

En AX 7 el código se almacena en ficheros en el disco, como en la mayoría de lenguajes modernos, donde tenemos la versión de los ficheros que nosotros estamos modificando. No en ficheros XPO como en ficheros anteriores, sino en un formato nuevo del que hablaremos más adelante, y estos nuevos ficheros pueden abrirse desde Visual Studio utilizando Proyectos y Soluciones propias de este editor para organizar nuestros desarrollos.

Modelos vs Paquetes

Aparte de este cambio en el almacenaje y gestión de los metadatos, en la nueva versión X++ es un lenguaje completo y nativo de la plataforma .NET, y por tanto el compilador y la ejecución son la misma que en los lenguajes .NET. El resultado más evidente de este cambio es que el código compilado (que en la versión anterior se guardaba, también, en base de datos) genera ensamblados (librerías DLL) que se ejecutan en CLR, como el resto de la plataforma .NET.

packages models projects

Continue Reading…

Microsoft Dynamics AX 7 y el nuevo X++

El nuevo Microsoft Dynamics AX también trae consigo “el nuevo X++“. La mayoría de cambios recibidos por el nuevo X++ son relativos al compilador y las herramientas para desarrollarlo. El compilador es totalmente nuevo, haciendo de X++ un lenguaje más del stack de .NET, lo que ha permitido integrarlo totalmente con Visual Studio y evitar el compilado en dos partes de versiones anteriores: No más p-code, todo el código X++ es compilado ahora directamente a CIL. Pero de esto hablaremos otro día, hoy vamos a ver los cambios en el lenguaje en sí mismo, en la sintaxis, disponibles en la nueva versión:

luke-skywalker

Mejoras respecto a AX 2012

  • Finally… añadido el bloque finally a las estructuras try..catch. Su funcionamiento es el mismo que en C#, este bloque se ejecuta siempre se produzcan o no errores en el bloque try.
  • Se puede inicializar el valor de las variables de clase en la propia declaración.
  • Se pueden declarar variables en cualquier parte del código, ya no es necesario realizar todas las declaraciones al principio de los métodos, lo que permite declarar variables en un ámbito más específico (dentro de bucles, por ejemplo).
  • Se añade el tipo especial var, que permite al compilador inferir el tipo concreto de la variable. Su funcionamiento es el mismo que en C# pero cuidado, en .NET se usa este tipo para manejar tipos genéricos, en X++ los tipos genéricos no están disponibles todavía.
  • Añadida la instrucción using para que podemos utilizar igual que en C#, esto es:
    • Para abreviar las referencias a espacios de nombres complicados:
using System.Collections;

class ClaseEjemploXpp
{
    public static void main(Args args)
    {
        // No es necesario especificar el tipo completo
        // System.Collections.Arraylist

        ArrayList arrayList = new ArrayList();
        arrayList.Add('Prueba');
    }
}

Para crear alias a espacios de nombres:

using SysCol = System.Collections;

class ClaseEjemploXpp
{
    public static void main(Args args)
    {
        SysCol.ArrayList arrayList = new SysCol.ArrayList();
        arrayList.Add('Prueba');
    }
}

Para garantizar el uso correcto de tipos como los IDisposable, por ejemplo (más información aquí):

using (Font font = new Font())
{
    // font.Method(...);
}

// ES EQUIVALENTE A:

Font font = new Font();
try
{
    // font.Methods(...);
}
finally
{
    font.Dispose();
}
  • Las variables de clase pueden ser estáticas.
  • Las clases pueden tener un constructor estático mediante la nueva palabra clave typenew. Por ejemplo:
class ClaseConConstructor
{
    static str variableDeClaseEstatica = "Inicializada";

    static void typenew()
    {
        variableDeClaseEstatica = "Asignada sin this.";
    }
}
  • Los atributos aplicados en clases y métodos pueden omitir el sufijo Attribute en su nombre, igual que ocurre en C#. Por ejemplo, para un atributo llamado [PruebaAttribute] también será válido utilizar sólo [Prueba].
  • Los delegados que antes podían declararse en clases, ahora también se pueden declarar en tablas formularios y consultas (objetos Query).
  • La relación entre estos delegados y los métodos manejadores se realiza ahora mediante atributos.
  • Dentro de formularios, se pueden encontrar clases anidadas dentro de clases. La clase base representa el formulario (una instancia de FormRun) y las clases interiores manejan los componentes del formulario (Controles, Orígenes de datos, etc.).

Incompatibilidad con versiones anteriores

Aunque se ha intentado reducir al mínimo los problemas de retro-compatibilidad en el lenguaje, el cambio de plataforma ha llevado inevitablemente a descatalogar las partes del lenguaje que gestionan aspectos de la plataforma que ya no existen, como los siguientes:

  • Eliminadas las siguientes instrucciones: changeSite, pause, windows. Provocan errores de compilación.
  • Puesto que todo el código se ejecuta ahora en CIL en el servidor, ya no tienen sentido las sentencias client y server. No provocan errores de compilación pero son ignoradas y deben eliminarse.
  • En Microsoft Dynamics AX 2012 había algunas diferencias en cuanto a la ejecución del mismo código en CIL o interpretando el p-code. En la nueva versión todos estos casos funcionan igual que en su anterior ejecución CIL. Por ejemplo:
    • El tipo base real es ahora un System.Decimal en todos los casos. La precisión decimal se ha modificado respecto al tipo real de p-code. Esta diferencia provocaba a menudo pequeñas variaciones de decimales cuando el código se ejecutaba en CIL respecto a su interpretación en p-code.
  • La asignación directa de un array a otro array se realiza por referencia. En p-code se realizaba por valor.

AX TIP: Ejecutar una expresión matemática desde X++

Un truco antiguo, pero muy útil en algunos casos, es la posibilidad de utilizar el compilador de X++ para calcular expresiones matemáticas. Una simplificación de este interprete matemático está implementada en todos los campos numéricos de la aplicación, donde, en vez de un número, se puede introducir una expresión sencilla. Por ejemplo: +15+7-10/3

El compilador va un poco mas ayá y nos permite utilizar funciones matemáticas más complejas. La lista completa de funciones, según la documentación, es: abs, acos, asin, atan, corrFlagGet, corrFlagSet, cos, cosh, decRound, exp, exp10, frac, log10, logN, power, round, sin, sinh, tan, tanh y trunc, aunque probablemente haya más, la lista de funciones en MSDN no ha sido nunca totalmente completa.

Para poder interpretar estas funciones utilizamos la clase XppCompiler, de la que hablaré también en el siguiente artículo dentro de unos días, de esta forma:

static void JAEE_XppCompiler_Math(Args _args)
{
    XppCompiler comp;
   
    str expr = "sin(3 * 3.14159265358979323 / 2)";

    new ExecutePermission().assert();
   
    comp = new XppCompiler();
    if (comp.compileExpr(expr))
    {
        info(comp.execute());
    }
    else
    {
        throw error("Expresión inválida.");
    }
   
    CodeAccessPermission::revertAssert();
}

La clase XppCompiler es una de las llamadas API’s seguras del sistema, y por tanto, son un riesgo para la seguridad de la aplicación (pueden permitir inyección de código X++ en las formulas, por ejemplo). Antes de utilizar esta clase en producción es necesario tener en cuenta la seguridad del código. Más información:

Microsoft Dynamics AX 2012 R2 AxBuild.exe

Cuando nos enteramos de las novedades del reciente Cumulative Update 7 para Microsoft Dynamics AX 2012 R2, creo que como la mayoría de técnicos cercanos a AX, me puse inmediatamente a hacer alguna prueba con la nueva utilidad AxBuild. No es porque fuera la única novedad, pero sin ninguna duda fue una novedad muy esperada y esperanzadora para reducir los tiempos de compilado de la aplicación que se habían disparado desde el lanzamiento de la R2 (llevamos tiempo comentándolo).

Para entender esta utilidad y cómo es capaz de mejorar tanto el rendimiento hay que tener presentes algunos conceptos:

  • El servicio que corre el AOS es un servicio de 64 bits. El cliente de AX es una aplicación de 32 bits.
  • Hasta ahora, el compilado de X++ y la validación de los objetos del AOT se ejecutaba en el cliente. Así sigue siendo si ejecutamos el compilador desde el cliente, como venimos haciendo desde siempre.
  • Estos dos puntos anteriores nos muestran un cuello de botella, primero por el tráfico entre el cliente y servidor de todos los objetos para poder compilarse, y segundo por la merma de rendimiento que supone realizar todo el proceso en una aplicación de 32 bits, con sus limitaciones en cuanto al uso del procesador y la memoria.

Esta nueva utilidad AxBuild lo que nos permite es, en primer lugar eliminar totalmente al cliente del proceso de compilado (eliminando la parte de 32 bits), y por otro lado lanzar tantos procesos de AOS como sea posible para aprovechar todos los procesadores de la máquina. Por defecto, el proceso lanza 1.4 procesos por cada procesador disponible en el servidor, aunque este número se puede configurar.

AxBuild.exe - Rendimiento

Continue Reading…

Cumulative Update 7 for Microsoft Dynamics AX 2012 R2

Microsoft Dynamics

Esta semana se ha publicado la última actualización acumulativa para Microsoft Dynamics AX 2012 R2 . Esta revisión (6.2.1000.4051), como de costumbre, agrupa todos los hotfixes publicados desde el lanzamiento de la primera versión (ver los CU publicados con anterioridad). Se puede descargar del siguiente enlace:

Igual que ocurrió en el anterior CU6, no se limita a incluir hotfixes y soluciones de problemas como venía siendo habitual, sino que desde el pasado CU6 en estos paquetes se incluyen además mejoras funcionales e incluso funcionalidad nueva. En este caso hay tantas novedades a nivel funcional que han creado una página en TechNet para explicar las novedades, algunas de ella son tan importantes que dedicaré algún post a comentarlas individualmente, y también una guía de instalación:

Comentar brevemente, a nivel funcional, que para España y otros países europeos es muy importante la actualización al nuevo sistema de pagos SEPA que viene incluida en este CU7, entre otras muchas cosas. A nivel técnico las mejoras son también numerosas importantes, y aquí es donde dedicaré futuros post a profundizar sobre ellos individualmente:

En siguientes post comentaremos algunas de estas novedades en mayor profundidad.

Hotfix para mejorar el tiempo de compilación en AX 2012 R2!

No suelo publicar actualizaciones de hotfixes concretos porque normalmente sólo son útiles en algunos casos concretos, pero este vale la pena comentarlo porque es bien conocido por cualquiera que haya manejado mínimamente una instalación de Dynamics AX 2012 R2. Los tiempos de compilación desde la versión R2 son insostenibles, retrasándose hasta varias horas incluso con servidores sobradamente potentes y llegando a ser verdaderamente molestos en entornos virtualizados con recursos limitados como es el caso de la mayoría de consultores y desarrolladores.

Es por eso que es tan importante comentar este hotfix (KB2844240) que acaba de publicarse hace minutos y (todavía no lo he probado) mejora el tiempo de compilación en un 50% y equipara el tiempo de compilación de la R2 con la 2012RTM ¿Algo es algo, no?. Esta mejora se basa en una optimización del esquema (en los índices) de la nueva base de datos que almacena la Model Store.

Este hotfix estará disponible en el próximo CU6 ¿Ya lo estás descargando? Yo si!

P.D. Parece que tuviera preparada esta serie de post sobre hotfixes (1, 2, 3) pero prometo que ha sido totalmente fortuito 😉

Actualizado 05/05/2013

Después de instalar el parche en mi máquina virtual de pruebas (AX 2012 R2 CU1) he de decir que la mejora en el compilado X++ y CIL es muy notable. No puedo compararlo de manera eficaz y tampoco se si este resultado será extrapolable a servidores reales, pero he de decir que en una máquina virtual ejecutada en un PC normal (no un servidor) con 6Gb de memoria y 4 cores el compilado X++ se ha reducido prácticamente a la mitad!!