Picando Código
Generar un enlace automático para compartir posts en un canal de Telegram
diciembre 29, 2025 09:00
Los posts de Picando Código se comparten automáticamente en un canal de Telegram ni bien se publican. Esto se hace mediante una función PHP en el archivo functions.php de mi tema de WordPress. Escribí al respecto en Actualiza un canal en Telegram automáticamente desde WordPress.
El canal es relativamente popular, al momento de escribir esto cuenta con 89 miembros (91 contándome a mí y al bot que publica los posts). El código viene funcionando lo más bien desde 2018. La función genera una dirección web con los datos necesarios y hace un request a esa URL.
La semana pasada, la publicación automática no funcionó al publicarse un post. Así que fui a fijarme en el log de errores de mi servidor, y me encontré con el siguiente mensaje:
Hubo un timeout en la conexión, esto puede pasar por muchas razones: problemas en la red, el servidor está sobrecargado, o estuvo caído por un tiempo determinado.
Debería capturar este error en mi código y agendar un reintento, pero no sé si vale la pena tanta complejidad. El pedido HTTP que se hace a la API de Telegram para compartir los posts en el canal es relativamente simple. Usa el método GET, así que se puede hacer desde cualquier navegador web (o curl, o cualquier herramienta que pueda hacer un pedido HTTP). Así que me escribí un código Ruby que genera la URL que necesito para compartir el enlace en el canal de Telegram.
El código:
require 'uri'
def uso
puts <<~MSG
Uso:
#{__FILE__} link
E.g.
#{__FILE__} https://picandocodigo.net
MSG
end
if ARGV.empty?
uso
abort 'Es necesario pasar un link como parámetro'
end
link = ARGV[0]
unless link =~ URI::DEFAULT_PARSER.make_regexp
uso
abort 'El URL no es válido'
end
api_token = File.read(File.expand_path('./.telegram_api_token'))
chat_id = '@picandocodigo'
url = "https://api.telegram.org/bot#{api_token}/sendMessage?chat_id=#{chat_id}&text=#{CGI.escape(link)}"
puts url
La función uso explica cómo usar el script. Tenemos que ejecutarlo con un argumento que es la URL que queremos compartir. Se muestra cuando no pasamos ningún argumento o el argumento no es una URL válida. El id del chat está hardcodeado a @picandocodigo, pero se podría usar cualquier otro. Lee el token para usar la API de Telegram desde un archivo .telegram_api_token en el mismo directorio. Finalmente arma el String final de la url escapando los caracteres del url que pasamos como argumento con CGI.escape.
La ejecuté y obtuve la URL, hice clic directamente en la consola y el post se compartió en el canal de Telegram de Picando Código:
> https://api.telegram.org/bot[API_KEY]/sendMessage?chat_id=@picandocodigo&text=https%3A%2F%2Fpicandocodigo.net%2F2025%2Frecomendaciones-de-podcasts-2%2F
Es la primera vez que tengo que hacer esto a mano desde que dejé andando la automatización. Pero si por alguna razón vuelve a pasar, tengo este script para solucionarlo rápido.
El post Generar un enlace automático para compartir posts en un canal de Telegram fue publicado originalmente en Picando Código.Picando Código
Recomendaciones de Podcasts
diciembre 26, 2025 09:00

Desde hace un tiempo he cambiado bastante mi postura respecto a los podcasts. En mi primer post sobre podcasts en 2020, decía que no escuchaba podcasts. Y lo cierto es que no había encontrado podcasts que me interesaran (excepto Sonido Bragueta, de Gustavo Sala e Ignacio Alcuri. Sigo escuchando Sonido Bragueta... ¡escuchen Sonido Bragueta!). Hoy en día sigo algunos podcasts más, que me resultan muy interesantes y entretenidos.
Y está bueno, eso de evolucionar y cambiar de opinión. Que al final si uno se queda siempre en la misma, nos perdemos de un montón de cosas. Como dijo Bill Stevenson, legendario baterista de Descendents, en uno de los podcasts que escuché: "Si no estás avergonzado de lo que hiciste cuando eras joven, no has crecido como persona". O algo así, ni siquiera me acuerdo exactamente la frase, y él mismo estaba parafraseando a alguien más. Pero se entiende la idea (espero).
Hoy en día veo a los podcasts como veía a la radio en otros tiempos. Sigo escuchando radio también, tanto online como en mi transmisor analógico de radio que tiene una perilla para sintonizar las estaciones. Así que lo podcasts no la han reemplazado, sino que complementan lo que escucho además de radio y música. Mantengo el tema de que no puedo trabajar y escuchar podcasts a la vez. O me concentro en lo que estoy haciendo del trabajo o en el podcast. Si escucho algo en el trabajo generalmente es música (tanto en la radio como mi música), como de compañía. Pero no me sale prestar atención a un podcast mientras trabajo, programo o escribo para cosas mías.
Las veces que escucho podcasts, lo hago desde mi teléfono. Caminando por la calle siempre uso mis auriculares. Callejeo bastante, camino a todos lados, y me molesta mucho el ruido del tránsito y demás. Lo que tiene vivir en una ciudad con tanta gente y tanto movimiento. Ni que hablar que las ambulancias de Edimburgo son una amenaza, tienen la sirena más alta que he oído en mi vida, capaces de dejar a uno sordo. Otra amenaza son los potenciales infartos cuando vas caminando y empieza una sirena de golpe al lado tuyo...
Software para podcasts
En cuanto a software, para los que están basados en YouTube (como Sonido Bragueta, espero que ya hayan escuchado Sonido Bragueta a esta altura), uso NewPipe. NewPipe es genial para interactuar con YouTube. No tengo la aplicación de YouTube en mi teléfono, sólo uso NewPipe:
NewPipe fue creado con el propósito de obtener la experiencia original de YouTube en tu smartphone sin anuncions molestos o permisos cuestionables.
Es intuitiva, llena de características útiles, respeta la privacidad de sus usuarios y es software libre bajo licencia GPLv3. Aparte te permite bloquear el teléfono y dejar ejecutando un video (aunque sea sólo audio) de YouTube. Hasta donde llegué a usar la aplicación oficial de YouTube, no permitía hacer esto. Y muy importante también es que bloquea los malditos anuncios de YouTube.
Para los que son podcasts más "tradicionales" uso AntennaPod. Es una aplicación para escuchar podcasts y suscribirse a feeds RSS, también software libre bajo licencia GPLv3. No tiene intereses comerciales y respeta nuestra privacidad. Está bueno porque las veces que me enteré de algún podcast que podía interesarme, lo busqué directamente en AntennaPod y lo agregué a mis suscripciones desde ahí mismo.
Ambos programas están disponibles a través de F-Droid en Android: el catálogo instalable de aplicaciones FOSS (software libre y de código abierto, en inglés) para la plataforma Android.
Video Game History Hour
De los podcasts que más disfruto y más he escuchado en 2025. Video Game History Hour es el podcast de la Video Game History Foundation. [link de suscripción]
Usé material de la fundación en mi artículo Nintendo en América Latina en la década de los 90 - piratería y Famicom :
Recientemente The Video Game History Foundation abrió al público el acceso digital a su biblioteca. La fundación es una organización sin fines de lucro dedicada a preservar, celebrar y enseñar la historia de los videojuegos. Entre sus proyectos se encuentra la preservación del código fuente de juegos, educación, archivo de arte e información, recuperación y restauración.
El podcast está actualmente integrado por Frank Cifaldi fundador y director de la fundación, Robin Kunimune productora del podcast y más en la fundación y Phil Salvador, director de la biblioteca. En sus comienzos entrevistaban a una persona invitada denominada experta en algún tema en particular relacionado a la historia de los videojuegos. Ya sea porque investigaron un tema o porque lo vivieron. Me encanta escuchar o leer este tipo de entrevistas, y aprender y conocer anécdotas y curiosidades de distintos aspectos del mundo de los videojuegos y su historia. Increíblemente interesante.
En los capítulos más recientes también hablan del trabajo de la fundación, y han ido presentando personalmente a los integrantes, lo cual también me resulta muy interesante. Dato curioso al azar: la protoconsola de Nintendo que terminó siendo el Famicom, usaba como controles consolas Game & Watch hackeadas para conectarse y usar sus controles. Y así como ese hay muchos más. Van 145 episodios al momento de escribir esto, así que hay un montón de material para escuchar y entretenerse.
No sé el orden exacto del resto de los podcasts porque la referencia que tengo es mi año según AntennaPod:

