Carlos Ble

Carlos Ble

I am a professional software developer, I solve problems.

I also teach and mentor developers to build better software.

Developing software since 2001.

Can I help you?

  • Do you need high quality tailor-made software?
  • Need training on TDD, clean code or refactoring?
  • Is it risky? do you need advise?
  • May I pair with you to write better code?

Events

Upcoming public training courses:

  1. [Online - en Español] 25 y 26 de Junio
    Test Doubles con JavaScript - Online
  2. [in English] July 7, 8 & 9
    TDD (open to the public) - Tenerife, Canary Islands
  3. [en Español] 14 y 15 Julio
    TDD (en abierto) - Gran Canaria, Canary Islands
  4. [in English] October 13, 14 & 15
    TDD (open to the public) - London, UK
  5. [en Español] 29, 30 y 31 de Octubre.
    TDD (en abierto) - Madrid, Spain

Conferences:

  1. I'll be at SocratesUK 2014
  2. I'll be at the London Test Gathering Workshops.

Diseño emergente, también para la base de datos

Nota: Me apetecía escribir este post en inglés pero me surgió la siguiente duda.. ¿cuántos de los visitantes hispano parlantes dejarían de leer el post por estar en inglés? Si lees este post y te resuta de ayuda estaría bien que añadieses un comentario diciendo si lo hubieses leído en inglés tambien. Así puedo tener feedback sobre si escribir más en castellano o con mi inglés chungo.

Aunque las bases de datos No-Sql están a la vanguardia, muchos seguimos usando también Sql y seguirá siendo así porque Sql y No-Sql tienen ventajas y desventajas. Sin embargo habiendo trabajado con ambos paradigmas, me he llevado cosas que he aprendido con No-Sql a Sql y la ventaja es muy "agil" :-)

Normalmente las bases de datos Sql se diseñan normalizadas, es decir, se evita la duplicidad de datos mediante tablas que se relacionan entre sí con claves foráneas y demás restricciones. Unas tablas apuntan a otras mediante los identificadores y estas cosas. La ventaja de la normalización y de las restricciones tipo "unique", etc, es que no se repiten datos y por tanto el motor optimiza el acceso a ellos. Además podemos mantener una cierta integridad de los datos evitando que se inserten datos sin sentido.
La desventaja es que los cambios estructurales en la bd cuestan muchísimo. Hay herramientas de migración automática que funcionan bastante bien cuando los cambios son relativamente sencillos pero hay migraciones muy complicadas.

Ahora bien... ¿con qué frecuencia hay que hacer cambios en la bd cuando estamos en pleno desarrollo? Pues en cada iteración. Cuando la funcionalidad es nueva, practicamente cada dia o cada semana.
¿Y cuánto nos cuesta manejar en el código un diseño de base de datos complejo? Es caro, porque la optimización se paga con tiempo de desarrollo. Una base de datos es compleja porque tiene relaciones.
Cargar con relaciones entre tablas desde el inicio es muy caro. Diseñar una bd normalizada desde el inicio me parece tremendamente ambicioso, demasiado optimista. Me supone crear capas de anticorrupción para que la lógica de negocio no se vea afectada por la extrema complejidad del esquema de datos. Me supone mucho tiempo en las migraciones.

Personalmente prefiero crear bases de datos los más planas posibles, que me permitan
desarrollar muy rápido y hacer cambios sin problemas de migraciones. Una vez que el feedback de los usuarios me dice que ya conozco suficiente del negocio, de verdad, me planteo ir normalizando la bd para optimizar.
Para esto suelo crear un campo en la tabla de tipo texto, donde puedo guardar serializada toda la información que voy necesitando, usando un formato clave-valor. Luego en código cuando cargo los datos me encargo de deserializar e interpretar esos datos. Así cuando necesito quitar o poner un campo no tengo que tocar la estructura de la base de datos. Ejemplo:
Quiero gestionar las tareas de un usuario. Un usuario debe tener un nombre unico, algunos datos de contacto y puede tener muchas tareas. Cada tarea tiene una serie de datos, de momento titulo y descripcion.
Esquema de BD inicial:

Estructura Tabla user:

field type
id Pk, autoincremental...
username varchar(50)
fields text
userdata text

Ejemplo de una fila rellena en la tabla:

id username fields userdata
0 fulanito email=fulanito@gmail.com#age=20#phone=30 {tasks: [{'title': 'un titulo', 'description': 'probando'}]}

