Ejemplo de POO
Para este primer ejemplo, vamos a reescribir un juego escrito de forma procedimental a programación orientada por objetos. El juego se trata de adivinar el número secreto, veamos la implementación procedimental:
Este código empieza inicializando las variables que vamos a utilizar: num_attempts
y number
. También creamos una variable found
que nos va a indicar si ya se encontró la respuesta.
Después iteramos mientras que found
sea false
. En cada iteración le pedimos al usuario que adivine el número y si es correcto termina el juego (cambiamos found
a true
para que termine la iteración). De lo contrario, incrementamos el número de intentos.
En este momento nuestro juego está muy acoplado a la línea de comandos y sería muy difícil adaptarlo a otros ambientes como una aplicación de escritorio o Web. Lo que vamos a hacer con programación orientada a objetos es separar el juego de la interfaz de usuario.
Primero vamos a crear una clase Game
que se encargue de la lógica del juego. Crea un nuevo archivo llamado game.rb
y escribe lo siguiente:
Nuestra clase Game
va a tener 3 métodos públicos: attempt
, num_attempts
y found
(los últimos dos los crea el attr_reader
). El constructor se va a encargar de inicializar los atributos, incluyendo el número que se va a adivinar.
Ahora, si quisiéramos utilizar nuestro juego en otro ambiente lo podríamos hacer fácilmente, sería cuestión de copiar esta clase. Ahora veamos cómo lo utilizaríamos desde una interfaz de línea de comando (como lo hicimos anteriormente). Reemplaza el contenido de guess_number.rb
con el siguiente código:
Veamos qué hace este código. El primer paso es importar el archivo con la clase Game
. Luego creamos una nueva instancia de Game
e iteramos mientras que el número no haya sido encontrado. En cada iteración utilizamos nuestra case Game
para realizar los intentos y verificar si ya fue encontrado.
Código más fácil de probar
Supongamos que queremos crear pruebas automatizadas para nuestra clase Game
. Lo que queremos probar es que:
Al crear un nuevo juego el número de intentos es 0 y no se ha encontrado el número.
El número de intentos (
num_attempts
) se incremente correctamente.found
se actualiza atrue
cuando sea adivina el número.
Crea un archivo game_test.rb
y escribe lo siguiente:
Tenemos un problema para implementar las dos últimas pruebas. Actualmente el número se genera de forma aleatoria. ¿Cómo podemos saber cuál es el número?
Vamos a hacer uso de la programación orientada a objetos para solucionar este problema. Primero, vamos a crear una clase RandomNumberGenerator
con un único método generate
que retorne un número aleatorio. Crea una nueva clase random_number_generator.rb
y escribe lo siguiente:
Ahora, vamos a cambiar Game
para que reciba un argumento en el constructor, que por defecto va a ser una nueva instancia de RandomNumberGenerator
:
¿Cuál es la ventaja de este cambio? Que para las pruebas podemos crear un nueva clase que nos devuelva un número fijo para poder probar fácilmente. Al constructor de Game
no le importa qué objeto le llegue como argumento siempre y cuando responda al método generate
. A esto se le conoce en el mundo de la programación como duck typing.
Crea un nuevo archivo llamado fixed_number_generator.rb
con el siguiente contenido:
Esta clase recibe un argumento en el constructor, el número que se va a generar. El método generate
siempre retorna el número que le pasamos en el constructor. De esta forma vamos a saber cuál es el número que se debe adivinar.
Ahora podemos utilizar nuestro FixedNumberGenerator
para implementar nuestras pruebas:
Hemos utilizado la programación orientada a objetos para dos cosas:
Separar la lógica del juego de la forma en que se le muestra al usuario.
Hacer nuestro código más fácil de probar.
Esto, en el mundo de la programción, es muy valioso!
Last updated