Está en la página 1de 53

Curso de OO dirigido por

la introduccin de ambigedad

Diseo evolutivo

6. Diseo evolutivo
NDICE

1. Introduccin.............................................................................................................192
1.1 El mtodo de trabajo....................................................................................................193
Primero, lo esencial..........................................................................................................................193
Hacer justo, lo necesario..................................................................................................................194
Software cerrado y abierto...............................................................................................................194
Definiciones flexibles.......................................................................................................................195

2. Diseo de un cajero automtico simple...................................................................197


2.1 Introduccin.................................................................................................................197
2.2 Extraccin sobre una cuenta.......................................................................................197
Tarea inicial: hacer una sola extraccin sobre una cuenta...............................................................197
Diagrama de Clases de una extraccin sobre una cuenta.................................................................200
Cdigo Java de una extraccin sobre una cuenta.............................................................................202

2.3 Primera Ampliacin. Hacer varias extracciones sobre una cuenta.........................205


Diagrama de secuencia de muchas extracciones sobre una cuenta.................................................207

2.4 Segunda Ampliacin. Varias extracciones sobre una cuenta de varias posibles......212
2.4 Tercera Ampliacin: Control de Acceso......................................................................216
Escena de acceso..............................................................................................................................216
Cdigo Java ACCESO....................................................................................................................218
Integracin de acceso y extraccin..................................................................................................219
Estudio de alternativas de unin......................................................................................................221
2.4.1 Una iteracin. Otra forma de unin.........................................................................................224
2.4.2 Otra iteracin...........................................................................................................................225
2.4.3 Otra iteracin ms...................................................................................................................226
Interpretacin Arquitectnica del Sistema.......................................................................................230

2.5 Cuarta Ampliacin: Ingreso de Dinero.......................................................................232


Ejercicio...........................................................................................................................................233
Diseo del mecanismo de ingreso....................................................................................................234
Cdigo Java INGRESO....................................................................................................................236
Integracin de ingreso al sistema.....................................................................................................237
Cdigo Java Selector........................................................................................................................240
Diagrama de clases del sistema completo........................................................................................241

2. 6 Recapitulemos.............................................................................................................242

191

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

1. Introduccin
Despus de haber hecho un recorrido por los cimientos del modelo orientado a
objetos, por sus conceptos y por partes de su cdigo, debemos comenzar a ver cmo se
pueden conseguir desarrollo y software evolutivo.
Una forma de desarrollo evolutivo es el llamado desarrollo iterativo e
incremental. Iterativo en el sentido amplio de correccin. Es decir, en el sentido de
reducir el error, de aproximarse ms. Se trata de corregir el rumbo del proyecto al
evaluar los resultados con el cliente, de eliminar las equivocaciones detectadas durante
las pruebas y de mejorar las cualidades internas del software, por ejemplo su
consistencia. Incremental en el sentido de aadir capacidades y funciones al software de
acuerdo con el crecimiento de las necesidades. Lo incremental y lo iterativo van juntos,
aunque no siempre se presentan los dos.
Hay muchas formas de desarrollo iterativo e incremental, con sus tcnicas y
mtodos respectivos. Probablemente, casi todas son buenas o, al menos, tienen muchos
aspectos buenos. Por tanto, lo ms importante es crear una actitud evolutiva hacia el
diseo y su modo de hacerlo, que se enriquezca despus con la diversidad de fuentes
disponibles. Este es el objetivo central del captulo.
Las palabras iterativo e incremental se utilizan en los procesos de
aproximaciones sucesivas. Se han tomado de ah porque tienen una finalidad semejante:
resolver problemas con incertidumbre. Tanto el desarrollo de software iterativo e
incremental como los procesos de aproximaciones sucesivas buscan un valor
desconocido. Pero, en el desarrollo de software ese valor desconocido es, adems,
inestable; se desplaza con el tiempo. Es como disparar a una diana poco visible que se
mueve con una componente de imprevisilidad.
Esa distincin establece una diferencia cualitativa entre el desarrollo evolutivo y
los procesos de aproximaciones sucesivas, sobre todo al acentuarse la componente
futura de la incertidumbre. Por tanto, son diferentes. No obstante, podemos aprovechar
sus similitudes, al menos en primera instancia.

192

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Los sistemas software se pueden considerar como sistemas complejos alejados


del equilibrio que se organizan con una estabilidad transitoria, gracias al trabajo de los
desarrolladores. En cierto sentido hay una analoga con las denominadas estructuras
disipativas, presentes en la naturaleza viva e inanimada. De este parecido se pueden
obtener diversas ideas para el diseo software. Una de las ms interesantes es la ruptura
y restablecimiento de la simetra, como veremos en este captulo.
Un sistema software con capacidad de evolucin deber tener holguras para
adaptarse a la incertidumbre. Si todo est rgidamente definido, difcilmente se podr
amoldar a los cambios. Por tanto, deber tener holguras en sus definiciones, que son uno
de los elementos adversos para la evolucin. Aunque necesite definiciones exactas y
concretas para funcionar, el sistema debe operar con definiciones flexibles. Es decir, con
definiciones parciales, definiciones diferidas e, incluso, con definiciones ausentes, para
conseguir libertad de modificacin. En este captulo veremos cmo se pueden utilizar
las cualidades del modelo de software orientado a objetos para conseguir definiciones
flexibles en el sentido de evolucin y de reutilizacin.
El captulo tiene como hilo conductor la construccin de dos aplicaciones
software sencillas, pero relevantes. En la primera nos concentraremos en ver un mtodo
de diseo evolutivo, suponiendo incertidumbre y en la segunda, al tema de la
reutilizacin, tcnica comn en las ingenieras.

1.1 El mtodo de trabajo


Primero, lo esencial
Como el objetivo primordial de la evolucin del software es la supervivencia del
software, nos debemos ocupar primero de los aspectos de mayor riesgo del proyecto.
Donde el riesgo debe evaluarse por la incertidumbre y las consecuencias de esa
incertidumbre.
La secuencia evolutiva debe ser acordada con el cliente despus de un estudio de
los riesgos del proyecto; estudio que nunca ser exhaustivo. Si no hay elementos
inciertos en la tcnica de desarrollo, se deben desarrollar primero las prioridades ms
altas del cliente, porque de no cumplirlas, el proyecto fracasa. En general, las
prioridades ms altas del proyecto se refieren al comportamiento esencial del sistema, a
193

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

sus operaciones ms frecuentes. Las excepciones y los detalles, dependiendo del riesgo,
se pueden dejar para despus.

Hacer justo, lo necesario


Los procesos evolutivos son costosos porque se enfrentan a la carga adicional de
complejidad que representa la incertidumbre. Por tanto, conviene conducirlos justo con
lo necesario para ahorrar recursos y, tambin, para no dilapidar. Es decir, para perder lo
menos posible cuando obtenemos resultados negativos. De aqu que, generalmente, se
postergue el desarrollo de las excepciones hasta comprobar el rumbo adecuado de la
esencia del sistema.
Sin embargo, no debemos confundir la chapucera, ni la negligencia, con el
delicado balance de hacer justo lo necesario, expuesto en el prrafo anterior. Construir
software escribiendo su cdigo directamente, tiene malas consecuencias sobre la
capacidad evolutiva del software. El cdigo est hecho para la mquina. Es el intrincado
bosque de los detalles ms pequeos del sistema; un bosque impenetrable e
incomprensible. Como si visemos a un ser humano a partir de sus clulas.
El software debe ser diseado con mucho ms cuidado si se quiere software
evolutivo. Conviene hacer el diseo con recursos informticos que faciliten las
modificaciones y de paso, generen la documentacin. Pero, si no se tienen con papel y
lpiz. Los documentos de diseo son esenciales al proceso de diseo y construccin. El
delicado equilibrio de hacer justo lo necesario significa detallar lo imprescindible para
la comprensin del equipo de trabajo en ese ciclo de desarrollo. La informacin
complementaria que aclara y recuerda aspectos para el prximo ciclo debe aadirse
despus de alcanzar resultados satisfactorios. Esta documentacin adicional se perdera
en el caso de resultados negativos. La queja burocrtica sobre el modelo en Cascada no
se debe a la cantidad de documentacin. Hasta ah se pudiera justificar, el problema es
cuando hay que modificarla o peor an, echarla en el cesto.

Software cerrado y abierto


Cada incremento supone una entrega de software, al menos para su contraste con
el cliente, que decide sobre el curso del producto que estamos desarrollando. Por tanto,
cada entrega supone un software, en cierto sentido cerrado, terminado. Pero, tambin,
194

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

