viernes, 29 de marzo de 2013

La importancia de reescribir el código.

Artículo perteneciente a la sección de calidad de código
Artículo íntimamente relacionado con como mejorar la calidad del código

Hola a todos,

Bajo mi punto de vista hay dos factores importantes que pueden destruir nuestros proyectos de software:

- Duplicación de código: La duplicación de código es según los padres de TDD la principal causa de mala calidad de los códigos actuales. Duplicación de código tanto es ctrl+c, ctrl+v como funciones repetidas mal parametrizadas,  parámetros de funciones innecesarios,etc.... Todos estos problemas los arregla TDD y más concretamente la refactorización.

- Pereza/miedo a reescribir trozos de código erróneos o poco mantenibles: A todos nos ha pasado que cuando hemos acabado un proyecto o una parte importante de él, nos hemos dicho : "o vaya!! esto lo podría haber hecho mucho mejor.... de hecho, debería arreglarlo ahora mismo por que sino todo lo que se construya encima va a sufrir bastante.... pero.... me da miedo/pereza, lo dejo como está que así funciona...".  Y así nos va.  Aunque parezca una perdida de tiempo,  reescribir un trozo de código dándole un enfoque más mantenible o más robusto ante los cambios es extremadamente necesario.

Para dar un ejemplo más concreto. En el PakEngine estaba creando una interficie para C y otra idéntica para C++ para que se pudiese utilizar de cualquier manera, ambas devolvían siempre tipos básicos (ints,chars, etc...) de forma que la interficie era sencilla e intuitiva. Ahora, 17 capítulos después de haber tomado esa decisión. me he dado cuenta que cualquier cosa que haga a partir de ahora me hará crecer de forma exponencial el número de funciones de la interficie.

La explicación es muy sencilla. Imaginemos una interficie de pintado de gráficos  como la que tenemos en el motor, a la que le iremos incorporando nuevas funcionalidades:
- Al principio tenemos solamente una función  de pintado: Draw. Pinta un gráfico en determinadas coordenadas.

- Queremos incorporar las rotaciones de gráficos, así que tendremos dos funciones: Draw y DrawRotate

- Queremos incorporar el escalado de imagenes, así que tendremos 4 funciones :
1. Draw
2. DrawRotate
3. DrawEscale
4. DrawRotateEscale

- Queremos incorporar flip en x y flip en y, así que las funciones que tendremos al final serán:
1. Draw
2. DrawRotate
3. DrawEscale
4. DrawFlipX
5. DrawFlipY
6. DrawRotateEscale
7. DrawRotateFlipX
8. DrawRotateFlipY
9. DrawRotateFlipXY
10. DrawEscaleFlipX
11. DrawEscaleFlipY
12. DrawEscaleFlipXY
13. DrawRotateEscaleFlipX
14. DrawRotateEscaleFlipY
15. DrawRotateEscaleFlipXY
16. DrawFlipXY

1 función,2 funciones,4 funciones.... 16 funciones!!! Como entenderéis esta estructura de código no es mantenible por ningún lugar.

Algún lector avispado podría decir que todas estas características podrían unirse en una sola función con muchos parámetros del aspecto de la siguiente:
Draw (int graf, int x, int y, int z, float rotate_angle, float escale_factor, bool flipx,  bool flipy).

El problema de esta "solución" es que se aumentaría muchísimo la complejidad del sistema para pintados sencillos  e implicaría cambios continuos en el código de los juegos a cada mejora del motor (cada característica nueva implicaría cambiar todas las llamadas de pintado).

La única solución lógica (aunque de pereza hacerlo :D) es aceptar que no se escogió una buena solución y proponer una interficie que se base en objetos, y que estos objetos contengan gráficos que acepten modificaciones. De esta manera la complejidad queda reducida y se permite seguir aumentando el número de características sin problemas.

En breve colgaré un capítulo en la sección del pakengine que os dejará mucho más claro este concepto.

Espero que os haya gustado y servido

Nos vemos,
LordPakusBlog

0 comentarios :

Publicar un comentario

Entradas populares