Porqué Owl?
La opinión generalizada es que no se debe reinventar la rueda, porque eso supondría desperdiciar esfuerzos y recursos. Esto es cierto en muchos casos. Un framework de JavaScript es una inversión considerable, por lo que es bastante lógico preguntarse: ¿por qué Odoo decidió crear OWL en lugar de utilizar un framework estándar o conocido, como React o Vue?
Como es de esperar, la respuesta a esa pregunta no es sencilla. Pero la mayoría de las razones que se analizan en esta página son consecuencia de un único hecho: Odoo es extremadamente modular.
Esto significa, por ejemplo, que las partes centrales de Odoo no saben, antes del tiempo de ejecución, qué archivos se cargarán o ejecutarán, o cuál será el estado de la interfaz de usuario. Por eso, Odoo no puede depender de una cadena de herramientas de compilación estándar. Además, esto implica que las partes centrales de Odoo deben ser extremadamente genéricas. En otras palabras, Odoo no es realmente una aplicación con una interfaz de usuario. Es una aplicación que genera una interfaz de usuario dinámica. Y la mayoría de los marcos no están a la altura de esa tarea.
Apostar por Owl no fue una decisión fácil, porque sin duda hay muchas necesidades conflictivas que queremos equilibrar cuidadosamente. Elegir algo que no sea un framework conocido seguramente será controvertido. En esta página explicaremos algunas de las razones por las que seguimos creyendo que construir Owl es una iniciativa que vale la pena.
Estrategia
Es cierto que queremos mantener el control de nuestra tecnología, en el sentido de que no queremos depender de Facebook o Google, ni de ninguna otra empresa grande (o pequeña). Si deciden cambiar su licencia, o ir en una dirección que no nos conviene, esto puede suponer un problema. Esto es aún más cierto porque Odoo no es una aplicación javascript convencional, y nuestras necesidades probablemente sean bastante diferentes a las de la mayoría de las demás aplicaciones.
Componentes de clase
Está claro que los frameworks más importantes se están alejando de los componentes de clase. Existe la suposición implícita de que los componentes de clase son terribles y que la programación funcional es el camino a seguir. React llega incluso a decir que las clases son confusas para los desarrolladores.
Si bien hay algo de verdad en eso y en el hecho de que la composición es ciertamente un buen mecanismo para la reutilización de código, creemos que las clases y la herencia son herramientas importantes.
Compartir código entre componentes genéricos con herencia es la forma en que Odoo creó su cliente web. Y está claro que la herencia no es la raíz de todos los males. A menudo es una solución perfectamente simple y adecuada. Lo que más importa son las decisiones arquitectónicas.
Además, Odoo tiene otro uso específico fuera de los componentes de clase: cada método de una clase proporciona un punto de extensión para complementos. Puede que no sea un patrón de arquitectura claro, pero es una decisión pragmática que le ha funcionado bien a Odoo: a veces se le aplican parches a las clases para agregarles comportamiento desde el exterior. Un poco como los mixins, pero desde el exterior.
El uso de React o Vue haría que fuera mucho más difícil parchar componentes, porque gran parte del estado está oculto en sus componentes internos.
Herramientas
React o Vue tienen una comunidad enorme y se ha hecho un gran esfuerzo en sus herramientas. Esto es maravilloso, pero al mismo tiempo, un gran problema para Odoo: dado que los recursos son totalmente dinámicos (y podrían cambiar cada vez que el usuario instala o elimina un complemento), necesitamos tener todo ese tipo de herramientas en los servidores de producción. Esto ciertamente no es ideal.
Además, esto hace que sea muy complicado configurar las herramientas Vue o React: el código de Odoo no es un simple archivo que importa otros archivos. Cambia todo el tiempo, los activos se agrupan de manera diferente en diferentes contextos. Esta es la razón por la que Odoo tiene su propio sistema de módulos, que se resuelven en tiempo de ejecución, por el navegador. La naturaleza dinámica de Odoo significa que a menudo necesitamos retrasar el trabajo lo más posible (en otras palabras, ¡queremos una interfaz de usuario JIT!)
Nuestro marco ideal tiene herramientas mínimas (obligatorias), lo que facilita su implementación. Usar React sin JSX o Vue sin el archivo vue no es muy atractivo.
Al mismo tiempo, Owl está diseñado para resolver este problema: compila plantillas por parte del navegador, no necesita mucho código para eso, ya que utilizamos el analizador XML integrado en cada navegador. Owl funciona con o sin herramientas adicionales. Puede utilizar cadenas de plantillas para escribir componentes de un solo archivo y es fácil de integrar en cualquier página HTML con una simple etiqueta <script>
.
Basado en Plantillas
Odoo almacena plantillas como documentos XML en una base de datos. Esto es muy potente, ya que permite el uso de xpaths para personalizar otras plantillas. Esta es una característica muy importante de Odoo y una de las claves de la modularidad de Odoo.
Por este motivo, todavía esperamos escribir nuestras plantillas en un documento XML. Por extraño que parezca, ningún framework importante utiliza XML para almacenar plantillas, aunque es extremadamente conveniente.
Entonces, usar React o Vue significa que necesitamos crear un compilador de plantillas. Para React, sería un compilador que tomaría una plantilla QWeb y la convertiría en una función de renderización de React. Para Vue, la convertiría en una plantilla de Vue. Luego, también necesitamos incluir el compilador de plantillas de Vue.
Esto no solo sería complejo (compilar un lenguaje de plantillas en otro no es una tarea fácil), sino que también afectaría negativamente la experiencia del desarrollador. Escribir componentes Vue o React en una plantilla QWeb sería ciertamente complicado y muy confuso.
Experiencia del Desarrollador
Esto nos lleva al siguiente punto: la experiencia del desarrollador. Vemos esta elección como una inversión de futuro y queremos que la incorporación de los desarrolladores sea lo más sencilla posible.
Si bien muchos profesionales de JavaScript creen claramente que React/Vue no es difícil (lo cual es cierto hasta cierto punto), también es cierto que muchos especialistas que no son de JavaScript están abrumados con el mundo del frontend: componentes funcionales, ganchos y muchas otras palabras elegantes. Además, lo que está disponible en el contexto de compilación puede ser difícil, hay mucha magia negra en prácticamente todos los marcos. Vue de alguna manera une varios espacios de nombres en uno, bajo el capó, y agrega varias claves internas. Svelte transforma el código. React requiere que las transformaciones de estado sean profundas y no superficiales.
Owl is trying very hard to have a simple and familiar API. It uses classes. Its reactivity system is explicit, not implicit. The scoping rules are obvious. In case of doubt, we err on the side of not implementing a feature.
Ciertamente es diferente de React o Vue, pero al mismo tiempo, resulta bastante familiar para los desarrolladores experimentados.
Compilación JIT
También existe una clara tendencia en el mundo frontend a compilar el código con la mayor antelación posible. La mayoría de los frameworks compilan plantillas con antelación. Y ahora Svelte está intentando compilar el código JS para poder eliminarse del paquete.
Esto es razonable para muchos casos de uso, pero no es lo que Odoo necesita: Odoo obtendrá las plantillas de la base de datos y deberá compilarlas solo en el último momento posible, para que podamos aplicar todos los xpaths necesarios.
Más aún: Odoo necesita poder generar (y compilar) plantillas en tiempo de ejecución. Actualmente, las vistas de formulario de Odoo interpretan una descripción xml. Pero el código de la vista de formulario debe realizar muchas operaciones complicadas. Con Owl, podremos transformar una descripción de vista en una plantilla QWeb, luego compilarla y usarla inmediatamente.
Reactividad
Existen otras opciones de diseño que creemos que no son óptimas en otros marcos. Por ejemplo, el sistema de reactividad. Nos gusta la forma en que Vue lo hizo, pero tiene un defecto: no es realmente opcional. En realidad, hay una forma de optar por no participar en el sistema de reactividad congelando el estado, pero en ese caso, se congela.
Y sin duda hay situaciones en las que necesitamos un estado que no sea de solo lectura y que no se observe. Por ejemplo, imaginemos un componente de hoja de cálculo. Puede tener un estado interno muy grande y sabe exactamente cuándo debe mostrarse (básicamente, cuando el usuario realiza alguna acción). En ese caso, observar su estado supone una pérdida neta de rendimiento, tanto para la CPU como para la memoria.
Concurrencia
Muchas aplicaciones se conforman con mostrar un indicador cada vez que se realiza una nueva acción asincrónica, pero Odoo quiere una experiencia de usuario diferente: la mayoría de los cambios de estado asincrónicos no se muestran hasta que están listos. Esto a veces se denomina modo concurrente: la interfaz de usuario se procesa en la memoria y se muestra solo cuando está lista (y solo si no ha sido cancelada por acciones posteriores del usuario).
React tiene ahora un modo concurrente experimental, pero no estaba listo cuando Owl comenzó. Vue no tiene realmente una API equivalente (la suspensión no es lo que necesitamos).
Además, el modo concurrente de React es complejo de usar. La concurrencia era uno de los puntos fuertes del antiguo framework Odoo js (widgets), y creemos que Owl tiene ahora un modo concurrente muy sólido, que es simple y poderoso al mismo tiempo.
Conclusión
Este largo debate demostró que hay muchas razones pequeñas y no tan pequeñas por las que los marcos normativos actuales no están adaptados a nuestras necesidades. Y esto no tiene ningún problema, porque cada uno eligió un conjunto diferente de concesiones.
Sin embargo, creemos que todavía hay lugar en el mundo de los frameworks para algo diferente, para un framework que haga que las decisiones sean compatibles con Odoo.
Y es por eso que construimos Owl 🦉.