Ordenando tu JavaScript en Oracle APEX con el Patrón Namespace Parte 1

Tiempo de lectura: 3 minutos

Cuando tu app en APEX crece, el JavaScript suele crecer “a la mala”: funciones sueltas en el Global Scope, nombres duplicados, y lógica de UI regada en 10 Dynamic Actions diferentes. El resultado: mantenimiento caro, bugs difíciles de rastrear y cero consistencia.

El patrón Namespace es una solución simple y efectiva: en lugar de llenar window con funciones sueltas, agrupas tu código en un objeto raíz (por ejemplo App) y lo organizas por módulos (App.apex, App.rules, etc.). Eso te da orden, escalabilidad y un sitio único donde encontrar las cosas.

El problema: JavaScript suelto por todas partes

Esto es típico:

  • En una DA pones hideTotal()
  • En otra DA defines setStatus()
  • En otra DA agregas un toggleFields()… y a los 3 meses ya nadie sabe dónde vive cada cosa

Además, si alguien crea otra función con el mismo nombre en otra página, buena suerte.

La idea del Namespace

Un namespace es un “contenedor” que cuelga de un objeto raíz (normalmente window). Ejemplo mental:

  • App.apex → utilidades genéricas para APEX
  • App.rules → reglas de pantalla y lógica de UI (qué mostrar/ocultar según valores)
  • En el futuro podrías tener: App.ajax, App.ui, App.security, etc.

Paso 1: una función mínima para crear/obtener namespaces

Esta función te permite escribir ns("App.apex") y asegurar que exista window.App.apex.

function ns(path) {
  const parts = String(path).split('.').filter(Boolean);
  let ctx = window;

  for (const p of parts) {
    ctx[p] = ctx[p] || {};
    ctx = ctx[p];
  }

  return ctx;
}

Qué hace:

  • Divide el path por puntos
  • Crea objetos intermedios si no existen
  • Devuelve el objeto final

Con esto, dejas de escribir if (!App) App = {}; if (!App.apex) App.apex = {}; manualmente.


Paso 2: Un módulo App.apex con wrappers básicos

Aquí viene el “hack” práctico: si siempre estás escribiendo apex.item("P1_X").hide() por toda la app, centralízalo.

ns("App.apex");

App.apex.show = function(itemName) {
  apex.item(itemName).show();
};

App.apex.hide = function(itemName) {
  apex.item(itemName).hide();
};

App.apex.setValue = function(itemName, value) {
  apex.item(itemName).setValue(value);
};

App.apex.getValue = function(itemName) {
  return apex.item(itemName).getValue();
};

Beneficios inmediatos:

  • Menos repetición
  • Nombres consistentes
  • Si mañana quieres meter validaciones (por ejemplo, si el item no existe), lo haces en un solo lugar

Paso 3: Uso desde cualquier Dynamic Action (o Console)

Ejemplos simples:

App.apex.hide("P1_TOTAL");
App.apex.show("P1_TOTAL");

App.apex.setValue("P1_STATUS", "READY");

const status = App.apex.getValue("P1_STATUS");

Esto se vuelve tu “API” interna para manipular items. Ordenado y predecible.


Paso 4: Separar “helpers” de “reglas” con App.rules

Una buena práctica: no mezcles el “cómo” (APEX APIs) con el “qué” (reglas del negocio/UI).

Por eso creamos otro módulo:

ns("App.rules");

App.rules.toggleFields = function() {
  const type = App.apex.getValue("P1_TYPE");

  if (type === "A") {
    App.apex.show("P1_FIELD_A");
    App.apex.hide("P1_FIELD_B");
  } else {
    App.apex.hide("P1_FIELD_A");
    App.apex.show("P1_FIELD_B");
  }
};

Uso

App.rules.toggleFields();

Esto te permite:

  • Mantener la lógica de UI en un solo lugar
  • Reutilizar reglas entre páginas (si te conviene)
  • Evitar que tus Dynamic Actions se vuelvan “mini programas” incontrolables

Dónde poner este código en APEX

Opciones típicas:

  1. Global JavaScript File (lo más limpio si aplica a varias páginas)
  2. Page JavaScript (Function and Global Variable Declaration) si es solo para una página
  3. Static Application Files si quieres versionarlo y tener control de cambios

Para un patrón namespace, lo ideal es que la base (ns + App.apex) viva de forma central, y las reglas (App.rules) puedan vivir por página o por módulo, según tu arquitectura.


Qué ganas con esto (en serio)

  • Menos caos: nada de funciones sueltas en el global
  • Escala: tu JS crece por módulos, no por “parches”
  • Mantenibilidad: encuentras todo en App.*
  • Consistencia: todas las páginas llaman lo mismo para hacer lo mismo

Siguiente nivel (si quieres hacerlo aún más pro)

Una vez tengas App.apex como base, normalmente el siguiente paso es agregar:

  • App.apex.process(...) como wrapper para apex.server.process
  • App.ui.toast(...) para mensajes consistentes
  • App.util.debounce(...) para inputs y filtros
  • Un estándar para archivos y nombres por módulo

Pero el punto clave es este: si hoy ordenas el acceso a APEX items con un namespace, mañana tu app deja de depender del “developer de turno” y empieza a parecer un producto serio.

Post a Comment

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