10 min de lectura

Códice Cotalker: el linaje de las colecciones y la herencia del prefijo (parte 3)

Cofre arcano abierto con decenas de pergaminos sellados que comparten un mismo sigilo, y dos cofres menores sin sello al costado.
Contenido

    En la parte 1 vimos cómo el sello de tres letras entre paréntesis rescata a los formularios del olvido. En la parte 2 bajamos a las questions y descubrimos que su code es único en toda la company. Te dejo los posts por si necesitas un poco de ayudamemoria:

    Cómo nombrar formularios en Cotalker: la convención del prefijo
    La convención del prefijo entre paréntesis para formularios en Cotalker: cómo organizar tu workspace y migrar flujos entre ambientes sin perder el contexto.
    Codes de questions únicos en Cotalker: la convención
    En Cotalker los codes de questions son únicos por company, no por formulario. La convención de prefijos acortados y marcas de display para no chocar jamás.

    Ahora subimos un nivel. Los formularios y sus questions no viven solos: consultan elementos, escriben en elementos y dependen de elementos. Si los formularios necesitan prefijo, las colecciones necesitan algo más: un linaje.

    Una colección no es solo un nombre aislado, ya que también hereda ese nombre a sus hijos (los elementos)

    Acá quiero hacer énfasis en uno de los puntos más importantes a la hora de armar un flujo: cómo nombrar la data maestra. Esos valores fijos que tus rutinas van a consultar una y otra vez te pueden ahorrar un inmenso dolor de cabeza solamente con un nombrado en su code. Así que prepárate, porque acá empieza la tercera parte del Oráculo.

    Capítulo 1: por qué las colecciones piden más que los formularios

    Nombrar mal un formulario o sus questions no provoca un daño grave, a lo más te costaría crear questions porque los identifiers chocan. Pero con las colecciones hablamos de otras ligas. Una colección mal nombrada ya dificulta encontrarla en la interfaz y ni hablar de un elemento mal creado, ya que puede hacer que debas cambiar toda la lógica de un flujo para poder encontrar un solo elemento.

    Por eso la convención para colecciones es más estricta:

    • El nombre importa (lo ven los implementadores en la lista de colecciones).
    • El code importa (lo usan los desarrolladores en queries y snippets).
    • Y los elementos dentro de la colección heredan parte del code.

    Tres niveles de naming, no uno.

    Capítulo 2: el prefijo de la colección

    La base es simple: si la colección pertenece a un flujo específico, lleva el prefijo del flujo grabado como sello de pertenencia, igual que los formularios.

    Volvamos al flujo del que hablamos en la parte 1, (INV) Flujo de Inventario. Ahí ya hicimos una leve referencia a la colección (INV) Productos; ahora le toca ser protagonista:

    • ✅ Nombre: (INV) Productos
    • ✅ Code: inv_productos

    La regla es idéntica a la de formularios: (PREFIJO) en el display, prefijo_ en el code. El único detalle a destacar es que, al igual que las bases de datos, se deben nombrar en plural.

    Donde la convención de colecciones se separa de la de formularios es en lo que viene después: lo que ocurre dentro de la colección.

    Capítulo 3: la regla del singular, los elementos heredan en otra forma

    Acá está la convención que más se olvida y la que más beneficio entrega: cada elemento dentro de una colección lleva como prefijo una versión singular del code de su colección.

    Si el code de la colección es inv_productos, entonces cada elemento dentro de ella lleva el prefijo producto_ (singular del code de la colección, sin el prefijo de flujo).

    producto_zapatilla_running
    producto_polera_negra
    producto_mochila_tactica
    

    ¿Por qué singular y por qué sin el inv_? Tal como dije antes, a la hora del nombrado nos estamos basando en un estándar ya existente: las bases de datos relacionales. Ahí una tabla es un plural y sus registros se identifican en singular. Para el caso de Productos:

    • Cada elemento creado es un producto, no un "productos".
    • Sin inv_ porque el contexto del flujo ya está dado por la colección que los contiene. Repetirlo en cada elemento sería ruido.
    💡
    La regla práctica que uso: el code de la colección habla del conjunto, el code del elemento habla de cada uno. inv_productos es la colección. producto_X es cada elemento. Nunca al revés.

    Y el prefijo del elemento hace algo más, algo que agradeces al leer código ajeno: te dice de qué colección viene sin que tengas que buscarlo. Si en una rutina te cruzas con producto_polera_negra, no necesitas abrir nada para saber que ese elemento vive en la colección de productos. El code del elemento es un puntero legible a su origen: un hilo que siempre lleva de vuelta a la colección madre.

    ⚠️
    Esto no se aplica al display visible del elemento. El display es el nombre real del producto ("Zapatilla Running Negra"). El prefijo producto_ vive solo en el code.

    Capítulo 4: el code es la puerta

    Si recién entras a Cotalker, este es el capítulo con el que debes quedarte y con el que te aseguro que ahorrarás unos buenos dolores de cabeza cuando la implementación crezca.

    Hasta acá hablamos del prefijo casi como si fuera cosmética, pero no lo es. Recuerda de la parte 1 que el code es el sigilo verdadero de cada elemento: el nombre con el que el sistema lo invoca por dentro, no el que el usuario ve en pantalla.

    ¿Y esto por qué es tan importante? Porque muchas veces vas a necesitar hacer llamadas de red a los elementos de una colección, y si no estandarizas los codes, tendrás que llenarte de workarounds o reestructurar los flujos para poder encontrar los elementos que necesitas.

    Deja que te lo explique con un ejemplo práctico: tenemos una colección con data maestra donde el elemento tiene una constante que permite saber el porcentaje de descuento de un producto.

    Si en la rutina necesito acceder al descuento del producto, podría hacer esta llamada de red usando un get by id:

    GET .../properties/665f1c2a9b3e4d0012a7f8c1
    

    Si leo eso después de un tiempo (u otro implementador ve la rutina) a simple vista vienen las clásicas preguntas: "¿qué es eso?", "¿por qué hago esta llamada de red?", "¿en qué colección estará ese elemento?", "¿qué representa?"…

    Ahora, si tenemos un code bien nombrado, podemos hacer esta magia con un get by code:

    GET .../properties/code/descuento_zapatillas
    

    Ese sí se lee. Sabes rápidamente a qué colección hace referencia (Descuentos), y exactamente qué elemento estás llamando sin necesidad de abrir nada.

    4.1 El abismo de los que recién empiezan

    Acá es donde no aplicar estas reglas de nombrado te puede empezar a costar horas de trabajo. Cuando subes data maestra (esos catálogos de cientos o miles de valores fijos que las rutinas consultan) cada elemento necesita un code que signifique algo.

    Esta es la parte traicionera: el editor te deja cargar la colección y, si no le pones code, te lo autogenera con el slug del nombre. Con esto, obviamente, todo funciona bien: los formularios muestran los displays y quedas convencido de que hiciste un buen trabajo. Pero el problema no aparece el día que cargas la data, aparece cuando necesitas trabajar con esa data maestra en los flujos o en las rutinas.

    El caso clásico: una colección de productos cargada sin pensar en el code.

    [
    	{
    		"display": "Zapatilla Negra",
    		"code": "producto_zapatilla_negra",
    		"schemaInstance": { "sku": "PUM-ZAP-NE" }
    	},
    	{
    		"display": "Polera Azul",
    		"code": "producto_polera_azul",
    		"schemaInstance": { "sku": "NI-POL-AZ" }
    	}
    ]
    

    Se ve inofensivo y el code se lee bien, hasta da gusto leerlo. El problema viene cuando te das cuenta (o mejor dicho, aprendes) de que los usuarios no hacen búsquedas por el code que acabamos de crear, sino por el SKU, ya que es la forma interna que tienen para saber específicamente a qué producto hacen referencia ("Zapatilla Negra" puede ser de múltiples marcas, tallas o colores).

    Añadamos más casos a esto. Puede ser que, por temas de marketing, el display de ese producto cambie: ya no es "Zapatilla Negra", ahora es "Zapatilla Negra Acolchada". Cambió el display, pero el code nunca se podrá cambiar. ¿Qué hacemos aquí? Si forzamos a que busquen por el code, intentarían buscar producto_zapatilla_negra_acolchada, pero como imaginarás, ese elemento no existe o quizá sea otro elemento en la colección.

    Sé que parece un caso muy específico, pero créeme, es muy común que lo hagan así. Incluso muchas veces ya se saben algunos SKU de memoria, por lo que los ingresan en los formularios sin pensarlo.

    ¿Cómo se soluciona esto? Simplemente utilizando el SKU del producto como code. De esta forma quedaría así:

    [
    	{
    		"display": "Zapatilla Negra",
    		"code": "producto_pum_zap_ne",
    		"schemaInstance": { "sku": "PUM-ZAP-NE" }
    	},
    	{
    		"display": "Polera Azul",
    		"code": "producto_ni_pol_az",
    		"schemaInstance": { "sku": "NI-POL-AZ" }
    	}
    ]
    

    Con esto, ahora no importa que el display del producto cambie: los usuarios siempre buscarán por un identificador interno de ellos que es único y no cambiará nunca.

    Sí, ya sé lo que estás pensando: producto_pum_zap_ne se lee bastante peor que producto_zapatilla_negra, y tienes razón. Pero acá conviene cambiar el chip. Lo que pierdes en legibilidad lo ganas justo donde más lo necesitas: al encontrar el elemento dentro de una rutina. El display se maquilla y cambia con el tiempo; el SKU es el ancla que no se mueve, y además es lo que el usuario ya tiene en la mano cuando llena el formulario. Un code un poco más feo a la vista, pero muchísimo más fácil de referenciar.

    💡
    Siempre, pero siempre que cargues data maestra, pregúntale al cliente cómo identifican sus elementos a almacenar: puede ser un código propio de ellos, un SKU, un número interno que referencia el producto. Con esto ya tendrás una idea de qué valor debe ir en el code. Si no logras identificarlo, puedes hacerles la clásica pregunta: "¿Cuál de todos estos valores es único e irrepetible?"

    4.2 El code también puede ser una llave compuesta

    Hay un caso donde esto brilla todavía más: cuando un elemento existe por una combinación de valores, no por uno solo.

    Piensa en el stock. No tienes "stock" a secas: tienes el stock de un producto en una bodega específica. La misma zapatilla puede tener 40 pares en la bodega central y 3 en la sucursal norte. Ese registro no se identifica por un valor, sino por el cruce de dos.

    Si dejas que el code sea autogenerado, referenciar ese cruce es un dolor: desde una rutina tendrías que consultar la colección entera, filtrar por bodega, filtrar por producto y recién ahí sacar el registro.

    Aquí hay dos formas que se pueden usar; ninguna es mejor que la otra. Solo debes ponerte de acuerdo o ver cuál se adapta mejor a tu caso:

    • Caso 1: Solo codes propios sin identificación específica
    Code: producto_{bodega_code}_{producto_sku}
    
    - producto_central_pum_zap_ne
    - producto_norte_ni_pol_az
    • Caso 2: codes con su referencia de la colección
    Code: bodega_{bodega_code}_producto_{producto_sku}
    
    - bodega_central_producto_pum_zap_ne
    - bodega_norte_producto_ni_pol_az

    Gracias a esto, todo se vuelve directo. El usuario elige la bodega y el producto en el formulario, tú armas el code concatenando esos dos valores, y un solo get by code te trae el registro con su stock (suponiendo que el stock es un campo dentro de esa colección). Una llamada, cero búsquedas intermedias.

    💡
    La idea de fondo: el code no tiene por qué ser un nombre suelto. Puede ser una llave que reconstruyes desde los datos que ya tienes a mano. Cuando el code es predecible a partir del contexto (bodega + producto), dejas de buscar elementos y pasas a direccionarlos. Esa es la diferencia entre una integración que vuela y una que se arrastra consultando colecciones enteras.

    4.3 Cuando la misma data maestra vive en varios flujos

    Recuerda de la parte 2 que el code de una question es único en toda la company. Con las colecciones pasa lo mismo, y va un paso más allá: tanto el code de la colección como el de cada uno de sus elementos son únicos por company. Eso, que suena a limitación, es justo lo que hace que el prefijo del flujo valga oro.

    Porque la data maestra se repite. Inventario tiene sus estados, Compras tiene los suyos, y muchas veces son idénticos en concepto pero cada flujo necesita el propio. Sin prefijo, ambas colecciones querrían llamarse estados y chocarían (solo puede haber un estados por company). Con prefijo, conviven sin pisarse:

    inv_estados   (estados del flujo de inventario)
    com_estados   (estados del flujo de compras)
    

    Dos colecciones, la misma data maestra conceptual, cero colisión. El prefijo no solo documenta de dónde viene cada cosa: es lo que permite que dos flujos tengan su propia copia de un catálogo sin que la restricción de unicidad de la company los obligue a compartir uno solo.

    Capítulo 5: catálogos compartidos, la excepción que confirma la regla

    Recién vimos que dos flujos pueden tener cada uno su propia copia de un catálogo (inv_estados, com_estados). Pero no siempre quieres copias: a veces hay data que es una sola para toda la empresa, y duplicarla sería el error opuesto.

    No todas las colecciones pertenecen a un flujo. Algunas son catálogos transversales, bibliotecas comunes del grimorio que cualquier flujo puede consultar: monedas, regiones, sucursales, etc.

    Para estas colecciones, no aplica el prefijo de flujo. ¿Razones?

    • Si le pones (INV) Sucursales, das a entender que la colección pertenece al flujo de inventario. Pero el flujo de Compras también la usa. Y el de Vacaciones. El prefijo miente.
    • Una colección sin prefijo señala explícitamente: "esto es transversal, lo puede consultar quien necesite".
    ✅ Sucursales         (compartida)
    ✅ Monedas            (compartida)
    ✅ (INV) Productos    (exclusiva del flujo de inventario)
    ✅ (COM) Proveedores  (exclusiva del flujo de compras)
    

    Capítulo 6: cierre

    Las colecciones no son listas, son todo un linaje. El prefijo del flujo viaja desde la colección, y la regla del singular baja a cada hijo. Cuando todo está bien nombrado, una colección entera se busca, se migra y se entiende con dos regex. Cuando no, cada elemento es una sorpresa.

    Pero el grimorio aún tiene un círculo más. Los flujos, los cargos, los bots, las rutinas, los webhooks, y API tokens también tienen su convención de nombrado. Algunos importan en el nombre, otros solo en el code. Algunos llevan un prefijo extra. Y algunos no llevan prefijo en absoluto, por una buena razón.

    Eso lo cerramos en la parte 4 del Oráculo del Prefijo.

    ¿Tienes una colección que arrastra un naming caótico desde hace años? Cuéntamelo en los comentarios.

    Sigue leyendo "Códice Cotalker"