Viaje multiplataforma

Las fronteras digitales en términos de qué Sistema Operativo se utiliza para el desarrollo cada vez más desaparecen para dejar paso a las posibilidades de equipos de desarrollo donde cada uno utilice aquél S.O. que le apetezca.

Las tecnologías y herramientas que utilizamos, además, ya no dependen de la plataforma sobre la que corren, y es la tendencia que deberían seguir si es que esperan mantenerse con fuerza en este mundo donde el crecimiento de S.O. como Linux o MacOSX sigue de manera constante sin vías a futuro a detenerse.

¿Cómo debemos reaccionar los desarrolladores? La respuesta es sencilla: orientarnos a desarrollar aplicaciones que puedan ejecutarse en cualquier entorno, tratando que al menos las funcionalidades principales sean comunes.

Existen diversas tecnologías que nos permiten (al menos en principio) atender este requerimiento no funcional. Si utilizamos plataformas basadas en una máquina virtual, teóricamente ya tenemos esa parte del partido ganado. Pero también nos podemos apoyar del uso de frameworks que nos permiten abstraer de la capa nativa y de la comunicación con el Sistema Operativo.

En uno de los proyectos en los cuáles trabajo actualmente, tuvimos el requerimiento de mudar el código de la plataforma Windows originalmente, a Linux (por algunos motivos que probablemente comente en otro artículo). Uno de los módulos que se habían desarrollado demoró aproximadamente cuatro meses en ser mudado a Linux. Otro se mudó a Linux (y también a Mac) en aproximadamente dos semanas.

¿Cuál fue la diferencia?

En sólo dos palabras: frameworks multiplataforma. El módulo que habíamos desarrollado para la presentación en 3D utilizaba Ogre3D, un motor de renderizado abierto, que poseía entre sus principales características la facilidad de ejecutarse en cualquier plataforma.

De esa forma, la mudanza de código demoró sólo el tiempo que nos tomó aprender a desarrollar en Linux (que, debo admitir, era algo que nunca había hecho y que de otra manera habría reducido el tiempo muchísimo más), léase aprender a utilizar el IDE, entender la forma en que se hacía el despliegue, los conceptos propios que tenía para compilar y similares.

Pero el otro módulo había sido desarrollado por un compañero apoyándose en buena medida en MFC, un API de clases propias de Windows. Eso significaba, en otras palabras, empezar prácticamente de cero (bueno, reutilizamos las interfaces :P ).

Sin embargo, el problema no había sido de la tecnología utilizada, si no en qué forma se la había usado. Revisando el código encontramos que no había una separación lógica entre las capas de presentación y lógica, y el código de MFC estaba totalmente enlazado en diversas clases, haciendo muy complicado su entendimiento para migrar (y sin mencionar la falta de documentación).

Lecciones Aprendidas