abierto a los prximos incrementos. El software debe estar cerrado, funcionando, para
cobrar o para evaluarlo y, a la vez, debe ser relativamente sencillo de modificar para que
se adecue a las nuevas condiciones inciertas del contexto.
Se puede establecer una similitud con los mtodos numricos aproximados que
aportan, al final de cada vuelta, una solucin concreta, cerrada, para su evaluacin, pero
tambin abierta, susceptible de ser mejorada. Cada vuelta del proceso de desarrollo de
software debe ofrecer una solucin concreta para ser evaluada, al menos, y debe facilitar
la siguiente. ste es el sentido de software cerrado y abierto, un equilibrio difcil sobre
el que descansa una buena parte de las cualidades evolutivas del software, y tambin
nuestras cualidades como diseadores.
Sobre las cualidades que otorgan modificabilidad al software se puede decir
mucho, pero como mnimo, un software abierto debe permitir que las modificaciones
requieran muy poca revisin de lo anterior y, adems, que lo perturben muy poco.
La contradiccin cerrado y abierto es antigua en el mundo de la ingeniera.
Cualquier mquina debe tener construidas y ensambladas sus piezas, por lo menos, para
que funcione. Pero tambin se exige, a veces, que sea fcil de modificar. Sucede igual
en el software, slo que la exigencia de modificabilidad est presente casi siempre. Para
abordar esa contradiccin, la ingeniera tradicional invent la modularidad. Es decir, el
aislamiento y la independencia de los componentes. Insistimos, se invent, porque en la
naturaleza no se encuentran mdulos al estilo de la ingeniera.

Definiciones flexibles
Para resolver la contradiccin cerrado y abierto, la ingeniera de software
tambin utiliza la modularidad, pero adems, usa otras tcnicas propias del software, ya
referidas. Aunque los textos las tratan de forma independiente, nosotros proponemos
verlas de conjunto, como variantes de definiciones flexibles: definiciones parciales,
definiciones diferidas y definiciones ausentes.
Las definiciones parciales se consiguen ocultando una parte de la definicin, ya
sea dentro de los mdulos o delegando tareas a otros mdulos. Ambas tcnicas son
fundamentales y se aplican desde los tiempos del modelo estructurado para facilitar los
cambios en el software. Nosotros las utilizaremos sistemticamente en el diseo.
195

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Algunos lenguajes de programacin permiten acceder directamente a los datos


contenidos en los objetos. Es decir, sin recurrir a las funciones de los objetos encargadas
de manipular los datos. Es ms fcil, pero las consecuencias se pagan despus, cuando
se requieren cambios. La tcnica de ocultar informacin tiene una motivacin prctica,
no acadmica, aunque se ensee en las universidades.
Las definiciones diferidas se obtienen mediante los mecanismos de herencia y
polimorfismo. Procuraremos no utilizar la herencia con el objetivo de clasificar, ni con
el objetivo de ampliar el software, modificando la definicin de los progenitores.
Preferiremos la delegacin para conectar objetos semejantes, como se explic en el
captulo dedicado al mundo de los objetos.
Y por ltimo, trataremos de prescindir de las definiciones innecesarias. Por
ejemplo, la definicin del sistema. Esto quiere decir que evitaremos el uso de las
relaciones de agregacin, salvo que estn justificadas para conseguir el mismo tiempo
de vida de los objetos o para lograr efectos de transitividad.

196

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

2. Diseo de un cajero automtico simple

2.1 Introduccin
Se trata de construir el software para un cajero automtico muy simple. Un
problema familiar, por razones didcticas. Pero donde vamos a suponer que las
necesidades del cliente aparecern poco a poco y que no las conocemos de antemano. El
objetivo es apreciar el mtodo de desarrollo y diseo para abordar la incertidumbre. Si
el problema fuese realmente desconocido se desviara la atencin hacia la comprensin,
que no es nuestro asunto. Debemos concentrarnos en el mtodo de trabajo.
Desarrollaremos el software por aproximaciones sucesivas, comenzando por lo
ms importante. Las decisiones complementarias se van dejando para despus, cuando
se demuestre que hemos alcanzado lo esencial. As reducimos nuestro riesgo de hacer
algo ms all y tenerlo que desechar. Este ser nuestro modo cclico de actuar frente a la
incertidumbre: reducir progresivamente el riesgo. Hacer apuestas pequeas, contrario a
la Cascada, que lo apuesta todo a un disparo, supuestamente certero. Para que el
desarrollo sea evolutivo, el diseo tiene que serlo tambin.

2.2 Extraccin sobre una cuenta


Empezaremos por la extraccin de dinero que es la operacin de mayor inters.
Siguiendo la lnea de desarrollo evolutivo, es decir, crecimiento y mejora progresiva del
software, partiremos de una situacin simple.

Tarea inicial: hacer una sola extraccin sobre una cuenta.


Como el diseo es un acto creativo se nos pueden ocurrir muchas soluciones
vlidas; unas sern mejores que otras, de acuerdo a las condiciones especficas del
problema y su entorno. Ahora, como no tenemos experiencia, comenzaremos con la
primera que se nos ocurre cuando respondemos a la pregunta Qu mecanismo software
se necesita para realizar esta operacin?

197

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

El mecanismo debe averiguar la cantidad de dinero que desea extraer, solicitar la


autorizacin de ese retiro sobre la cuenta y averiguar si el dispositivo fsico puede
entregar el dinero solicitado. En el caso que no se pueda entregar el dinero, el
mecanismo software debe explicar la causa. La Figura 1 muestra una implementacin
en objetos del mecanismo descrito. Los mensajes forman parte del cdigo del mtodo
trabaja del objeto oExtraccin.

oExtraccin

oInterfaz
Extraccin

oCuenta

oMonedero

trabaja
dameImporte
autoriza(importe)
entrega(importe)
resta(importe)

Figura 1. Diagrama de Secuencia de una extraccin sobre una cuenta


En esta implementacin hemos diseado el objeto oExtraccin para que su
mtodo trabaja se ocupe de ejecutar el mecanismo de extraccin. Lo primero que hace
este mtodo es, crear al objeto oInterfazExtraccin y pedirle el importe de la extraccin.
El objeto oInterfazExtraccin, de alguna forma no definida an, suministra esa
informacin. Su papel es ocultar al objeto oExtraccin la forma de obtener el valor del
importe. As no se compromete el algoritmo de extraccin con obtener el valor del
importe, que es algo accesorio a la extraccin. En el primer prototipo, se puede inventar
ese valor y asignarlo directamente en el cdigo de oInterfazExtraccin.
Cuando el objeto oExtraccin recibe el valor del importe, le pide la autorizacin
de entrega del importe al objeto oCuenta. Suponiendo que lo autoriza, oExtraccin le
dice al objeto oMonedero que entregue el importe y a oCuenta que reste el importe del
saldo.

198

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Siguiendo nuestro estilo de primero lo esencial, nos ocuparemos despus de lo


que sucede si, por alguna causa, no se puede entregar el importe.
Los objetos que se han diseado para que participen en la escena

EXTRACCIN

son:

oExtraccin : responsable de la tarea de extraccin de dinero

oInterfazExtraccin: delegado por el objeto oExtraccin para obtener el valor del


importe. Aunque el objeto oExtraccin puede conseguir este valor directamente
con el usuario, se debe dejar esa tarea a otro objeto porque conseguir el importe
no forma parte de la esencia de su trabajo. La separacin de tareas reduce el
impacto del cambio. En definitiva, el papel de oInterfazExtraccin es
independizar la forma de solicitar el valor del importe, del uso del importe, que
es lo que es importante para oExtraccin. El objeto oInterfazExtraccin oculta a
oExtraccin cmo averigua la cantidad y as cuando sea necesario modificar ese
cmo no hay que leer ni modificar oExtraccin.

oCuenta: encargado de operar con la cuenta donde se extrae el importe. Una vez
ms, su papel es ocultar la forma de trabajar con la cuenta. Conoce el
mecanismo particular para autorizar una extraccin, incluso cmo hacerlo para
cada cliente. Por tanto, es el objeto que debe autorizar la entrega de dinero. La
variante de disear el objeto oCuenta slo para ocultar la informacin de la
cuenta, por ejemplo el saldo, requerira demasiada especializacin en
oExtraccin, que debe ser una operacin general.

oMonedero: es el intermediario o interfaz del sistema software con el dispositivo


externo que controla el dinero del cajero. Su razn de ser es independizar el
resto del sistema software de ese dispositivo, ocultando la forma de operar con
l. La presencia de oMonedero permite que el sistema se defienda del impacto de
un cambio en el dispositivo ya que es el nico que se debe modificar, si hay un
cambio de efecto moderado.
Resumiendo, oExtraccin es la pieza de software que hemos diseado para que

se ocupe de la extraccin de dinero. Este objeto delega en oInterfazExtraccin la


obtencin del importe, mientras que oCuenta y oMonedero se ocupan de operar con el
199

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

dinero en la cuenta y en el monedero del cajero respectivamente. El diseo consiste en


concebir piezas software para que realicen tareas y enlazarlas entre s. Observe la
importancia que le hemos dado a la delegacin de tareas con el objetivo de ocultar
detalles del funcionamiento al mtodo que se ocupa de realizar la extraccin para poder
cambiar los detalles sin afectar a este mtodo. Todos los objetos se comunican en forma
individual, uno con otro y de manera secuencial.

Diagrama de Clases de una extraccin sobre una cuenta