En el campo "fields" de la tabla voy poniendo lo que creo que son campos de esta tabla, separados por el simbolo #. Si necesito poner o quitar campos o necesito que unos objetos tengan un campo y otros no, no tengo que tocar la BD.
Para gestionar este tipo de campos tengo una clase que sabe leerlos y transformarlos en un diccionario por ejemplo y luegos los "getters" de mi objeto de negocio los puedo implementar consultando a ese parser. No importa que use algun tipo de ORM, normalmente admiten métodos en los objetos de negocio.
En el campo "userData" he metido informacion en formato "json" (por poner un ejemplo de formato) que me permite guardar cualquier cosa.

La desventaja de esto es que cuando haya varios usuarios, habra datos duplicados. En la versión normalizada tendriamos una tabla User con varios campos, una tabla Task. Si la relacion es de muchos a muchos, ademas necesitamos una tabla UserTasks que una ambas. La otra gran desventaja es que si tengo que hacer ciertas consultas, las tendre que hacer en código en vez de usar SQL.

La ventaja es que puedo desplegar nuevas versiones sin preocuparme por las migraciones estructurales de base de datos. Puedo retrasar la normalización de la base de datos hasta que de verdad conozca lo suficiente del negocio. De esta manera consigo el esquema más simple posible que me permite programar con comodidad y que a la vez está optimizado. No tengo que cargar con sobreingeniería.

Si normalizo primero, igual decido crear la tabla UserTasks para que exista una relación de muchos a muchos. Si mas adelante las estadisticas de uso de nuestra aplicación y el conocimiento que tenemos de nuestros usuarios nos dicen que una tarea no la pueden tener dos usuarios, entonces hemos sobrediseñado.
Tenemos una tabla que no sirve. El problema es el coste que tiene mantener un código que hace frente a un requisito innecesario.

A menudo se piensa en el coste que tiene escribir una funcionalidad. Pero muy pocas veces se mide el coste que tiene mantener código que no se usa. Y en mi experiencia es un coste altísimo que te hace ir lento. Es una bola de nieve.

Para ir del esquema desnormalizado al normalizado, la prioridad es ir creando campos en las tablas para aquellos atributos por los que quiero poder hacer consultas. Por ejemplo, si nunca hay necesidad de buscar por el numero de telefono, este campo no tengo por qué extraerlo a un campo de bd. Incluso puede que nunca.

Por otra parte, para argumentar sobre el rendimiento de la BD, como con muchas otras cosas, conviene tener datos empíricos objetivos. Es decir, no voy a trabajar en un problema de rendimiento hasta que no haya hecho pruebas de estres o de carga y tenga unos datos que vemos que no son buenos y que hay que mejorar.
A menudo, optimización y rendimiento son enemigos de mantenibilidad. Por eso en mi opinión y mi experiencia (a base de equivocarme) sólo hay que optimizar cuando hay algo que ya funciona bien.

Esta forma de evolucionar las bases de datos puede suponer para algunos hacer las cosas al revés. Lo que ya les pasa con algunas prácticas como TDD. Sin embargo cuanto más experiencia tengo más pienso justo lo contrario, que he pasado demasiado tiempo haciendo las cosas al revés.

