La IA generativa ha estado constantemente (y errónameante), entronada como la sustituta de los programadores. Ya he publicado algún comentario en este medio sobre las experiencias (casi siempre, decepcionantes) que he tenido con la IA (1 2 3 4). Esto no quiere decir que la IA no sirva: es una herramienta más, como trataré de describir aquí.
Hace algunos días, estaba trabajando con Java, su toolkit gráfico Swing, que estaba utilizando para mostrar el contenido de notas creadas por el usuario. Una de las posibilidades contempladas es la de crear cajas de verificiación como listas de tareas. Por ejemplo:
[ ] - Comprar pan.
[X] - Crear el programa para la mañana.
[ ] - Reunión de las 11h.
Estas cajas en Mark Down se interpretarían como HTML, concretamente como un check box. El único componente que puede interpretar HTML es un JEditorPane.
La forma de representar un check box en HTML 5 es la siguiente:
<input type="checkbox">
Si el check box está marcado, entonces aparecería con el atributo checked. Este atributo no se asigna a ningún valor, sino que su mera existencia indica el marcado o no (algo que, por cierto, no me gusta nada... ¿era demasiado tener un atributo como cheched="1" o similar?).
<input type="checkbox" checked>
Pues nada, hago mis pruebas, las notas con casillas se convierten a HTML con estos check boxes, y después vuelven a guardarse como MarkDown.
Pero entonces, me encuentro con algo sorprendente, un error extraño: daba igual si marcabas o no la casilla, nunca se generaba el atributo checked... ¿qué estaba pasando?
Las búsquedas mediante los buscadores habituales enseguida devolvían respuestas relacionadas con JavaScript, lo que no era demasiado útil. Decidí irme a la IA. Elegí Deep Seek. Sobre todo, porque me permite usarlo de manera gratuita, más que nada.
Le pregunté a la IA la razón de por qué me pasaba lo que me pasaba, y... sí, me entendió a la primera. Es decir, no tuve que refinar mi pregunta descartando posibles problemas y soluciones orientadas al navegador con JavaScript. Esto es un buen punto para la IA.
Su respuesta me sorprendió: This is a known issue with HTMLEditorKit - when you call getText(), it serializes the current document state and resets all input values to their default values (as defined in the HTML). Traducido, este es un problema conocido en JEditorPane empleando un HTMLEditorKit, o sea, trabajando con HTML. El problema es que los señores de Sun Microsystems decidieron no "conectar" los valores de entrada de este tipo de campos input, según parece, debido a que JEditorPane no es un navegador. De acuerdo, pero entonces... ¿por qué los input de tipo text sí se respetan, de modo que los valores de entrada sí se reflejan en el DOM HTML del editor? Mi personal interpretación es que se cansaron a mitad de trabajo, probablemente pensando algo así como: "total, esto lo no lo va a usar nadie..."
Bueno, el caso. La cuestión es que me da varias soluciones. Una de ellas es captar, (1) mediante un código en JavaScript los valores de las check boxes y meterlas en los elementos del DOM HTML del editor. Otra es (2) crear una versión propia de HTMLEditorKit quer genere el código correctamente, y otra es (3) tomar el atributo checkeddel DOM HTML del editor y almacenarlo en una estructura de datos.
Hay varios problemas con estas soluciones. La (1), utilizando JavaScript es excesiva, en mi opinión. Tras examinar la (2), resulta que o bien no existe una manera elegante de recorrer los nodos, o bien la IA no la conoce y no tengo tiempo de investigarlo, y en contraste, la tercera es la que parece más interesante. Así que me la leo, la entiendo, elimino todo el código redundante, y la incorporo a mi código. Pero no funciona.
Y es que, en realidad, ninguna de las soluciones funcionan, porque todas tienen que ver con el HTML DOM que mantiene el editor. Y tiene todo el sentido, porque si volvemos a leer el origen del problema, la cuestión es que la parte visual no está conectada con el DOM HTML. Así, podemos "trastear" con el HTML DOM lo que queramos. Nos pongamos como nos pongamos,no tendremos los checked aunque los check boxes están marcados.
Para mi, esto supone un problema con la IA. Me ha propuesto varias soluciones que seguramente fueron ensayadas por alguien, pero que fueron solo meros intentos, pues no solucionan el problema. Además, no le molesta proponer una solución basada en ejecutar JavaScript dentro del editor, lo que me parece especialmente subóptimo. Por último, es necesario "pulir" la respuesta: hay mucho código redundante, que no aporta nada a la solución.
El caso es que le respondo a la IA que la solución propuesta no es válida. Su respuesta es:
You're right to be skeptical! This is actually a known limitation of HTMLEditorKit - checkbox states are not stored in the document attributes the way we might expect. The checked state is maintained in the visual representation/View, but not in the underlying Document model's attributes.
Es decir, que al no estar conectada la parte visual del HTML DOM, no tiene sentido manejar el DOM.
No puedo evitar pegar un respingo cuando la leo. No tiene sentido que me propongas las soluciones anteriores "sabiendo" esto. De hecho, debería haberme dado cuenta, pero he confiado en que la IA me propondría soluciones válidas.
Las soluciones propuestas son (1) tomar las marcas directamente de la vista del documento (no del HTML DOM), o (2) usar el ElementIterator de HTMLDocument . La segunda solución tiene un código kilométrico, y visto lo visto, no me fio de adoptarlo sin más. Además, lo que hace básicamente es crear un listener que, en caso de marcar un check box, pasa un booleano a una estructura de datos aparte... esta estructura de datos es la misma que utiliza la primera solución, mucho más corta, así que me centro en esta.
Leo el código. Básicamente, lo que hace es recorrer los "nodos" de la vista, y busca objetos JChecbBox, asociados a un objeto ParagraphView, clase derivada de ComponentView (que se corresponde con un elemento de HTML DOM <input type="checbox">). Cuando se encuentra uno, accede a su marca. El algoritmo es el siguiente:
private static void traverseViewForCheckboxes(View view, Map<String, Boolean> states) {
if (view instanceof javax.swing.text.html.ParagraphView) {
// Check if this view contains a checkbox
Component component = findComponentInView(view);
if (component instanceof JCheckBox) {
JCheckBox checkBox = (JCheckBox) component;
String name = checkBox.getName();
if (name != null) {
states.put(name, checkBox.isSelected());
}
}
}
// Recursively traverse child views
for (int i = 0; i < view.getViewCount(); i++) {
traverseViewForCheckboxes(view.getView(i), states);
}
}
La división entre el HTML DOM y la vista sigue el patrón Bridge.
Primero se busca en la vista los objetos ParagraphView. Entonces se comprueba con su método getComponent() si el componente visual equivalente es un JCheckBox, accede a su marca. Y entonces me fijo en el método findComponentInView( view ). Está justo debajo:
private static Component findComponentInView(View view) {
// This is a simplified approach - in reality, you might need to
// access the ComponentView's component
if (view instanceof javax.swing.text.html.ComponentView) {
try {
java.lang.reflect.Method getComponentMethod =
ComponentView.class.getDeclaredMethod("getComponent");
getComponentMethod.setAccessible(true);
return (Component) getComponentMethod.invoke(view);
} catch (Exception e) {
// Reflection failed, try alternative approach
}
}
return null;
}
¡Está utilizando reflexión para acceder al método View::getComponent, y retornarlo. Me resulta realmente extraño este código. Supongo que será parte de algún código de prueba de alguien, pero... no tiene sentido. No tiene sentido porque View::getElement es un método totalmente accesible.
Dicho de otra forma, la llamada al método propuesto findComponentInView( view ), especialmente subóptimo pues emplea reflexión...
Component component = findComponentInView(view);
Se puede sustituir por una línea de código:
var component = view.getComponent();
Cuando le señalo este extremo a la IA, reconoce que sí, que View::getComponent(), se puede llamar directamente (?). No hay explicación, pero si no te das cuenta, pues te comes el código.
Podemos resumir el proceso anterior en unos puntos fuertes y débiles de esta sesión con IA como sigue:
| Cuestión | Punto fuerte de la IA | Punto debil de la IA |
|---|---|---|
| Búsqueda de problemas | La IA encuentra el problema específico, mientras con un buscador necesitas mucho más esfuerzo. | |
| Resolución de problemas | La IA puede generar soluciones que no son correctas. | |
| No le importa generar soluciones que suponen una elevada carga, al resultar extremadamente subóptima (ejecutar JavaScript). | ||
| Genera un código excesivo, que hay que pulir y sobre todo, recortar. | ||
| Al final, analizar las posibles soluciones propuestas, encuentras una que es prometedora, lo que evita de nuevo costosas y esforzadas búsquedas. | ||
| En general, crea código subóptimo; de nuevo, es necesaria una revisión detallada (llamada mediante reflexión). |
Si leemos detalladamente este resumen, y damos un paso atrás, entendemos, efectivamente, cómo funciona la IA: proporciona texto con una alta probabilidad de aparecer junto al texto de entrada. Si tenemos esto último en cuenta, es obvio el por qué es necesario leer, entender, analizar, y pulir tanto las posibles soluciones como el código que proporciona. No hay otra.

Top comments (0)