Resumen del 2025 en AntennaPod. Qué lindo ver el mensaje "generado de manera privada en tu teléfono", algo cada vez menos común.
Pero estoy seguro que en el top 5 deberían estar Sonido Bragueta y el siguiente podcast a recomendar:
The Atari Podcast
No tengo nostalgia por el Atari de los 80's, llegué tarde para ser de la generación que creció con un Atari 2600. Pero reconozco su legado y admiro mucho al Atari moderno. Han hecho un muy buen trabajo con los relanzamientos de sus consolas, con mucho respeto a lo que vino antes. Pero más que nada vienen destacando en cuanto a desarrollo. Por un lado han revivido y reinventado conceptos de los juegos clásicos de aquellas épocas. Por otro trabajan en desarrollos nuevos también han adquirido un par de estudios cuyo trabajo admiro y disfruto mucho: Nigthdive Studios y Digital Eclipse. Ambos estudios combinan lo retro con lo moderno en un balance ideal.
El trabajo de Digital Eclipse con su Golden Master Series es increíble. Implementaron un formato documental interactivo que le agregan contexto a cada juego, lo que amplifica la experiencia de jugarlos. Totalmente recomendable, y mientras sigan sacando de éstos títulos, los seguiré obteniendo. El año pasado también publicaron un título original Mighty Morphin Power Rangers: Rita's Rewind. Un excelente beat 'em up que captura el sentimiento de alquilar un juego nuevo de Super Nintendo un fin de semana y sentarse a jugarlo con un amigo.
Nightdive Studios también trabaja con lo retro, portando y desarrollando para plataformas modernas juegos que consideran "tesoros perdidos". Su trabajo incluye restauración y tienen una reputación por las mejoras que actualizan estos clásicos y los hacen disponibles en todas las plataformas modernas. También han desarrollado y publicado títulos propios manteniendo un estilo clásico.
Y si bien menciono no tener nostalgia por los videojuegos de Atari de los 80's, disfruté muchísimo Atari 50: the Anniversary Celebration. El primer título del formato que se convirtió en Golden Master Series de Digital Eclipse. Aprender de la historia y evolución de Atari e ir jugando los juegos cronológicamente en paralelo con el documental interactivo los hace apreciar mucho más que simplemente jugarlos de una colección.
El podcast está a cargo de Jason Polansky, Director Asociado de Juegos. Jason invita a desarrolladores tanto de los estudios de Atari, como de terceros trabajando en títulos publicados por Atari y demás. También somete a los invitados a algunos juegos basados en trivia que resultan entretenidos.
El podcast está disponible en YouTube, link de AntennaPod y feed.
Chris DeMakes A Podcast
El anfitrión es Chris DeMakes, cantante, guitarrista y escritor de canciones en la famosa banda de skapunk que voy a tener el gusto de ver en vivo en marzo en Glasgow: Less Than Jake. Me encanta la música, y tengo una afición muy especial por el punk rock, ska punk, hardcore melódico y demás sub-géneros del Punk. El podcast generalmente se concentra en analizar una canción en particular invitando a alguno de los artistas involucrados en su creación y desarrollo.
Entre los invitados han estado los legendarios Descendents: Milo Aukerman, Bill Stevenson, Stephen Egerton y Karl Alvarez, así como Chad Price de ALL. Brian Baker y Brett Gurewitz de la mejor banda del universo, Bad Religion. Otros invitados de lujo incluyen a Aaron Barrett y Scott Klopfenstein de Reel Big Fish (¡juntos!), su compañero de banda Roger Lima, John Feldmann de Goldfinger, Joey Cape de Lagwagon, Angelo Moore de Fishbone, Stacey Dee de Bad Cop Bad Cop, Nikola Šarčević de Millencolin, Ray Carlisle de Teenage Bottlerocket... Y estos son sólo algunos de los nombres de las bandas que más me gustan, hay casi 300 episodios para escuchar. A veces también conversa con su productor de canciones y artistas en particular, como Zombie y Dolores O'Riordan de The Cranberries.
Me encanta este podcast porque Chris DeMakes es no sólo protagonista de la escena a la que celebra y difunde, también es muy nerd con las canciones. Analiza de forma relativamente técnica las canciones compás por compás junto al artista invitado. Es divertido cuando le hace alguna pregunta técnica de composición al entrevistado, y éste responde "no tengo ni idea". En muchos casos simplemente hacen algo "porque suena bien", y así sale.
Este estilo de música y gran parte de las bandas que invita -a pesar de su legado y popularidad- son un poco nicho. No reciben tanta atención masiva, y no conozco muchos medios que le den este tipo de difusión. Así que disfruto mucho de escuchar a los artistas, las anécdotas y detalles de la producción de música que tanto disfruto. Chris DeMakes es un nerd del mismo estilo de música que me gusta a mí, nerdeando con la gente que crea esa música, excelente.
El podcast está disponible en YouTube, link de AntennaPod y feed.
Historic Scotland Podcast
Soy miembro de Historic Scotland, una organización pública a cargo de investigar, cuidar, mantener y promover el ambiente histórico de Escocia. Mantienen colecciones históricas así como edificios y estructuras (castillos, monasterios, museos, etc.). Además de producir información de eventos históricos y noticias sobre su trabajo, hace poco empezaron a publicar un podcast. La primera temporada cuenta con 8 episodios, y hay una segunda temporada ya anunciada. En algún lado dice algo así como que el podcast es "exclusivo para miembros", pero está disponible públicamente.
Además de aprender un poco más de historia, inspira a encontrar potenciales lugares a visitar. Tomo éstas cosas como punto de partida, y de ahí planeo un paseo a alguna parte de Escocia que todavía no conozco. De repente un poco específico porque vivo acá, pero puede interesarle a más gente que tenga interés en Escocia y su historia.
El feed del podcast de Historic Scotland.
Coffee Break Gaelic
Este es otro podcast bastante específico. Desde hace unos años empecé a estudiar Gaélico Escocés. Hice unos cuantos cursos en la Universidad de Edimburgo, he ido a varios eventos, mirado novelas en Gaélico, leído bastante, y pasé muchas horas en el curso de Duolingo. Pero todavía me falta muchísimo para poder decir que sé Gaélico. Los podcasts Coffee Break son bastante populares para aprender idiomas, me los recomendó mucha gente distinta en distintos ambientes.
En este podcast Mark, un aprendiz de idomas, conversa y aprende Gaélico desde cero con Susanna, profesora de Gaélico Escocés. Lo empecé a escuchar bastante después de haber empezado a estudiar, así que los primeros episodios me resultan super básicos. Pero es un buen recurso para repasar. Lo recomiendo como extra si están aprendiendo un idioma distinto, hay para Alemán, Italiano, Chino, Sueco, Japonés e incluso uno de Español a Inglés.
Párrafos finales a modo de conclusión o algo... (para mantener la cohesión con el uso de títulos)
Es interesante rever lo que escribí en 2020:
Otro tema que me juega en contra de los podcasts, son muy largos. Me interesaría escuchar un podcast si incluye algo de información que no puedo leer en ningún lado, o una opinión o punto de vista de alguien cuya opinión o punto de vista respeto/admiro o me importa por alguna razón. Pero muchos podcasts dan un montón de vueltas para decir algo, como esas reuniones que podrían haber sido un email. En parte volvemos a párrafo anterior donde despotrico contra los podcasts y YouTube cual viejo gruñón.
Y el tema es que no había encontrado podcasts buenos. Sí había tenido experiencia con algunos que eran básicamente 2 o 3 personas sin nada muy interesante para decir que grababan una conversación larga con un mínimo hilo conductor. Pero cuando se trata de algo entretenido, gente interesante y/o divertida, el tiempo se pasa volando. Como decía, escucho los podcasts mientras camino pero también haciendo tareas que no requieren absoluta concentración, las hacen más llevaderas. Ahora que encontré podcasts que me gustan, me resulta tal cual un equivalente a escuchar radio.
Si bien, como decía, escucho algo casi todo el tiempo cuando ando por la calle, hay excepciones. Cuando camino por un parque o un lugar con muchos árboles o naturaleza, me quito los auriculares. En Edimburgo hay bastantes caminos y parques lejos del tránsito que son ideales para escuchar pájaros, agua corriendo y demás sonidos naturales. ¡Lo recomiendo!
También hay un ejercicio mental extra que hago a veces gracias a los podcasts. No pasa seguido, pero si un capítulo en particular me aburre o no me engancha, me desconecto completamente y mi cerebro empieza a divagar y pensar en otras cosas. Y es un buen ejercicio, "aburrirse" y reflexionar, imaginar, y demás procesos creativos por los que pasa el cerebro cuando no está comprometido con una actividad. Como dijo Satoru Iwata: "El tiempo que pasas pensando en cosas totalmente aleatorias nunca es tiempo perdido".
Pero en fín, esos son los podcasts que vengo escuchando recientemente. Si tienen alguna recomendación, pueden dejarla en los comentarios, ¡gracias!
El post Recomendaciones de Podcasts fue publicado originalmente en Picando Código.Navegapolis
Spec-Driven Development
diciembre 24, 2025 08:53
El contexto: los problemas del vibe coding
Para entender Spec-Driven Developmen (SDD) o, hablando en nuestro idioma: desarrollo guiado por especificaciones, es bueno empezar conociendo el problema que intenta solucionar.
En febrero de 2025, Andrej Karpathy (cofundador de OpenAI y exdirector de IA en Tesla) acuñó el término vibe coding en un tweet que se hizo viral(1)
«Hay un nuevo tipo de programación que llamo ‘vibe coding’, donde te dejas llevar completamente por las vibraciones, abrazas los exponenciales, y olvidas que el código siquiera existe. […] Acepto todo siempre, ya no leo los diffs. Cuando recibo mensajes de error, simplemente los copio y pego sin comentarios, y normalmente eso lo arregla.»
Para proyectos de fin de semana o prototipos rápidos, dejarse llevar por la IA puede funcionar, pero tiene limitaciones: código aparentemente correcto, pero con bugs sutiles, arquitecturas inconsistentes, vulnerabilidades de seguridad, y la incomodidad de no conocer la lógica que implementa el código generado.
Los datos son reveladores: según Y Combinator, el 25% de las startups de su cohorte de invierno 2025 tenían bases de código generadas en un 95% por IA(2). Es impresionante, pero: ¿quién entiende y mantiene ese código?
Qué es Spec Driven Development
Spec Driven Development es, en esencia, un enfoque en el que la especificación precede y guía al código. No es un framework ni una metodología prescriptiva como scrum. Es una filosofía de trabajo que propone:
- Escribir primero una especificación clara de lo que se desea construir: objetivos, reglas de negocio, criterios de aceptación, restricciones técnicas.
- Usar esa especificación como fuente tanto para humanos como para agentes de IA.
- Generar código a partir de la spec, no de prompts improvisados.
Como lo resume GitHub en su documentación de Spec Kit: «En este nuevo mundo, mantener software significa evolucionar especificaciones. […] El código es el enfoque de última milla.»(3)
Los tres niveles de SDD
Birgitta Böckeler, de Thoughtworks, propone una taxonomía útil para entender las diferentes implementaciones(4):
- Spec-first: Escribes la spec antes de codificar, la usas para la tarea en curso, y luego la descartas. Es el nivel más básico.
- Spec-anchored: La spec se mantiene después de completar la tarea y se usa para evolución y mantenimiento del feature.
- Spec-as-source: La spec es el artefacto principal. Solo editas la spec, nunca tocas el código directamente. El código se regenera desde la especificación.
La mayoría de herramientas actuales operan en el nivel spec-first, algunas aspiran a spec-anchored, y solo unas pocas experimentan con spec-as-source (como Tessl Framework).
La relación con IA: el catalizador del resurgimiento
Aunque la idea de «especificar antes de codificar» está en el origen de la ingeniería de software, SDD ha resurgido ahora por una razón específica: los LLMs necesitan contexto estructurado para generar código coherente.
Piénsalo así: cuando le das a un agente de código un prompt vago como «hazme un login», está adivinando arquitectura, patrones, validaciones y flujos de error. Cuando le das una especificación detallada que define exactamente qué debe pasar, el código resultante tiene muchas más probabilidades de hacer lo que necesitas.
La spec funciona como un «super-prompt» persistente y versionable. Como describe el equipo de Kiro (AWS): «Una especificación es una especie de super-prompt (versionado, legible por humanos).»(5)
Herramientas del ecosistema
El ecosistema de herramientas SDD está creciendo rápidamente(6):
- GitHub Spec Kit: Toolkit open source que proporciona un flujo estructurado: Constitution → Specify → Plan → Tasks → Implement. Funciona con Copilot, Claude Code y otros.
- Kiro (AWS): IDE basado en VS Code con flujo integrado de Requirements → Design → Tasks.
- Tessl Framework: Explora el nivel spec-as-source con mapeo 1:1 entre specs y archivos de código.
- BMAD Method: Usa agentes virtuales (Analyst, Product Manager, Architect) para generar PRDs y specs de arquitectura.
SDD, TDD y BDD: primos cercanos, no competidores
Si trabajas con metodologías ágiles, probablemente te preguntarás cómo encaja SDD con prácticas que ya conoces. La buena noticia: no son excluyentes, son complementarias(7).
- TDD (Test Driven Development): Tests primero. Escribes un test que falla, luego el código para pasarlo. Excelente para calidad a nivel de unidad, pero no captura el intent de producto completo.
- BDD (Behavior Driven Development): Comportamiento primero. Escenarios en formato Given-When-Then que describen cómo se comporta el sistema. Fuerte para alineación con stakeholders, pero deja decisiones técnicas abiertas.
- SDD (Spec Driven Development): Especificación primero. Define el qué y el por qué, añade un plan técnico, y descompone en tareas. La spec es el ancla que mantiene a todos (humanos y agentes) alineados.
En la práctica, puedes usar SDD para definir el feature completo, TDD para cada tarea individual, y BDD para validaciones end-to-end. Como dice Beam.ai: «SDD te dice qué y por qué. BDD verifica comportamiento en todo el sistema. TDD asegura corrección a nivel de código. Estas prácticas funcionan bien juntas.»
La tensión con Agile (y cómo resolverla)
La pregunta incómoda surge porque el Manifiesto Ágil dice «software funcionando sobre documentación extensiva», y esto contradice SDD ese principio al pedir especificaciones detalladas.
La respuesta corta es que depende de cómo lo implementes; y la respuesta larga es que SDD no propone documentación extensiva estilo waterfall. Propone especificaciones vivas, ejecutables y versionadas que evolucionan con el código. Como GitHub lo describe: «Spec-Driven Development no se trata de escribir documentos de requisitos exhaustivos que nadie lee. Tampoco se trata de planificación waterfall.» (3)
En la práctica, SDD funciona bien a nivel de feature o sprint. No estás especificando todo el producto de antemano; estás especificando la siguiente funcionalidad con suficiente detalle para que un agente de IA pueda implementarla correctamente.
Consideraciones críticas y limitaciones
Pero SDD puede no ser una bala de plata. Estos son los puntos de crítica más relevantes en la comunidad profesional:
El problema humano
Como señala Daniel Sogl en DEV Community: «El problema principal no es la IA, es el factor humano. SDD requiere que los desarrolladores especifiquen sus intenciones con precisión. […] Después de más de 10 años en desarrollo de software, rara vez he experimentado proyectos donde los requisitos estuvieran completamente formulados antes de la implementación.»(8)
Escribir buenas specs es difícil. Requiere claridad de pensamiento, conocimiento del dominio, y la disciplina de pensar antes de actuar.
Overhead vs. beneficio
Birgitta Böckeler de Thoughtworks probó varias herramientas SDD y encontró que para tareas pequeñas, el proceso era desproporcionado: «Cuando pedí a Kiro que arreglara un pequeño bug, el documento de requisitos lo convirtió en 4 ‘user stories’ con 16 criterios de aceptación […] Era como usar un mazo para romper una nuez.»(4)
SDD tiene más sentido para features medianos a grandes donde la inversión upfront se amortiza en menos correcciones posteriores.
Falsa sensación de control
Las ventanas de contexto son más grandes, pero eso no significa que la IA siga todas las instrucciones. Böckeler observó: «Frecuentemente vi al agente no seguir todas las instrucciones. […] También vi al agente excederse porque seguía instrucciones demasiado ávidamente.»(4)
Las specs ayudan, pero no eliminan el no-determinismo de los LLMs. Todavía necesitas revisar y validar.
¿Revisar markdown o código?
Algunas herramientas generan cantidades masivas de archivos markdown. Como comenta Böckeler: «Honestamente, preferiría revisar código que todos estos archivos markdown. […] Eran repetitivos y tediosos de revisar.»(4)
Una buena herramienta SDD debería proporcionar una experiencia de revisión de specs genuinamente mejor que revisar código, no peor.
Entonces, ¿merece la pena?
Como con cualquier práctica emergente, la respuesta honesta es: depende.
SDD probablemente te beneficie si:
- Trabajas regularmente con agentes de código IA
- Tus proyectos tienen complejidad media-alta
- Valoras la trazabilidad y la documentación viva
- Tu equipo puede invertir tiempo en aprender un nuevo flujo de trabajo
Probablemente no lo necesites si:
- Solo haces prototipos rápidos o proyectos personales
- Tu trabajo consiste principalmente en fixes pequeños y mantenimiento
- Prefieres un control directo y granular sobre cada línea de código
Si decides probarlo, el consejo del equipo de AI Native Dev es pragmático: «Empieza con un feature. No especifiques toda tu aplicación. Elige una funcionalidad bien entendida y escribe una spec detallada. Ve cómo rinde tu agente de IA.»(9)
Como resume el equipo de AI Native Dev: «Estamos todos descubriendo esto juntos, y los patrones que emerjan vendrán de experiencias compartidas entre cientos de equipos.»(9)
Fuentes citadas
[1]: Andrej Karpathy en X (Twitter), 2 de febrero de 2025: x.com/karpathy/status/1886192184808149383
[2]: «Vibe coding» – Wikipedia. Datos de Y Combinator: es.wikipedia.org/wiki/Vibe_coding
[3]: GitHub Blog – Spec-driven development with AI: github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai
[4]: Birgitta Böckeler, Thoughtworks – Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl: martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html
[5]: Kiro – The future of AI spec-driven software development: kiro.dev/blog/kiro-and-the-future-of-software-development
[6]: Microsoft for Developers – Diving Into Spec-Driven Development With GitHub Spec Kit: developer.microsoft.com/blog/spec-driven-development-spec-kit
[7]: Beam.ai – Spec Driven Development: The Future of Building with AI: beam.ai/agentic-insights/spec-driven-development
[8]: Daniel Sogl – Spec Driven Development: A initial review, DEV Community: dev.to/danielsogl/spec-driven-development-sdd-a-initial-review-2llp
[9]: AI Native Dev – Spec-Driven Development: 10 things you need to know about specs: ainativedev.io/news/spec-driven-development-10-things-you-need-to-know-about-specs
La entrada Spec-Driven Development se publicó primero en Navegápolis.
Picando Código
Metroid Prime 4: Beyond - Nintendo Switch 2
diciembre 23, 2025 10:51
Tras una espera de 8 años, el 4 de diciembre de 2025 se publicó Metroid Prime 4: Beyond para Nintendo Switch y Nintendo Switch 2. Es un juego muy entretenido, con gráficos y mundos espectaculares. Intenta cosas nuevas con resultados variables, pero no se aleja mucho de la fórmula que define a Metroid Prime.
Es la primera entrega de la serie después de Metroid Prime 3: Corruption en 2007. Metroid Prime 4 fue anunciado originalmente en el E3 de 2017 para Nintendo Switch. Sería el primer título no desarrollado por Retro Studios, sino por Bandai Namco. Dos años más tarde, Nintendo anunció que se había reiniciado el desarrollo desde cero, esta vez a cargo de Retro Studios otra vez. El trabajo del estudio anterior no había alcanzado los estándares impuestos por Nintendo.
Por un lado el optimismo de que Nintendo quería que esta fuera una entrega a la altura de las anteriores. Pero la noticia desalentaba un poco por la demora extra y cómo afectaría a su desarrollo general. Como se le atribuye a Shigeru Miyamoto: "Un juego demorado es eventualmente bueno, pero un juego sacado a las apuradas es malo para siempre" (esto antes que existieran los parches por internet).
Pasaron muchos años más en los que en cada presentación de Nintendo esperaba noticias de Metroid Prime 4. Entre medio disfruté de Metroid Dread y Metroid Prime: Remastered en Nintendo Switch. Hasta que finalmente en 2024 anunciaron el título Beyond y mostraron las primeras imágenes. Miré algún tráiler más, pero no quise averiguar mucho antes de jugarlo. Tampoco leí reseñas porque quería ir con la cabeza fresca y sin estar pre-dispuesto a nada.
Finalmente, llegó la versión física Metroid Prime 4: Beyond Nintendo Switch 2 Edition a mi puerta. De destacar que el cartucho rojo para Nintendo Switch 2 también funciona en el Nintendo Switch. No llegué a probarlo en mi Switch viejo porque me preguntó si quería importar el archivo guardado (al usar Nintendo Online, se respalda el guardado en los servidores de Nintendo), y me asusté y cerré por las dudas. No hubo edición especial como Metroid Dread, la cual hasta incluía un libro de arte. Pero sí 3 amiibos distintos, de los que no compré ninguno.