En el diagrama de clases del mecanismo de extraccin sobre una cuenta se
ilustran las clases de cada uno de los objetos que participan en la construccin del
mecanismo y las relaciones que existen entre ellas. Figura 2. Desde el punto de vista
sintctico, debe existir una lnea entre clases si existe al menos un mensaje entre los
objetos de esas clases.

Interfaz
Extraccin

Extraccin

Cuenta

Monedero

Figura 2 Diagrama de Clases de una extraccin sobre una cuenta

La clase Extraccin usa a la clase InterfazExtraccin: el mensaje dameImporte que


enva el objeto oExtraccin al objeto oInterfazExtraccin establece una relacin de
uso del primer al segundo objeto. En el diagrama de Clases se refleja esta relacin,
como una lnea que une ambas clases. Algunos autores emplean puntas de flecha
para indicar el sentido de uso.

La clase Extraccin usa a la clase Cuenta: esta relacin representa los mensajes que
el objeto oExtraccin enva al objeto oCuenta: autoriza(importe) y resta(importe).

200

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

La clase Extraccin usa la clase Monedero: oExtraccin enva un mensaje al objeto


oMonedero: entrega(importe).

El diagrama de clases de la Figura 3, tambin representa la estructura de clases


del mecanismo de extraccin sobre una cuenta pero con una notacin resumida que une
la clase y su interfaz correspondiente. Esta notacin, aunque la mayora de las
herramientas CASE no la permiten, es la que vamos a usar en este documento porque
facilita la comprensin de los diagramas, al dejar clara la esencia del mecanismo
software.

Interfaz
Extraccin

Cuenta

Monedero

Figura 3 Diagrama de Clases reorganizado de una extraccin sobre una cuenta


Hecho el diseo lo codificamos, Figura 4, lo probamos y le mostramos al cliente
este primer prototipo para evaluarlo y, si es necesario, corregir el rumbo del proyecto.
Slo arriesgamos el trabajo que hemos hecho sobre la esencia del problema. En caso de
fallo, no se pierde el trabajo hecho sobre los detalles o las excepciones. Es una manera
de ser prudente ante la incertidumbre.

201

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Cdigo Java de una extraccin sobre una cuenta


//Clase Extraccin Versin 01
//Extraccin sobre una nica cuenta
public class Extraccion {
Cuenta oCuenta;
public Extraccion(){
}
public void trabaja(){
InterfazExtraccion oInterfazExtraccion;
Monedero oMonedero;
float importe;
oInterfazExtraccion= new InterfazExtraccion();
importe=oInterfazExtraccion.dameImporte();
oCuenta=new Cuenta(12345,1000000);
oMonedero=Monedero.dameSolitario();
oCuenta.autoriza(importe))
oMonedero.entrega(importe);
oCuenta.resta(importe);
}

<- 1
<- 2
<- 3

1-> oInterfazExtraccion= new InterfazExtraccion();


Se crea el objeto oInterfazExtraccin.
2-> oCuenta=new Cuenta(12345,1000000);
Se crea la nica cuenta con la que se est trabajando en este
prototipo.
La cuenta creada tiene nmero de cuenta 12345 y saldo 1000000, por
simplicidad. Despus se podr enriquecer su contenido.
3-> oMonedero=Monedero.dameSolitario();
Se obtiene la nica instancia del objeto Monedero.
Para garantizar que la clase Monedero solo tenga una instancia y que
proporcione un nico punto de acceso global a ese instancia, se ha
decidido usar el patrn Solitario. El mtodo dameSolitario es el
nico punto de acceso a la instancia nica del Monedero.

Figura 4. Cdigo Java de una extraccin sobre una cuenta


Observe que el prototipo slo considera casos positivos. Es decir, hay dinero en
la cuenta y en el monedero, porque es la condicin ms frecuente. Los objetos oCuenta
y oMonedero se pueden implementar de cualquier manera en el primer prototipo, que
sirve para evaluar la esencia del mecanismo. Despus, podemos ajustar esas
implementaciones.

202

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Una vez ms, si invertimos tiempo, considerando los detalles, y la validacin de


la parte esencial resulta negativa, podemos perder el tiempo invertido en esos detalles.
Por esta causa, abordamos el diseo de los detalles y las alternativas despus de
validado el prototipo y dejamos la validacin de las alternativas para otro momento.
A continuacin se muestra el cdigo Java para las clases Monedero y Cuenta.
Figuras 5.1 y 5.2 respectivamente.

//Clase Monedero Versin 01

//Monedero Simple
import java.io.*;

public class Monedero {


private static Monedero solitario;
private float saldo;

<-1
<-2
<-3

public static Monedero dameSolitario(){


if (solitario==null)
solitario=new Monedero(5000000);
return(solitario);
}

<-4

private Monedero(float saldoInicial){


saldo=saldoInicial;
}

<-5

public void entrega(float importe){


saldo-=importe;
}
}

1-> private static Monedero solitario;


