Hace poco me encontraba revisando algunos discos de backups (de los tiempos en los que hacía backups) buscando una pieza de código que pretendía utilizar en un proyecto que estoy realizando. Además de encontrarla, me topé con un CD donde se albergaban algunos juegos que había programado en el colegio, hace unos siete años.
Mientras la nostalgia me invadia, procedí a revisarlos. Estaban en Visual Basic 6, así que no pude abrirlos directamente, pero felizmente el README.TXT que solía colocar en esas épocas hacía un buen trabajo en describirlo:
"AlSoft Entertainment Development Studio Presents Old-School POKER"
Además de despertar una sonrisa (en ese tiempo, todo proyecto que realizaba era firmado con ese nombre de empresa, y mi sueño era ser un desarrollador de juegos), encontré en el Readme información buena (bastante buena para esa época donde mis conocimientos eran muy diferentes a los de ahora).
Decidí entonces usar un editor de textos para revisar el código y ver como programaba yo en ese tiempo.
No puede entender practicamente nada
No estaba tan mal. Usaba código poco optimizado, y muy desordenado, pero lo peor de todo, es que no estaba documentado. Ok, me dije. Es un juego de Póker, no debe ser tan complicado entender por donde iba el tema. Sólo después de un buen momento pude entender donde se llamaba a la lógica, qué manejaba el código y.. *horror*, ver la forma como usaba los módulos.
Este escenario es muy común. Dejamos un código sin mantener, aprendemos más, comprendemos la necesidad y cuando usar -o no- un patrón. Y al volver a revisar un código antiguo nos vemos enfrentados a una mente tan distinta ahora a la nuestra que incluso podríamos pensar que es el trabajo de otro programador más. Y es lo normal y siempre ocurrirá, ¿no?
No. Rotundamente no. Cuando programamos y nos encontramos desarrollando un algoritmo o implementando una función, siempre debemos tratar de que el código pueda ser legible incluso para nuestros Yo futuros.
Existe una recomendación muy inteligente que encontré en el libro "Code Complete" (libro que recomendo a todos los que estén metidos en esta profesión y les interese y sienta pasión por ella). Programa un día un código, y regresa una semana después a tratar de entenderlo. Si no lo puedes hacer, no puedes pretender que alguien más (tu inclusive) lo pueda entender un mes o un año después.
La idea es buena, y no tiene que ser aplicada al pie de la letra. Desde que la leí, me puse como meta tratar de hacerlo lo más posible, y puedo asegurar que funciona. Luego de revisar el código del Póker, entré a mi servidor de archivos y cargué unos archivos de un proyecto de hace un año. La diferencia era notable, ya que, si bien no recordaba bien qué línea de pensamiento me había llevado a implementar ese código, podía entenderlo y recordar lo necesario para saber qué modificar y que respetar.
Ahora bien, ¿vale la pena darle más tiempo a revisiones continuas a códigos que tal vez nunca más vayamos a utilizar? Yo creo que sí. Tal vez nunca más volvamos a realizar un sistema que implemente un tipo de lógica en particular, pero si tenemos presente prácticas de claridad en el código, hará que seamos más eficientes, y podamos entender con mayor facilidad rutinas y funciones que escribimos actualmente. Además que disminuirá la cantidad de errores ya que cuidaremos más que sea legible, descubriendo potenciales fallas o implementaciones erróneas.
Buscamos la claridad en el código, y para lograrlo podemos implementar siguiendo algunas reglas sencillas que trato de tener presente siempre:
- Realizar una programación semántica en el código
- Buscar la consistencia a lo largo del sistema
- Separar valores y reglas de la implementación
Realizar una programación semántica en el código
Es siempre mucho más sencillo entender que realizar una función o rutina de código, si la nombramos como "ShuffleCards()" que "GenerateValues()" . Ambas tendrán el mismo funcionamiento en el programa (reordenar las cartas, en el ejemplo de la aplicación de Póker), pero el primer caso nos hace comprender de una manera muy rápida lo que hace la función sin necesidad de ver el código (incluso, a veces puede ser imposible si se han perdido las bibliotecas respectivas) y refuerza el concepto de Encapsulamiento en el código: sólo necesitamos llamarla y utilizarla.
Una programación semántica es utilizar los nombres y los conceptos del dominio del problema dentro de nuestra aplicación. Nos da una facilidad para comprender la lógica en un nivel mayor sin recurrir a hacer seguimientos línea a línea de código, y nos brinda una interfaz más clara para trabajar.
Igualmente, en la implementación de la rutina, nos permite abstraernos del resto de elementos y concentrarnos en el problema. Digamos que al implementar la rutina, utilizamos este pseudocódigo:
for i from 1 to 52 do
j = i + random(53 - i) - 1
collection.swap(i, j)
Probablemente en el momento de implementarla nos parezca bastante sencilla y eficiente. Pero si la revisamos fuera de contexto, nos complicará muchas cosas que pudo ser evitado reemplazando algunos valores por nombres relacionados con la funcionalidad. Comparémoslo con:
for i from 1 to deckSize do
otherCard = i + random(deckSize + 1 - i) - 1
deck.swap(i, otherCard)
La diferencia es notable. Incluso, podríamos extender más el ejemplo y reemplazar cada variable por una contraparte del dominio del problema, pero ya será la experiencia y manejo del programador encontrar el balance perfecto entre redactar un párrafo sobre el tema e implementar una rutina.
Los que han utilizado Ruby on Rails, pueden haber encontrado muchas funciones e indicadores con nombres como :has_many o :belongs_to, que simplifican el proceso de creación de código, y manteniéndolo legible para lectores futuros.
Buscar la consistencia a lo largo del sistema
Mantener una consistencia en el proceso de nombrar identificadores, variables y rutinas también nos permitirán mantener la claridad en el código. Reduce la cantidad de pensamiento que quien ajeno a éste tenga que emplear para entender y utilizar nuestro código y facilita el uso de Interfaces, ya que sabemos que esperar de éste, sin importar si estamos hablando de una clase padre o una hija, de una función matemática o una de manejo de cadenas.
Muchas veces podemos encontrar un código como éste (pensemos que es una clase que implementa el patrón Facade):
class PokerManager { public CreateCard(); public InsertPlayer(); public StartGame(); }
Todas ellas tienen un comportamiento similar sobre un ámbito que manejan: inicializarlo, crearlo o darle vida. Pero la diferencia en los nombres y su falta de consistencia dificultan el proceso de entendimiento del código. ¿Crear involucrará un paso adicional que Insertar? ¿Empezar estará asumiento un llamada a otra rutina previamente?
Si este fuera la interfaz que le demos a un programador tercero para que implemente una aplicación adicional, el tendrá que recurrir muchas veces a la documentación y a comunicarse con nosotros para preguntar sobre las diferencias en los métodos, y para buscar un lineamiento para llamar a los propios.
Evitar esos problemas nos llevará a buscar que el código que utilicemos sea consistente a lo largo de toda la aplicación y las bibliotecas de código que desarrollemos y utilicemos, y disminuirá el tiempo que se emplea para poder entender qué hace una función u otra. Brindará seguridad a quien use el código (nosotros o terceros) sobre qué esperar sobre éste, como responderá o en que forma nos comunicamos con él y facilitará el entendimiento global de éste.
Separar valores y reglas de la implementación
Separar los valores y reglas específicas de un caso o problema, de la implementación es una idea que se predica bastante en diversas áreas. Principalmente, nos habla sobre como no mezclar información específica de una implementación en especial, o un valor que utilicemos, con la implementación que lo utilice o la llame.
¿Cómo beneficia esta práctica a la claridad del código? Nos permite utilizar nombres descriptivos para información que, aún siendo constante, puede ser referenciada de manera externa a donde residan, con un nombre acorde a ésta (como lo vimos en el punto anterior) y así facilitar la lectura de los campos.
En el ejemplo anterior, utilizamos la constante deckSize para referenciar al número de la baraja (52). De esa manera, aunque sepamos que el valor no cambiará, simplificamos la lectura y nos tomará menos tiempo deducir qué valor representará a que significa un valor directo como "52" en el código. Y si en caso alguna vez decidimos limitar el tamaño de la baraja, podríamos modificar ese valor sin ninguna dificultad..
De manera idéntica, separar las reglas de implementación de la misma hace que nos concentremos en los detalles del desarrollo y no en los detalles específicos que nos brindan las restricciones o reglas.
Tener claridad en el código es uno de los pasos que nos podrán diferenciar en el mercado, nos brindará la capacidad para poder reutilizar y brindar código más limpio a terceros y compañeros de trabajo, y hasta a nosotros mismos cuando revisemos de nuevo el código en el futuro. Igualmente, nos permitirá entender como otros piensan: al tener claro como simplificar el nuestro, podemos comprender cómo pudieron haberlo hecho otros, lo que nos facilitará también la lectura de rutinas de otros que también hayan tenido en cuenta establecer el concepto en su trabajo.
Apuntes similares
- Viaje multiplataforma (4): Las fronteras digitales en términos de qué Siste
- No nos compliquemos (7): Recuerdo que en una ocasión, mientras cursa
- Sobre editores de código o cómo usar uno no afecta mi productividad (6): Hace unos días un amigo me comentó que cómo era
- ¿es la programación un arte perdido? II (0): Freddie exponía en un comentario de mis pos
- La guerra santa en el desarrollo (9): Lo vemos diariamente en diversos sitios web y el p

Buen artículo, sin duda despues de algunos años, incluso de uno, regresa uno y ve lo que ah hecho y uno se da cuenta que no es lo mismo, que muchas veces no lo puede ni entender.
A mi también me ah pasado al revisar cosas de los primeros años del colegio.
Gran articulo lo aplicare ya que solo llevo un año como programador profesional y no tengo mucho codigo que revisar.
Intentare aplicar los consejos que das.
Un saludo y gracias
Bize
muy bueno, y real
felicidades
buen articulo pero necesito el codido completo para poder realizar un juego de poker alguien podria pasarmelo porfavor?