Mis primeras impresiones fueron muy positivas. Me entró la emoción de estar jugando un Metroid Prime nuevo. La introducción tiene bastante acción y muy rápido todo se vuelve familiar. Los controles son súper cómodos, controlar a Samus con el Pro Controller es genial.
Al día de hoy sigo sin probar el modo mouse en el Nintendo Switch 2, pero también se puede usar si se quiere. Lo que sí probé un poco fue jugar con los Joy Con como si fueran Wiimotes. Recuerdo haber jugado hace unos años así en la casa de un amigo. Creo que fue o el original en Wii o Metroid Prime 3: Corruption. Pero recuerdo tener que mover el brazo para abrir cosas y apuntar, y en su momento me gustó mucho. Pero bueno, fue sólo un rato para alimentar la nostalgia.
Jugué todo el resto del juego con mi Nintendo Switch Pro Controller. No he tenido la necesidad de comprar un Pro Controller de Switch 2. La única funcionalidad extra que le veo es "despertar el Nintendo desde el control" y nunca usé GameChat. La televisión está a dos pasos del sillón, me parece que no amerita... (todavía). Pero como decía, Samus se controla muy bien. También podemos apuntar con los controles de movimiento en el Pro Controller, lo cual es hasta necesario en algunas partes para tener más precisión o por la naturaleza de algún jefe.
Me llamó la atención lo espectacular que se ve todo. No necesariamente porque los gráficos sean ultra realistas, pero están muy bien logrados. Jugué en el modo con mejores gráficos, no el performance que nos permite jugar a 120Hz que ni sé si mi tele lo soporta. Retro Studios creó un mundo muy llamativo y con atención al detalle. Es el juego que más capturas de pantalla he sacado por lejos en cualquier consola. A veces me demoraba en avanzar porque me ponía admirar los detalles en los ambientes. ¿Alguien más se cuelga a mirar los renders de agua en los videojuegos?

La ambientación de los distintos biomas es muy particular. Hay uno en particular que se siente como muy misterioso y un poco aterrador. Era como estar en la película Alien, que justamente fue una de las influencias de Metroid. También tiene secuencias muy cinematográficas que acompañan muy bien la aventura.
La banda sonora también suma. En Fury Green, el lugar donde empieza la aventura principal, la música me dió "es muy Metroid Prime". Y se destacan también los temas de otros lugares. Los gritos de Samus suenan bastante dolorosos cuando algún enemigo nos daña. Y logra esa tensión de escuchar algo a veces que no vemos, y no sabemos si realmente está ahí. Le da esa percepción de ser un mundo viviente, con organismos acá y allá, muy bueno.
Como decía al principio, se siente como Metroid Prime en esencia, pero "nuevo". Tanto el mundo como los personajes, es exactamente lo que quería. Otro título de la saga, pero "distinto". Si bien no es perfecto, ya llego a eso, el balance es muy positivo.
Una de las ideas nuevas son los personajes que acompañan a Samus, soldados de la Federación Galáctica. La idea de los personajes en sí está bien, creo que podrían funcionar para ayudar a avanzar la jugabilidad o la historia. Incluso la conexión con la Federación Galáctica, y expandir el mundo de Samus, está bueno. Pero como otros intentos de esto último, la ejecución no fue muy buena.
El primer personaje que nos encontramos se convirtió en meme por lo mal escrito que está. Myles McKenzie es un "nerd" cuyos diálogos iniciales parecen escritos por alguien que consumió demasiadas sitcoms y películas malas de Estados Unidos hasta 1999. El el único personaje que usa lentes, porque cómo nos daríamos cuenta que es nerd sino... Y su presentación desencaja totalmente con el resto de la ambientación. La impresión que me dió fue de ser el equivalente a Jar Jar Binks.
Otro aspecto negativo que no se lo atribuyo necesariamente al personaje o cómo está escrito es el "hand-holding" (que te lleven de la mano). Cuando en un juego te ayudan al punto de hacerte enojar. Eso cae en el personaje de McKenzie durante el juego. Entiendo por qué está ahí, Metroid Prime 4 va a ser el primer Metroid de mucha gente. Esto de repente lo hace más amigable a principantes.
Imagino que Nintendo incluso pudo haber sido quien determinó que el juego necesitaba una guía que te dijera a cada rato qué hay que hacer o dónde hay que ir ahora. Lo han hecho un poco con los juegos de Mario, que pasaron de ser un ejemplo de aprender jugando con Super Mario Bros. a "te explico todo con un personaje secundario que no deja de hablar" en títulos más recientes.
Pero es un concepto que resulta medio opuesto a lo que es Metroid. Parte de la gracia de Metroid es perderse, volver para atrás, explorar. Entiendo que es una funcionalidad que puede ayudar. Pero debería ser opcional. Generalmente las ayudas no me aportaron nada, y muchas veces me decían "ahora andá a tal lugar" estando en camino a dicho lugar. Pero bueno, es un detalle, se podría mejorar.
El resto de los personajes no me molestaron tanto. Sí resulta un poco raro que tengan conversaciones con Samus quien a veces ni siquiera es capaz de responder con un gesto de las manos o moviendo la cabeza. Entonces queda como incómoda la conversación unilateral. Pero también imagino que quieren mantener la idea de que uno asume el rol de Samus al jugar Metroid el estilo Link en Zelda. Y también para alejarse de Metroid: Other M supongo.
Y ya que menciono Zelda, no pude evitar encontrar potenciales influencias de Breath of the Wild, tanto en el estilo como las ideas. En el desierto hay Shrines, que incluso visualmente me recuerdan a BotW. ¿Será que todo tiene que ser open world ahora?

La moto Vi-0-La es un concepto nuevo que está muy bueno. Es fácil y divertida de manejar. Me entretuve bastante rato manejando por el desierto, recogiendo cristales verdes y haciendo la derrapada Akira constantemente. Pero creo que no se desarrolló tanto su potencial. El desierto está bastante vacío, y los enemigos que aparecen no son muy interesantes de vencer ni muy variados.
La forma en que nos la presentan es muy rara. Nos tiran en un tutorial en una pista de carreras futurista que se siente muy desconectado: "¿Por que estoy jugando F-Zero en Metroid?". A pesar de esos detalles, me gusta que la hayan agregado y ojalá desarrollen ese potencial un poco más en futuras entregas. Y sacando todo eso, es entretenido manejarla.
También podría mencionar que algunas cosas parecen como de relleno (como la búsqueda de cristales verdes). Cosas que se le agregan para que usemos una mecánica en particular (en este caso Vi-O-La) y alargar el tiempo de juego, pero que no aportan realmente.
Por último un problema que tengo que también se atribuye a títulos anteriores. El juego cuenta con los mismos sistemas de guardado, tenemos que encontrar las estaciones y guardar. También tiene checkpoints que se autoguardan, pero algunas veces guardan mucho tiempo antes de terminar la partida. Una de las veces que perdí, tuve que volver a por lo menos media hora antes. Entiendo que esto fuera así en el GameCube por limitaciones de hardware o lo que sea. Pero que en 2025 esto siga siendo un problema es un poco frustrante.