Ahora que ya hemos finalizado la ardua tarea de migrar el código de prácticamente dos años de trabajo a uno (o dos) plataformas distintas, existen varias lecciones que hemos aprendido en la marcha, y que expongo brevemente en las siguientes líneas:

  • Nunca desestimes el valor de la documentación Aunque creas que todos los participantes del proyecto estarán siempre ahí, no siempre será así, y sólo una adecuada documentación de cada pieza de código de los participantes permitirá que el resto del equipo entienda qué se ha desarrollado, de qué manera, y, vital en este caso, qué áreas pertenecen a qué capa.

    No siempre podrenos -ni tendremos porqué si es un grupo de trabajo multidisciplinario- entender totalmente el código que utilizan nuestros compañeros, pero al menos debemos saber qué módulo o sección podemos cambiar sin afectar el funcionamiento total del resto de la aplicación.

  • Utiliza en la medida de lo posible frameworks multiplataforma La facilidad de mudar código cuando éste está desarrollado sobre una base que nos desliga del Sistema Operativo no tiene pierde, y elimina la dificultad a practicamente 0 (dependiendo del framework) en el caso de mudar.

    Además, nos permite abstraernos y concentrarnos en la lógica específica de la Aplicación, y no en las dificultades técnicas propias de cada Sistema Operativo

  • No utilices, de ser posible, frameworks que dependan o sólo funcionen en una plataforma específica . Puede parecer que nunca tendrás que mudar tu código, pero tal vez alguna vez tengas la necesidad de hacer que tu aplicación corra en otras plataformas, y pueden haber secciones que tengas que cambiar totalmente, duplicando y alargando los tiempos de desarrollo.

    Y aunque no lo pienses ahora, el futuro de las aplicaciones se orienta a tener versiones para todo y no limitarse a una sóla. Salvo que desees perder a clientes potenciales que decidieron saltar al otro lado de la cerca.

  • Si utilizas frameworks sólo existentes en una plataforma, define correctamente las interfaces Habrán situaciones donde existe la necesidad de utilizar piezas de código que no tengan alternativas en otras plataformas, o de construir código sobre éstas. Si este es el caso, es vital separar esa pieza de código específica del resto, creando interfaces que abstraigan las llamadas a la biblioteca de código específica.

    De esa manera, en lugar de tener

    public NetworkManager GetPackets() {
    char* bufferStrm;
    CSocket::OnReceive(nErrorCode);
    DWORD dwReceived;
    if (IOCtl(FIONREAD, &dwReceived))
    {
    if (dwReceived >= dwExpected) // Process only if you have enough data
    m_pDoc->ProcessPendingRead(bufferStrm);
    DataContext->setData(bufferStrm);
    }
    }

    Podemos tener algo como

    public NetworkManager GetPackets() {
    char* bufferStrm;
    NetworkConnection.getSocket(bufferStrm);
    DataContext->setData(bufferStrm);
    }

    No sólo obtenemos un código mucho más limpio, sino que en el caso de mudar nuestro código a otra plataforma, simplemente tendremos que modificar la clase NetworkConnection (que puede estar en otra biblioteca o módulo) sin tocar el código propio de la conexión.

  • Investiga las posibilidades que posee el lenguaje que utilizas para definir plataformas Entender qué facilidades nos brinda el lenguaje donde trabajamos actualmente nos permite tener claras la forma en que trataremos el código en el momento de separar las piezas de código en cada plataforma. Conocerlas, y o al menos tener las referencias necesarias a mano es siempre una buena idea.

    #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
    #else
    int main(int argc, char *argv[])
    #endif

Pensar siempre en términos del dominio, sin preocuparnos en las implementaciones nativas de cada solución, nos permiten orientarnos a la lógica a resolver, y no tanto en las peculiaridades específicas que cada plataforma posee. Una solución multiplataforma nos permite tener código más limpio, abstrayendo las capas más bajas de comunicación e interacción con el SO a otros módulos o frameworks, lo cual finalmente elimina los tiempos de desarrollo y los problemas que pueden ocurrir durante el desarrollo.

This entry was posted in desarrollo, herramientas, predicciones and tagged . Bookmark the permalink.

4 Responses to Viaje multiplataforma

  1. XK says:

    Este artículo no estaba aburrido U_U…aunque al comienzo si parecía aburrido XD

  2. Reymond says:

    Excelente post, y si ciertamente la tendencia es hacia lograr que los sistemas sean multi-plataforma, pero a continuación cualquier persona haría la pregunta de ¿y cual es el mejor lenguaje?.

    Ciertamente como lo decía el conejo en Clab, hay que buscar librerías y frameworks que se encarguen de todo lo que ocurre a bajo nivel y nosotros solo ocuparnos de la lógica de negocios para arriba en las capas.

    Saludos :wink:

  3. Pingback: Reymond Blog » El desarrollo multiplataforma

  4. daveon says:

    Una tecnología prometedora es C# y los frameworks de proyecto mono.
    Saludos.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>