Se define una variable privada de clase static llamada solitario.
Esta variable contiene a la nica instancia de la clase Monedero.
2-> private float saldo;
En esta implementacin, por razones de simplicidad, estamos
considerando que el nico atributo que interesa conocer del Monedero
es su saldo.
3-> public static Monedero dameSolitario(){
Este mtodo es el punto de acceso a la instancia nica del Monedero.
Lo que ocurre en este mtodo es que, si la instancia nica no ha sido
creada - if (solitario==null) -, la crea llamando al constructor del
Monedero - solitario=new Monedero(5000000) - ; que es un mtodo
privado.Hemos supuesto un saldo inicial de 5,000,000, por razones de
simplicidad. Si la instancia nica ya ha sido creada, el constructor
da su referencia.
4-> private Monedero(float saldoInicial){
Este es el mtodo creador de la clase objeto. Observe que el mtodo
es privado private -. Es decir, slo es visible para la clase

203

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Monedero. Al hacer privado el mtodo creador garantizamos que nadie


pueda crear nuevas instancias de Monedero.
5-> public void entrega(float importe){
Se ha implementado de manera muy simple, considerando que lo nico
que le interesa al Monedero es su saldo.

Figura 5.1: Cdigo Java Monedero

//Clase Cuenta versin 01


//Cuenta sin persistencia

<-1

public class Cuenta{


private String numero;
private float saldo;
public Cuenta(String cuentaNumero,float
cuentaValorInicial){
numero=cuentaNumero;
saldo=cuentaValorInicial;
}
public boolean autoriza(float importe){
return(saldo>=importe);
}

<- 2

<- 3

public void resta(float importe){


saldo-=importe;
}

1-> private String numero;


private float saldo;
En esta primera versin se considera que los nicos datos que
interesan de una cuenta son su nmero y su saldo.
2-> public boolean autoriza(float importe)
Se supone que se autoriza la entrega del importe siempre que este sea
mayor que el saldo de la cuenta. Se ha omitido, intencionalmente,
programar el resto del comportamiento del mtodo.
3-> public void resta(float importe)
Se est actualizando el saldo de la cuenta considerando el importe
entregado.

Figura 5.2. Cdigo Java de la clase Cuenta

204

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

2.3 Primera Ampliacin. Hacer varias extracciones sobre una cuenta

En el prototipo anterior nos concentramos en conseguir el mecanismo para una


sola extraccin. Ahora debemos ampliarlo a varias extracciones guardando la
informacin de cada extraccin. Por tanto, crearemos un objeto oExtraccin por cada
extraccin y almacenaremos dentro de l, la informacin relevante, por ejemplo, el
importe y la fecha. Esta informacin aparecer como atributos del objeto oExtraccin.
Figura 6.

Extraccin
Importe
Fecha
Cuenta
Trabaja
DameImporte
DameFecha
dameCuenta
Figura 6. Representacin de la clase Extraccin
Se aade una nueva responsabilidad al objeto oExtraccin: custodiar los datos
de una extraccin.
Este diseo muestra una diferencia notable con un diseo equivalente en
software estructurado. Mientras que en el software estructurado tendramos una sola
funcin para hacer todas las extracciones y guardar la informacin en un almacn,
separado de la funcin, en el software orientado a objetos hay un objeto por cada
extraccin que realiza la tarea y guarda, en su interior, la informacin.
La causa de esa importante diferencia radica en sus interpretaciones respectivas
del software. El modelo estructurado interpreta el software como funciones que actan
sobre datos, mientras que el modelo orientado a objetos interpreta el software como
mdulos integrales de datos y funciones, que interactan entre ellos para realizar tareas.

205

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Por tanto, si queremos conservar informacin debemos hacerlo en objetos, lo que en el


fondo no es tan diferente, porque los objetos son las variables del modelo orientado a
objetos. La novedad es que esas variables son activas, realizan tareas. En nuestro diseo
cada objeto :Extraccin se ocupa de hacer una extraccin y de almacenar la informacin
relevante. Hemos sustituido el objeto concreto oExtraccin por el objeto annimo
:Extraccin, porque ya no tenemos uno solo, sino muchos.Despus tendremos que
encargarnos de no perder esos objetos cuando se apague la mquina.
Los diversos objetos :Extraccin se irn creando segn se hagan las extracciones
y formarn una coleccin que necesitaremos manejar. Agregamos, entonces, un objeto
para gestionar la coleccin formada por los objetos :Extraccin. Se llamar
oGestorExtracciones.
En general, el manejo de colecciones de objetos se hace a travs de objetos
especializados que se denominan Gestores. Sus funciones bsicas son tres: entregar,
aadir y quitar un objeto de su coleccin cuando se le solicita. Los gestores de
colecciones no deben modificar los contenidos de los miembros de su coleccin. Si nos
restringimos a estas funciones bsicas todos los gestores sern muy similares entre s,
independiente de la coleccin que manejen. Es una decisin de diseo para no elevar,
gratuitamente, la complejidad del software teniendo gestores distintos.
Vistos en el sentido de ocultamiento, el papel fundamental de los gestores es
ocultar los detalles de acceso a la coleccin. Los que disean la parte esencial del
sistema software no tienen que preocuparse por la coleccin, ni de dnde est, ni cmo
est organizada. Esto es una tarea de los que disean los gestores de colecciones. Si se
trabaja con bases de datos externas, los gestores actan como interfaces con esas bases
de datos.
Con los gestores hemos resuelto el manejo de las colecciones de objetos, pero
nos queda el asunto pendiente de los objetos :Extraccin, an despus de apagada la
mquina. Los debemos hacer persistentes. Es decir, objetos que tienen la propiedad de
estar presentes, siempre que se les necesite. Pero, una vez ms, diremos que no nos
interesan, por ahora, los detalles de cmo se consigue la persistencia. Alguien se
ocupar de conseguirlo, en su momento.

206

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Diagrama de secuencia de muchas extracciones sobre una cuenta


Cuando cada objeto :Extraccin termine de ejecutar la extraccin, debe solicitar
al objeto oGestorExtracciones que lo aada a su coleccin. Si la extraccin no ha tenido
xito, por alguna razn, no se incluye el objeto creado y la coleccin se mantiene como
antes. Este diagrama de secuencia slo considera que la extraccin ha tenido xito.
Figura 7.

:Extraccin

oInterfaz
Extraccin

oGestor
extracciones

oCuenta

oMonedero

trabaja
dameImporte
autoriza(importe)
entrega(importe)
resta(importe)
agrega(me)

Figura 7. : Diagrama de secuencia de varias extracciones sobre una cuenta


La nueva solicitud de nuestro cliente ha obligado a aumentar la capacidad del
sistema, respecto a la cantidad de informacin que maneja. Ha sido un cambio
cuantitativo en los requisitos, que resolvimos con un cambio cuantitativo en la solucin,
aadiendo un objeto y un mensaje, sin necesidad de alterar el cdigo anterior. El objeto
oGestorExtracciones y el mensaje agrega(me) estn indicados en negrilla en la Figura
7.1. La redaccin del mensaje agrega(me) aprovecha un rejuego con el espaol para
expresar mejor qu solicita. El parmetro (me) contiene la referencia del objeto
:Extraccin. Observe que el mtodo de trabajo ha sido disear el mecanismo para un
nico objeto y despus tener en cuenta la coleccin.

207

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Sin embargo, la sencillez de la modificacin para asimilar cambios cuantitativos


no debe inducirnos a pensar que siempre puede ser as. La modificacin ha sido simple
porque hemos supuesto un cambio cuantitativo modesto. Si el cambio cuantitativo es
muy pronunciado, puede requerir un cambio cuantitativo en el sistema, de manera
anloga al cambio de velocidad de 10 km/h a 100 km/h.
En las siguientes pginas se muestran el nuevo diagrama de clases del software y
el nuevo cdigo, ambos, ajustados a realizar muchas extracciones sobre una cuenta.
La Figura 8.1 destaca la clase GestorExtraccin que se ha aadido y la Figura
8.2, reorganiza el diagrama para no perder la esencia de la estructura del software entre
tantos elementos accesorios. Por ejemplo la interfaz y el gestor. Pero se debe recordar
que esta forma peculiar de representar el diagrama de clases es una convencin slo
nuestra, inspirada en Coad.
La figura 9 muestra el cdigo Java del programa. Los elementos aadidos se
realzan en negrilla.

208

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Gestor
Extraccin

Interfaz
Cuenta

Extraccin

Monedero

Figura 8.1: Diagrama de clases de varias extracciones sobre una cuenta

Gestor
Interfaz
Cuenta

Extraccin

Monedero

Figura 8.2: Diagrama de clases reorganizado de varias extracciones sobre una


cuenta

209

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

//Clase Extraccion Versin 02


//Varias extracciones sobre una cuenta
//Con registro histrico de las extracciones
import java.io.*;
import java.util.*;
public class Extraccion implements Serializable{

<- 1

private Cuenta oCuenta;


private Date fecha;
private float importe;
public Extraccion(){
fecha=new Date();
}

<- 2

public float dameImporte() {


return (importe);
}
public Date dameFecha() {
return (fecha);
}
public Cuenta dameCuenta() {
return (oCuenta);
}
public void trabaja(){
InterfazExtraccion oInterfazExtraccion;
Monedero oMonedero;
GestorExtracciones oGestorExtracciones;
oInterfazExtraccion= new InterfazExtraccion();
importe=oInterfazExtraccion.dameImporte();
oCuenta=new Cuenta(12345,1000000);
oMonedero=Monedero.dameSolitario();
oCuenta.autoriza(importe));
oMonedero.entrega(importe);
oCuenta.resta(importe);

<- 3

oGestorExtracciones=GestorExtracciones.dameSolitario()
;
oGestorExtracciones.agrega(this);
}
}
}
1-> public class Extraccion implements Serializable{
Al decir que la clase Extraccion implementa la interfaz Serializable,
se est se consigue la capacidad para transformar el estado completo
de un objeto en una secuencia de bytes, y poder crearlo nuevamente
leyendo la secuencia de bytes correspondientes. Esta cualidad nos
permite, entre otras cosas, que un objeto pueda ser guardado y ledo
de un archivo de objetos.
Es importante observar que esta interfaz no define mtodos,
simplemente indica que la serializacin es permitida.

210

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

2-> fecha=new Date();


Al crear una instancia de la clase Extraccin se asigna la fecha
actual del sistema a su atributo fecha.
3-> oGestorExtracciones=GestorExtracciones.dameSolitario();
La clase GestorExtracciones tambin tiene una nica instancia.
Nuevamente se utiliza el patrn Solitario y en esta lnea se
solicita la instancia nica de la clase GestorExtracciones.

Figura 9: Cdigo Java de varias extracciones sobre una cuenta

211

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

2.4 Segunda Ampliacin. Varias extracciones sobre una cuenta de


varias posibles
Han aumentado los clientes, necesitamos poder realizar varias extracciones sobre una
cuenta de varias posibles.
Antes los objetos :Extraccin conocan la direccin del objeto oCuenta sobre el
que delegaban la autorizacin porque haba un solo objeto oCuenta. Sin embargo, ahora
hay muchos, de manera que cada objeto :Extraccin debe conocer la cuenta en
particular sobre la que debe actuar. El cliente dice que el identificador de la cuenta se
obtiene de una tarjeta. Se disea un objeto oTarjeta para suministrar el identificador de
la cuenta, ocultando la manera de obtenerlo. Con este identificador se debe localizar el
objeto :Cuenta especfico que trabaja con la cuenta referida. Hemos sustituido el objeto
oCuenta conocido por el objeto annimo :Cuenta. Figura 10.

:Extraccin

oInterfaz
Extraccin

oGestor
Extracciones

oTarjeta

:Cuenta

oGestor
Cuentas

oMonedero

trabaja
dameImporte
dameIdCuenta
Dame(idCuenta)
autoriza(importe)
entrega(importe)

resta(importe)
agrega(me)

Figura 10: Diagrama de secuencia de una extraccin sobre una cuenta, de


varias posibles.
Puesto que hay una coleccin de objetos :Cuenta, debe existir un objeto gestor
de esta coleccin que proporcione el objeto cuenta a partir del identificador de la cuenta.
212

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Ahora tenemos a un gestor de colecciones, en otra de sus funciones bsicas: dar un


elemento de su coleccin. Es decir, un objeto. Para hacer esta nueva ampliacin hemos
supuesto que la coleccin est formada de antemano, justo lo contrario de la situacin
anterior, donde formamos la coleccin al aadir cada objeto :Extraccin.
Resumiendo. De nuevo, el incremento de la complejidad del problema ha
obligado a elevar la complejidad de la solucin. Hemos logrado resolver el cambio
cuantitativo en los requisitos mediante cambios cuantitativos en la solucin, aadiendo
elementos software al diseo. En concreto, dos nuevos objetos:

oTarjeta: suministra el identificador de la cuenta de inters.

oGestorCuentas: suministra al objeto :Cuenta encargado de operar con la


cuenta, cuyo identificador ha dado el objeto oTarjeta. En el prototipo
anterior, el objeto :Extraccin acceda al objeto oCuenta mediante el recurso
del Solitario, porque exista un solo objeto oCuenta. Ahora, hay varios
objetos :Cuenta. Por tanto, debe conocer a cul se debe dirigir y despus
solicitarlo al objeto oGestorCuentas.

En esta etapa es suficiente considerar que tenemos un solo objeto :Cuenta en la


coleccin de cuentas porque estamos diseando el mecanismo de extraccin. El
funcionamiento del objeto oGestorCuentas debe ser simple para no distraer nuestra
atencin. Despus, podremos ocuparnos de enriquecerlo, sin modificar el mecanismo de
extraccin que hemos diseado.
De manera semejante a la extensin anterior, el aumento de la capacidad
cuantitativa del sistema se ha conseguido aadiendo objetos y mensajes, sin necesidad
de alterar lo que ya estaba escrito. Los objetos aadidos son: oTarjeta y oGestorCuentas
mientras que los mensajes aadidos son: dameIdCuenta y dame(idCuenta) indicados en
negrilla en la Figura 10.
La tcnica de diseo se repite: trabajar con un objeto como si fuese nico y
despus agregar los medios de acceso a ese objeto, en este caso los objetos oTarjeta y
oGestorCuentas. La esencia del mecanismo no se altera, cuando en vez ser un nico
objeto, son muchos. Esto permite obtener un prototipo simple, que se concentre en la

213

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

esencia, y despus ampliarlo de forma natural. Insistimos, siempre que no se rebasen los
lmites que provoquen cambios cualitativos.

Tarjeta

Gestor
Interfaz

Gestor

Extraccin

Cuenta

Monedero

Figura 11: Diagrama de clases del software de la segunda ampliacin


El camino de considerar primero una situacin simple y despus hacerla ms
compleja nos ha permitido avanzar poco a poco, haciendo apuestas pequeas de cada
vez, sin desviar la atencin de los objetivos prioritarios. Pero, adems, ese camino
tambin nos ha conducido a un diseo de software que nos ha defendido de los cambios
que se han producido y, lo ms importante, que nos defender contra muchos de los
cambios que se pueden producir en el futuro.
La condicin de conocer, desde el principio, la presencia de varias
extracciones y varias cuentas debe conducirnos a un diseo de la misma naturaleza
defensiva que el conseguido, suponiendo incertidumbre, porque es una manera de
protegernos de la incertidumbre del maana.

214

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

//Clase Extraccion Versin 03


//Extraccin sobre varias cuentas
//Con registro histrico de las extracciones
import java.io.*;
import java.util.*;
public class Extraccion implements Serializable{
private Cuenta oCuenta;
private Date fecha;
private float importe;
public Extraccion(){
fecha=new Date();
}
public float dameImporte() {
return (importe);
}
public Date dameFecha() {
return (fecha);
}
public Cuenta dameCuenta() {
return (oCuenta);
}
public void trabaja(){
InterfazExtraccion oInterfazExtraccion;
Monedero oMonedero;
GestorExtracciones oGestorExtracciones;
GestorCuentas oGestorCuentas;
Tarjeta oTarjeta;
String idCuenta;
oInterfazExtraccion= new InterfazExtraccion();
importe=oInterfazExtraccion.dameImporte();
oTarjeta=Tarjeta.dameSolitario();
idCuenta=oTarjeta.dameIdCuenta();
oGestorCuentas=GestorCuentas.dameSolitario();
oCuenta=oGestorCuentas.dame(idCuenta);
oMonedero=Monedero.dameSolitario();
oCuenta.autoriza(importe);
oMonedero.entrega(importe);
oCuenta.resta(importe);

<- 1
<- 2

oGestorExtracciones=GestorExtracciones.dameSolitario();
oGestorExtracciones.agrega(this);
}
}
1-> oTarjeta=Tarjeta.dameSolitario();

La clase Tarjeta, por tener una nica instancia, se implementa con el


patrn Solitario.
2-> oGestorCuentas=GestorCuentas.dameSolitario();
La clase GestorCuentas se implementan tambin con el patrn

215

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Solitario.

Figura 12. Cdigo Java de varias extracciones sobre varias cuentas

2.4 Tercera Ampliacin: Control de Acceso


Han estafado al dueo del cajero. Se necesita un control de acceso.
Escena de acceso
Nos dice el cliente: el control de acceso se realizar contrastando el nmero de
identificacin personal (pin) que debe teclear el usuario del cajero, con el nmero de
identificacin contenido en una tarjeta que lee un dispositivo del cajero.
El diseo de esta parte se har sin tener en cuenta el diseo del mecanismo de
extraccin para ver, despus, un ejemplo de acoplamiento de secciones hechas por
separado.
Los objetos diseados para participar en esta escena son:

oControlAcceso: objeto especializado en autorizar o rechazar el acceso.

oInterfazControlAcceso: responsable de comunicarse con el usuario para


pedir su pin y drselo a oControlAcceso.

oLectorTarjeta: al igual que oMonedero, oLectorTarjeta es la interfaz de


nuestro sistema con el dispositivo fsico Lector de Tarjeta.

216

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

oLector
Tarjeta

oControl
Acceso

oInterfaz
ControlAcceso

{el siguiente
objeto}

trabaja
trabaja
damePin
damePin
trabaja

Figura 13: Diagrama de secuencia de acceso


Cuando el objeto oLectorTarjeta recibe una tarjeta le pide al objeto
oControlAcceso que trabaje. El objeto oControlAcceso solicita entonces el pin tanto al
objeto oLectorTarjeta como al objeto oInterfazControlAcceso y si ambos coinciden
autoriza el acceso.
Esta escena de acceso ignora totalmente lo hecho en extraccin. La solucin
planteada aqu puede servir, potencialmente como idea, para controlar el acceso en otros
sistemas.

Lector
Tarjeta

Interfaz
Control
Acceso

{Clase
siguiente}

Figura 14: Diagrama de Clases para el acceso

217

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Cdigo Java ACCESO


//Clase ControlAcceso versin 01
//LectorTarjeta custodia los datos de la tarjeta
public class ControlAcceso{
public ControlAcceso(){
}
public void trabaja(){
InterfazControlAcceso oInterfazControlAcceso;
LectorTarjeta oLectorTarjeta;
String pinTarjeta;
String pinControl;
oInterfazControlAcceso=newInterfazControlAcceso();
oLectorTarjeta = LectorTarjeta.dameSolitario();
pinTarjeta=oLectorTarjeta.damePin();
pinControl=oInterfazControlAcceso.damePin();

<- 1
<- 2

<- 3

if (pinTarjeta.compareTo(pinControl)==0)
System.out.println("Autorizado");
}

1-> oInterfazControlAcceso=new InterfazControlAcceso();


Se crea el objeto oInterfazControlAcceso, responsable de la interfaz.
2-> oLectorTarjeta = LectorTarjeta.dameSolitario();
En esta lnea se obtiene el nico objeto de la clase LectorTarjeta.
Usando el patrn Solitario garantizamos que en el sistema existe un
nico representante del dispositivo fsico Lector Tarjeta.
3-> (pinTarjeta.compareTo(pinControl)==0)
Se verifica si el pin de la tarjeta corresponde al pin escrito por el
usuario al identificarse.

Figura 15: Cdigo Java para el control de acceso

218

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Integracin de acceso y extraccin


Intente unir los mecanismos de acceso y extraccin que hemos diseado, a travs
de los principales diagramas de secuencia respectivos. Los hemos copiado aqu para
facilitar el trabajo.

:Extraccin

oInterfaz
Extraccin

oGestor
Extracciones

oTarjeta

:Cuenta

oGestor
Cuentas

oMonedero

trabaja
dameImporte
dameIdCuenta
Dame(idCuenta)
autoriza(importe)
entrega(importe)

resta(importe)
agrega(me)

oLector
Tarjeta

oControl
Acceso

oInterfaz
ControlAcceso

trabaja
trabaja
damePin
damePin
trabaja

219

{el siguiente
objeto}

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Hoja para trabajar.

220

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Estudio de alternativas de unin


Tratemos de conectar los dos mecanismos, Extraccin y Acceso, comenzando
por la lnea del menor esfuerzo. Es decir, haciendo cambios mnimos, respecto a sus
diseos independientes.
Como, el objeto oControlAcceso es el ltimo que trabaja en la parte de acceso y
el objeto :Extraccin es el primero que lo hace, en la parte de extraccin, pasemos la
pelota de uno a otro. El objeto oControlAcceso le pide al objeto Extraccin que trabaje.
Figura 16.
oLector
Tarjeta

oControl
Acceso

oInterfaz
ControlAcceso

oExtraccion

oInterfaz
Extraccion

oGestor
Extracciones

oTarjeta

oCuenta

oGestor
Cuentas

oMonedero

trabaja
trabaja
damePin
damePin
trabaja
dameImporte
dameIdCuenta
dame(idCuenta)
autoriza(importe)
entrega(importe)
resta(importe)
agraga(me)

Figura 16: Conexin de acceso y extraccin. Primer paso.


Cuando diseamos el objeto oExtraccin hicimos que solicitara el identificador
de la cuenta al objeto oTarjeta, que fue colocado ah para dar esa informacin y ocultar
cmo la obtena. En ese momento diseamos un objeto oTarjeta simple, con el objetivo
de estudiar el mecanismo de extraccin. Pero, ahora, hay un lector de tarjetas. Por tanto,
el objeto oTarjeta debe solicitarle al objeto oLectorTarjeta el identificador de la cuenta
Figura 17.

221

Curso de OO dirigido por


la introduccin de ambigedad

oLector
Tarjeta

oControl
Acceso

oInterfaz
ControlAcceso

Diseo evolutivo

oExtraccion

oInterfaz
Extraccion

oGestor
Extracciones

oTarjeta

oCuenta

oGestor
Cuentas

oMonedero

trabaja
trabaja
damePin
damePin
trabaja
dameImporte
dameIdCuenta
dameIdCuenta
dame(idCuenta)
autoriza(importe)
entrega(importe)
resta(importe)
agraga(me)

Figura 17: Conexin de acceso y extraccin. Segundo paso


Antes de estudiar con ms detalle las consecuencias de la conexin que hemos
hecho, observemos la Figura 18. La unin se ha producido con una hernia en el
mecanismo de extraccin que puede ser dolorosa si hay movimientos en el mecanismo
de acceso, como sucede en todas las hernias. El mensaje dameIDCuenta del objeto
oTarjeta al objeto oLectorTarjetas introduce el mecanismo de extraccin en el interior
del mecanismo de acceso, llegando incluso hasta la frontera exterior del sistema. Hemos
hecho muy vulnerable la extraccin respecto a cambios en acceso.

acceso

extraccin

Figura 18. Hernia en el mecanismo de extraccin

222

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Por otra parte, aunque el sistema funciona, hay un problema. oControlAcceso le


solicita el pin a oLectorTarjeta y oExtraccin le solicita el nmero de cuenta a oTarjeta.
Esta diversidad, adems de crear problemas de consistencia, eleva la complejidad del
software innecesariamente.
La dualidad aparente entre oLectorTarjeta y oTarjeta puede inducir a eliminar
uno de ellos. El objeto oLectorTarjeta est encargado de ser la interfaz con el software
del artefacto de lectura. No lo debemos eliminar. Quitemos el objeto oTarjeta y hagamos
que el objeto oControlAcceso y el objeto oExtraccin soliciten los datos que necesiten
al objeto oLectorTarjeta. Esta solucin se presenta en Figura 19.
oLector
Tarjeta

oControl
Acceso

oInterfaz
ControlAcceso

oExtraccion

oInterfaz
Extraccion

oGestor
Extracciones

oTarjeta

oCuenta

oGestor
Cuentas

oMonedero

trabaja
trabaja
damePin
damePin
trabaja
dameImporte
dameIdCuenta
dame(idCuenta)
autoriza(importe)
entrega(importe)
resta(importe)
agraga(me)

Figura 19. Conexin que elimina al objeto oTarjeta


Se ha suprimido la diversidad y la posible inconsistencia, pero se agudiz el
problema de la hernia porque ahora afecta a la esencia de la extraccin, al objeto
:Extraccin.
Antes, el objeto oTarjeta protega el mecanismo de extraccin del mundo
exterior, ocultando la forma de conseguir el identificador de la cuenta. Despus de
colocar el mecanismo de acceso, el mundo exterior se alej del mecanismo de
extraccin. Una vez ms, puede parecer que sobra oTarjeta al alejar el peligro. Pero no
es as.

223

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Desde el punto de vista del mecanismo de extraccin se ha sustituido el mundo


exterior por el mecanismo de acceso. Debe seguir existiendo una frontera y, adems,
protegida. Al quitar el objeto oTarjeta, perdimos la proteccin contra los cambios en el
mecanismo de acceso, conectando el corazn de extraccin con acceso. El objeto
oTarjeta, que antes era una interfaz con el mundo exterior, ahora debe actuar como
interfaz con el mecanismo de acceso. Es el elemento que independiza el acceso de la
extraccin y tambin que los conecta.
Adems, si aadimos responsabilidades al objeto oLectorTarjeta, dndole la
custodia de la informacin de la tarjeta, estamos reduciendo la cohesin de esta clase,
cuya funcin fundamental es servir de interfaz con el dispositivo fsico de lectura, nada
ms.
En conclusin, el diseo funciona, pero no es adecuado desde la perspectiva
evolutiva. Hagamos una iteracin para tratar de mejorar esa perspectiva de diseo.

2.4.1 Una iteracin. Otra forma de unin


Dejemos el objeto oTarjeta y hagamos que sea el custodio de la informacin de
la tarjeta para ambas partes. Los objetos oControlAcceso y :Extraccin le pedirn a
oTarjeta el dato que necesiten. As, se gana en homogeneidad. Cuando el primero
solicite el valor del pin, al objeto oTarjeta, ste lo pide al objeto oLectorTarjeta y se lo
entrega a oControAcceso. Algo semejante ocurrir cuando :Extraccin solicite el
identificador de la cuenta.
Sin embargo, este mecanismo se aprecia complejo, sin necesidad de hacerlo
grfico. Los accesos de oTarjeta a oLectorTarjeta solicitndole informacin se
distribuyen, segn se necesite. Quedan diluidos en la madeja de mensajes. Busquemos
una solucin que ofrezca ms claridad, que sea menos compleja.

224

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

2.4.2 Otra iteracin


Concentremos todos los accesos de oTarjeta al objeto oLectorTarjeta al
comienzo. Despus que oLectorTarjeta hace su tarea de interfaz, le dice a oTarjeta que
trabaje, para que cargue la informacin. Una vez cargada la informacin, oTarjeta le
pide a oControAcceso que la valide. En la Figura 20 se muestra el mecanismo descrito.
Hemos desplazado la posicin de oTarjeta para resaltar su papel de interfaz.

ACCESO

oLector
Tarjeta

oControl
Acceso

EXTRACCION

oInterfaz
ControlAcceso

oTarjeta

:Extraccion

oInterfaz
Extraccion

oGestor
Extracciones

oCuenta

oGestor
Cuentas

oMonedero

trabaja
trabaja
damePin
dameIdCuenta
valida
damePin
damePin
trabaja
dameImporte
dameIdCuenta
dame(idCuenta)
autoriza(importe)
autoriza(importe)
entrega(importe)
resta(importe)
agraga(me)

Figura 20. Diagrama de secuencia de la unin, con oTarjeta como interfaz


Hemos ganado en claridad respecto a la divisin entre los dos mecanismos.
Ahora menos acoplados. Y, adems, hemos reducido la posibilidad de inconsistencia al
actualizar oTarjeta completamente, cada vez que oLectorTarjeta trabaje.
Esta solucin llega a un compromiso entre dos condiciones contradictorias de
diseo. Por un lado, eliminar las fuentes de informacin redundantes para evitar
problemas de inconsistencia si se actualizan indistintamente. Por otro, conseguir un
diseo modular protegido contra cambios. Se ha mantenido la redundancia porque nos
interesaba para desacoplar ambos mecanismos, pero se ha minimizado la posibilidad de
inconsistencia.

225

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

2.4.3 Otra iteracin ms


Sin embargo, ahora tenemos un efecto hernia de acceso a extraccin. El
mensaje de oControlacceso a Extraccin se desliza hacia la parte de extraccin.
Adems de, reforzar el acople entre acceso y extraccin porque es una conexin ms
entre ellos. Una de oTarjeta y otra de oControlAcceso.
Si pensamos un poco, veremos que podemos concentrar toda la comunicacin en
el objeto oTarjeta. Efectivamente, cuando este objeto termine de cargar la informacin
vuelve a recibir el control, y en ese momento puede invocar a :Extraccin para que
trabaje. Figura 21. El acoplamiento entre ambos mecanismos se ha reducido a un
mnimo, al concentrarse en el objeto oTarjeta. Ahora, este objeto acta como elemento
de enchufe de las dos partes del sistema.
ACCESO

oLector
Tarjeta

oControl
Acceso

EXTRACCION

oInterfaz
ControlAcceso

oTarjeta

:Extraccion

oInterfaz
Extraccion

oGestor
Extracciones

oCuenta

oGestor
Cuentas

oMonedero

trabaja
trabaja
damePin
dameIdCuenta
valida
damePin
damePin

trabaja
dameImporte
dameIdCuenta
dame(idCuenta)
autoriza(importe)
autoriza(importe)
entrega(importe)
resta(importe)
agraga(me)

Figura 21. Diagrama de secuencia de la unin, bien diferenciada


Hemos conseguido dos mdulos independientes unidos por un solo elemento.
Razonemos. Antes de unir el acceso y la extraccin el sistema estaba dividido, que es lo
aconsejable para reducir la complejidad por diversidad, pero no funcionaba porque
estaban separadas.
Cuando las unimos y las mezclamos aument la complejidad porque tuvimos
que enfrentarnos, de una vez, a todos los detalles del sistema en su conjunto. El

226

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

problema de diseo era, entonces, unirlas para que funcionen, manteniendo la


complejidad, al menos como antes. Se ha conseguido, porque el sistema funciona y
podemos tratarlo como dos secciones dbilmente acopladas con semntica propia, sin
tener que ver sus detalles.
La Figura 22 muestra el diagrama de clases del sistema, despus de unidas las
secciones de acceso y extraccin. Observe que el acople entre ellas slo es un punto de
tangencia.

Lector
Tarjeta
Gestor
Interfaz
Tarjeta

Extraccin

Gestor
Cuenta

Interfaz
Monedero

Control
Acceso

Figura 22 Diagrama de clases del sistema

227

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Pero esto ha requerido de un replanteamiento del diseo con modificaciones


importantes. Por cierto, slo en la parte de acceso. La extraccin no ha cambiado.
Las ampliaciones precedentes no produjeron modificaciones importantes porque
eran cambios cuantitativos en los requisitos, que pudimos resolver con cambios
cuantitativos en la solucin. Pero, considerar el acceso significa aadir una nueva
funcin. Por tanto, es un cambio cualitativo en los requisitos. Es de esperar, entonces,
que se produzcan cambios cualitativos en la solucin, como ha sucedido.
El diagrama de secuencia, el diagrama de clases del mecanismo de acceso y el
cdigo Java de la clase ControlAcceso se muestran en las figuras 23, 24 y 25
respectivamente.

oLector
Tarjeta

oControl
Acceso

oTarjeta

oInterfaz
ControlAcceso

{el sigiuente
objeto}

trabaja
trabaja
damePin
dameIdCuenta
valida
damePin
damePin
trabaja

Figura 23. Nuevo diagrama de secuencia del control de acceso


Es interesante analizar que el objeto oTarjeta, hace dos accesos a oLectorTarjeta,
uno por cada dato que solicita: dameIdCuenta y damePin. Se puede pensar en
solicitarlos de una vez. Es ms eficiente para la mquina, pero restringe la libertad de
cambio al mezclar las dos solicitudes. Si hay que modificar alguna, slo se toca esa.
La modificabilidad se basa en la separacin e independencia de los elementos,
tanto en el diseo, como en el cdigo.

228

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

//Clase ControlAcceso versin 02


//Tarjeta custodia los datos de la tarjeta
public class ControlAcceso{
public ControlAcceso(){
}
public void trabaja(){
InterfazControlAcceso oInterfazControlAcceso;
Tarjeta oTarjeta;
String pinTarjeta;
String pinControl;

oTarjeta = Tarjeta.dameSolitario();
pinTarjeta = oTarjeta.damePin();
oInterfazControlAcceso = new InterfazControlAcceso();
pinControl = oInterfazControlAcceso.damePin();
if (pinTarjeta.compareTo(pinControl)==0)
System.out.println(Autorizado);

<- 1

}
1-> oTarjeta =Tarjeta.dameSolitario();
En esta lnea se solicita el nico objeto de la clase Tarjeta. El
mismo objeto que recibe Extraccin cuando lo solicita. En esta
versin el objeto Tarjeta es el responsable del pin del cliente.
Falta por incluir la alternativa de No Autorizado

Figura 24. Nuevo cdigo Java de la clase ControlAcceso

Lector
Tarjeta

{Clase objeto
siguiente}

Tarjeta

Interfaz
Control
Acceso

Figura 25. Nuevo diagrama de clases de acceso

229

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Interpretacin Arquitectnica del Sistema


Si reorganizamos el diagrama de clases y lo relacionamos con su entorno,
pudiramos hacer una interpretacin arquitectnica del sistema, para enriquecer nuestra
visin de lo que hemos construido. Figura 26.

MUNDO EXTERIOR
Base de Datos

ACCESO

EXTRACCIN

Gestor
Extracciones

Gestor
Cuentas

Cuenta

Tarjeta
Extraccin
Control
Acceso

Lector
Tarjeta

Interfaz
Control
Acceso

Inferfaz
Extraccin

Monedero

pin
importe

Lector
Tarjeta

Monedero

dinero

tarjeta

MUNDO EXTERIOR

Usuario

Figura 26 Arquitectura del Sistema


El esquema de la Figura 26 delimita la frontera del sistema con el mundo
exterior y coloca, en esa frontera, las clases que hemos diseado para trabajar con el
mundo exterior. Unas clases se dedican a interactuar con los dispositivos fsicos, Lector
de Tarjeta y Monedero; otras se dedican a interactuar con el cliente y otras con los
lugares donde se guarda la informacin.

230

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Las clases interiores constituyen el ncleo del mecanismo del cajero, dividido en
dos secciones: el acceso y la extraccin, conectadas a travs de una clase comn.
El aislamiento del ncleo, respecto al mundo exterior, lo protege de los cambios,
mantiene su estabilidad. Pero adems, esta separacin permite un tratamiento
relativamente independiente de las interfaces que puede ser beneficioso.
La distincin de las secciones facilita la comprensin del sistema, reduce su
complejidad, porque permite la descripcin del sistema slo en trminos de sus
componentes y de la relacin que hay entre ellos. Un mecanismo de acceso y otro de
extraccin de dinero, sin tener que entrar en detalles de cada uno. Si no distinguimos
las secciones tendramos que describir el sistema dando todas sus clases y relaciones. La
introduccin de las secciones reduce la diversidad y adems, abre el camino para la
reutilizacin de mecanismos, fundamentalmente como ideas.

231

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

2.5 Cuarta Ampliacin: Ingreso de Dinero


Ahora, tambin se quiere ingresar dinero.
Para adicionar este nuevo servicio al cajero se debe crear el mecanismo de
ingreso y analizar despus la mejor manera de integrar este mecanismo al sistema
anterior. Como el ingreso es similar a la extraccin, a continuacin repetimos el
diagrama de clases de extraccin para reutilizar los aspectos comunes. Figura 27
Dejamos que intente este ejercicio.

oInterfaz
Extraccin

:Extraccin

oGestor
Extracciones

oTarjeta

:Cuenta

oGestor
Cuentas

oMonedero

trabaja
dameImporte
dameIdCuenta
Dame(idCuenta)
autoriza(importe)
entrega(importe)

resta(importe)
agrega(me)

Figura 27. Repeticin del diagrama de secuencia de extraccin

232

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Ejercicio
Disear el diagrama de secuencia del ingreso de dinero. Nuestro cliente desea
que el ingreso no produzca un aumento en el saldo hasta que una persona del banco
valide la cantidad de dinero ingresada. Un ingreso automtico a cargo del sistema,
hubiese sido ms simtrico con extraccin, pero la decisin de nuestro cliente fue
distinta.

233

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Diseo del mecanismo de ingreso


Los objetos oIngreso y oInterfazIngreso de esta escena se corresponden con los
objetos oExtraccin y oInterfazExtraccin de la escena de extraccin. El mtodo
registra(importe) del objeto oCuenta slo es un registro de la intencin del usuario del
cajero, no incrementa el valor del saldo de la cuenta. La autorizacin del saldo se har
despus, como ya se dijo.
Como el ingreso no se relaciona con ningn artefacto exterior, prescindimos de
un objeto interfaz, del estilo de oMonedero. En el caso de existir un artefacto debemos
crear un objeto interfaz especializado en ese artefacto. No es recomendable usar el
objeto oMonedero para este fin.

oInterfaz
Ingreso

oIngreso

oGestor
Ingresos

oTarjeta

oCuenta

trabaja
dameImporte
dameIdCuenta
dame(idCuenta)
registra(importe)
agrega(me)

Figura 28. Diagrama de secuencia del mecanismo de ingreso

234

oGestor
Cuentas

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Las figuras 29 y 30 muestran el diagrama de clases y el cdigo de ingreso,


respectivamente.

Tarjeta

Interfaz

Gestor

Ingreso

Cuenta

Figura 29. Diagrama de clases del mecanismo de ingreso

235

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Cdigo Java INGRESO


//Clase Ingreso
import java.io.*;
import java.util.*;
public class Ingreso implements Serializable{
private Cuenta oCuenta;
private Date fecha;
private float importe;
public Ingreso(){
fecha=new Date();
}

<- 1

public void trabaja(){


InterfazIngreso oInterfazIngreso;
GestorIngresos oGestorIngresos;
GestorCuentas oGestorCuentas;
Tarjeta oTarjeta;
String idCuenta;

oInterfazIngreso= new InterfazIngreso();


importe=oInterfazIngreso.dameImporte();
oTarjeta=Tarjeta.dameSolitario();
idCuenta=oTarjeta.dameIdCuenta();
oGestorCuentas=GestorCuentas.dameSolitario();
oCuenta=oGestorCuentas.dame(idCuenta);
oCuenta.registra(importe);
oGestorIngresos=GestorIngresos.dameSolitario();
oGestorIngresos.agrega(this);

<- 2
<- 3
<- 4
<- 5

}
1-> fecha=new Date();
Al igual que en Extraccin, al crear una instancia de la clase
Ingreso se asigna al atributo fecha la fecha actual del sistema.
2-> oInterfazIngreso= new InterfazIngreso();
Se pide la creacin de la interfaz correspondiente al Ingreso.
3-> oTarjeta=Tarjeta.dameSolitario();
Se pide el nico objeto Tarjeta del sistema.
4-> oGestorCuentas=GestorCuentas.dameSolitario();
Se obtiene el nico objeto GestorCuentas del sistema.
5-> oGestorIngresos=GestorIngresos.dameSolitario();
El objeto GestorIngresos, se implementa tambin usando el patrn
Solitario. Aqu se pide su nica instancia.

Figura 30.Cdigo Java de la clase Ingreso

236

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Integracin de ingreso al sistema


Al aadir un servicio nuevo se produce otra vez un cambio cualitativo en los
requisitos, que debe provocar cambios cualitativos en la solucin. En este caso, adems,
se rompe la estructura ms o menos lineal del diseo y aparece un punto de bifurcacin.
Se necesita una seleccin y una distribucin. Es decir, un mecanismo de eleccin del
camino y otro que nos conduzca a l.
Como la funcin del sistema se ha enriquecido, su geometra debe cambiar para
ajustarse a su nuevo trabajo, siguiendo la idea de que existe una relacin entre forma y
funcin. La figura 31 muestra la geometra anterior y la nueva.

ACCESO

EXTRACCI
ON

EXTRACCIO
N
ACCESO
INGRESO

Figura 31. Seleccin y distribucin de la orden de trabajo

El punto negro de la Figura 31 se transforma en un objeto oSelector para


recoger la seleccin del usuario y generar la orden de trabajo. Y a continuacin,
una estructura polimrfica que distribuya esa orden. Figura 32.

237

Curso de OO dirigido por


la introduccin de ambigedad

Selector

Diseo evolutivo

Operacin

Ingreso

Extraccin

Figura 32. Distribucin de la orden trabaja mediante polimorfismo


El polimorfismo permite que la orden de trabajo sea igual para extraccin e
ingreso y la encamina segn corresponda. Ha introducido homogeneidad en la
diversidad. Cualquier otra funcin, del mismo tipo definido en Operacin, puede ser
aadida sin perturbar a quienes usan la estructura polimrfica. Por tanto, hemos
conseguido estabilizar ese punto del diseo respecto a cambios en las operaciones. La
geometra vuelve a ser adecuada.
Al ofrecer un abanico uniforme y abierto de servicios, el polimorfismo convierte
cambios cualitativos en los requisitos, de aadir y quitar funciones, en cambios
cuantitativos en la solucin.
El diseo de la dinmica del sistema incorporando todas sus funciones debe ser
descrito en diagramas de secuencia diferente. Uno para la parte de acceso, que debe
conectarse, ahora, con el selector. Otro para la extraccin y otro para el ingreso.
Aunque el objeto selector puede ser una interfaz, hemos seguido el estilo
precedente, y creamos una interfaz de selector para conocer solicitud del usuario. Con
esta informacin el objeto oSelector enva un mensaje de trabaja a quien corresponda.
La direccin del mensaje viene dado desde la interfaz, as que el selector no toma
decisin alguna, la toma el usuario en la interfaz.

238

Curso de OO dirigido por


la introduccin de ambigedad

oLector
Tarjeta

Diseo evolutivo

oControl
Acceso

oTarjeta

oInterfaz
ControlAcceso

trabaja

{el sigiuente
objeto}
oSelector

oInterfaz
Selector

OSELECT
OR
trabaja

OTARJ
ETA

damePin
dameIdCuenta
trabaja
damePin
damePin
trabaja

dameOperacin

trabaja

Figura 33. Diagrama de secuencia que incorpora la seleccin


Para alterar lo menos posible al mecanismo de acceso, la seleccin debe ser un
elemento independiente. Lo hemos incorporado al esquema de acceso con el objetivo de
mostrar su encaje.
EN VEZ DE DEJAR LA FLECHA DEL MENSAJE TRABAJA SIN DESTINATARIO, SE
PUEDE DIRIGIR A LA CLASE

OPERACIN, PORQUE LA DIRECCIN DEL MENSAJE ES UNA

VARIABLE DE ESA CLASE, COMO SE APRECIA EN EL CDIGO DE LA

239

FIGURA 34.

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Cdigo Java Selector


//Clase Selector Versin 01
public class Selector{
public Selector(){
}
public void trabaja(){
InterfazSelector oInterfazSelector;
Operacion operacion;

oInterfazSelector=new InterfazSelector();
operacion=oInterfazSelector.dameOperacion();
operacion.trabaja();

<- 1
<- 2
<- 3
<- 4

}
1-> Operacion operacion;
operacin es una variable que pertenece a la clase abstracta
Operacion. Esta variable puede contener objetos que pertenezcan a
cualquier subclase de la clase Operacin; en particular objetos de la
clase Ingreso o de la clase Extraccion.
2-> oInterfazSelector=new InterfazSelector();
En esta lnea se crea el objeto interfaz oInterfazSelector.
3-> operacion=oInterfazSelector.dameOperacion();
oInterfazSelector solicita al usuario la operacin deseada y retorna
el objeto correspondiente a la operacin seleccionada por el usuario.
4-> operacion.trabaja();
En esta lnea de cdigo, si el usuario seleccion una operacin, el
selector da la orden a la operacin para que trabaje. El atributo
operacin puede ser de la clase Extraccin o de la clase Ingreso.

Figura 34. Cdigo Java de la clase Selector

240

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Diagrama de clases del sistema completo


La Figura 35 muestra el diagrama de clases del software del cajero.

Lector
Tarjeta

Tarjeta

Interfaz

Interfaz
Control
Acceso

Gestor
Operacin

Selector

Cuenta

trabaja

Gestor

Gestor

Interfaz

Interfaz

Extraccin

Ingreso

trabaja

trabaja

{Otra
Operacin}

Monedero

Figura 6 Diagrama de Clases CAJERO

Observe que no existe ningn objeto cajero. El software del cajero funciona sin
una definicin explcita. Este es uno de los recursos de la orientacin a objetos que
hemos empleado en el diseo para facilitar su evolucin. Empezamos con la extraccin,
despus aadimos el acceso y por ltimo, agregamos el ingreso sin tener que modificar
ninguna definicin, porque no exista. El sistema cumple su funcin sin necesidad de
una definicin explcita de un cajero dentro del cdigo

241

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Un objeto cajero, para definir el sistema, conteniendo los objetos del diseo no
desempea un papel relevante en el software. De tenerlo, habra que modificarlo cada
vez que se cambiara algo.
Otra observacin interesante es que podemos tener una visin integral de la
estructura del sistema con el diagrama de clases. Pero con los diagramas de secuencia,
slo tenemos trozos del comportamiento del sistema, como escenas sueltas de una obra
de teatro.

2. 6 Recapitulemos
El mtodo de trabajo ha sido considerar una situacin simple y despus
enriquecerla. Por ejemplo, una extraccin y despus, varias extracciones.
Cuando aumentamos la capacidad cuantitativa de nuestro sistema software, para
operar con ms de una extraccin y con ms de una cuenta, slo tuvimos que aadir
piezas de software, objetos y cdigo, que encajaron sin dificultad en el mecanismo
existente. Las exigencias cuantitativas del entorno se pudieron resolver con cambios
cuantitativos en el sistema, gracias a la aplicacin del principio de ocultamiento de
informacin.
Los diseos deben mostrar esta cualidad, siempre que los cambios cuantitativos
no impliquen cambios cualitativos. Como hemos dicho, manejar diez datos es
cualitativamente distinto de manejar un milln. Un salto cuantitativo de ese orden debe
provocar cambios sustanciales en el mecanismo, que no se resuelven solamente
aadiendo ms piezas de software. Pero, mientras que no ocurran tales cambios nuestro
software debe evolucionar de manera simple.
Cuando el entorno exigi agregar la funcin del control de acceso se produjo un
cambio cualitativo. Hubo que hacer modificaciones en el software precedente para
acoplarlo a la funcin de acceso. En general, los cambios cualitativos en el problema
provocan cambios cualitativos en la solucin software. Se deben aprovechar tales
cambios para mejorar las cualidades del sistema.
Algo parecido sucedi con la funcin ingreso, hubo que modificar el software
existente. Cambi la geometra del sistema al crearse un punto de bifurcacin.
242

Curso de OO dirigido por


la introduccin de ambigedad

Diseo evolutivo

Estabilizamos ese punto de futuros cambios colocando un mecanismo de estabilizacin


para enfrentar esa incertidumbre. Aqu empleamos el polimorfismo.
En ningn caso, hubo una anticipacin a los acontecimientos, slo se aplic una
disciplina de diseo: modularizar y aplicar sistemticamente el Principio de
Ocultamiento de la Informacin. Lo hicimos cada vez que separamos y delegamos
tareas, al utilizar objetos interfaces con el exterior y entre secciones del sistema, y
tambin cuando usamos el polimorfismo. Las operaciones particulares quedan ocultas
detrs de la clase abstracta. En fin, introduciendo incertidumbre dentro del diseo.

243

También podría gustarte