Imagino que es posible que algunos de estos detalles sean consecuencia del desarrollo complejo que tuvo el juego. Además de haber reiniciado su desarrollo después de 2 años, demoró bastante, e imagino que en el medio se cambió de ser un título de Switch a Switch 2. Vaya uno a saber qué pasó detrás de cámaras. Me encantaría leer entrevistas con los desarrolladores, diseñadores y demás gente involucrada en su producción. Cualquier cosa que nos deje saber más del desarrollo.
Las ideas nuevas como la moto y los personajes extra de repente no están ejecutadas de la mejor manera posible. Pero a lo mejor en unos años salga Metroid Prime 5. Y toman el feedback de los jugadores para explorar un poco más esas ideas y ejecutarlas mejor.
Asumo que la mayoría de la gente que trabajó en la trilogía original ya no están en Retro Studios. Tengo entendido que Metroid Prime Remastered fue en parte para que gente nueva del equipo aprendiera a desarrollar un Metroid Prime y estuviera lista para trabajar en este título. Teóricamente ahora tendrían a la gente a punto y con suerte tengamos uno nuevo en menos de 8 años. Todo depende de cuánto venda...
Me dieron ganas de volver a jugar Metroid Dread, terminar Metroid Prime 2: Echoes en el Game Cube y ver de conseguir para jugar Metroid Prime 3 de alguna forma. La trilogía debería estar todavía en el disco duro de mi Wii U, si la memoria (o el Wii U en sí) todavía sobrevive. Pero está guardado en una caja con todos sus implementos a unos 11.000 km de donde estoy ahora.
Como resumen, Metroid Prime 4: Beyond es un excelente juego para Nintendo Switch 2. Mantiene la esencia de la saga, agrega algunos aspectos nuevos con resultados variables, pero expande el mundo de Samus. Tiene una excelente presentación, jugabilidad muy buena y entretenido para seguidores de Metroid. ¡Recomiendo!
El post Metroid Prime 4: Beyond - Nintendo Switch 2 fue publicado originalmente en Picando Código.Variable not found
Enlaces interesantes 632
diciembre 22, 2025 07:05
Mucho contenido interesante en la última recopilación del año 🙂
Me ha alegrado verde nuevo a Juan María Hernández que, tras algunos años de parón, vuelve con una reflexión bastante certera sobre por qué el proceso de desarrollo es cada vez más lento y costoso conforme los productos van creciendo en complejidad. Os recomiendo su lectura.
También me ha parecido interesante el artículo de Alexey Fedorov sobre el devastador efecto de una estampida en la caché de nuestras aplicaciones, junto con algunas estrategias para evitarlo.
El proyecto MinimalWorker, de Joshua Jesper Krægpøth Ryder, puede resultar útil para reducir significativamente el boilerplate necesario para registrar workers en aplicaciones ASP.NET Core y .NET.
Vladan Petrovic nos muestra TUnit, un nuevo framework de testing para .NET que promete ser una alternativa interesante a los ya existentes.
Y, como siempre, vale la pena leer a Derek Comartin, esta vez reflexionando sobre por qué los debates sobre si debemos usar o no microservicios suelen perder el foco del verdadero problema que se intenta resolver: el acoplamiento.
Por último, como este será el último recopilatorio hasta la vuelta de las fiestas navideñas, aprovecho para desearos a todos unas felices fiestas y un próspero año nuevo 2026.
Por si te lo perdiste...
- Otras formas de obtener dependencias en controladores ASP.NET Core MVC
José M. Aguilar - Propiedades parciales en C# 13 y .NET 9
José M. Aguilar
.NET
- Custom Scripting for Web Applications
Nevio Medancic, Enzo Grubisa & Vassili Kaplan - Dynamically Changing Decimal & Thousand Separators At Runtime
Conrad Akunga - TUnit: The New Sheriff in Town for .NET Testing
Vladan Petrovic - Refactoring Legacy C# Codebases: Modernizing Async, Collections, and Architecture for Safe, Maintainable .NET
Sudhir Mangla - C# Tip How to create and access custom C# Attributes by using Reflection
Davide Bellone - Creating a .NET CLR profiler using C# and NativeAOT with Silhouette
Andrew Lock - .NET Job Scheduling — Choosing the Right Framework
Martin Stühmer - New in .NET 10 and C# 14: Optimizations in log aggregation jobs
Ali Hamza Ansari - Angular Signals, But Better Now for .NET
I Looked Inside .git and You Won't Believe What I Found - How to Analyse Large CSV Files with Local LLMs in C# (English)
Scott Galloway - Stop Typing: The .NET CLI Tab Completion You've Been Missing
Martin Stühmer - Flatten your models with Facet .NET
Tim Maes - Fetching and Analysing Web Content with LLMs in C#
Scott Galloway - Streams Record Truth. Queues Do Work: A .NET Way To Keep Them Straight
Christopher Johnson - Your cache is not protected from cache stampede
Alexey Fedorov - The New Features and Enhancements in .NET 10
Joydip Kanjilal
ASP.NET Core / ASP.NET / Blazor
- .NET 10 en el desarrollo de APIs REST modernas: Qué aporta realmente en la industria
Gerson Azabache Martínez - MinimalWorker: simplify background worker registration in ASP.NET Core and .NET applications
Joshua Jesper Krægpøth Ryder - Showing custom metrics in Aspire
Bart Wullems - Blazor SaaS Starter Kits Compared: When to Choose Brick Starter for Full‑Stack C#
Brick Starter Team - Clean Architecture for Blazor with DDD & CQRS
Aliaksandr Marozka - MVVM vs MVU in Blazor for Enterprise Apps
Aliaksandr Marozka - Deploy Aspire to Azure Container Apps using the Aspire CLI
Aspire Team - Managing Content Security in Telerik ASP.NET Core Applications
Peter Vogel - Blazor WebAssembly Using Local Storage in Offline Scenarios
Claudio Bernasconi
Azure / Cloud
- JSON Web Token (JWT) Validation in Azure Application Gateway: Secure Your APIs at the Gate
Pierre Roman
Conceptos / Patrones / Buenas prácticas
- Why “Microservices” Debates Miss the Point
Derek Comartin
Data
- One Minute Knowledge: Is ToArrayAsync or ToListAsync faster for Entity Framework?
Steven Giesel - Introducing Kepler.Core — Smart Field Selection for EF Core APIs
Mohammad Ali Ebrahimzadeh - EF Core Bulk Data Retrieval: 5 Methods You Should Know
Anton Martyniuk - EF Core 10 Turns PostgreSQL into a Hybrid Relational-Document DB
Stefan Mitic
Machine learning / IA
- Introducing GPT-5.2-Codex
OpenAI Team - What Building AI Agents in .NET Taught Me in 2025
Bruno Capuano - Prompt Noise Is Killing Your AI Accuracy: How to Optimize Context for Grounded Output
Chris Pietschmann - GPT-5.2 Prompting Guide
Mandeep Singh & Emre Okcular - Local AI Power: Vision and Function Calling with Microsoft Agent Framework and Ollama
Bruno Capuano - Understanding RAG (Retrieval-Augmented Generation)
Hassan Djirdeh
Web / HTML / CSS / Javascript
- Responsive List of Avatars Using Modern CSS, Part 1 & Part 2
Temani Afif - What’s !important #1: Advent Calendars, CSS Wrapped, Web Platform Updates, and More
Daniel Schwarz - New to the web platform in December
Rachel Andrew - Forced Colors Mode
Chris Ferdinandi - JWT Authentication in React: Secure Routes, Context, and Token Handling
Prashant Yadav - Smashing Animations Part 7: Recreating Toon Text With CSS And SVG
Andy Clarke - Add Some Class to Your JavaScript
Paul Sheriff - CSS Layout: How To 'Center a Div,' the Old School Way
Steven J. Vaugha - My HTML Web Component boilerplate for 2026
Chris Ferdinandi - Vite vs. Webpack for react apps in 2025: A senior engineer’s perspective
Peter Aideloje - Masonry Layout is Now grid-lanes
Sunkanmi Fafowora
Visual Studio / Complementos / Herramientas
- Productividad avanzada con GitHub Copilot en el desarrollo backend con .NET
Gerson Azabache Martínez - 16 Tips for Writing AI-Ready C# Code
Matt Eland - A visual editor for the Cursor Browser
Cursor Team - Microsoft.Testing.Platform Now Fully Supported in Azure DevOps
Jeff Bowman - Visual Studio 2026: Debugging with Copilot
David Kahler - Behind the scenes of the Visual Studio feedback system
Mads Kristensen - Microsoft Quietly Kills IntelliCode as AI Strategy Shifts to Subscription Copilot
David Ramel - Investigating a deadlock in Visual Studio
Kevin Gosse
.NET MAUI
- How to Build iOS Widgets with .NET MAUI
Toine de Boer - .NET 10 for .NET MAUI: Exploring New Diagnostics and Metrics
Leomaris Reyes
Otros
- Sobre velocidad y coste de desarrollo
Juan María Hernández - A los desarrolladores de software se les fue de las manos cómo lo bautizan. Y ahora todos pagamos un 'impuesto cognitivo' por ello
Marcos Merino
Publicado en Variable not found.
Koalite
Sobre velocidad y coste de desarrollo
diciembre 19, 2025 09:19
Al desarrollar software, y más cuando se trata de un producto maduro, es habitual que surga la sensación de que «antes sacábamos cambios rápido y ahora todo va más lento» y, por tanto, se proponga «contratar más gente para volver a ir rápido».
Desde fuera puede parecer que el equipo simplemente se ha vuelto menos eficiente. Desde dentro, normalmente lo que está pasando es bastante más mecánico y predecible:
- A medida que el software crece, su coste mínimo de mantenimiento y evolución sube.
- A medida que crece el equipo, la capacidad productiva media por persona decrece.
Esto, que puede parecer algo exclusivo del mundo del desarrollo, es algo que pasa en más ámbitos, como el nivel de vida de una persona o algo tan básico como organizar una habitación.
La complejidad tiene un coste
Cuando un software es pequeño, tiene pocas piezas, pocas reglas, pocas integraciones y pocos casos especiales. Cambiar algo es parecido a mover un mueble en una habitación vacía: lo haces rápido y rara vez rompes nada.
Con el tiempo el producto crece: más funcionalidades, más pantallas, más configuraciones, más clientes con necesidades distintas, más integraciones externas, más datos históricos, más restricciones.
El sistema se convierte en un conjunto de piezas que encajan entre sí. Y ese encaje tiene un precio. Ya no estamos moviendo un mueble en una habitación vacía; estamos intentando cambiar de sitio un armario ropero en una habitación llena de muebles.
En la práctica, esto se nota en tres cosas:
- Entender lo que hay cuesta más: antes podías leer una parte del código y ya. Ahora entender un cambio requiere saber cómo afecta a otras piezas.
- Hacer un cambio correctamente cuesta más : hay más validaciones, más tests, más revisiones, más compatibilidad hacia atrás, más escenarios que no puedes romper.
- Los errores se vuelven más probables y más caros: no porque la gente programe peor, sino porque hay más interacciones posibles. Además, cuando aparece un bug, cuesta más investigar su origen.
Si lo llevamos al nivel de vida de una persona, pasa algo parecido.
Si vives con tus padres, llevas una vida sencilla y no necesitas muchas cosas, tu coste fijo es bajo y puedes llegar a fin de mes sin problemas con poco dinero. A medida que tu vida se va complicado, y te compras una casa, tienes un hijo o te compras un coche, tu coste fijo va aumentando y cada vez necesitas más dinero para llegar fin de mes.
Esto es lo que pasa en software: cuando es sencillo, un cambio puede costar un par de días, pero cuando va ganando en complejidad, ese mismo cambio puede requerir un par de semanas para poder tener en cuenta todas las interacciones con el resto del sistema.
Es una consecuencia natural de tener más cosas funcionando y más cosas que no puedes romper.
Escalar el equipo ayuda, pero con rendimientos decrecientes
Cuando el coste sube la reacción típica es: «contratemos más gente». Es algo que ayuda y tiene un impacto positivo. Pero hasta cierto punto.
Hay quien piensa que si 2 personas producen 10, aumentando a 4 producirán 20. O producirán 10, pero en la mitad de tiempo. Por desgracia, no es tan sencillo, y, en general, al aumentar el número de personas, la productividad media por persona irá disminuyendo.
¿Por qué disminuye la productividad por persona al aumentar el número de personas?
Hay dos motivos principales.
La falta de contexto. Una persona nueva puede ser muy buena, pero empieza con desventaja:
- No conoce el producto en detalle.
- No conoce los “porqués” históricos (decisiones pasadas, limitaciones, clientes clave).
- No conoce los riesgos escondidos (lo que no se debe tocar sin cuidado).
Al principio, esa persona necesita tiempo de formación y, además, tiempo de otras personas para ayudarle: explicaciones, revisiones, acompañamiento, correcciones. Con el tiempo se convierte en productiva, pero no es inmediato.
El coste de coordinación interno del equipo.
Cuando un equipo es pequeño pasa mucho tiempo junto, hay pocas tareas abiertas en paralelo, y todo el mundo está al tanto de todo. Al ir creciendo esto cambia: aparecen más reuniones, más tareas en paralelo que dependen unas de otras, más necesidad de alinear criterios (qué se hace, cómo, etc.).
Aunque se pueda trabajar en más frentes en paralelo, cada iniciativa individual suele avanzar más lento porque necesita más coordinación y aumenta el coste de comunicación.
Si volvemos a compararlo con el nivel de vida, es similar a lo que ocurre con los impuestos. Supongamos que cuando tenías una vida sencilla, con 12.000€ brutos al año conseguías 1.000€ netos al mes y te podías apañar. Podrías pensar que cuando la complejidad de tu vida aumenta te basta con aumenta linealmente tus ingresos, pero no es así: si duplicas tu ingresos y ganas 24.000€ brutos al año, mensualmente sólo recibes 1.600€. Los siguientes 12.000€ no han multiplicado por dos tu capacidad de asumir costes, sino sólo por 1.6.
Algo parecido ocurre al incorporar personas a un equipo. Duplicar el tamaño del equipo no multiplica su capacidad de producción por 2, sino por un factor menor.
Conclusiones
Es necesario entender que cuando aumenta la complejidad del software los cambios cuestan más, no porque el equipo sea menos competetente, sino porque, sencillamente, los cambios son más difíciles y costosos de hacer.
Contratar más gente ayuda, pero es necesario asumir un coste inicial de formación y un coste de coordinación creciente, por lo que no cabe esperar un crecimiento de la productividad lineal con respecto al número de personas.
Para recuperar la velocidad hay que tener en cuenta otros factores, como reducir la complejidad simplificando el software, eliminando casos especiales, automatizando procesos y, sobre todo, teniendo unas prioridades claras para evitar que unas tareas acaben compitiendo con otras.
Si entendemos que el software tiene un coste fijo creciente y que los equipos tienen rendimientos decrecientes al crecer, el foco de la conversación cambia. Ya no es «¿por qué somos más lentos?», sino «¿qué complejidad estamos acumulado? ¿la necesitamos? ¿cómo la vamos a gestionar?».
Variable not found
¿Estás usando tus expresiones regulares en .NET de forma óptima?
diciembre 19, 2025 07:47
La relación de muchos desarrolladores con las expresiones regulares es de amor-odio. Aunque indudablemente son una herramienta muy potente, su uso puede ser complicado y a menudo se convierten en un dolor de cabeza.
Pero hoy no vamos a hablar de su (oscura) sintaxis, ni de lo difícil que es depurarlas, ni de cómo utilizarlas en .NET, sino de distintas técnicas que pueden ayudarnos a disparar su velocidad de proceso, algo bastante importante si las utilizamos en los procesos críticos o hot paths de nuestra aplicación.
En este artículo vamos comparar el rendimiento de distintos escenarios de uso de expresiones regulares, y cómo podemos optimizar su uso en .NET.
Chequear direcciones de email usando expresiones regulares
Como punto de partida, echemos un vistazo al siguiente código, un ejemplo donde definimos la clase estática EmailValidator, con un método IsValid() que utiliza la clase RegEx para validar el email que recibe como parámetro:
Console.WriteLine(EmailValidator.IsValid("john@server.com")); // true
Console.WriteLine(EmailValidator.IsValid("john@smith@server.com")); // false
public static class EmailValidator
{
public static bool IsValid(string email)
{
string emailPattern = @"^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|""(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*"")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$";
var regex = new Regex(emailPattern, RegexOptions.IgnoreCase);
return regex.IsMatch(email);
}
}
No vamos a entrar en el debate de si la expresión regular que hemos utilizado es la mejor para validar un email. Simplemente es la recomendación de un LLM asegurando que cumple la RFC 5322, y, para la prueba que queremos hacer es totalmente válida porque tiene una cierta complejidad.
Si ejecutamos el código anterior, veremos que la expresión regular funciona correctamente y el método IsMatch() nos devuelve true o false dependiendo de si el email es válido o no. Y además, aparentemente la ejecución es bastante rápida, suficiente si no es algo que se vaya a ejecutar con mucha frecuencia.
Sin embargo, internamente, cada vez que llamamos a ese método estático IsValid(), estamos instanciando la clase Regex suministrándole el patrón de la expresión regular, que es parseado, verificado, optimizado, compilado y posteriormente ejecutado por un intérprete para realizar la validación que le estamos solicitando. Todo este proceso puede ser costoso en términos de rendimiento, sobre todo si esa parte del código se ejecuta con mucha frecuencia.
Seguro que podemos mejorar esto...
Primera mejora: reutilización de Regex
La primera optimización que podemos aplicar en este punto es reutilizar la instancia de Regex. De esta forma, evitaremos la sobrecarga de crear una nueva instancia cada vez que llamamos al método IsValid() y evitaremos el proceso de verificación y compilación de la expresión regular.
Esto podríamos conseguirlo fácilmente insertando en la clase anterior el siguiente código:
public static class EmailValidator
{
private const string EmailPattern = @"^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|""(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*"")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$";
private static Regex SharedInstance = new Regex(EmailPattern, RegexOptions.IgnoreCase);
public static bool IsValid_Shared(string email)
{
return SharedInstance.IsMatch(email);
}
}
Si ejecutamos de nuevo la aplicación, veremos que el funcionamiento es exactamente el mismo, y que aparentemente sigue siendo igual de rápido. Pero si usamos BenchmarkDotNet para medir el rendimiento de las dos implementaciones, nos llevaremos una sorpresa:
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|-----------------|-----------:|----------:|----------:|--------:|----------:|
| IsValid | 206.716 us | 1.5089 us | 1.2600 us | 27.3438 | 233969 B |
| IsValid_Shared | 2.742 us | 0.0312 us | 0.0276 us | - | - |
Esta segunda implementación se ejecuta casi 80 veces más rápido que la primera, sin consumo de memoria adicional. Impresionante, ¿verdad? Realmente se trata de una mejora brutal a cambio de muy poco esfuerzo de implementación.
Hay que tener en cuenta que las cifras no son siempre tan espectaculares, y que el rendimiento de la primera implementación puede variar dependiendo de la complejidad del patrón de la expresión regular. En expresiones más simples, la diferencia de rendimiento puede ser mucho menor, pero en cualquier caso habrá mejoras.
Pero... ¿aún podemos hacerlo mejor?
Segunda mejora: compilación de la expresión regular
Por defecto, las expresiones regulares se compilan a una serie de instrucciones de alto nivel que indican las operaciones que deben realizarse para comprobar si la cadena de texto suministrada coincide con el patrón de la expresión regular. Luego, en cada llamada a IsMatch() o métodos similares, un intérprete ejecuta esas instrucciones para realizar la validación.
Sin embargo, la clase Regex también permite compilar la expresión regular a código IL, por lo que el runtime de .NET puede ejecutarlo directamente e incluso, gracias al JIT, generar y ejecutar el código máquina nativo para la plataforma donde corre la aplicación, a cambio, eso sí, de consumir un poco más de memoria y tiempo durante su inicialización.
Esto lo conseguimos de nuevo con muy poco esfuerzo, simplemente añadiendo el RegexOptions.Compiled a la llamada al constructor de la clase Regex:
private static Regex SharedCompiledInstance
= new Regex(EmailPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
Si volvemos a llevarnos las tres opciones a BenchmarkDotNet, y medimos su rendimiento, veremos que en este último caso hemos mejorado algo más el rendimiento:
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|------------------ |-----------:|----------:|----------:|--------:|----------:|
| IsValid | 202.007 us | 2.4068 us | 2.2513 us | 27.3438 | 233969 B |
| IsValid_Shared | 2.606 us | 0.0276 us | 0.0258 us | - | - |
| IsValid_Compiled | 2.570 us | 0.0141 us | 0.0132 us | - | - |
En este caso la diferencia es mínima, pero es algo que también depende de la complejidad de las operaciones que hay que realizar para validar los valores contra la expresión regular. Por ejemplo, si en lugar de usar la expresión regular que hemos visto anteriormente para detectar emails, ejecutamos el mismo benchmark para un patrón aparentemente simple como "(\d+)*\1" y hacemos que se compruebe un string numérico muy largo (unos 100.000 dígitos), la diferencia de rendimiento es mucho más notable:
| Method | Mean | Error | StdDev | Allocated |
|----------------- |---------:|---------:|---------:|----------:|
| IsValid | 65.70 ms | 1.107 ms | 1.088 ms | 5401 B |
| IsValid_Shared | 63.74 ms | 0.925 ms | 0.772 ms | 57 B |
| IsValid_compiled | 19.52 ms | 0.147 ms | 0.130 ms | 12 B |
La expresión regular
"(\d+)*\1"permite buscar cadenas que contengan un número seguido de un número repetido, como por ejemplo123123,456456,789789, etc. Esta expresión regular es ejemplo conocido por dar lugar al llamado catastrophic backtracking, un problema que puede dar lugar a un rendimiento muy bajo en ciertas expresiones regulares, que incluso puede ser explotado en ataques de denegación de servicio (DoS) en aplicaciones web.
Estos resultados son fácilmente explicables: la diferencia de rendimiento entre la primera y segunda opción es pequeña, porque la expresión regular es muy simple y, por tanto, el coste de su compilación es bajo. Pero el rendimiento se multiplica por tres en la tercera opción porque la ejecución de la expresión regular se beneficia de la compilación a código IL.
Hasta aquí, hemos comprobado cómo realizando un par de modificaciones simples en el código podemos lograr mejorar considerablemente el rendimiento de las expresiones regulares en .NET. Pero aún hay más...
Tercera mejora: compilar la expresión regular en tiempo de diseño
La compilación de la expresión regular a código IL es una mejora muy interesante, pero tiene un coste adicional el términos de memoria y proceso, que se produce en el momento de la inicialización de la expresión regular, es decir, en tiempo de ejecución.
De hecho, también podemos realizar un benchmark del tiempo de creación de la instancia de Regex con y sin compilación, y veremos que la diferencia es prácticamente del triple, tanto en tiempo de proceso como en consumo de memoria:
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|-------------------- |---------:|---------:|---------:|--------:|-------:|----------:|
| CreateRegex | 28.64 us | 0.204 us | 0.170 us | 3.4180 | - | 29.27 KB |
| CreateRegexCompiled | 99.51 us | 0.973 us | 0.863 us | 10.7422 | 1.4648 | 90 KB |
Si queremos evitar este sobrecoste, a partir de .NET 7 podemos compilar la expresión regular en tiempo de diseño usando source generators. De esta forma, el compilador de C# generará el código C# necesario para ejecutar la expresión regular, y lo incluirá en el ensamblado de la aplicación, por lo que no pagaremos ningún coste adicional en tiempo de ejecución. Pero además, como veremos algo más adelante, el código generado será mucho más eficiente que la versión compilada en tiempo de ejecución 🙂
Para conseguirlo, en una clase cualquiera debemos un método parcial de tipo Regex y asignarle el atributo [GeneratedRegex] especificando el patrón de la expresión regular y las opciones que queramos utilizar. Por ejemplo, en el siguiente código podemos ver el método al que hemos llamado GeneratedEmailRegex() sobre la clase estática parcial EmailRegex (ambos nombres son arbitrarios):
public static partial class EmailRegex
{
[GeneratedRegex(@"^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|""(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*"")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$", RegexOptions.IgnoreCase)]
public static partial Regex GeneratedEmailRegex();
}
Podéis ver fácilmente el código generado ejecutando la aplicación y, en el explorador de soluciones de Visual Studio, desplegando la carpeta "External Sources", el ensamblado de la aplicación, y abriendo el archivo
RegexGenerator.g.cs, o bien, siguiendo estos pasos.
Una vez tenemos este método disponible, para utilizar la expresión regular simplemente debemos usar la instancia de Regex retornada por el mismo, por ejemplo así:
public static class EmailValidator
{
public static bool IsValid(string email)
{
return EmailRegex.GeneratedEmailRegex().IsMatch(email);
}
}
Y si de nuevo nos llevamos estos cambios a BenchmarkDotNet, y medimos el rendimiento de las distintas implementaciones, de nuevo nos llevaremos una alegría:
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|-------------------------- |-------------:|------------:|------------:|--------:|----------:|
| IsValid_Initial | 213,564.0 ns | 1,532.91 ns | 1,280.05 ns | 27.3438 | 233969 B |
| IsValid_Shared_Instance | 2,667.7 ns | 39.86 ns | 35.33 ns | - | - |
| IsValid_Compiled_Instance | 2,745.5 ns | 37.81 ns | 35.37 ns | - | - |
| IsValid_UsingGenerators | 788.3 ns | 7.91 ns | 7.40 ns | - | - |
¡Uau! De nuevo hemos conseguido dividir por tres el tiempo de ejecución de la expresión regular respecto a la versión compilada en tiempo de ejecución. Y bueno, si lo comparamos con la versión inicial, la que implementamos sin pensar en ninguna optimización, es cerca de 300 veces más eficiente.
Conclusiones
A veces, el código que escribimos puede no ser el más óptimo: a veces por costumbre, a veces por comodidad, u otras simplemente porque no conocemos fórmulas mejores. En algunos casos no importará demasiado porque quizás nuestros requisitos de rendimiento no son excesivamente exigentes, pero en otros muchos escenarios sí debemos prestar atención a este tipo de detalles.
Lo que hemos visto en este post es un claro ejemplo de cómo las mejoras que se van introduciendo en el framework y el SDK de .NET pueden ayudarnos a mejorar el rendimiento de nuestras aplicaciones con muy poco esfuerzo.
Publicado en: www.variablenotfound.com.Variable not found
Enlaces interesantes 631
diciembre 15, 2025 07:42
La semana pasada estuve unos días fuera y no publiqué la habitual recopilación de los lunes. Pero ya me he puesto al día, y, como se me acumuló el trabajo, en esta entrega tenemos más de ¡100! enlaces a contenidos a los que vale la pena echar un vistazo.
Por destacar algunos, en primer lugar el profundo análisis que está llevando a cabo Martin Stühmer sobre soluciones de scheduling en .NET, muy interesantes para estar al tanto de las opciones disponibles.
También Gerson Azabache ha publicado varios artículos interesantes sobre ASP.NET Core, como la comparativa entre Minimal APIs y controladores, resultados tipados y algunas buenas prácticas en el desarrollo de APIs empresariales.
Braulio Díez comparte sus reflexiones y experiencias sobre el impacto de la IA en la programación y el futuro de los desarrolladores de software, que igual no es tan malo como algunos pintan.
Y en la misma línea, José Manuel Alarcón habla sobre cómo los juniors deben enfocar su proceso de aprendizaje, integrando la IA como una aliada imprescindible.
Muchos más enlaces, a continuación.
Por si te lo perdiste...
- Mi controlador tiene muchos parámetros en el constructor, ¿estoy haciendo algo mal?
José M. Aguilar - HybridCache, la nueva caché híbrida de .NET 9
José M. Aguilar
.NET
- C# 14 New Feature: Field-Backed Properties
Ian Griffiths - Recent updates to NetEscapades.EnumGenerators: [EnumMember] support, analyzers, and bug fixes
Andrew Lock - “Classic” .NET Domain Events with Wolverine and EF Core
Jeremy D. Miller - .NET Job Scheduling: Quartz.NET for Enterprise Scale & Coravel and Fluent Simplicity & NCronJob and Native Minimalism & TickerQ and Modern Architecture
Martin Stühmer - How to Build a Production-Ready Invoice Builder in .NET Using IronPDF
Anton Martyniuk - How can my process read its own standard output?
Raymond Chen - Mime Type Helper in .NET 11
Steven Giesel - Single File Test Suites in Dotnet Csharp
Steve Smith - Create Types on Demand and Cecilifier
Roman Stoffel - Creating a custom MSBuild SDK to reduce boilerplate in .NET projects
Gérald Barré - Debug Dumps in Visual Studio
Stephen Cleary - Building Modular .NET Applications with CShells
Sipke Schoorstra - .NET 10 Networking Improvements
Marie Píchová - What the heck is a
\\.\nulpath and why is it breaking my Directory Files Lookup?
Rick Strahl - .NET 10 Validation
Ricardo Peres - .NET Performance: Efficient Async Code
Nick Kovalenko - .NET 10 and Memory: Less Heap, Smarter GC, Faster Apps
Hazem Ali - Immutable Collection Add() Trap: Don’t Get Burned — Use a Builder Instead
David McCarter - How .NET 10.0 boosted AIS.NET performance by 7%
Ian Griffiths - Resolving Overload Ambiguity with Collection Expressions
Gérald Barré - Typemock Architecture: Inside the .NET Isolator Engine (Part 2)
Eli Lopian - Cleaner Code: C# 14 Null-Conditional Assignment Operator
Dave Brock
<!--more-->
ASP.NET Core / ASP.NET / Blazor
- Minimal APIs vs Controllers en .NET 10: la guía corta y honesta & Por qué tus APIs en .NET deberían usar Result Contracts (Typed Results) & Las 5 mejores prácticas modernas para APIs empresariales en .NET (2026)
Gerson Azabache Martínez - Enterprise Patterns for ASP.NET Core Minimal API: Transaction Script Pattern – The Shortcut That Quietly Reshapes Your System
Chris Woodruff - How to upload files in an ASP.NET Core Web API
David Grace - Stop Letting Your Controllers Talk to SQL: Layered Architecture in ASP.NET Core
Chris Woodruff - Best Practices For Building REST APIs
Anton Martyniuk - How to Choose the Best Blazor Dropdown Component for Your Web App
Prince Oliver - mostlylucid.MinimalBlog - How Simple Can an ASP.NET Blog Really Be? (English)
Scott Galloway - Enterprise Patterns for ASP.NET Core Minimal API: Domain Model Pattern – When Your Core Rules Deserve Their Own Gravity
Chris Woodruff - Load Testing ASP.NET Core Applications with k6: Introduction & Practical Implementation
Scott Galloway - How Aspire composes itself: an overview of Aspire's Docker Compose integration
Safia Abdalla - Migrating from Bootstrap Blazor or MudBlazor to Blazorise
Mladen Macanović - Using Strategy Pattern with Dependency Injection in ASP.NET Core
Ali Hamza Ansari - Getting Started with the Aspire CLI - A Complete Guide
Chris Ayers
Azure / Cloud
- You Can't Use Azure Migrate to Move Between Tenants (Even if you Try to Run it in Azure)
Shannon B. Kuehn - How to Deploy a Spreadsheet Server on Azure App Service Using Visual Studio and Docker
Parthasarathy Ranjan
Conceptos / Patrones / Buenas prácticas
- Domain-Driven Design Misconceptions
Derek Comartin - Treat test code like production code
Mark Seemann - Aggregates in DDD: Model Rules, Not Relationships
Derek Comartin - 10 Habits That Make You a Great Programmer
Shalitha Suranga - 12 Essential Distributed System Design Patterns Every Architect Should Know
Anton Martyniuk - Power of Ten Rules: More Relevant Than Ever for .NET
Martin Stühmer - Stop Naming Your Variables "Flag": The Art of Boolean Prefixes
Christopher Johnson
Data
- Data Access in .NET: Comparing ORMs and Mapping Strategies (Part 1 & * Comparing ORMs and Mapping Strategies (Part 2
Scott Galloway - Debugging Entity Framework Core: 8 Real-World Query Anti‑Patterns (and How to Fix Them)
Chris Woodruff - Named global query filters in Entity Framework Core 10
Tim Deschryver - DbContext is Not Thread-Safe: Parallelizing EF Core Queries the Right Way
Milan Jovanović - Why your EF Core queries are slow and how to fix them
David Grace
Machine learning / IA
- Meet EuroLLM: Large language model made in Europe built to support all official 24 EU languages
EuroLLM - Introducing: Devstral 2 and Mistral Vibe CLI
Mistral - Introducing GPT-5.2
OpenAI - Introducing the Microsoft Agent Framework – A Dev-Friendly Recap
Bruno Capuano - Introducing Data Ingestion Building Blocks (Preview)
Luis Quintanilla - Anomaly Detection Using K-Means Clustering with JavaScript
James McCaffrey
Web / HTML / CSS / Javascript
- Cómo probar tu aplicación con Vue en GitHub Pages
Gisela Torres - Prevent a page from scrolling while a dialog is open
Geoff Graham - Getting Creative With “The Measure”
Andy Clarke - Scrollytelling on Steroids With Scroll-State Queries
Lee Meyer - Masonry: Things You Won’t Need A Library For Anymore
Patrick Brosset - Frederik Braun: Why the Sanitizer API is just
setHTML()
Frederik Braun - Creating Scroll-Based Animations in Full view()
Preethi - CSS Wrapped 2025
Chrome DevRel Team - Fit width text in 1 line of CSS
Geoff Graham - That Time I Tried Explaining HTML and CSS to My 5-Year Old Niece
Kevine Nzapdi - ::target-text: An easy way to style text fragments
Saron Yitbarek - Stop using JavaScript to solve CSS problems
Chizaram Ken - Simulating the Enigma Machine
Andrew S. Erwin - Tailwind CSS: Targeting Child Elements (when you have to)
Christian Ekrem - How to Prevent XSS Attacks in React Rich Text Editor
Thangavel E. - What's wrong with this HTML, and is it valid?
Patrick Brosset - How to create Liquid Glass effects with CSS and SVG
Rahul Chhodde - What Else Could Container Queries... Query?
Daniel Schwarz - Denial of Service and Source Code Exposure in React Server Components – React
The React Team
Visual Studio / Complementos / Herramientas
- Why changing keyboard shortcuts in Visual Studio isn’t as simple as it seems
Steven Miller - Unlock GitHub Copilot’s Full Potential: Why Every Repo Needs an AGENTS.md File
Chris Pietschmann - Progress on TypeScript 7 - December 2025
Daniel Rosenwasser - Introducing Stack Overflow AI Assist—a tool for the modern developer
Stack Overflow Team - Microsoft Learn MCP Server Elevates Development
Wendy Breiding - Trying out the Zed editor on Windows for .NET and Markdown
Andrew Lock - Previewing the JavaScript/TypeScript Modernizer for VS Code Insiders
Sayed Ibrahim Hashimi - DarkGPT: Malicious Visual Studio Code Extension Targeting Developers — Real-time Open Source Software Supply Chain Security
SafeDep Team - Streamlining your Git workflow with Visual Studio 2026
Mads Kristensen - Making Windows Terminal awesome with GitHub Copilot CLI
Linda Berns
.NET MAUI / Cross-Platform
- Cross-Platform Age Verification in .NET MAUI Applications
Gerald Versluis - Securing Sensitive Mobile Operations with Device-Bound Request Signing
Fernando de Oliveira - Mastering Popups in .NET MAUI: Alerts, Action Sheets, Overlays & More
Jayaleshwari N. - Implementing Cross-Platform In-App Billing in .NET MAUI Applications
Gerald Versluis - How to Add and Remove Digital Signatures in PDF Using .NET MAUI
Rangarajan Ashokan - How to Integrate Google Maps in .NET MAUI: A Cross-Platform Guide Using the Google Maps Tile API
Jeyasri Murugan - Avalonia MAUI Progress Update
Tim Miller - .NET 10: Quick UI Changes Worth Noticing in .NET MAUI
Leomaris Reyes
Otros
- El picar se va acabar
Braulio Díez - Aprende a programar en 2026: guía práctica para juniors (que tienen miedo a la IA, o no)
José Manuel Alarcón
Publicado en Variable not found.
Picando Código
Anunciado Mega Man: Dual Override
diciembre 12, 2025 11:30
Capcom anunció la duodécima entrega principal de la serie Mega Man durante The Game Awards: Mega Man: Dual Override. El bombardero azul regresa en 2027 en Nintendo Switch 2, Nintendo Switch, PlayStation 5, PlayStation 4, Xbox Series X|S, Xbox One y PC a través de Steam.

El último título en la serie fue Mega Man 11 en 2018. Parece que Capcom nos va a dar un Mega Man nuevo por década aproximadamente
En 2027 se celebran 40 años de Mega Man, así que es posible que hayan más anuncios al respecto durante el año.
En el mundo de los cómics, después de una muy buena serie Mega Man Timelines durante 2025, vamos a tener cómics de Mega Man X. El primer número, Mega Man X #0, va a estar disponible en Enero de 2026, seguido de una mini-serie de 5 números. Esperemos ver algo de Mega Man X en el terreno de los videojuegos también...
El tráiler del anuncio muestra que sigue el estilo gráfico 2.5D de Mega Man 11. De repente se notan algunos detalles más en lo gráfico. Vuelve la clásica deslizada y el disparo cargado con el mega buster. Hacia el final del tráiler vemos una animación como de expansión de elementos en la armadura de Mega Man. ¿Cómo estará relacionado eso al juego? Habrá que ver también qué protagonismo tiene Proto Man, del que escuchamos el silbido característico al final del tráiler. Por el momento no hay mucho más información, pero seguro sepamos más el año que viene.

Jugué Mega Man 11 en su momento en Nintendo Switch y lo disfruté mucho. Hace poco lo empecé de nuevo, a ver si lo vuelvo a terminar. Es entretenido y desafiante, como nos tiene acostumbrados la saga. En ese título se introdujo una mecánica nueva, el sistema "Double Gear". Este incluye dos habilidades, Speed Gear que permite enlentecer el tiempo, permitiendo atacar y esquivar ataques más fácilmente. La otra es Power Gear, que permite disparar ataques más potentes. Ni idea si esto vuelve en Mega Man 12.
Si todavía no han probado Mega Man 11, en los próximos días va a recibir un descuento en tiendas digitales. Va a estar de oferta en la PlayStation Store, Nintendo eShop, Xbox Store y Steam. También hoy recibió una actualización que expande las opciones de idioma a portugués brasileño y español latinoamericano.
Siguiendo con Mega Man: Dual Override, este mes Capcom organiza un concurso especial de diseño de jefes. Como hizo en alguna entrega anterior hace muchos años, tendremos la oportunidad de crear un nuevo robot que aparecerá en el juego:
Periodo de inscripción: 11 de diciembre de 2025, 22:00 h - 1 de enero de 2026, 01:59 h CST
Convocatoria: Estamos aceptando inscripciones en X (antes Twitter) para el concurso de diseño de Robot Maestro para Mega Man: Dual Override. ¡Utiliza el modelo de abajo como base para crear tu propio diseño único de un Robot maestro con un brazo de succión gigante!
Aceptaremos diseños de las siguientes cuatro regiones: Japón, las Américas, Europa y Asia.
Buscamos diseños de un Robot maestro que tenga un brazo derecho con inmensos poderes de succión!
Premios: Elegiremos los 6 mejores diseños y seleccionaremos un ganador entre ellos.
- Gran premio: 1 ganador
Tu diseño de Robot maestro se usará en Mega Man: Dual Override
- Premios a la excelencia: 6 ganadores
Tu nombre aparecerá en los créditos de Mega Man: Dual Override
Voy a ver si mando algo... Una lástima que el concurso se haga a través de ese sitio web al que las marcas ya deberían haber abandonado hace rato.
Todavía falta al menos un año entero para poder jugar Mega Man Dual Override. Pero es bueno ver que Capcom no se ha olvidado de Mega Man.
Otro título interesante de Capcom que recibió noticias durante el evento fue Pragmata. Cuando vi el primer tráiler me resultó un juego "como un Mega Man más adulto". Es una IP nueva de Capcom, aventura de acción y ciencia ficción con elementos de hackeo. ¡Se ve muy bien! Mediante un tráiler nuevo, se anunció su disponibilidad también para Nintendo Switch 2. Además está disponible una demo gratuita en Steam, y próximamente va a haber demo para Nintendo Switch 2, PlayStation 5 y Xbox Series X|S. El juego va a estar disponible el 24 de abril de 2026 en todas las plataformas, algo para ir jugando mientras esperamos Mega Man 12...

El post Anunciado Mega Man: Dual Override fue publicado originalmente en Picando Código.
Picando Código
Piques Firefox: Contar cantidad de pestañas abiertas en Firefox 2025
diciembre 11, 2025 11:30

Hace unos años publiqué el pique para contar las pestañas abiertas en Firefox. Me sirve para convencerme de que tengo demasiadas pestañas abiertas y que los 16GB de Ram de mi laptop no son suficientes para aguantar tanta cosa. Pero desde hace un tiempo esto no me venía funcionando. Al abrir la consola del navegador con Ctrl Shift J, no me aparecía la línea de comando. Así que no podía ejecutar comandos.
Resulta que desde hace algunas versiones de Firefox la línea de comando de la consola del navegador está deshabilitada por defecto. Para habilitarla, tenemos que ir a about:config en la barra de dirección de Firefox y cambiar el valor de devtools.chrome.enabled de false a true. Tambien se puede habilitar seteando la opción "Enable browser chrome and add-on debugging toolboxes" en las preferencias de las Web Developer Tools.
Así que pude volver a contar mis pestañas abiertas en Firefox:
← 445
Debería seguir cerrando algunas 
De esa misma página de documentación de Firefox que enlacé: La consola del navegador es como la consola web, pero aplicado a todo el navegador en vez de al contenido de una pestaña única. Loguea un montón de información como pedidos de red, JavaScript, CSS, seguridad, errores advertencias y más pero de todo el contenido abierto. Podemos ejecutar JavaScript, y tenemos acceso a todas las pestañas a través de la variable global gBrowser. También podemos modificar la interfaz del navegador al tener acceso al objeto window, cerrar pestañas con código y mucho más.
Tendría que buscar algo divertido para programar con este conocimiento. Pero por ahora me limito a contar las pestañas abiertas a mano cada vez que pienso que tengo demasiadas. Hay un montón de extensiones de Firefox diseñadas con este mismo propósito, pero para qué instalar una extensión más si se puede hacer en pocos pasos.
El post Piques Firefox: Contar cantidad de pestañas abiertas en Firefox 2025 fue publicado originalmente en Picando Código.Picando Código
[Libro] Mike Drucker - Good Game No Rematch
diciembre 04, 2025 11:15

Mike Drucker es un escritor y comediante. Escribió para programas de televisión como Bill Nye Saves the World, The Tonight Show y Full Frontal with Samantha Bee. Ha contribuido a The Onion y Saturday Night Live (el actor de Scrubs hizo de él en un sketch de SNL). Pero más importante (para mí) que todo eso, trabajó en Nintendo y escribió la localización al inglés de Kid Icarus Uprising, entre otras cosas. Ah, ¡también escribió un cómic de Spider-Man!
Solía seguirlo en Twitter, y como muchos hicimos, abandonó el barco cuando se destapó como antro fascista. Pero se abrió un newsletter al que me suscribí desde el primer día: At The Mountains of Sadness, está alojado en Substack. Substack es otro sitio web que se destapó como antro fascista, y Mike Drucker está al tanto y tiene planeado migrar a Ghost. Pero estas migraciones son más complicadas de lo que parecen y requieren un montón de tiempo y esfuerzo...
Hace un buen tiempo ya, anunció en su newsletter que había vendido la idea del libro. No sé cómo funciona eso, supongo que uno presenta parte de lo que tiene escrito a una empresa que se compromete a pagar para publicarlo. En fin, el tema es que desde entonces lo esperé con ansias. Habiendo disfrutado mucho de lo que escribía tanto en su newsletter como en artículos que enlazaba, tenía muchas ganas de leerlo.
Lo describía como una colección de ensayos sobre videojuegos. Y si bien es cierto en parte, los capítulos tienen una cohesión cronológica que van contando experiencias en distintas etapas. El elemento que conecta todo son los videojuegos, con referencias y chistes, pero han sido algo muy presente en su vida. El libro está dividido en cuatro secciones principales que agrupan capítulos de las distintas etapas de las que escribe. Algunos capítulos son más cortos con contenido más al estilo lista como Manuales de videojuegos a través de las décadas. Éstos son como experimentos literarios que me recuerdan al trabajo de mi amigo Nacho Alcuri, por ejemplo:
What your favorite classic arcade game says about you (Lo que tu juego clásico de maquinitas favorito dice de tí)
- Street Fighter 2: You're already a little mad I didn't specify which Street Fighter 2.
Street Fighter 2: Ya estás un poco enojado que no especifiqué cuál Street Fighter 2.
Si bien es un libro gracioso, también tiene historias muy personales e identificables. No recuerdo la última vez que un libro me hizo lagrimear como éste, encima más de una vez. No sólo son historias emocionantes (y devastadoras), algunas experiencias resultan dolorosamente identificables: I'm a man who plays fighting games alone without considering the depths of sadness that represents (soy un hombre que juega juegos de pelea sólo sin considerar las profundidades de tristeza que eso representa... ¡OUCH! No sé si necesitaba que un libro me dijera lo triste que soy).
Su humor es autocrítico al extremo. Mientras leía pensaba "qué forma de darse palo, pero sabemos que es hipérbole, al final del día es una persona que dentro de todo hace las cosas bien y tiene relativo éxito. Pero tanto autocrítica al final le puede jugar en contra porque... ¿Dónde escuché esto antes?" Y ahí me pegó como si me hubiera chocado contra un muro y recordé las tantas veces que escuché ese discurso dirigido a mi persona, particularmente en el ámbito profesional. También es que me gusta mucho el humor autocrítico y cínico. Otro ejemplo de su newsletter: from 1977, long before my parents cursed me with life (de 1977, mucho antes que mis padres me maldijeran con la vida).
Con eso y otras tantas experiencias generé esa conexión con el libro que está escrito por Mike Drucker pero al momento de liberarlo al mundo se vuelve la experiencia única de cada individuo que lo lee y el artista pierde el control. Uno trae a un libro todo de sí mismo y saca de él enriquecimiento diverso. Como comenté antes, me generó diversas emociones, más que nada risa e identificación. También disfruté mucho de las anécdotas relacionadas a los videojuegos, ese conocimiento anecdótico de la historia de esto que tanto me apasiona es mi adicción.
Tras leerlo me fui a fijar algo que sospechaba y sí, Mike Drucker y yo somos de la misma generación. Nació un año antes que yo. Salvando las diferencias geográficas y sociales, hay mucho en común. Es un libro gracioso y entretenido, pero si nacieron en las décadas de 1980 o 1990 y crecieron jugando videojuegos, probablemente encuentren mucho en común también.
¿Quiero jugar Nier: Automata después de leer este libro? Sí. ¿Va a empeorar mi depresión? Probablemente. ¿Este párrafo está inspirado en el estilo del libro? Gracias por usar "inspirado en el" y no "robando del", voz imaginaria en mi cabeza que se hace preguntas retóricas a mí mismo.
Es un libro que me gustó mucho, recomiendo y me hizo reír, llorar, y querer estar en una cadena de texto con Mike Drucker por alguna razón. Es un muy buen regalo para gente aficionada a los videojuegos, se ve muy lindo en la biblioteca y seguramente vuelva a leer. El autor es un tipo famoso por las cosas que ha escrito (programas importantes de televisión y más), pero a mí me llega porque es terrible nerd. Y si ves el término nerd como algo distinto al mayor de los cumplidos, estás leyendo el blog equivocado.
El post [Libro] Mike Drucker - Good Game No Rematch fue publicado originalmente en Picando Código.Variable not found
Soporte para el TLD .localhost en ASP.NET Core 10
diciembre 02, 2025 07:05
Al desarrollar aplicaciones ASP.NET Core (APIs, MVC, Razor Pages o Blazor) y ejecutarlas en local, ya sabes que todas ellas comparten el mismo nombre de host: localhost, y lo único que las diferencia es el puerto en el que se encuentran a la escucha.
Esto puede dar lugar a ciertos problemas. Aparte de no ser sencillo identificarlas a partir de la URL mostrada en el navegador, hay ciertos recursos web que pueden mezclarse entre proyectos (por ejemplo, las cookies) y pueden dar lugar a comportamientos inesperados.
En ASP.NET Core 10 se ha puesto solución a esto añadiendo el soporte para el TLD (Top Level Domain) .localhost, lo que permite que cada aplicación pueda tener su propio nombre de host único.
Lo vemos a continuación.
Soporte para TLD .localhost en ASP.NET Core 10
El nombre .localhost es un dominio de nivel superior (TLD, Top Level Domain) reservado por las RFC 2606 y 6761 para ser utilizado en entornos de desarrollo y pruebas, y siempre está asociado a la dirección de loopback, es decir, a la dirección local del propio equipo.
Por tanto, cualquier nombre de host que termine en .localhost (por ejemplo, miapp.localhost, api.localhost, MyApp.dev.localhost, etc.) debería resolverse siempre a la dirección IP 127.0.0.1 o ::1, dependiendo de si se utiliza IPv4 o IPv6.
A partir de ASP.NET Core 10, Kestrel entenderá que todos los nombres de host que terminen en .localhost son alias válidos para localhost, por lo que podemos utilizarlos para configurar el servidor, definir las URLs de nuestras aplicaciones (tanto en launchSettings.json como en variables de entorno), etc. Esto nos permitirá usar distintos nombres de host para cada aplicación, evitando los problemas mencionados anteriormente.
Otro tema que han actualizado es el certificado HTTPS utilizado en desarrollo. Dado que el antiguo certificado solo era válido para localhost, al utilizar otros nombres de host el navegador mostraría advertencias de seguridad. Por esta razón, el certificado que se registra al instalar .NET 10 es un wildcard del dominio *.dev.localhost.
Observad que no han podido hacerlo directamente para soportar
*.localhost. Han tenido que introducir el subdominio.devpor delante porque no es posible crear wildcards sobre top level domains comolocalhost.
En la práctica, esto implica que podremos asignar a nuestras aplicaciones ASP.NET Core nombres de host como miapp.dev.localhost, api.dev.localhost, etc., aunque no es algo que esté habilitado por defecto.
Para activar esta característica, debemos seleccionar la opción "Use the .dev.localhost TLD in the application URL" al crear una nueva aplicación, como se muestra en la siguiente imagen:
Al hacerlo, se configurará el launchsettings.json para que utilice el nombre de proyecto como subdominio. Por ejemplo, a continuación se muestra la configuración generada para el proyecto MyWebApplication, donde podemos ver el uso del host mywebapplication.dev.localhost:
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://mywebapplication.dev.localhost:5244",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://mywebapplication.dev.localhost:7279;
http://mywebapplication.dev.localhost:5244",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
También podemos conseguir lo mismo si utilizamos la línea de comandos de .NET para crear los proyectos. Por ejemplo, el siguiente comando crea una aplicación MVC que utiliza el TLD .dev.localhost:
C:\MyProjects\MyWebApp>dotnet new web --localhost-tld
The template "ASP.NET Core Empty" was created successfully.
Processing post-creation actions...
Restoring C:\MyProjects\MyWebApp\MyWebApp.csproj:
Restore succeeded.
C:\MyProjects\MyWebApp>type .\Properties\launchSettings.json
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://mywebapp.dev.localhost:5024",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://mywebapp.dev.localhost:7125;
http://mywebapp.dev.localhost:5024",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
C:\MyProjects\MyWebApp>_
Con estas configuraciones, al lanzar el proyecto se utilizarán estos nombres de host exclusivos para el proyecto, evitando los problemas de compartir el mismo localhost entre varias aplicaciones.
C:\MyProjects\MyWebApp> dotnet run
Using launch settings from C:\MyProjects\MyWebApp\Properties\launchSettings.json...
Building...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://mywebapp.dev.localhost:5024
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5024
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\MyProjects\MyWebApp
_
Un último detalle importante: podremos utilizar los nombres de host personalizados cuando accedamos a las aplicaciones desde el navegador web, pero probablemente no desde otras herramientas como curl, Postman, etc., o al menos de directamente.
Esto se debe a que, aunque el TLD .localhost está reservado para este propósito, no todas las aplicaciones cliente o los sistemas operativos resuelven automáticamente estos nombres a la dirección de loopback. Por esta razón, en estos casos tendríamos que añadir entradas manuales en el archivo hosts de nuestro sistema operativo para que los nombres personalizados funcionen correctamente.
Afortunadamente, los navegadores web modernos implementan esta resolución de forma automática, por lo que funcionará directamente 🙂
Publicado en Variable not found.
Una sinfonía en C#
¿Cómo conectar Kakfa-UI con Event Hubs de Azure?
diciembre 02, 2025 12:00
“Introducción”
Si usamos Eventhubs de Azure como broker Kafka, y queremos usar Kafka-UI para monitorizar los topics, tenemos que tener en cuenta algunas cosas para que funcione. Hablando siempre de autenticación utilizando SASL_SSL con mecanismo PLAIN. (Esto no funciona para Managed Identity).
En principio sabemos que podemos definir un connection string SAS para conectarnos a Event Hubs, pero Kafka-UI no soporta directamente este formato, por lo que tenemos que hacer algunos ajustes.
KAfka en generar no soporta este formado, sino que hay que hacer un mapeo de los valores del connection string a las propiedades que Kafka espera, más específicamente en el usuario y password, además de protocolo de comunicación.
Configuración de Client Kafka
Para conectar un cliente Kafka a Event Hubs, tenemos que mapear los valores del connection string a las propiedades de usuario y password. Pero primero hay que configurar:
- Protocol: SASL_SSL
- Mechanism: PLAIN
Y luego en las propiedades de autenticación:
- Username: $ConnectionString
- Password: Endpoint=sb://.servicebus.windows.net/;SharedAccessKeyName=;SharedAccessKey=;EntityPath=
El EntityPath es opcional, y solo si queremos conectarnos a un Event Hub específico. Si no se especifica, se puede acceder a todos los Event Hubs dentro del namespace.
Básicamente el username es el literal $ConnectionString (con el signo $) y el password es el connection string completo.
Conectar Kafka-UI
En el caso de Kafka-UI tenemos un truco adicional, que sería agregar al user name un $ adicional al inicio, quedando así:
- Username: $$ConnectionString
- Password: Endpoint=sb://.servicebus.windows.net/;SharedAccess
Esto en la propiedad KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG (reemplazar el 0 por el índice del cluster que estemos configurando).
En el caso de un docker-compose.yml, quedaría algo así:
version: '2'
services:
kafka-ui:
image: provectuslabs/kafka-ui:latest
ports:
- 9999:8080
environment:
- KAFKA_CLUSTERS_0_NAME=azure
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=xxxx.servicebus.windows.net:9093
- KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL=SASL_SSL
- KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM=PLAIN
- KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG=org.apache.kafka.common.security.plain.PlainLoginModule required username='$$ConnectionString' password='Endpoint=sb://<NAMESPACE>.servicebus.windows.net/;SharedAccessKeyName=<KEY_NAME>;SharedAccessKey=<KEY_VALUE>';
El connection string tiene que tener scope del namespace (lo que sería el broker de Kafka).
Especial cuidado al doble $ en el username y al ; final
Nos leemos.
Variable not found
Enlaces interesantes 630
diciembre 01, 2025 07:01
Esta semana me gustaría destacar en primer lugar el detallado análisis de Andrew Lock sobre el proceso de arranque de una aplicación .NET, muy interesante para saber cómo funcionan las cosas por dentro.
Bipin Joshi da un gran repaso a Kestrel, el motor de todas las aplicaciones ASP.NET Core: cómo configurarlo, tunearlo, ejecutarlo y buenas prácticas de uso.
Milan Jovanović nos recuerda que el happy path no es el único camino en nuestras aplicaciones, y nos muestra técnicas para desacoplar servicios para hacerlos más robustos.
Por último, Ricardo Peres nos habla de la relación entre tipos anulables y miembros requeridos en C#, algo que, cuando empezamos a trabajar con ellos, puede resultar algo confuso.
El resto de enlaces, a continuación.
Por si te lo perdiste...
- Soporte para colecciones en parámetros
paramde .NET 9
José M. Aguilar - Establecer textos por defecto y localizados en validaciones de ASP.NET Core MVC
José M. Aguilar
.NET
- TUnit — Why I Spent 2 Years Building a New .NET Testing Framework
Tom Longhurst - C# 14: User-Defined Compound Assignment Operators
Anthony Giretti - Under Pressure: How Queueing Systems Handle Backpressure with Examples in C#
Scott Galloway - Precision Matters in C#: Correctly Handling Money, Time Zones, and Date Ranges
Sudhir Mangla - Exploring the .NET boot process via host tracing
Andrew Lock - .NET Job Scheduling — The Landscape
Martin Stühmer - Why Do You Need To Write Architecture Tests in .NET
Anton Martyniuk - Fetching GitHub content from C#
Thomas Ardal - Using CSX Scripts for Quick C# Testing (English)
Scott Galloway - The Worst Security Vulnerability in Akka.NET
Aaron Stannard - IDistributedCache (Redis)
Josef Ottosson - Adding Intelligence to Blazor with Telerik Smart Components
Héctor Pérez - How to ensure your expert C# knowledge doesn't make you a TypeScript noob
Lewis Cianci - Ix.NET v7.0: .NET 10 and LINQ for IAsyncEnumerable<T>
Ian Griffiths - Real-Time Recommendation Engines in .NET: Hybrid Retrieval, Deep Learning, and Vector Search
Sudhir Mangla - One shot tool execution in .NET 10
Bart Wullems - .NET Job Scheduling — Hangfire and Persistent Reliability
Martin Stühmer - Nullable and Required Types
Ricardo Peres - Unit Testing HttpClient WITHOUT Mocks
Scott Galloway
ASP.NET Core / ASP.NET / Blazor
- Multitenancy Techniques for the UI in ASP.NET Core
Ricardo Peres - Why you must use Minimal APIs over Controllers for new apps
David Grace - Mastering Kestrel: From Configuration to Cloud
Bipin Joshi - Securing Apps with the Telerik UI for ASP.NET Core OTP Control
Héctor Pérez - Optimizing Rendering and Reconciliation in Large Blazor Apps
Mladen Macanović - Performance Tuning in ASP.NET Core: Best Practices for 2025
Arulraj Aboorvasamy - HTMX with ASP.NET Core Partials: The Server-Side Renaissance
Scott Galloway - Announcing ASP.NET Core OData 10.0.0 Preview 1
Samuel Wanjohi
Azure / Cloud
- Azure MCP Server II - Configuración y primeros pasos
Juan Irigoyen
Conceptos / Patrones / Buenas prácticas
- Minimal APIs, CQRS, DDD… Or Just Use Controllers?
Derek Comartin - WebSockets vs HTTP: Key Differences Explained
The Postman Team - The False Comfort of the "Happy Path": Decoupling Your Services
Milan Jovanović
Data
- Announcing OData .NET (ODL) 9 Preview 3 Release
John Gathogo - Using sortable UUID / GUIDs in Entity Framework
Steven Giesel - You're Probably Doing EF Migrations wrong...
Scott Galloway - MSSQL Extension for VS Code: Introducing Edit Data (Public Preview)
Yo-Lei Chen
Machine learning / IA
- Introducing Claude Opus 4.5 \ Anthropic
Anthopic - RAG in Practice: Building Real-World Applications
Scott Galloway - Building our first MCP Resources enabled MCP Server with C#
Bart Wullems
Web / HTML / CSS / Javascript
- Angular 21: desarrollo web empresarial más rápido, inteligente y accesible
José Manuel Alarcón - Todo lo que el navegador web revela sin que se sepa
Álvaro Ibáñez - How to Create Interactive Fillable PDF Forms Using JavaScript PDF Viewer
Arun Kumar Chandrakesan - On Inheriting and Sharing Property Values
Daniel Schwarz - Shuffling a CSS grid using custom properties
Christian Heilmann - CSS Backgrounds Module Level 4 - Working Draft
Elika J. Etemad & Lea Verou & Sebastian Zartner - How to Simplify Your React Components with Derived State
Olaleye Blessing - Angular 21: My Favorite New Features, Demo, What’s Next
Alyssa Nicoll - You're doing JavaScript testing wrong
Chris Ferdinandi - Securing Apps with the Telerik UI for ASP.NET Core OTP Control
Héctor Pérez - Managing Side Effects: A JavaScript Effect System in 30 Lines or Less
Aycan Gulez - Angular 21 Is Here: How Syncfusion Delivers Compatibility Support
Sabari Anand S. - How to Hallucinate using Web Components—zachleat.com
Zach Leatherman - How Closures Work in JavaScript: A Handbook for Developers
Sumit Saha - New to the web platform in November
Rachel Andrew - WebGPU is now supported in major browsers
François Beaufort
Visual Studio / Complementos / Herramientas
- Visual Studio – Built for the Speed of Modern Development
Paul Chapman - Manage Containers the Easy Way: Copilot + VS Code
Matt Hernandez - Automatically Signing a Windows EXE with Azure Trusted Signing, dotnet sign, and GitHub Actions
Scott Hanselman - How to Create an MSI Installer with Visual Studio 2026
Renato Ivanescu
.NET MAUI
- Visualize Monthly Weather Forecasts with .NET MAUI Scheduler
Jeyasri Murugan - Replicating a Christmas UI in .NET MAUI
Leomaris Reyes
Otros
- Scaling culture in a scale-up
Rob Nicholson
Publicado en Variable not found.
Variable not found
Enlaces interesantes 629
noviembre 24, 2025 07:05
Años atrás, en los inicios de la informática, se programaba de forma bastante diferente: conectando cables y usando paneles de interruptores. Por eso me ha parecido muy curioso el simulador del Minivac 601, un ordenador de los años 60, donde podemos probar de primera mano cómo era su experiencia de uso.
Y continuando con temas vintage, Microsoft ha anunciado la liberación del código fuente de los juegos Zork I, II y III, la mítica saga de aventuras conversacionales de los años 80. Pura historia del software.
También esta semana encontramos una interesante lectura de Sudhir Mangla donde explica cómo usar patrones modernos y características recientes de C# para construir modelos más expresivos, seguros y mantenibles que los que ofrece la aplicación estricta de SOLID.
El resto de enlaces interesantes recopilados esta semana, entre los que podéis encontrar información sobre .NET 10, ASP.NET Core, IA, desarrollo web y mucho más, los tenéis a continuación.
Por si te lo perdiste...
- Creando GUIDs con orden natural en .NET 9
José M. Aguilar - Localizar errores de validación del binding en ASP.NET Core MVC
José M. Aguilar
.NET
- Introducing C# 14
Uwe Keim - Introducing F# 10
Adam Boniecki - Exploring C# File-based Apps in .NET 10
Milan Jovanović - How to Upgrade to .NET 10 LTS - Complete Guide for .NET Global Tools with Multi-Targeting
John Smith - Post-Quantum Cryptography in .NET
Jeremy Barton - Reinventing how .NET Builds and Ships (Again)
Gábor Szabó - Companies complaining .NET moves too fast should just pay for post-EOL support
Andrew Lock - .NET 10 Testing: Microsoft Finally Fixed the Test Runner (Mostly)
Martin Stühmer - Optimize GUID creation performance in .NET applications
Gérald Barré - How to Update .NET on Wsl or Ubuntu
Steve Smith - No more public partial class Program in .NET 10
Steven Giesel - Streamlining Remote C# Scripts with .NET 10 runfile
Daniel Cazzulino - A Practical Approach to DI Variation in .NET: Introducing Child Service Providers
Fernando Escolar - State of Native AOT in .NET 10
Peter Ritchie
ASP.NET Core / ASP.NET / Blazor
- Multitenancy Techniques for ASP.NET Core
Ricardo Peres - Implement forgot your password using swiyu, ASP.NET Core Identity and Aspire
Damien Bowden - How to Add Video Preview to the Blazor File Upload Component
UdhayaKumar Duraisamy - OpenAPI.NET: The Biggest Update Ever
Darrel Miller - What’s New in ASP.NET Core 10 for .NET 10: Key Features and Enhancements
Arulraj Aboorvasamy - Blazor Basics: Building Drag-and-Drop Functionality
Claudio Bernasconi - How Blazor's Unified Rendering Model Shapes Modern .NET Web Apps
David Ramel - Securing WebSocket Connections in ASP.NET Core using Sec WebSocket Protocol Header
Bjoern Meyer
Azure / Cloud
Conceptos / Patrones / Buenas prácticas
- La Capa de Dominio en Clean Architecture: Qué debe contener y por qué
Gerson Azabache Martínez - Primitive Obsession
Fran Iglesias - Empirical software prototyping
Mark Seemann - A Developer’s Guide to OAuth 2.0 Workflows: Web, Mobile, SPA, Machine-to-Machine, and Device Flows
Subodh Shetty - Beyond SOLID in Modern C#: Smart Enums, Discriminated Unions & Railway-Oriented Programming
Sudhir Mangla
Data
- SQL Server 2025 is Now Generally Available
Venkata Raj Pochiraju - How I Have Increased the Production Payment System Performance by 15x With One Line of Code in EF Core
Anton Martyniuk - Building Read Models with EF Core Projections
Ali Hamza Ansari
Machine learning / IA
- GPT-5.1-Codex-Max: nuevo modelo hiperespecializado en programación
José Manuel Alarcón - Gemini 3: Introducing the latest Gemini AI model from Google
Sundar Pichai & Demis Hassabis & Koray Kavukcuoglu - Google brings Gemini 3 AI model to Search and AI Mode
Elizabeth Hamon Reid
Web / HTML / CSS / Javascript
- Angular Signal Forms: un cambio de paradigma
Saúl Moro - Announcing Angular v21
Jens Kuehlers & Mark “Techson” Thompson - How to Fix Memory Leaks in JavaScript PDF Viewers: Best Practices and Debugging Tips
RajaVignesh BalaSankar - The “Most Hated” CSS Feature: asin(), acos(), atan() and atan2()
Juan Diego Rodríguez - Should We Even Have :closed?
Sunkanmi Fafowora - Keyframes Tokens: Standardizing Animation Across Projects
Amit Sheen - Six Things I Bet You Didn't Know You Could Do With Chrome's Devtools, Part 1 & Part 2
Rachel Kaufman - Typescript without Typescript
Chris Ferdinandi - Angular Signal Forms vs. Reactive Forms
Jonathan Gamble - React 19.2: The async shift is finally here
Jack Herrington - Practical Introduction to Async Generators in JavaScript
Peter Mbanugo
Visual Studio / Complementos / Herramientas
- Spend Less Time Upgrading, More Time Coding in Visual Studio 2026
Narayan Subramanian - A step-by-step guide to modernizing .NET applications with GitHub Copilot agent mode
Jason Baginski - Supercharge Your Test Coverage with GitHub Copilot Testing for .NET
McKenna Barlow - tree-me: Because git worktrees shouldn’t be a chore
Phil Haack - Introducing the Visual Studio Code Private Marketplace: Your Team's Secure, Curated Extension Hub
Sean Iyer - Hands-on with MCP Resources in Visual Studio
Bart Wullems - Inspect and Validate JSON Web Tokens with the Duende JWT Decoder
Wesley Cabus
.NET MAUI
Otros
- ¿Qué es Cloudflare y por qué su caída paraliza internet?
CampusMVP - Minivac 601 Simulator
Greg Sadetsky - Preserving code that shaped generations: Zork I, II, and III go Open Source
Stacey haffner & Scott hanselman
Publicado en Variable not found.
Arragonán
Viviendo en el péndulo. Hasta la vista Genially
octubre 13, 2025 12:00
Tras casi 4 años, esta fue mi última semana en Genially. Una decisión que me costó mucho tomar tanto por motivos personales, con un ambiente de compañerismo en la compañía que creo que no es habitual en otros lugares que tienen cierta escala y haber construido lazos con un buen puñado de personas; como por motivos profesionales, con unos cuantos desafíos que se venían a corto y medio plazo en los que sé que hubiera disfrutado y aprendido.
En este tiempo, mi rol en la empresa se fue transformando poco a poco casi sin darnos cuenta, primero influenciando solo a nivel de tecnología y terminando haciéndolo a nivel de producto, negocio y operaciones. Hubo algo que fue una constante: vivir en el péndulo entre individual/team contributor y el management.
Incorporación
Entré casi por casualidad. Conocí a Chema, CTO de Genially, unos años antes en una Pamplona Crafters y mantuvimos el contacto vía redes sociales (cuando tuiter aún molaba). Tiempo después, hablamos por otro tema y me propuso explorar si tenía sentido incorporarme. La compañía venía de crecer mucho y vieron que podía asumir un rol que resultase complementario.
Justo era un momento en el que empezaba a sentir que necesitaba un cambio profesional, pero quería estar seguro de mi siguiente paso. Así que tras haber hecho el proceso de selección, nos tomamos un par de meses y tuvimos varias conversaciones hasta que finalmente me incorporé a la compañía.
Plataforma y organización
Entré con un rol de Platform Lead, por lo que mi responsabilidad iba a ser ayudar a los equipos de producto a que pudieran enfocarse en tener impacto, tratando de mejorar la experiencia de desarrollo y la efectividad de los equipos. Como bonus, también iba a echar una mano en cuestiones más organizativas.
Aunque este era un rol de liderazgo, no había un equipo dedicado, de modo que iba a tener que influir, colaborar con distintos equipos y empujar algunas iniciativas por mi cuenta.
Sobre el trabajo de plataforma
Una vez hecho el onboarding, empezar a tener algunas iniciativas ya lanzadas y conociendo más la compañía, traté de aterrizar una serie de metas:
Las iniciativas y actividades de plataforma deben facilitar la Developer Experience y ayudar a los equipos en distintos aspectos:
- Reducir su carga cognitiva, que se enfoquen en complejidad intrínseca y no en la extrínseca, potenciando la germana (generando aprendizaje, construyendo esquemas o automatizando su uso)
- Habilitar actitudes data-informed en la toma de decisiones
- Aportar la mayor autonomía y empoderamiento posibles
- Tratar de ser lo más eficientes en cuestiones de costes económicos
- Dar fiabilidad, que las herramientas apenas fallen
Metas que traté de tener en cuenta, definiendo e implantando prácticas, procesos y herramientas, automatizando tareas, creando documentación… Y darles seguimiento unas veces de manera cuantitativa y otras de forma cualitativa.
Algunas de las iniciativas más relevantes fueron estas:
- Actuar como puente entre el equipo de infraestructura y los equipos de producto para acelerar la implantación del stack de observabilidad de Grafana (Loki, Mimir, Tempo).
- Formalizar la redacción de postmortems blameless tras incidencias que afecten al servicio junto a CTO y VP de ingeniería, para fomentar el aprendizaje sistémico.
- Apoyar al equipo de Design System con distintas actividades.
- Ayudar en la introducción de Snowplow + Amplitude para la instrumentación de producto colaborando con el equipo de data y los primeros equipos de producto involucrados.
- Introducir el uso de Turborepo en el monorepo para simplificar el proceso de build.
- …
A nivel organizativo
Durante esos primeros meses se estaba planteando una reorganización del área de desarrollo de producto bastante importante. Básicamente era pasar de una estructura de squads que se organizaba de forma recurrente a una basada en líneas de trabajo que tuvieran continuidad en el tiempo.
Esto fue algo en el que me involucraron aún sin tener mucho contexto junto al resto de managers de tech y producto, en parte venía bien tener a alguien con mirada limpia aunque en ocasiones pudiera pecar de ingenuo, para cuestionar supuestos y detectar disonancias.
En aquel entonces me resultó muy útil que alguna de la gente involucrada en la reorganización estuviera hablando en términos de Team Topologies, porque nos ayudaba a tener un lenguaje común. Eso lo terminamos enfrentando con un ejercicio de Context Mapping (en un par de eventos charlé sobre ello), donde representamos buena parte del funcionamiento de la compañía para ver el encaje de equipos respecto a la situación actual.
Este ejercicio sirvió para completar la foto real a la que íbamos, e incluso permitió detectar potenciales problemas de bounded contexts en los que había muchas manos y algunas en las que había muy pocas. Así que cuando con el paso del tiempo surgieron algunos problemas relacionados, no nos pilló tan por sorpresa.
Además, institucionalizamos el dar seguimiento a lo que surgía de las retros de los equipos, ya que se estableció como práctica que se documentase por escrito al menos lo más destacado de ellas y las acciones que surgieran. Esta práctica se mantiene a día de hoy, y resulta muy útil a la capa de management como complemento a los 1:1s para detectar fricciones y puntos de mejora.
Mucho de esto y algunas cosas más, las compartí en la charla Desarrollo de producto en una Scale-Up precisamente en la Pamplona Crafters 2024.

Volviendo a hacer producto (interno)
Tras un año, mi foco cambió a ser algo más todoterreno. Por un lado, ya tenía bastante controladas las dinámicas en el área de desarrollo de producto y a nivel de plataforma había aún puntos de mejora en los que iba trabajando, pero estábamos ya más en una fase de mejora continua y constante, además el equipo de infraestructura seguía introduciendo grandes mejoras. Mientras tanto, en otras áreas de la compañía se identificaban problemas mayores con los que creíamos que podía aportar más.
Ventas
Uno que terminó surgiendo fue en el equipo de ventas, al que había que buscarle solución de forma prioritaria, ya que ninguna de las líneas de trabajo a priori tenía foco en ese tema. Teníamos un proceso interno ineficiente y propenso a errores que terminaban sufriendo clientes High Touch de gran tamaño: muchos emails y llamadas de coordinación, uso de spreadsheets de gestión, tiempos de espera por parte de clientes y account managers, etc.
Para solventar el problema se decidió montar un squad específico moviendo a algunos perfiles técnicos desde algunas líneas de trabajo, y como no queríamos sacar de foco a product managers terminé involucrado en la fase de discovery para abordarlo.
Así que tocó entender los problemas que el equipo de ventas se estaba encontrando y, junto a compañeras de customer experience, entrevistarnos con clientes y gente del área de ventas. A partir de ahí, documentar el impacto que estaba teniendo, definir un primer alcance del MVP usando un user story map y preparar un kick-off para tener tanto al squad, stakeholders y el resto de la compañía alineados.
El squad trabajó en una herramienta que diera mayor autonomía a esos clientes de gran tamaño, permitiendo a account managers mantener el control y darles seguimiento. Y en mi caso, aunque no tiré ni una línea de código y que luego me quedase acompañando al squad de lejos casi como un stakeholder más, me lo pasé como un enano volviendo a participar en hacer producto en fases iniciales.
Creativo
Tiempo más tarde, nos encontrarnos otro problema importante en el área de creativo. Uno de los valores que ofrece Genially a las personas usuarias son las plantillas diseñadas por este equipo. Nos encontramos con un problema de atasco en la publicación de nuevas plantillas y cambios en las existentes que antaño no ocurría, el producto había evolucionado de un modo en el que terminó afectando en la operativa diaria de este equipo.
Esto es porque una vez diseñadas, existía un cuello de botella en el proceso de publicación tanto en el producto como en la web pública. Esta ineficiencia en el Go to Market provocaba tardar más tiempo en recuperar la inversión, era propenso a errores y frustraba a las personas de ese equipo.
Al final era un problema para el que la perspectiva Lean encajaba como anillo al dedo: Identificar el valor, mapear el flujo de trabajo, mantener un flujo continuo, aplicar sistema pull y buscar la mejora continua. Para lo cual se decidió crear de nuevo un squad que se enfocara en esta área.
Una vez analizado y mapeado el journey principal que queríamos resolver, habiendo identificado los distintos hand-offs y limitaciones de las herramientas, planteamos crear un nuevo backoffice diseñado para habilitar mayor autonomía y que simplificase su proceso. De ese modo podríamos sustituir de forma incremental el backoffice legacy, un CMS y un par de spreadsheets de gestión.
Para acelerar el proceso de publicación introdujimos: soporte i18n, gestión de estados, uso de IA generativa, mejoras en las validaciones… Además de crear un servicio que pudiera consumirse desde el producto y la web, cosa que evitaba el uso de herramientas externas y, a nivel técnico, simplificaba la infraestructura y la mantenibilidad futura.
Una vez eliminado ese cuello de botella, que con la combinación del trabajo del squad con el equipo creativo pasó de un retraso de 4 meses a estar al día, nos centramos en mover y mejorar el resto de procesos que se soportaban aún en el legacy en esta nueva herramienta, y en el camino colaborar con uno de los equipos de producto para introducir algunas mejoras conjuntamente.
Operaciones y tech
Aproximadamente el último año en Genially mi rol terminó pivotando de manera oficial a trabajar con foco en las operaciones internas de la compañía. Esto significaba estar en un punto medio entre tecnología, producto, negocio, organización y su potencial impacto en la operativa diaria de cualquier área de la compañía. Esto implicaba mucha amplitud y normalmente menor profundidad, mucha comunicación, intentar promover iniciativas que tuvieran sentido o frenar las que aparentemente necesitasen reflexionarse más, identificar posibles problemas entre áreas de forma prematura, moverme todavía más habitualmente entre diferentes grados de abstracción, etc.
Siempre con una perspectiva de desarrollo de producto, durante ese tiempo tuve oportunidad de trabajar de nuevo y esta vez mucho más involucrado con el área de ventas y desarrollo de negocio; además de empezar a hacerlo también con las de financiero, personas, soporte y comunidad.
Trabajando con más áreas
Con el área de ventas empezamos a trabajar en hacer crecer el MVP que arrancamos antaño, soportando nuevas casuísticas primero y luego acercando e integrando esta herramienta con el CRM que se usa en la compañía. En mi caso había estado involucrado en el día a día de la línea de trabajo que lo evoluciona, con un rol de facilitador y ocasionalmente de desatascador.
Junto a las áreas de financiero y personas hicimos pequeñas iniciativas coordinadas con líneas de trabajo de producto, aunque algunas más ambiciosas se quedaron en el tintero porque el coste de llevarlas a cabo las hacían inviables al menos en el medio plazo.
Con soporte empecé a trabajar muy de cerca, ya que había una tormenta perfecta de cambios en el producto, iteraciones de negocio, atasco en los tiempos de respuesta y degradación de la experiencia de cliente.
Lanzamos varias acciones para solventar la situación: mejorar flujos en el chatbot, rehacer la integración con la herramienta de soporte para enriquecer la información de clientes y mejorar la gestión de colas, introducir automatizaciones, contratar e integrar a un proveedor para pasar a tener un chat basado en agentes de IA que escalase sólo casos complejos, etc. Una vez recuperada una situación de normalidad pudimos entrar en un modo de mejora continua en soporte, y poder dedicar más tiempo a iniciativas relacionadas con comunidad.
Y en medio de todo esto apoyar en ajustes organizacionales, tanto a nivel de desarrollo de producto como en el resto de áreas; y en iniciativas transversales, por ejemplo y para sorpresa de nadie, últimamente con foco en un par relacionadas con IA generativa.

Conclusión
Aunque al inicio costó un poco ver cómo gestionar ese tipo de rol pendular en el que a veces era difícil manejar la cantidad de cambios de foco y de niveles de abstracción, se me dio siempre confianza y autonomía. Finalmente me sentí muy cómodo con ese tipo de responsabilidades.
Me permitió poder influir a nivel organizativo como un manager primero a nivel de área y luego tratar de hacerlo a nivel de compañía, aunque sin las responsabilidades de gestión de personas. Y de vez en cuando poder ejecutar trabajo directamente por ejemplo programando, documentando o investigando de forma autónoma o colaborando con más personas en equipo.
Tras tener la oportunidad de trabajar con tanta gente diferente y variedad de áreas en el contexto de una scale-up, cierro esta etapa en Genially habiendo crecido mucho profesionalmente y con un montón de aprendizajes: técnicos, organizativos, de personas, de negocio… y siendo un fan de la marca y la compañía.
Y ahora ¿qué?
Toca arrancar una aventura nueva que no esperaba, uno de esos trenes que sientes que son una gran oportunidad que tienes que tomar, pero eso lo cuento un poco más adelante en otro post.
Juanjo Navarro
LinkBridge, gestor de enlaces
septiembre 25, 2025 05:46
¡He creado una extensión para navegador!
Este verano, aprovechando las vacaciones, he creado una extensión para navegador que puedes utilizar si te apetece.
Se llama LinkBridge y es un gestor de enlaces para que puedas acceder fácilmente a las webs que utilizas más frecuentemente.
Te dejo un vídeo de su uso y los enlaces de descarga y después te cuento algo más sobre ella.
Algunos otros navegadores pueden usar las extensiones de Chrome o Firefox.
De dónde viene la idea
Hace tiempo que venía usando como gestor de enlaces frecuentes en el navegador el software Flame.
Software de este tipo hay mucho, algunos muy populares, pero a mi me gusta Flame por su estilo minimalista tanto en lo visual como en lo funcional.
El problema de Flame es que es una aplicación que tienes que instalar en tu propio servidor, lo cual obviamente no está al alcance de muchas personas.
Pensé que estas funciones (especialmente las que yo usaba, que no son todas) se podrían cubrir perfectamente desde una extensión del navegador que no requiriese montar nada en nuestro propio servidor.
Funciones de la extensión
Las funciones que he implementado son las principales (y las que yo uso) del software Flame:
- Tus enlaces aparecen cada vez que abres una nueva pestaña del navegador
- Puedes agrupar los enlaces en grupos temáticos con dos niveles: Aplicaciones (de mayor tamaño) y Bookmarks.
- Soporte de temas, tanto claros como oscuros
- Exportación e importación de los enlaces
Acceso al código fuente
El código fuente (por si te interesan estas cosas) está disponible en GitHub: LinkBridge en GitHub
¡Espero que te guste y te sirva si te animas a probarla!
Blog Bitix
Novedades y nuevas características de Java 25
septiembre 19, 2025 07:00
Habitualmente publicaba un artículo por cada versión de Java, pero teniendo en cuenta que para producción es recomendable usar preferentemente las versiones LTS estoy prefiriendo publicar uno en cada versión LTS con el acumulado de características de la versión anterior. En este caso de Java 25 como nueva LTS que sucede a Java 21.
Meta-Info
¿Que es?
Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.
Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
![]()
![]()
Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.
Idea: Juanjo Navarro
Diseño: Albin
Fuentes
- Arragonán
- Bitácora de Javier Gutiérrez Chamorro (Guti)
- Blog Bitix
- Blog de Diego Gómez Deck
- Blog de Federico Varela
- Blog de Julio César Pérez Arques
- Bloggingg
- Buayacorp
- Coding Potions
- DGG
- Es intuitivo...
- Fixed Buffer
- Header Files
- IOKode
- Infectogroovalistic
- Ingenieria de Software / Software Engineering / Project Management / Business Process Management
- Juanjo Navarro
- Koalite
- La luna ilumina por igual a culpables e inocentes
- Made In Flex
- Mal Código
- Mascando Bits
- Metodologías ágiles. De lo racional a la inspiración.
- Navegapolis
- PHP Senior
- Pensamientos ágiles
- Picando Código
- Poesía Binaria
- Preparando SCJP
- Pwned's blog - Desarrollo de Tecnologia
- Rubí Sobre Rieles
- Spejman's Blog
- Thefull
- USANDO C# (C SHARP)
- Una sinfonía en C#
- Variable not found
- Yet Another Programming Weblog
- design-nation.blog/es
- info.xailer.com
- proyectos Ágiles
- psé
- vnsjava