Hay que poner en perspectiva lo que uno aprende en la universidad porque a veces son conceptos de hace muchos años, que ahora tienen que ser revisados de otra manera.

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.
  • http://www.aguasnegras.es Agustín Ventura

    Hola Carlos,

    En primer lugar felicitarte por tu libro de TDD (que me amenizó un tratamiento de rehabilitación para la rodilla).
    En segundo lugar decir que me da lo mismo si en inglés o en español, yo lo poco que escribo lo hago en español para contribuir al (poco) “acervo” tecnológico español. Pero creo que para cualquier persona inquieta en relación con la informática es imprescindible tener al menos un buen nivel de inglés técnico.

    Al lío y por meter algo más de discordia ;)
    Creo que describes tu método de trabajo y me parece estupendo que contribuyas, el problema viene con la búsqueda de la “silver bullet”, no existe y tu método creo que esta muy bien para ti pero no para mí (por ejemplo, en realidad creo que cada uno ha de desarrollar su propio método).
    En particular el defecto que veo en este sistema es que es muy dependiente de tu equipo humano. Necesitas gente que conozca esta forma de trabajar y sepan adaptarse y lo que es más complicado aún, usarla de forma correcta. No quiero entrar en el campo de la anécdota, pero recientemente me entregaron un proyecto que pasaba todas las pruebas unitarias… porque estaban en blanco. Pero no deja de ser una anécdota.
    Poniéndonos más formales, creo que por ahí arriba ya te han reseñado el artículo del “Tío Bob” sobre No DB.
    Yo soy más de esa escuela, primero pienso/diseño/modelo (más o menos formalmente) un sistema (usando orientación a objetos) y después decido si necesito base de datos o no (tengo por ahí en producción una aplicación que solo tira de servicios web y ldap) y en el caso de necesitarla ya decido como pasar de objeto a relacional (para mis proyectos profesionales, que por aquí aún no saben nada de NoSQL ni quieren, jeje).
    Aquí se demuestra la potencia de un ORM, en cualquier momento puedes pasar de un atributo de tipo primitivo (digamos un String) a otro de tipo objeto sin invertir apenas tiempo (unas tres horas incluyendo tests por lo general). Creo que en este aspecto también coincidimos, y es que hemos de ser ágiles a la hora de adaptarnos a los cambios del cliente en SU sistema.

    Como conclusión, por una parte agradecerte tu difusión (¡y el debate generado!) y en algo creo que sí coincidimos plenamente, la base de datos es lo último que se ha de diseñar.
    Peeeero por otra decirte que no estoy para nada de acuerdo. Creo que el proyecto seguirá siendo dependiente de tu equipo y ese no es mi “estilo” ;)
    Como ejercicio, ¿qué pasaría si otro equipo de tu empresa al cual tu no has formado tuviera que hacerse cargo del mantenimiento? O, por poner una situación más normal, solo quedaran dos personas del equipo original y no tuvieras tiempo/recursos de formar a los nuevos.

    Un saludo y gracias de nuevo por tu contribución.

  • http://www.carlosble.com Carlos Ble

    Gracias Agustin.
    Hay algunas cuestiones que vemos diferentes. Para mi el equipo de trabajo debe estar formado por gente bien cualificada que no puede ser facilmente reemplazable, mas que por gente cualificada. Gente profesional. Y la calidad del codigo debe ser excelente por lo tanto, aunque hagamos la persistencia de una manera diferente, cualquier persona con un fuerte conocimiento de orientacion a objetos entenderia lo que se hace y cómo se hace. Sobre todo porque existen tests especificos y bien explicados que documentan todo.

    Como he comentado en otro comentario, las practicas dependen mucho del contexto en que las pongas. En una consultora que se dedica al bodyshopping y que tiene en plantilla un ejercito de becarios sin experiencia, mis practicas serian diferentes.

    Otro punto fuerte que tiene esto de gestionar en mi código los datos, es que me facilita el uso de “Feature Toggles”. Por ejemplo el poder ofrecer una funcionalidad nueva a uno de mis usuarios de confianza pero no al resto, incluso cuando esa funcionalidad requiere un esquema de datos diferente. Lo cierto es que no conozco mucha gente que tenga un nivel de excelencia tecnica que le permita usar Feature Toggles bien. A lo mejor por eso tambien hay poca gente que entiende este tipo de tecnicas que cuento en el post.
    Todo depende de experiencia y contexto/entorno de aplicacion.
    http://martinfowler.com/bliki/FeatureToggle.html

  • Jaime Carmona Loeches

    Muy interesante, gracias por compartir

  • http://www.aguasnegras.es Agustín Ventura

    Carlos, coincido completamente en lo que dices sobre la gente profesional. Como bien dices el contexto lo marca todo.
    Quizás sea salir por los cerros de Úbeda, pero, ¿crees que si tienes un equipo de las características que comentas hay mucha diferencia entre usar estas técnicas o realizar un buen diseño por adelantado?
    Por cierto, gracias por el enlace, no sabía que eso tuviera un nombre.

  • http://carlosble.com Carlos Ble

    Hola Agustín,
    Pensar que por ser profesionales podemos anticiparnos a todo por adelantado es ir demasiado lejos. Una de las cualidades que para mi forman parte de un profesional, es la de conocer sus limitaciones y saber que te vas a equivocar, para de esa manera tomar medidas.
    Y yo…. siempre me equivoco! por eso hago TDD y pair programming :-)

    Ser profesional significa ser metodico y riguroso, no necesariamente tener más capacidad que ninguna otra persona :-)

    Gracias

  • Patxi Esteban

    Buenas,

    casi siempre dependiendo del problema, entorno o casuística se tienen varías opciones sin que ninguna sea la verdad absoluta.

    Una de las características que se parían usar de algunas de las bases de datos relacionales es que mientras lo necesites usar el tipo de campo xml que cuando sea necesario se le puede “interrogar” ya que estan preparados para ello.
    Como bien se comen en alguno de los posts, no toda la base de datos tienen que estar siempre normalizada, ya que a algunas veces es mejor no normalizar alguna parte para tener un mayor rendimiento o evitar complejidad que aporta poco.

    Saludos,
    Patxi