Nuestro objetivo es obtener descripciones apropiadas de los objetos, para lo cual se necesita un mtodo que satisfaga tres condiciones: Las descripciones deben ser precisas y no ambiguas. Deberan ser completas, o al menos tan completas como sea necesario en cada caso. Qui! se decidan omitir algunos detalles. No deberan especificar m!s de lo necesario. "l #ltimo punto es el que $ace que la respuesta no sea trivial. Despus de todo es f!cil ser preciso, no ambiguo y completo si se %descorre la cortina& y se dejan ver todos los detalles de la representaci'n de los objetos. (ero normalmente esto es demasiada informaci'n para los creadores de elementos soft)are que necesitan acceder a los objetos. *l proporcionar el c'digo fuente de la clase como fuente primaria de informaci'n para los creadores de elementos soft)are que se apoyan en dic$o clase, lo que ocurre es que se permite que los elementos soft)are usen un objeto de una cierta clase tomando como base una informaci'n que ata+e m!s a la representaci'n del objeto que a sus propiedades esenciales, lo que implica que estamos sumergiendo a los creadores de elementos soft)are en un mar de detalles, impidindoles concentrarse en su propio trabajo y poniendo obst!culos para nuestras esperanas de una evoluci'n suave del soft)are. "s m!s, distintas clases, que por tanto muy probablemente definen estructuras de datos distintas entre s, pueden compartir las mismas propiedades esenciales. De $ec$o, cada una de estas estructuras de datos es una representaci'n posible de las mismas propiedades esenciales, y adem!s cada una de estas representaciones posibles es #til en determinados casos. ,eleccionar una de ellas como la definici'n de dic$as propiedades esenciales sera realmente utiliar una representaci'n particular como especificaci'n y sera adem!s un caso tpico de especificar m!s de lo necesario. "s m!s, no $ay forma de justificar que una de las representaciones es m!s representativa que otra dado que la mayora de la informaci'n propia de la representaci'n del objeto es irrelevante para comprender las propiedades esenciales del mismo. "ntonces, -c'mo conservar la completitud, la precisi'n y la no ambig.edad sin pagar el precio de una especificaci'n e/cesiva0 La respuesta es que si ocurre que dos o m!s representaciones distintas entre s 1que por tanto $an sido definidas en clases tambin distintas entre s y donde cada representaci'n o estructura de datos describe la forma de los objetos de la clase que la define1 comparten las mismas propiedades esenciales es porque $ay algo que las une. (ues bien, lo que une a las diferentes representaciones a pesar de todas sus diferencias es que los respectivos conjuntos de objetos asociados a cada una tienen todos en com#n ciertas operaciones que goan de ciertas propiedades. ,i se centra la atenci'n no en una forma particular de representaci'n sino en estas operaciones y sus propiedades, se puede obtener una caracteriaci'n abstracta y #til de esas propiedades esenciales. 2a $emos establecido el porqu de nuestra b#squeda de una manera de describir apropiadamente los objetos. *nte estos problemas, la teora formal de los tipos abstractos de datos es la respuesta, ya que proporciona el modo de lograr una especificaci'n de los objetos que es completa y precisa, no e/cesiva y carente de ambig.edad, centr!ndose, para lograr tales fines, en describir las propiedades esenciales de los objetos en ve de su representaci'n fsica. De $ec$o, la teora formal de los tipos abstractos de datos es la base te'rica del mtodo orientado a objetos, y en verdad lo que $ace esta teora es e/presar formalmente la idea ya presente en el mtodo orientado a objetos de que los objetos que describe una clase se definen #nicamente por lo que se puede $acer con ellos: los mtodos 1o rutinas1 y las propiedades formales de estos mtodos 1los contratos1. La falta de una forma de describir apropiadamente los objetos no s'lo ocasiona los problemas indicados m!s arriba. De $ec$o, el impacto de todas estas ideas en la pr!ctica es realmente importante. ,e estima que el 345 del coste del soft)are se dedica al mantenimiento. * su ve, m!s del 635 del coste del mantenimiento proviene de la necesiad de tener en cuenta cambios en los formatos de los datos. 7ay demasiados sistemas soft)are que est!n muy estrec$amente ligados a la estructura fsica de los datos que manipulan. ,i un mtodo de desarrollo de soft)are se basa en la representaci'n fsica de las estructuras de datos para guiar el an!lisis y el dise+o, es probable que no sea adecuado para producir soft)are fle/ible. "s importante tener claro entonces que es una necesidad evitar asociar el soft)are con las representaciones fsicas e/actas de los datos. *ntes de que alguien se $aga la pregunta, es conveniente tener claro que la cuesti'n no es que alguna parte del sistema soft)are conoca la representaci'n fsica de los datos: esto es inevitable puesto que los datos deben ser accedidos finalmente para su manipulaci'n interna, sino que con los mtodos tradicionales de dise+o este conocimiento se distribuye sobre muc$as partes del sistema, provocando modificaciones injustificadamente grandes en los sistemas soft)are en el momento en que cambia alguna de las representaciones fsicas de los datos 1como inevitablemente ocurrir! tarde o temprano. ,i cambia el formato de los datos, es raonable suponer que un sistema soft)are que manipule dic$os datos necesite ser adaptado8 lo que no es aceptable es que esa necesidad se e/tienda a todo el sistema, de tal modo que un cambio en dic$o formato cause cambios en el sistema soft)are en una magnitud desproporcionada con el tama+o conceptual del cambio en la especificaci'n. 2.- Concepto y definicin de un tipo abstracto de datos 9na confusi'n $abitual es considerar que el concepto matem!tico de conjunto es el m!s indicado para e/plicar qu es un tipo de datos8 sin embargo, el concepto matem!tico m!s apropiado para e/plicar la naturalea de un tipo de datos es el de !lgebra. 9n tipo de datos es un !lgebra, es decir, un conjunto de valores, llamado dominio, caracteriados por el conjunto de operaciones que sobre ellos se pueden aplicar y por el conjunto de propiedades que dic$as operaciones poseen y que determinan inequvocamente su comportamiento. 9n valor perteneciente al dominio de un tipo de datos se denomina una instancia o ejemplar del tipo de datos. 9n tipo abstracto de datos es un tipo de datos que se define mediante una especificacin que es independiente de cualquier implementacin. (or tanto, la especificaci'n del tipo abstracto de datos es la definici'n del mismo. La idea principal que est! detr!s de la palabra %abstracto& es precisamente la separaci'n e independencia de la especificaci'n del tipo abstracto de datos de una implementaci'n suya. :eamos con detenimiento lo que supone la independencia de la especificaci'n respecto de una implementaci'n suya. La especificaci'n del tipo abstracto de datos describe el comportamiento e/terno del mismo, es decir, qu $ace el tipo abstracto de datos, mientras que una implementaci'n suya describe c'mo lo $ace. La especificaci'n es independiente de cualquier implementaci'n puesto que no es necesario saber nada de sta para desarrollar aqulla8 sin embargo, cualquier implementaci'n es dependiente de la especificaci'n correspondiente ya que se lleva a cabo bas!ndose en sta, puesto que para que una implementaci'n sea correcta debe conservar las propiedades de la especificaci'n que dice implementar. *dem!s, una misma especificaci'n puede tener varias implementaciones asociadas, cada una con sus propios requisitos de consumo de espacio de memoria y de tiempo de ejecuci'n, de manera que puede variar qu implementaci'n es la m!s apropiada usar en un conte/to dado seg#n los requerimientos de ste. :eamos a$ora con detenimiento lo que supone la separaci'n de la especificaci'n respecto de una implementaci'n suya. La separaci'n de la especificaci'n del tipo abstracto de datos de su implementaci'n implica que sta es inaccesible a los clientes, lo que ayuda a stos a la producci'n de soft)are correcto ya que se evitan los errores debidos al conocimiento de la implementaci'n del tipo abstracto de datos. "ste ocultamiento de la informaci'n de la implementaci'n al cliente tambin ayuda a que ste no se despiste en un mar de detalles a la $ora de desarrollar sus propios elementos soft)are. (or todo ello, desde la perspectiva del cliente, no es deseable acceder a la implementaci'n del tipo abstracto de datos para poder usar dic$a implementaci'n8 pero, adem!s, es que tampoco es necesario ya que el cliente, para poder usar una implementaci'n de un tipo abstracto de datos, s'lo necesita conocer qu $ace ste, es decir, su especificaci'n. * partir de a$ora abreviaremos a veces Tipo Abstracto de Datos con el acr'nimo TAD. "n ingls el acr'nimo es ADT, de Abstract Data Type. 3.- Especificacin de un tipo abstracto de datos 3.1.- Motivacin de la especificacin foral de un TAD * continuaci'n vamos a estudiar c'mo desarrollar la especificaci'n de un ;*D, para lo que vamos a tomar como ejemplo el ;*D Pila. De manera informal, podemos definir o especificar el ;*D Pila como el conjunto de las pilas tal que una pila es una secuencia de elementos, que puede estar vaca, tal que un #nico e/tremo, conocido como la cima, es el que se usa para insertar y recuperar elementos, de modo que el #ltimo que entra es el primero que sale, comportamiento conocido en ingls por las siglas LIFO <Last In First Out=, es decir, que el #ltimo elemento que se inserta en la pila es el primero que se recupera. "l ;*D Pila tiene tpicamente disponibles las siguientes operaciones de inters: 9na orden que pone un elemento en la cima de la pila. Llamaremos a esta operaci'n apila. 9na orden que quita el elemento que est! en la cima de la pila, si sta no est! vaca. ,e la llamar! desapila. 9na consulta para ver cu!l es el elemento que est! en la cima de la pila, si sta no est! vaca. ,e la llamar! cima. 9na consulta para determinar si la pila est! vaca, lo que permite a los clientes determinar de antemano si pueden $acer desapila o cima. Llamaremos a esta operaci'n vaca. 9na constructora que proporciona una pila inicialmente vaca. Llamaremos a esta operaci'n crea. "s verdad que la elecci'n de los nombres de las operaciones es totalmente arbitraria en el sentido de que cambiar el nombre de una operaci'n no altera las propiedades que cumple, y as, por ejemplo, se podra $aber escogido el nombre a en lugar de apila, d en lugar de desapila, c en lugar de cima, v en lugar de vaca y cr en lugar de crea8 o, lo que es peor, $aber escogido el nombre de apila en lugar de desapila, desapila en lugar de cima, cima en lugar de vaca, vaca en lugar de crea y crea en lugar de apila. ,in embargo, no podemos por ello concluir que la elecci'n de los nombres es un mero asunto de cosmtica. *unque es informaci'n puramente subjetiva la que proporcionan los nombres de las operaciones, es bien cierto que los nombres significativos contribuyen a facilitar la comprensi'n del comportamiento de la operaci'n, lo que facilita el desarrollo de soft)are reutiliable. No $ay que olvidar que un buen soft)are reutiliable es un soft)are que proporciona una funcionalidad correcta y que la proporciona con nombres correctos. 9na especificaci'n de un ;*D como la anterior dada en lenguaje natural es informal. "s el primer paso para la comprensi'n del ;*D, pero es evidente que las descripciones informales como las anteriores no son suficientes. Las especificaciones dadas en lenguaje natural tienden a ser imprecisas, ambig.as, redundantes, incompletas, verbosas y a menudo meclan de manera aleatoria diferentes niveles de abstracci'n 1es decir, no est!n en una forma bien estructurada1. Dado que es necesario conocer con precisi'n c'mo los clientes pueden utiliar estas operaciones y lo que ellas realiar!n para estos clientes, es necesario un paso m!s que consiste en llevar a cabo una especificaci'n del ;*D que sea formal. :amos a ver una tcnica para especificar formalmente tipos abstractos de datos, conocida como especificacin algebraica o ecuacional. 3.2.- !i"natura de la especificacin foral de un TAD 9na especificaci'n formal algebraica de un tipo abstracto de datos consta de cuatro p!rrafos o cl!usulas: TIPO, FUNCIONES, AIO!AS y P"ECONDICIONES. "l p!rrafo TIPO indica el nombre del ;*D que se define en la especificaci'n. TIPO Pila[G] La especificaci'n ser! la de un ;*D Pila#$%, que describe las pilas de elementos de un ;*D arbitrario $. "n Pila#$%, $ denota un ;*D arbitrario y no concretado. $ se denomina parmetro genrico formal del ;*D Pila#$% y se dice que Pila#$% es un ;*D genrico. "l mecanismo que permite este tipo de especificaci'n parametriada se conoce con el nombre de genericidad. "s posible escribir especificaciones de tipos abstractos de datos sin genericidad, pero al precio de repeticiones injustificadas. -De qu sirve tener especificaciones separadas para los tipos abstractos de datos %pilas de cuentas bancarias&, %pilas de enteros& y dem!s0 "stas especificaciones seran idnticas e/cepto all! d'nde se refieran e/plcitamente al ;*D de los elementos de la pila 1cuentas bancarias o enteros en nuestros ejemplos1. "scribir estas especificaciones y llevar a cabo despus la sustituci'n de los tipos abstractos de datos manualmente resultara tedioso. La reutiliaci'n es deseable no s'lo para los programas sino >tambin para las especificaciones? @racias a la genericidad se puede $acer e/plcita la parametriaci'n de tipos abstractos de datos escogiendo alg#n nombre arbitrario, en este caso $, para representar el ;*D variable de los elementos de las pilas. Aomo resultado, siendo rigurosos, un TAD genrico como Pila#$% no es ya e/actamente un ;*D, sino un patrn de tipos abstractos de datos, lo que implica, si no olvidamos que un ;*D es un tipo de datos, que un ;*D genrico como Pila#$% es un tipo de datos genrico y, por tanto, no es ya tampoco e/actamente un tipo de datos, sino un patrn de tipos de datos. (ara obtener un ;*D 1 y, por tanto, un tipo de datos1 directamente utiliable, se debe conseguir un cierto ;*D 1que, por tanto, es un cierto tipo de datos1, por ejemplo el ;*D Cuenta que modela las cuentas bancarias, y $ay que proporcionarlo como parmetro genrico real correspondiente al par!metro genrico formal $. De modo que aunque Pila#$% en en s un patr'n de tipos abstractos de datos 1y por ende un patr'n de tipos de datos1, la notaci'n Pila#Cuenta% e/presa un ;*D totalmente definido y, por tanto, tambin es un tipo de datos totalmente definido. ;al ;*D y, por tanto, tambin tal tipo de datos, obtenido al proporcionar par!metros genricos reales a un ;*D genrico 1que, por tanto, es un tipo de datos genrico1, se dice que es derivado genricamente. Las nociones que se acaban de ver se pueden aplicar recursivamente, de manera que un ;*D que se utilia como par!metro genrico real de Pila#$% para producir un ;*D derivado genricamente puede ser a su ve derivado genricamente, de modo que es perfectamente correcto utiliar la notaci'n Pila#Pila#Cuenta%% para nombrar un ;*D y, por consiguiente, un tipo de datos: intuitivamente puede entenderse que las instancias de este ;*D 1y, por tanto, las instancias de este tipo de datos1 son pilas, cuyos elementos son a su ve pilas de cuentas bancarias8 los elementos de estas #ltimas pilas son cuentas bancarias. "stricamente $ablando, por tanto, una pila particular es una instancia no de Pila#$% 1porque como $emos visto es m!s un patr'n de tipos abstractos de datos que un ;*D y, por tanto, es m!s un patr'n de tipos de datos que un tipo de datos1 sino de alg#n ;*D derivado genricamente 1por tanto, de alg#n tipo de datos derivado genricamente1 de Pila#$%, como por ejemplo Pila#Cuenta%. 9na ve $ec$a la aclaraci'n, seguiremos en ocasiones, por sencille y donde no d lugar a confusi'n, $ablando tanto del ;*D como del tipo de datos Pila#$%, e igualmente de las instancias de Pila#$%, comprendiendo que realmente se est! $ablando tanto de un patr'n de tipos abstractos de datos como de un patr'n de tipos de datos, e igualmente de una instancia de una de sus derivaciones genricas, respectivamente. Despus del p!rrafo TIPOS viene el p!rrafo FUNCIONES, que enumera las operaciones aplicables a las instancias del ;*D. "stas operaciones ser!n las componentes esenciales de la definici'n del ;*D ya que describen sus instancias no por lo que son sino por lo que tienen que ofrecer. * continuaci'n se puede ver el p!rrafo FUNCIONES para el ;*D Pila#$%: FUNCIONES apila: Pila[G] x G Pila[G] desapila: Pila[G] Pila[G] cima: Pila[G] G vaca: Pila[G] Boolean crea: Pila[G] "n una especificaci'n algebraica, cada operaci'n de un ;*D se modela mediante una funci'n matem!tica. De a$ la notaci'n funcional empleada arriba. Aomo sabemos, una funci'n matem!tica es un mecanismo para obtener un resultado que pertenece a un cierto conjunto destino a partir de alguna posible entrada que pertenece a un cierto conjunto origen. 9na funci'n matem!tica no produce efectos laterales ni cambios de ninguna clase. "n matem!ticas el concepto de cambiar algo no e/iste como tal. * diferencia de la ejecuci'n de un sistema soft)are en un computador, evaluar una e/presi'n matem!tica nunca cambia un elemento involucrado en ella8 as, por ejemplo, calcular la ra cuadrada del n#mero B no modifica el valor de dic$o n#mero. (or lo tanto, la funci'n matem!tica apila: Pila[G] x G Pila[G] significa que apila tiene dos argumentos, una Pila de instancias de $ y una instancia de $, y produce como resultado, no la pila ya e/istente del primer argumento modificada con un elemento adicional en la cima de la pila, sino una nueva Pila de instancias de $ que tiene los mismos elementos que la del primer argumento m!s un elemento adicional en la cima de la pila. C!s formalmente, podemos decir que el conjunto origen de la funci'n apila es el conjunto Pila#$% x $, conocido como el producto cartesiano de Pila#$% y $8 ste es el conjunto de pares &p' () cuyo primer elemento p est! en Pila#$% y cuyo segundo elemento ( est! en $. De manera semejante, La funci'n desapila tiene un argumento, una Pila de instancias de $, y produce como resultado una nueva Pila de instancias de $ que tiene los mismos elementos que la del primer argumento menos el elemento que estaba en la cima si es que $aba alguno. La funci'n cima tiene un argumento, una Pila de instancias de $, y produce como resultado una instancia de $ que es el elemento que est! en la cima de la pila, si lo $ay. La funci'n vaca tiene un argumento, una Pila de instancias de $, y produce como resultado una instancia del ;*D *++lean que indica si la pila del argumento est! o no vaca. ,e supone que el ;*D *++lean se $a definido previamente por separado. La funci'n crea no tiene argumentos y produce como resultado una Pila de instancias de $ que est! vaca. "l p!rrafo FUNCIONES no define completamente estas funciones, sino que s'lo presenta sus perfiles, es decir, la lista de tipos abstractos de datos de sus argumentos y el ;*D del resultado. "l perfil de una funci'n tambin recibe el nombre de signatura de la funci'n. "n la especificaci'n informal que dimos al principio de esta secci'n clasificamos las operaciones del ;*D en 'rdenes, consultas y constructoras. Aon la especificaci'n formal algebraica de un ;*D T, como en nuestro ejemplo Pila#$%, se puede definir la correspondiente clasificaci'n de las funciones de forma m!s rigurosa. La clasificaci'n e/amina simplemente d'nde aparece T, con respecto a la flec$a, en la signatura de cada funci'n, proporcionando tres categoras de funciones: 9na funci'n como crea para la cual T aparece s'lo a la derec$a de la flec$a es una funci'n de construcci'n o funci'n constructora o abreviadamente una constructora. Codela una operaci'n que produce instancias de T a partir de instancias de otros tipos abstractos de datos o, como en el caso de una funci'n constructora constante como crea, sin partir de argumento alguno. 9na funci'n como cima y vaca en las cuales T s'lo aparece a la iquierda de la flec$a es una funci'n de consulta o abreviadamente una consulta. Codela una operaci'n que da como resultado propiedades de las instancias de T, e/presadas en trminos de instancias de otros tipos abstractos de datos 1*++lean y el par!metro genrico $ en los ejemplos1. 9na funci'n como apila y desapila en las que T aparece en ambos lados de la flec$a es una funci'n de orden o abreviadamente una orden. Codela una operaci'n que produce nuevas instancias de T a partir de instancias e/istentes de T y posiblemente tambin de instancias de otros tipos abstractos de datos. La parte de la especificaci'n algebraica del ;*D compuesta por las cl!usulas TIPO y FUNCIONES recibe el nombre de signatura del ;*D. La signatura de un ;*D tambin recibe el nombre de interfaz del ;*D. "n el ejemplo que nos ocupa, dado que Pila#$% es un ;*D genrico, y por tanto un patr'n de tipos abstractos de datos, la parte de la especificaci'n algebraica del ;*D genrico compuesta por las cl!usulas TIPO y FUNCIONES no es ya e/actamente una signatura de un ;*D sino un patr'n de signaturas de tipos abstractos de datos. 3.3.- !e#ntica de la especificacin foral de un TAD ,upongamos que el ;*D Enter+, que modela los n#meros enteros y que $a sido definido previamente por separado 1del mismo modo que suponemos que el ;*D *++lean $a sido tambin definido previamente por separado1, se proporciona como par!metro genrico real correspondiente al par!metro genrico formal $ en Pila#$%, obteniendo as como derivaci'n genrica el ;*D Pila#Enter+% que contar!, por tanto, con su propia signatura, la cual est! definida implcitamente a travs del mecanismo de genericidad. De nuevo nos permitimos recordar que un ;*D es un tipo de datos, luego por consiguiente un ;*D es un !lgebra. (or tanto, consta de un conjunto de valores, llamado dominio, un conjunto de operaciones sobre dic$os valores y un conjunto de propiedades de esas operaciones. Aomo estamos viendo, este !lgebra est! definida formalmente mediante una especificaci'n algebraica. La cl!usula FUNCIONES modela el conjunto de operaciones del !lgebra mediante funciones matem!ticas. "sta cl!usula describe las instancias del ;*D no por lo que son, sino por lo que tienen que ofrecer, es decir, por el conjunto de operaciones aplicables sobre ellas. * continuaci'n, vamos a construir los restantes elementos del !lgebra 1el dominio y el conjunto de propiedades de las operaciones1 estudiando para ello cu!l es la sem!ntica de la tcnica de especificaci'n algebraica, tarea para la cual usaremos como ejemplo el ;*D Pila#Enter+%. Cediante la aplicaci'n sucesiva y correcta de las funciones de una signatura se pueden construir trminos sobre ella. *s, crea o bien apila(crea, cima(desapila(apila(apila(crea, -2), 3)))) o bien desapila(apila(apila(apila(crea, 0), 4), -)) o bien cima(desapila(apila(apila(crea, -2), 3))) o bien vaca(desapila(apila(crea, !))) son cinco ejemplos de trminos sobre la signatura del ;*D Pila#Enter+%. La sem!ntica de la tcnica formal de especificaci'n algebraica establece que cada trmino sint!cticamente correcto construido sobre una signatura denota un valor del dominio del ;*D al que pertenece el trmino construido. Aomo es l'gico, un trmino pertenece al ;*D resultado que figura en el perfil de la funci'n m!s e/terna de dic$o trmino. *s, los tres primeros trminos de ejemplo pertenecen al ;*D Pila#Enter+%, por lo que denotan un valor del dominio del ;*D Pila#Enter+%8 sin embargo, el cuarto trmino de ejemplo, por pertenecer al ;*D Enter+, denota un valor del dominio del ;*D Enter+, mientras el quinto trmino de ejemplo, por pertenecer al ;*D *++lean, denota un valor del dominio del ;*D *++lean. * su ve, esta sem!ntica afirma que s'lo pertenecen al dominio de un ;*D aquellos valores que pueden ser generados mediante los trminos sint!cticamente correctos que pertenecen a dic$o ;*D, independientemente de la signatura sobre la que $ayan sido construidos. *s, al igual que el quinto trmino de ejemplo anterior pertenece al ;*D *++lean, tambin puede $aber otros trminos que pertenecan al ;*D Doolean y que $ayan sido construidos sobre otra signatura distinta a la del ;*D Pila#Enter+%. (ara empear, dado que suponemos que el ;*D *++lean $a sido definido de manera correcta previamente por separado, es seguro y cierto que sobre la signatura del propio ;*D *++lean se pueden construir trminos que pertenecen a este ;*D. (or tanto, no necesitamos inventar una notaci'n especial para nombrar los valores del dominio de un ;*D. "l %nombre& de una instancia de un ;*D es simplemente el trmino sint!cticamente correcto que construye dic$o valor del dominio del ;*D mediante la aplicaci'n reiterada de funciones de una signatura. *s, por ejemplo, no es necesario inventar un nombre para el valor del dominio del ;*D Doolean significado por el trmino vaca(crea) dado que el mismo trmino es el nombre de la instancia. *$ora bien, f!cilmente nos encontramos con una nueva situaci'n que obliga a $acer ciertas modificaciones a la sem!ntica vista $asta a$ora. (uede ocurrir que dos trminos sint!cticamente distintos signifiquen el mismo valor seg#n la idea intuitiva que el desarrollador posee acerca del ;*D que est! construyendo. :eamos varios ejemplos con el ;*D Pila#Enter+%. "n el primer ejemplo, el trmino desapila(apila(apila(apila(crea, 0), 4), -)) y el trmino apila(apila(crea, 0), 4) denotan ambos una instancia del ;*D Pila#Enter+% que es una pila en la que est!n apilados los n#meros enteros 4 y E, siendo el elemento de la cima el E y el siguiente y #ltimo elemento el 4. "n el segundo ejemplo, el trmino vaca(desapila(apila(crea, !))) y el trmino vaca(desapila(apila(desapila(apila(crea, 0)), 3))) denotan ambos el valor ,erdader+ del dominio del ;*D *++lean, puesto que en ambos trminos la funci'n vaca se est! aplicando sobre subtrminos sint!cticamente distintos entre s que pertenecen al ;*D Pila#Enter+% y que denotan el mismo valor del dominio del ;*D Pila#Enter+% que es una pila vaca, es decir, que carece de elementos. "n el tercer ejemplo, el trmino cima(desapila(apila(apila(crea, -2), 3))) y el trmino cima(apila(apila(crea, !), -2)) denotan ambos el valor 1B del dominio del ;*D Enter+, ya que en ambos trminos la funci'n cima se est! aplicando sobre un subtrmino tal que el valor del dominio denotado por l es una pila tal que tiene en la cima el n#mero entero 1B. "n este caso, los dos subtrminos, que pertenecen al ;*D Pila#Enter+%, son distintos entre s y adem!s denotan valores distintos del dominio del ;*D Pila#Enter+%. "l primer trmino denota la pila que tiene un #nico elemento, el 1B, que adem!s es el elemento de la cima, mientras que el segundo subtrmino denota la pila que tiene dos elementos, los n#meros enteros 6 y 1B, donde el elemento de la cima es el 1B y el siguiente y #ltimo elemento es el 6. No obstante, no tiene por qu ser as, ya que los dos subtrminos del ;*D Pila#Enter+% sobre los que se aplica la funci'n cima podran denotar el mismo valor del dominio del ;*D Pila#Enter+%. *s ocurre, por ejemplo, con el trmino cima(desapila(apila(apila(crea, -2), 3))) y el trmino cima(apila(crea, -2)) "n todos los ejemplos anteriores, intuitivamente ambos trminos significan el mismo valor del dominio. ,in embargo, la sem!ntica de la tcnica formal de especificaci'n algebraica considera, por defecto, valores distintos a aqullos que se construyen mediante trminos sint!cticamente distintos. (or tanto, necesitamos alg#n mecanismo para poder e/presar la igualdad de valores construidos de modo distinto, es decir, necesitamos alg#n mecanismo para poder e/presar que dos trminos sint!cticamente distintos son equivalentes. "ste mecanismo son los axiomas o ecuaciones que se sit#an en la cl!usula AIO!AS que toda especificaci'n algebraica debe incluir. ,int!cticamente, una ecuaci'n o a/ioma de una especificaci'n algebraica tiene la forma " ! # " 2 siendo t - y t . dos trminos sint!cticamente correctos del mismo tipo de datos, o lo que es lo mismo, del mismo ;*D o que pertenecen al mismo ;*D. ,em!nticamente, un a/ioma e/presa que el trmino t - es equivalente al trmino t . o, lo que es igual, que el valor del dominio de dic$o ;*D construido mediante el trmino t - es el mismo que el valor del dominio del mismo ;*D construido mediante el trmino t . . (ara no tener que escribir infinitas ecuaciones, se admite que los trminos que aparecen en una ecuaci'n tengan variables. Dic$as variables $an de ser de los tipos abstractos de datos apropiados y se acostumbra a declararlas antes del conjunto de ecuaciones. La interpretaci'n de las ecuaciones es, entonces, la de establecer la igualdad de los pares de valores que se obtienen asignando a las variables todos los posibles valores del dominio de su ;*D. "s decir, cada ecuaci'n es una f'rmula l'gica cuantificada universalmente por sus variables. N'tese, finalmente, que las ecuaciones constituyen un conjunto y, por tanto, el orden en que se escriban es irrelevante. No obstante, la tarea de escribir los a/iomas de la especificaci'n algebraica de un ;*D dista muc$o de ser sencilla. "s difcil estar seguros de si las ecuaciones escritas $asta el momento e/presan todas las igualdades que deseamos. -No podra ocurrir que, pese a las ecuaciones, tengamos todava m!s valores en el dominio del ;*D de los debidos0 -A'mo podemos estar seguros de que no $acen falta m!s ecuaciones0 F, igualmente, -c'mo podemos estar seguros de que no sobran ecuaciones0 La realidad es que no e/iste un mtodo e/acto para escribir de manera correcta una especificaci'n algebraica. *$ora bien, partiendo de la idea intuitiva e informal que el desarrollador tiene en su cabea del ;*D que quiere especificar, s vamos a estudiar un mtodo sistem!tico para construir especificaciones algebraicas basado en un conjunto de $eursticas que, en la mayora de los casos, se $an revelado #tiles y que conduce, con gran probabilidad, a que el desarrollador especifique lo que realmente desea y no un ;*D distinto. * la ve que estudiamos este mtodo sistem!tico para desarrollar especificaciones algebraicas vamos a ir profundiando m!s en la sem!ntica de la tcnica formal de este tipo de especificaciones. La sem!ntica de la especificaci'n algebraica de un ;*D establece que e/iste al menos un subconjunto del conjunto formado por las funciones constructoras y de orden de la signatura de dic$o ;*D, cuyos elementos reciben el nombre de funciones generadoras o simplemente generadoras, tal que tiene la propiedad de que s'lo con ellas es posible generar cualquier valor del dominio del ;*D, y e/cluyendo cualquiera de ellas $ay valores del dominio que no pueden ser generados8 es decir, s'lo pertenecen al dominio del ;*D aquellos valores que pueden ser generados mediante trminos sint!cticamente correctos construidos sobre la signatura de dic$o ;*D y formados #nicamente por generadoras. 9n conjunto de generadoras de un ;*D puede ser a su ve libre o no libre. 9n conjunto de generadoras es libre cuando todo trmino sint!cticamente correcto formado #nicamente por ellas denota un valor diferente del dominio del ;*D. 9n conjunto de generadoras es no libre cuando dos o m!s trminos sint!cticamente correctos y distintos formados #nicamente por ellas denotan un mismo valor del dominio del ;*D. "l mtodo sistem!tico para desarrollar especificaciones algebraicas indica que para escribir los a/iomas es necesario escoger un conjunto de generadoras para un ;*D. Dado que puede $aber varios conjuntos posibles de generadoras para un determinado ;*D, siempre es mejor escoger, de e/istir, uno que sea libre, ya que, si el conjunto de generadoras escogido para escribir las ecuaciones de la especificaci'n algebraica del ;*D no es libre, en la cl!usula AIO!AS ser! necesario escribir las correspondientes ecuaciones entre generadoras, que e/presan la equivalencia entre trminos formados e/clusivamente por funciones generadoras.
*dem!s de escribir las ecuaciones entre generadoras, si son necesarias, $ay que escribir, para cada funci'n constructora o de orden que no est en el conjunto de generadoras, tantas ecuaciones como sean necesarias para que quede completamente especificado lo que la funci'n devuelve cuando es aplicada a una instancia arbitraria creada por las generadoras, garantiando que todo trmino que tiene a esta funci'n como la m!s e/terna es equivalente a alg#n trmino formado #nicamente por generadoras. ;ambin es necesario escribir, para cada funci'n de consulta, tantas ecuaciones como sean necesarias para que quede completamente especificado lo que la funci'n devuelve cuando es aplicada a una instancia arbitraria creada por las generadoras, garantiando en este caso que todo trmino que tiene a esta funci'n como la m!s e/terna es equivalente a alg#n trmino cuya funci'n m!s e/terna es una constructora o una orden del ;*D resultado de la consulta. "sta garanta tiene un doble objetivo: por un lado no introducir nuevos valores en el dominio del ;*D resultado de la consulta y, por otro lado, no $acer iguales valores del dominio del ;*D resultado de la consulta que antes no lo eran. (ara cada funci'n para la que $ay que escribir ecuaciones, a veces una ecuaci'n bastar! y otras ser!n necesarias varias. 9na estrategia que suele funcionar es poner la funci'n como la m!s e/terna de un trmino, y descomponer cada argumento del ;*D que se define en la especificaci'n en todos sus posibles patrones formados con las generadoras. Los trminos as construidos se igualan a trminos derec$os en los que la funci'n ya no es la m!s e/terna. "ste tipo de ecuaciones pueden considerarse, ledas de iquierda a derec$a, como reglas de reescritura que permiten reducir, en un n#mero finito de pasos, un trmino que contiene una funci'n a otro en el que sta no figura. "n ocasiones, una funci'n puede especificarse e/clusivamente en trminos de otra u otras funciones de su misma categora, sin que aparecan en las ecuaciones las generadoras del ;*D que se define en la especificaci'n. ,e dice entonces que se trata de una funcin derivada. (or tanto, podemos concluir de nuestro estudio de la sem!ntica de la tcnica formal de especificaci'n algebraica que todos los valores del dominio del ;*D son alcanables a partir de sus funciones generadoras, y que dos trminos construidos sobre la signatura de dic$o ;*D son equivalentes si y s'lo si su equivalencia puede deducirse de las ecuaciones. *unque $emos utiliado como ejemplo en esta e/posici'n el ;*D Pila#Enter+%, que es un ;*D derivado genricamente de Pila#$%, las conclusiones e/tradas son independientes de $, y de $ec$o, la naturalea del ;*D Enter+ no $a influido en la argumentaci'n. (or ello, las conclusiones son aplicables al ;*D genrico y no s'lo a una de sus derivaciones genricas. 3.$.- Construccin de la especificacin foral de un TAD "l conjunto de generadoras obvio para el ;*D Pila#$% es el formado por crea y apila, ya que con estas dos funciones es posible generar cualquier pila imaginable. *dem!s, estas dos funciones forman un conjunto libre de generadoras, puesto que, en efecto, toda aplicaci'n de apila produce una pila distinta a la que ya e/ista y todas ellas son distintas de la pila vaca producida por crea. No $acen falta, por tanto, ecuaciones entre generadoras. (ara escribir las ecuaciones asociadas al resto de las funciones, se realia un an!lisis por casos sobre los patrones posibles del argumento de tipo Pila#$%. "ste argumento, que representa cualquier pila posible, o bien es una pila vaca y entonces tendr! la forma crea, o bien es una pila no vaca y entonces tendr! la forma apila&p' () para alguna pila ya e/istente p y alg#n elemento ( que se desee apilar. *s, por tanto, las ecuaciones para vaca son: Para c$al%$ier &:G, p:Pila[G], vaca(crea) # 'erdadero vaca(apila(p, &)) # (also "stas ecuaciones son l'gicas y nos dicen cu!ndo est! o no vaca una pila: una pila resultante de la constructora1generadora crea est! vaca8 toda pila resultado de la orden1generadora apila que inserta un elemento en alguna pila e/istente <vaca o no= no est! vaca. La especificaci'n de cualquier ejemplo realista, incluso tan b!sico como las pilas, debe encontrarse con el problema de las operaciones indefinidas: algunas operaciones no son aplicables a todos los elementos de sus conjuntos origen. Gste es el caso de desapila y de cima: no se puede quitar un elemento de una pila vaca8 y una pila vaca no tiene cima. La soluci'n utiliada en las especificaciones algebraicas consiste en modelar estas operaciones como funciones parciales. 9na funcin matemtica de un conjunto origen a un conjunto destino / es parcial si no est! definida para todos los miembros de . 9na funci'n que no es parcial se denomina total. "l dominio de una funci'n parcial es el subconjunto de que contiene aquellos elementos para los cuales la funci'n proporciona un valor. La especificaci'n del ;*D Pila#$% aplica estas ideas a las pilas declarando desapila y cima como funciones parciales en el p!rrafo FUNCIONES, tal y como se indica mediante la flec$a discontinua que aparece en sus respectivos perfiles, mientras que la flec$a continua se reserva para las funciones totales. "sto plantea un nuevo problema: c'mo especificar el dominio de estas funciones parciales. Las funciones parciales son un $ec$o del que uno no puede evadirse en la vida del desarrollo del soft)are, ya que reflejan simplemente la observaci'n de que no toda operaci'n es aplicable a cualquier valor. (ero son tambin una fuente potencial de errores: si 0 es una funci'n parcial de en /, no se puede estar seguro de si la e/presi'n 0&() tiene o no sentido aunque el valor de ( est en : tambin tenemos que ser capaces de garantiar que el valor de ( pertenece al dominio de 0. (ara que esto sea posible, cualquier especificaci'n de un ;*D que incluya funciones parciales debe especificar el dominio de cada una de ellas. Gste es el papel del p!rrafo P"ECONDICIONES. (ara el caso de Pila#$% el p!rrafo sera: PRECONDICIONES desapila(p:Pila[G]) require vaca(p) ) (also cima(p:Pila[G]) require vaca(p) ) (also en donde, para cada funci'n, la palabra reservada re1uire indica qu condiciones tienen que satisfacer los argumentos de las funciones para pertenecer al dominio de las funciones. La e/presi'n booleana que define el dominio se llama precondici'n de la funci'n parcial correspondiente. *qu la precondici'n tanto de desapila como de cima e/presa que la pila que se d como argumento no debe estar vaca. *ntes de la palabra reservada re1uire viene el nombre de la funci'n con nombres para los argumentos <p para el argumento Pila#$% en el ejemplo=, de modo que la precondici'n se pueda referir a stos. N'tese la diferencia entre la operaci'n de igualdad ) y la equivalencia algebraica entre trminos # ya que las ecuaciones de la especificaci'n indican equivalencias entre trminos mientras que la operaci'n de igualdad es una operaci'n m!s 1en este caso infija a diferencia de las dem!s descritas que son prefijas1 que devuelve una instancia del ;*D *++lean, de modo que los trminos construidos por ella ser!n equivalentes algebraicamente a 'erdadero o (also. *s, en cada una de las precondiciones anteriores, la cl!usula re1uire indica, como es l'gico, que el trmino que aparece a continuaci'n $a de ser equivalente algebraicamente a 'erdadero. Catem!ticamente, la precondicin de una funci'n 0 es la funcin caracterstica del dominio de 0. La funci'n caracterstica de un subconjunto A de un conjunto es la funci'n total c: * +'erdadero, (also, tal que c&() es ,erdader+ si ( pertenece a A, y Fals+ en caso contrario. *$ora que ya $emos establecido la precondici'n de las funciones parciales, podemos escribir el resto de los a/iomas de la especificaci'n, que son los que corresponden a desapila y cima. Dado que los a/iomas solamente $acen equivalentes trminos definidos, al $acer el an!lisis por casos sobre los patrones posibles del argumento de tipo Pila#$% s'lo se considerar!n, en el caso de las ecuaciones que involucran funciones parciales, aquellos patrones que den lugar a trminos definidos, donde la condici'n para que el trmino est definido es precisamente la e/presada en la precondici'n. (or tanto, las ecuaciones que corresponden a desapila y cima son #nicamente las que se aplican sobre el argumento que es una pila no vaca y que entonces tiene la forma apila&p' () para alguna pila ya e/istente p y alg#n elemento ( que se desee apilar. *s, por tanto, las ecuaciones para desapila y cima son: Para c$al%$ier &:G, p:Pila[G], desapila(apila(p, &)) # p cima(apila(p, &)) # & ,e puede observar que el comportamiento intuitivo de las pilas est! reflejado en estas dos #ltimas ecuaciones: la cima de una pila no vaca es el #ltimo elemento apilado, y al despilar una pila no vaca desaparece el #ltimo elemento apilado. La especificaci'n completa es: TIPO Pila[G] FUNCIONES apila: Pila[G] x G Pila[G] desapila: Pila[G] Pila[G] cima: Pila[G] G vaca: Pila[G] Boolean crea: Pila[G] AXIOMAS Para c$al%$ier &:G, p:Pila[G], desapila(apila(p, &)) # p cima(apila(p, &)) # & vaca(crea) # 'erdadero vaca(apila(p, &)) # (also PRECONDICIONES desapila(p:Pila[G]) require vaca(p) ) (also cima(p:Pila[G]) require vaca(p) ) (also 3.%.- Conclusiones 7aciendo una recapitulaci'n del trayecto recorrido, $emos visto c'mo un ;*D es un tipo de datos, y por tanto un !lgebra. 7emos establecido que este !lgebra est! definida formalmente mediante una especificaci'n algebraica. "sta definici'n del ;*D es implcita en dos sentidos: 7emos definido las operaciones del !lgebra mediante la cl!usula FUNCIONES de la especificaci'n algebraica, que modela el conjunto de operaciones del !lgebra mediante funciones matem!ticas. "sta cl!usula describe las instancias del ;*D no por lo que son, sino por lo que tienen que ofrecer, es decir, por el conjunto de operaciones aplicables sobre ellas, de modo que podemos afirmar que la definici'n de las instancias del ;*D tiene la cualidad de ser implcita. "sta cualidad de la definici'n de las instancias de un ;*D a travs de su especificaci'n algebraica se confirma de nuevo cuando despus $emos definido el dominio del !lgebra precisamente en trminos de estas operaciones. (osteriormente para esta tarea de definir el dominio del ;*D $emos necesitado definir el conjunto de propiedades que verifican las operaciones del !lgebra mediante la cl!usula AIO!AS de la especificaci'n algebraica. Lo que realmente est! $aciendo esta cl!usula es definir las funciones tambin de manera implcita: en lugar de definiciones e/plcitas se utilian a/iomas que describen las propiedades de las funciones. La potencia de las especificaciones de los tipos abstractos de datos proviene de su capacidad para captar las propiedades esenciales de los tipos de datos sin incurrir en una especificaci'n e/cesiva. La especificaci'n anterior de una pila cualquiera e/presa todo lo que $ay que saber acerca de la noci'n de pila en general, e/cluyendo todo lo que pueda ser aplicable a alguna representaci'n concreta de las pilas. ;oda la verdad respecto a las pilas, pero nada m!s que la verdad. "sto proporciona un modelo general de computaci'n con tipos de datos denominado c!lculo ecuacional. ,e pueden describir secuencias complejas de operaciones mediante e/presiones matem!ticas que goan de las propiedades $abituales del !lgebra: y se puede ver el proceso de llevar a cabo el c'mputo como un proceso de simplificaci'n algebraica. "sto es debido a que las funciones definidas en la especificaci'n de un ;*D permiten construir trminos posiblemente complejos que pueden verse como e/presiones matem!ticas, y los a/iomas del ;*D permiten simplificar tales e/presiones para generar un resultado m!s sencillo. 9na e/presi'n, sea compleja o no, de una pila cualquiera es el equivalente matem!tico de un programa8 el proceso de simplificaci'n es el equivalente matem!tico de un c'mputo, es decir, de la ejecuci'n de dic$o programa. :eamos un ejemplo, utiliando de nuevo Pila#Enter+% como derivaci'n genrica de Pila#$%. "s posible, a partir de la especificaci'n vista antes, escribir el siguiente trmino complejo: cima( desapila( apila( desapila( apila( apila( desapila( apila( ap ila( apila( crea, !), 2), 3)), cima( desapila( apila( apila( crea, 4), )))), -)), .))) ,e puede ver este trmino como una e/presi'n matem!tica que vamos a simplificar utiliando los a/iomas del ;*D. *plicando el primer a/ioma sobre la e/presi'n anterior, se simplifica a la siguiente e/presi'n: cima( desapila( apila( desapila( apila( apila( desapila( apila( ap ila( apila( crea, !), 2), 3)), cima( apila( crea, 4))), -)), .))) *plicando el segundo a/ioma sobre la e/presi'n anterior, se simplifica a la siguiente e/presi'n: cima( desapila( apila( desapila( apila( apila( desapila( apila( ap ila( apila( crea, !), 2), 3)), 4), -)), .))) *plicando el primer a/ioma sobre la e/presi'n anterior, se simplifica a la siguiente e/presi'n: cima( desapila( apila( desapila( apila( apila( apila( apila( crea, !), 2), 4), -)), .))) *plicando el primer a/ioma sobre la e/presi'n anterior, se simplifica a la siguiente e/presi'n: cima( desapila( apila( apila( apila( apila( crea, !), 2), 4), .))) *plicando el primer a/ioma sobre la e/presi'n anterior, se simplifica a la siguiente e/presi'n: cima( apila( apila( apila(crea, !), 2), 4)) *plicando el segundo a/ioma sobre la e/presi'n anterior, se simplifica a la siguiente e/presi'n: 4 *plicando una secuencia de simplificaciones, llevadas a cabo tan simple y mec!nicamente como las simplificaciones de la aritmtica elemental gracias a las reglas de reescritura que proporciona la especificaci'n mediante los a/iomas, obtenemos el valor de la e/presi'n, que es precisamente el n#mero entero E. "ste ejemplo da una visi'n de uno de los principales papeles te'ricos de los tipos abstractos de datos: brindar un model formal del concepto de programa y de la ejecuci'n de programas. "ste modelo es puramente matem!tico: no tiene ninguno de los conceptos imperativos de estado de programa, variables cuyos valores puedan cambiar con el tiempo, o del orden en que se efect#a la ejecuci'n. ,e basa en las tcnicas est!ndar de evaluaci'n de e/presiones de la matem!tica ordinaria. $.- &undaentos de la ipleentacin de un tipo abstracto de datos $.1.- Conceptos "enerales b#sicos de la ipleentacin de un TAD ;enemos como punto de partida una elegante teora matem!tica para el modelado de tipos de datos y, de $ec$o, como se $a visto al final del apartado anterior, del concepto de programa en general y tambin del concepto de la ejecuci'n de un programa. (ero el tema de trabajo aqu es la arquitectura del soft)are, no la matem!tica, ni siquiera la ciencia de la computaci'n o inform!tica te'rica, as que podemos preguntarnos si nos $emos desviado de nuestro camino. La respuesta a esa pregunta es que no muc$o. "n la b#squeda de una buena forma de describir los objetos, los tipos abstractos de datos proporcionan un mecanismo de descripci'n de alto nivel, por tanto libre de cuestiones de implementaci'n. *$ora es el momento de estudiar la implementaci'n de un tipo abstracto de datos, lo que a su ve nos va a llevar a las estructuras fundamentales del mtodo orientado a objetos. Auando se $abla de especificaci'n de un ;*D y de implementaci'n de un ;*D parece que el propio ;*D se divide en dos partes diferenciadas: por un lado su especificaci'n y por otro lado su implementaci'n. "sto no es as realmente. , es cierto que en el desarrollo de un sistema soft)are real es necesario tanto desarrollar la especificaci'n de un ;*D como al menos una implementaci'n suya, pero en realidad esto lo que significa es que no estamos ante un #nico tipo de datos sino ante dos tipos de datos distintos pero relacionados entre s. "l TAD viene definido por su especificaci'n algebraica y se llama tipo implementado, mientras que una implementaci'n de ese ;*D es un tipo de datos distinto al ;*D y se llama tipo implementador. Aomo es l'gico, es necesario garantiar que una implementaci'n de un ;*D es correcta8 es decir, es necesario garantiar que el tipo implementador implementa correctamente el tipo implementado. *$ora bien, lo que ocurre en el desarrollo soft)are real es que el tipo implementado, el ;*D, se da o se define mediante una especificaci'n algebraica, mientras que el tipo implementador se da o se define mediante un m'dulo soft)are. "so complica la comparaci'n entre ambos porque se trata de diferentes lenguajes matem!ticos. No obstante, el objetivo sigue siendo claro: garantiar que el tipo implementador implementa correctamente el tipo implementado. (ara que la implementaci'n sea correcta, se requieren ciertas condiciones matem!ticas que en esencia dicen que el tipo implementador guarda una relaci'n $omom'rfica con el tipo implementado8 es decir, que el tipo implementador simula adecuadamente el tipo implementado, o lo que es lo mismo, que el m'dulo soft)are implementador define un !lgebra que simula adecuadamente el !lgebra definida por la especificaci'n algebraica. "n definitiva, para que una implementaci'n sea correcta debe conservar las propiedades de la especificaci'n que dice implementar. Hntuitivamente, implementar un ;*D consiste en: ,imular o representar los valores del tipo a implementar, el ;*D, por medio de valores del tipo implementador. ,imular las operaciones del tipo a implementar mediante operaciones del tipo implementador. Hnformalmente, una implementaci'n es correcta cuando el usuario del tipo implementador no es capa de notar la diferencia entre el tipo de datos realmente especificado, el ;*D, y el tipo de datos implementador que lo simula. (ara garantiar que una implementaci'n de un ;*D es correcta, $ay que establecer una correspondencia entre los valores del tipo de datos implementado, el ;*D, y los del tipo de datos implementador utiliado para simular aqul. "sta correspondencia se llama funci'n de abstracci'n. La funcin de abstraccin es una aplicaci'n que establece una correspondencia entre el tipo implementador y el tipo implementado 1es decir, establece una correspondencia entre el !lgebra de la implementaci'n y el !lgebra de la especificaci'n1 de tal modo que a cada valor del dominio del tipo implementador le $ace corresponder a lo sumo un valor del dominio del tipo implementado. La inversa de la funci'n de abstracci'n, que se llama relacin de representacin, no es una funci'n dado que en general a un valor del dominio del tipo implementado le pueden corresponder varios valores del dominio del tipo implementador. "n general, las caractersticas de la funci'n de abstracci'n son las siguientes: "s parcial, ya que no todo valor del dominio del tipo implementador representa un valor del dominio del tipo implementado. (or tanto, se puede decir que el tipo implementador tiene valores basura en su dominio desde el punto de vista del tipo implementado. ,e llama invariante de la representacin o invariante de la implementacin a la aserci'n que define las condiciones l'gicas que debe cumplir un valor del dominio del tipo implementador para representar un valor del dominio del tipo implementado. "n trminos matem!ticos, el invariante de la representaci'n es la funci'n caracterstica del dominio de la funci'n de abstracci'n, es decir, la propiedad que define cu!ndo dic$a funci'n es aplicable. ,e define entonces el conjunto de representantes vlidos -o conjunto de valores vlidos- del tipo implementador como el conjunto formado por aquellos valores del dominio del tipo implementador que satisfacen el invariante de la representaci'n. "l invariante de la representaci'n $a de ser respetado por todas las operaciones del tipo implementador en dos sentidos: en primer lugar, las operaciones del tipo implementador s'lo est!n obligadas a funcionar correctamente sobre representantes v!lidos de dic$o tipo y, en segundo lugar, las operaciones del tipo implementador que generen valores del dominio de dic$o tipo deben comprometerse a que stos sean siempre representantes v!lidos. Aada valor v!lido del tipo implementador es un ejemplar o instancia del mismo. 9n valor v!lido del tipo implementador es una estructura de datos, es decir, una representaci'n fsica en la memoria del computador, y que por tanto puede ser creada y manipulada por un sistema soft)are durante su ejecuci'n, de un valor del dominio del tipo implementado, es decir, del ;*D que implementa el tipo implementador. "s sobreyectiva, ya que a todo valor del dominio del tipo implementado le corresponde al menos un valor del dominio del tipo implementador8 es decir, todos los valores del tipo implementado, del ;*D, se pueden representar con la implementaci'n escogida. No es necesariamente inyectiva, ya que varios valores del dominio del tipo implementador pueden representar el mismo valor del dominio del tipo implementado. Aonsecuentemente, la funci'n de abstracci'n induce una relaci'n de equivalencia que se llama equivalencia de representacin y que agrupa en cada clase los valores del dominio del tipo implementador que se corresponden con el mismo valor del dominio del tipo implementado. $.2.- 'elacin entre la ipleentacin de un TAD y el (todo orientado a ob)etos La teora formal de los tipos abstractos de datos es la base te'rica del mtodo orientado a objetos. De $ec$o, los tipos abstractos de datos sirven como base directa de los m'dulos que se necesitan en el mtodo orientado a objetos. C!s precisamente, un sistema softare orientado a objetos se construir! 1en el nivel de an!lisis, dise+o e implementaci'n1 como una colecci'n de tipos abstractos de datos parcial o totalmente implementados que interact#an entre s. *$ora bien, el concepto b!sico en el mtodo orientado a objetos es el de clase. :amos a ver entonces c'mo se relaciona el concepto de tipo abstracto de datos con el de clase. 9na clase es un m'dulo soft)are que define, qui! de forma parcial, un tipo implementador8 o, lo que es lo mismo, una clase es un m'dulo soft)are que define una implementaci'n, que puede ser parcial, de un tipo abstracto de datos. Aomo ya vimos, puede $aber varias implementaciones distintas de un ;*D, por lo que puede $aber entonces varias clases distintas que implementen el mismo ;*D. De modo que para obtener una clase se debe proporcionar un ;*D y $ay que decidir una implementaci'n para el mismo. ,in embargo, la definici'n establece que la implementaci'n puede ser parcial. La terminologa siguiente separa este caso de las clases que est!n completamente implementadas: 9na clase que est! completamente implementada define una implementaci'n completa de un tipo abstracto de datos y se denomina efectiva. 9na clase que est! implementada s'lo parcialmente define una implementaci'n parcial de un tipo abstracto de datos y se denomina abstracta o diferida. 9na clase puede ser o bien efectiva o bien diferida. (ara obtener una clase efectiva, se deben dar todos los detalles de la implementaci'n. (ara una clase diferida, se puede escoger un cierto estilo de implementaci'n pero dejar abiertos algunos aspectos de la misma. "n el caso m!s e/tremo de implementaci'n parcial puede uno abstenerse de tomar ninguna decisi'n de implementaci'n, por lo que la clase resultante ser! completamente diferida. ,eg#n lo visto, podemos definir la construccin de softare orientado a objetos como el mtodo de desarrollo de soft)are que basa la arquitectura de cualquier sistema soft)are en una colecci'n estructurada de implementaciones, que pueden ser parciales, de tipos abstractos de datos. La colecci'n de implementaciones que conforman un sistema soft)are orientado a objetos es estructurada gracias a dos relaciones entre clases: cliente y $erencia. "n el mtodo orientado a objetos se produce la fusi'n de dos conceptos, el de m'dulo soft)are y el de tipo de datos, dando lugar al concepto de clase que engloba a ambos. :amos a ver c'mo. ;oda clase es un m'dulo, como se $a visto, luego una clase puede ser vista como un m'dulo de tal modo que el nombre del m'dulo es el de la clase. La clase, como m'dulo, es la unidad b!sica de descomposici'n de un sistema soft)are orientado a objetos y proporciona a otros m'dulos distintos a ella 1es decir, otras clases1 una serie de facilidades relacionadas. * la ve, como toda clase define un tipo de datos implementador 1de forma semejante a como una especificaci'n algebraica define un ;*D o tipo de datos implementado1, podemos decir que toda clase es un tipo de datos, de modo que una clase puede ser vista como un tipo de datos de tal modo que el nombre del tipo de datos es el de la clase. (or tanto, una clase puede verse desde dos perspectivas diferentes pero complementarias: como m'dulo soft)are y como tipo de datos, de modo que la fusi'n m'dulo1tipo se produce debido a que las facilidades relacionadas que proporciona la clase, vista como m'dulo, constituyen a su ve la definici'n de la clase, vista como tipo de datos. "s decir, la clase, vista como m'dulo, es quien se define a s misma vista como tipo de datos8 o, de forma a#n m!s simple, el m'dulo define el tipo de datos.. Aomo $emos visto, una clase es un tipo de datos y, adem!s, es un tipo implementador, por lo que podemos aplicar al mtodo orientado a objetos los conceptos b!sicos generales vistos en el apartado anterior sobre implementaci'n de tipos abstractos de datos. (ara garantiar que una clase es una implementaci'n correcta de un ;*D, en primer lugar $ay que establecer una correspondencia entre los valores del tipo implementado, el ;*D, y los de la clase utiliada para simular aqul. "sta correspondencia se llama funci'n de abstracci'n. L a funcin de abstraccin es una aplicaci'n que establece una correspondencia entre la clase 1como tipo implementador1 y el ;*D 1como tipo implementado1, de tal modo que a cada valor del dominio de la clase le $ace corresponder a lo sumo un valor del dominio del ;*D. La inversa de la funci'n de abstracci'n, que se llama relacin de representacin, no es una funci'n dado que en general a un valor del dominio del ;*D le pueden corresponder varios valores del dominio de la clase. "n general, las caractersticas de la funci'n de abstracci'n son las siguientes: "s parcial, ya que no todo valor del dominio de la clase representa un valor del dominio del ;*D. (or tanto, se puede decir que la clase tiene valores basura en su dominio desde el punto de vista del ;*D. ,e llama invariante de la representacin o invariante de la implementacin a la aserci'n que define las condiciones l'gicas que debe cumplir un valor del dominio de la clase para representar un valor del dominio del ;*D. "n trminos matem!ticos, el invariante de la representaci'n es la funci'n caracterstica del dominio de la funci'n de abstracci'n, es decir, la propiedad que define cu!ndo dic$a funci'n es aplicable. ,e define entonces el conjunto de representantes vlidos -o conjunto de valores vlidos- de la clase como el conjunto formado por aquellos valores del dominio de la clase que satisfacen el invariante de la representaci'n. "l invariante de la representaci'n $a de ser respetado por todas las rutinas de la clase en dos sentidos: en primer lugar, las rutinas de la clase s'lo est!n obligadas a funcionar correctamente sobre representantes v!lidos de dic$a clase y, en segundo lugar, las rutinas de la clase que generen valores del dominio de la clase deben comprometerse a que stos sean siempre representantes v!lidos. Aada valor v!lido de la clase es un ejemplar o instancia de la misma, y recibe el nombre de objeto. (or tanto, un objeto es un ejemplar o instancia de una clase, es decir, una estructura de datos o representaci'n fsica en la memoria del computador, y que por tanto puede ser creada y manipulada por un sistema soft)are durante su ejecuci'n, de un valor del dominio del ;*D que implementa la clase de ese objeto. "s sobreyectiva, ya que a todo valor del dominio del ;*D le corresponde al menos un valor del dominio de la clase8 es decir, todos los valores del ;*D se pueden representar con la implementaci'n escogida. No es necesariamente inyectiva, ya que varios valores del dominio de la clase pueden representar el mismo valor del dominio del ;*D. Aonsecuentemente, la funci'n de abstracci'n induce una relaci'n de equivalencia que se llama equivalencia de representacin y que agrupa en cada clase de equivalencia los valores del dominio de la clase que se corresponden con el mismo valor del dominio del ;*D. Aomo es l'gico, que la funci'n de abstracci'n sea funci'n es un requisito universal: si el mismo objeto pudiera interpretarse como que representa a m!s de un valor del dominio del ;*D, entonces la representaci'n escogida sera ambigua y por consiguiente inadecuada. La definici'n de clase genera como subproducto, por tanto, la definici'n de objeto. (odemos concluir tambin que los te/tos de soft)are que sirven para producir los sistemas soft)are son las clases. Los objetos son s'lo un concepto relativo al tiempo de ejecuci'n ya que son creados y manipulados por el sistema soft)are durante su ejecuci'n. (or tanto, al igual que un ;*D, una clase es un tipo de datos. Aomo ya estudiamos, los tipos abstractos de datos, como las clases, tienen instancias: la diferencia es que una instancia de un ;*D es un elemento puramente matem!tico 1ya que es un miembro de alg#n conjunto matem!tico1, mientras que una instancia de una clase es una estructura de datos que puede ser creada y manipulada por un sistema soft)are. *$ora es necesario estudiar c'mo implementar de forma correcta un tipo abstracto de datos mediante el mtodo orientado a objetos. (ara ello, usaremos el lenguaje de programaci'n orientado a objetos Iava. *unque es verdad que no e/iste un mtodo e/acto para escribir, a partir de una especificaci'n algebraica de un ;*D, una clase que implemente este ;*D correctamente, s que e/iste un mtodo sistem!tico basado en un conjunto de $eursticas para construir implementaciones correctas de un ;*D a partir de su especificaci'n. "ste mtodo sistem!tico se fundamenta en el Dise!o por "ontrato, abreviado Dp" 1en ingls el acr'nimo es DbC, de Desi2n by C+ntract1, que fue definido por Dertrand Ceyer, creador del lenguaje "iffel. %.- &undaentos tericos del Diseo por Contrato %.1.- *ntroduccin Aomo ya $emos comentado, nuestro tema de trabajo es la arquitectura del soft)are en general y escribir sistemas soft)are correctos y robustos en particular. "l estudio de los tipos abstractos de datos no nos $a alejado demasiado de nuestro objetivo y s que nos $a proporcionado una serie de pistas sobre c'mo mejorar notablemente la correcci'n y robuste de las aplicaciones que desarrollamos. "s frecuente comprobar que no se presta debida atenci'n a la sem!ntica de las clases de un sistema soft)are. La necesidad de poner m!s atenci'n a las propiedades sem!nticas de las clases quedar! particularmente clara si se recuerda c'mo se definen las clases: como implementaciones de tipos abstractos de datos. Lo $abitual es que las clases consten simplemente de atributos y mtodos, que de $ec$o representan a las funciones de la especificaci'n de un ;*D. (ero un ;*D es algo m!s que una lista de operaciones disponibles: recurdese el papel que desempe+aban las propiedades sem!nticas, que se e/presan como a/iomas y precondiciones. Gstas son esenciales para captar la verdadera naturalea de las instancias de un ;*D. "sas clases que s'lo contienen atributos y mtodos pierden el aspecto sem!ntico del concepto de ;*D y es necesario introducirlo en el mtodo orientado a objetos para tener soft)are que no solamente sea fle/ible y reutiliable, sino tambin correcto y robusto. Lo primero que $abra que preguntarse es qu significa que un elemento soft)are sea correcto. (ara considerar significativa la pregunta se necesita tener no s'lo el elemento soft)are sino tambin una descripci'n precisa de lo que se supone que ste debe $acer, es decir, una especificaci'n. "s decir, un elemento soft)are no puede decirse que sea correcto o incorrecto por s mismo, sino que es correcto o incorrecto con respecto a cierta especificaci'n. "strictamente $ablando, no se debera discutir sobre si un elemento soft)are es o no correcto, sino sobre si es consistente con su especificaci'n. No obstante, se seguir! utiliando el trmino bien aceptado de %correcci'n& pero siempre se debe recordar que la pregunta de si es correcto no se aplica a elementos soft)are: se aplica a pares formados por un elemento soft)are y una especificaci'n. (or tanto, la correcci'n es un concepto relativo. :amos a aprender la forma de e/presar la especificaci'n de un elemento soft)are para ayudar a establecer la correcci'n del mismo. (ara e/presar dic$a especificaci'n usaremos aserciones. Aomprobaremos adem!s que el simple $ec$o de escribir la especificaci'n es un primer paso precioso $acia asegurar que el soft)are va a satisfacer realmente esa especificaci'n. (or tanto, se obtendr!n tremendos beneficios si se escriben las aserciones al mismo tiempo que se escribe el soft)are 1o incluso antes de escribir el soft)are. "ntre las consecuencias se pueden citar las siguientes: (roducir soft)are que es correcto desde el principio debido a que est! dise+ado para ser correcto. "l ttulo de un artculo escrito por 7arlan D. Cills <uno de los creadores de la %(rogramaci'n "structurada&= en los setenta proporciona la idea correcta: 3C4m+ escribir pr+2ramas c+rrect+s y saberl+5 (or %saberlo& se entiende equipar al soft)are, a la ve que se escribe ste, con los argumentos que pueden demostrar que es correcto. Ffrecer una comprensi'n muc$o mejor del problema y de sus soluciones finales. Jacilitar la tarea de la documentaci'n del soft)are. ,entar las bases para una demostraci'n y depuraci'n sistem!ticas. %.2.- Co e+presar una especificacin Las observaciones informales anteriores se pueden convertir en una notaci'n matem!tica simple, tomada de la teora de la verificaci'n formal de programas, y muy valiosa para raonar sobre la correcci'n de los elementos soft)are. ,ea A un cierto elemento soft)are de un sistema soft)are, como por ejemplo un mtodo o inclusive una #nica instrucci'n. 9na frmula de correccin, tambin denominada Tripleta de #oare, es una e/presi'n de la forma: $%& A $'& que denota la propiedad siguiente, que puede ser cierta o no: (na ejecucin de A que comience en un estado de ejecucin en el que se cumple % terminar en un estado de ejecucin en el que se cumple ') Las f'rmulas de correcci'n son una notaci'n matem!tica, no forman parte de un lenguaje de programaci'n, sino que s'lo est!n dise+adas para ayudarnos a e/presar las propiedades sem!nticas de los elementos soft)are. 9n estado de ejecucin de un sistema soft)are es el conjunto formado por los valores de todas las entidades alcanables de dic$o sistema soft)are en un momento dado de su ejecuci'n. P y 6 son aserciones. 9na asercin es una e/presi'n booleana que involucra algunas entidades de un sistema soft)are y que establece una propiedad l'gica que dic$as entidades deben satisfacer en uno o m!s estados de ejecuci'n. 9na tpica aserci'n puede ser la que e/presa que un entero es positivo o la que e/presa que una referencia no es vaca. Catem!ticamente, el concepto m!s cercano es el de predicado. De las dos aserciones, P se denomina precondicin y 6 postcondicin. ,i un estado de ejecuci'n cumple una aserci'n, se dice que dic$o estado de ejecuci'n satisface dic$a aserci'n. 9na aserci'n * 6 implica otra aserci'n * B o, lo que es lo mismo, una aserci'n * B es consecuencia l'gica de otra aserci'n * 6 si y s'lo si todo estado de ejecuci'n que satisface * 6 tambin satisface * B . De forma semejante, dos aserciones son equivalentes si las satisfacen los mismos estados de ejecuci'n. *$ora bien, en lugar de $ablar de los estados de ejecuci'n que satisfacen una aserci'n, podemos $ablar de forma completamente equivalente de los estados de ejecuci'n definidos por una aserci'n, de modo tal que toda aserci'n define un conjunto de estados de ejecuci'n formado por todos aquellos estados que la satisfacen. De este modo, la propiedad denotada por la f'rmula de correcci'n, que puede ser cierta o no, es interpretada del siguiente modo: (na ejecucin de A que comience en un estado de ejecucin definido por % terminar en un estado de ejecucin definido por ') * partir de esta segunda interpretaci'n de una f'rmula de correcci'n, es inmediato que se puede considerar que, en una ;ripleta de 7oare, un elemento soft)are A implementa una relaci'n parcial r del conjunto de posibles estados de entrada E en el conjunto de estados de salida S, tal que: La precondici'n especifica el dominio D+m de r, o sea, el subconjunto de E en el cual se garantia que r devuelve un resultado. La postcondici'n especifica, para cada elemento ( de D+m, un subconjunto de S K "esultad+s&()1, tal que r&() "esultad+s&(). "ste subconjunto puede tener m!s de un elemento, ya que una postcondici'n no tiene por qu definir el resultado unvocamente8 as, un estado de salida puede no ser #nico para un estado de entrada v!lido. "n este caso, A cumple la especificaci'n si termina en cualquiera de los estados permitidos o, incluso, si es no determinista y termina aleatoriamente en cualquiera de ellos. Auanto mayor sea el conjunto de estados que define una aserci'n, diremos que m!s dbil es dic$a aserci'n. * la inversa, cuanto menor sea el conjunto de estados que define, diremos que m!s fuerte es la aserci'n. ,e dice que la aserci'n * 6 es m!s fuerte que otra aserci'n * B o, lo que es lo mismo, una aserci'n * B es m!s dbil que otra aserci'n * 6 si y s'lo si el conjunto de estados definido por * 6 est! incluido en el conjunto de estados definido por * B . Fbviamente, la aserci'n * 6 es m!s fuerte que la aserci'n * B si y s'lo si * 6 implica * B 8 de forma semejante, la aserci'n * B es m!s dbil que la aserci'n * 6 si * B es consecuencia l'gica de * 6 . (or todo ello, la aserci'n Fals+ es la m!s fuerte posible ya que define el conjunto vaco de estados o, lo que es equivalente, implica cualquier otra aserci'n8 de forma semejante, la aserci'n ,erdader+ es la m!s dbil posible ya que define el conjunto de todos los estados posibles o, lo que es equivalente, es consecuencia l'gica de cualquier otra aserci'n. *s, la f'rmula de correcci'n 7Fals+8 A 768 ' para cual1uier 6 es la panacea perfecta para quien tiene que desarrollar A. La postcondici'n se $a dejado sin concretar porque no importa cu!l sea. "n general, una precondici'n fuerte es una buena noticia para el desarrollador de A, ya que significa que s'lo $ay que trabajar con un conjunto limitado de situaciones. Auanto m!s fuerte sea la precondici'n, mejor para el desarrollador de A. *$ora bien, la precondici'n Fals+ es la aserci'n m!s fuerte posible, ya que nunca se satisface. Aualquier solicitud de ejecutar A ser! incorrecta y la responsabilidad recae, no en el proveedor 1es decir, el desarrollador de A1, sino en el cliente 1es decir, el que invoca a A1, ya que ste no $a cumplido la precondici'n requerida, por la sencilla ra'n de que en este caso es imposible de cumplir. Lo que $aga A o deje de $acer puede ser in#til pero es siempre correcto 1en el sentido, definido anteriormente, de ser consistente con la especificaci'n1. (ara la postcondici'n, la situaci'n se invierte. 9na postcondici'n fuerte es una mala noticia para el desarrollador de A, ya que se restringe el conjunto de estados de salida v!lidos aumentando el n#mero de propiedades especficas que tienen que cumplir dic$os estados. (or tanto, cuanto m!s dbil sea la postcondici'n, mejor para el desarrollador de A. De $ec$o, la segunda panacea mejor del mundo para el desarrollador de A es la siguiente f'rmula de correcci'n: 7P8 A 7,erdader+8 ' para cual1uier P La precondici'n se $a dejado de concretar porque no importa cu!l sea. La postcondici'n ,erdader+ es la aserci'n m!s dbil posible ya que se satisface en todos los estados. *$ora bien, -por qu esta panacea es solamente la segunda mejor0 La ra'n tiene que ver con un detalle que se puede $aber observado en la definici'n del significado de una f'rmula de correcci'n: la terminaci'n. La definici'n establece que la ejecuci'n debe terminar en un estado que satisfaga 6 siempre que se comience en un estado que satisfaga P. Aon la primera panacea no $ay un estado que satisfaga P, por lo que no importa lo que $aga A, aun cuando sea un te/to de programa cuya ejecuci'n provoque un bucle infinito o provoque un fallo en el computador. Aualquier A va a ser correcto con respecto a esa especificaci'n, ya que la precondici'n Fals+ implica que nunca se tendr! que $acer el trabajo. ,in embargo, con la segunda panacea se debe por lo menos llegar a un estado final que, aunque no necesite satisfacer ninguna propiedad especfica, debe e/istir. Desde el punto de vista de lo que A debe $acer quiere decir que: no es necesario $acer nada, pero se debe $acer en un tiempo finito. "sto es as porque la ;ripleta de 7oare $a sido definida para denotar la correccin total, que implica que, si el elemento soft)are empiea su ejecuci'n cumplindose la precondici'n, terminar! de ejecutarse verificando la postcondici'n. *$ora bien, la propiedad de que un elemento soft)are satisfaga su especificaci'n s'lo si termina se denomina correccin parcial8 es decir, un elemento soft)are que es correcto parcialmente no est! obligado a terminar su ejecuci'n pero si lo $ace debe satisfacer su especificaci'n o, dic$o de otro modo, un elemento soft)are parcialmente correcto que empiea su ejecuci'n cumplindose la precondici'n puede no terminar pero si lo $ace terminar! de ejecutarse verificando la postcondici'n. ,.- Co utili-ar en la pr#ctica el Diseo por Contrato ,.1.- .a cone+in entre TAD y DpC 9na clase, como ya $emos dic$o varias veces, es una implementaci'n de un tipo abstracto de datos, bien sea especificado formalmente 1que sera lo ideal1 o bien como ocurre en muc$os casos tan s'lo comprendido implcitamente. Las aserciones se pueden ver como una forma de reintroducir en la clase las propiedades sem!nticas del ;*D subyacente. :amos a perfeccionar la comprensi'n de los conceptos de las aserciones aclarando la cone/i'n de stas con los componentes de la especificaci'n de un tipo abstracto de datos. ,eg#n establecimos, la especificaci'n de un ;*D est! formada por cuatro elementos: los p!rrafos ;H(F,, J9NAHFN",, *LHFC*, y (M"AFNDHAHFN",. Aon frecuencia se suelen pasar por alto los dos #ltimos elementos, lo que quita muc$o atractivo al enfoque ya que las precondiciones y los a/iomas e/presan las propiedades sem!nticas de las funciones. ,i se omiten los a/iomas y las precondiciones, la noci'n de un ;*D concreto pasa a ser un capara'n vaco, sin otra sem!ntica que la que sugieren los nombres de las operaciones. "ste riesgo se traslada a la programaci'n en un lenguaje orientado a objetos: los mtodos que deberan implementar las operaciones de los tipos abstractos de datos correspondientes podran en principio efectuar casi cualquier operaci'n. Las aserciones son las que impiden este riesgo al volver a aportar la sem!ntica. (ara entender la relaci'n entre las aserciones y los ;*D es necesario establecer primero la relaci'n entre las caractersticas de las clases y sus equivalentes en los ;*D, las funciones. *nteriormente distinguamos tres categoras de funciones en un ;*D: constructoras, consultas y 'rdenes. (ues bien, a una funci'n constructora de un ;*D le corresponde un constructor de la clase. * una funci'n de consulta de un ;*D le corresponde un mtodo de consulta 1tambin llamado mtodo de acceso1 de la clase. * una funci'n de orden de un ;*D le corresponde un mtodo modificador 1tambin llamado mtodo de modificaci'n1 de la clase. 9na ve establecida la correspondencia entre las funciones de los ;*D y las caractersticas de la clase, veamos la correspondencia entre las propiedades sem!nticas de los ;*D y las aserciones de la clase: 9na precondici'n para una funci'n del ;*D reaparece como cl!usula de precondici'n para el mtodo correspondiente. 9n a/ioma que involucra a una funci'n de orden, posiblemente con una o m!s funciones de consulta m!s e/ternas en la ecuaci'n, reaparece como cl!usula de postcondici'n del mtodo modificador correspondiente. Los a/iomas que involucran s'lo a funciones de consulta reaparecen como postcondiciones de los mtodos de consulta correspondientes o, especialmente si $ay m!s de una funci'n de consulta involucrada en el a/ioma o si al menos una de las funciones de consulta se implementa mediante un mtodo de consulta que devuelve directamente un atributo privado de la clase, como cl!usulas del invariante de la clase. Los a/iomas que involucran a funciones constructoras reaparecen en la postcondici'n del constructor correspondiente de la clase. ,.2.- /recondiciones y postcondiciones "l primer uso de las aserciones es la especificaci'n sem!ntica de los mtodos. 9n mtodo no es solamente un troo de c'digo8 como implementaci'n de alguna funci'n de la especificaci'n de un ;*D debera realiar alguna tarea #til. "s necesario e/presar esta tarea con precisi'n, como ayuda para el dise+o 1no se puede aspirar a asegurar que un mtodo sea correcto a menos que se $aya especificado lo que se supone que $ace1 y como ayuda para la comprensi'n posterior del te/to. ,e puede especificar la tarea que lleva a cabo un mtodo mediante dos aserciones asociadas al mtodo: una precondici'n y una postcondici'n. La precondici'n establece las propiedades que se tienen que cumplir cada ve que se llame al mtodo, es decir, e/presa las restricciones bajo las que un mtodo funcionar! correctamente. La precondici'n se aplica a todas las llamadas al mtodo, tanto desde dentro de la clase como desde los clientes. 9n sistema correcto nunca ejecutar! una llamada en un estado en que no se satisfaga la precondici'n del mtodo al que se llama. La postcondici'n establece las propiedades que debe garantiar el mtodo cuando retorne, es decir, e/presa propiedades del estado resultante de la ejecuci'n de un mtodo. La presencia de una postcondici'n en un mtodo e/presa una garanta por parte de quien implementa el mtodo de que ste producir! un estado en el que se satisfagan ciertas propiedades si se supone que ste $a sido invocado satisfacindose la precondici'n. Definir una precondici'n y una postcondici'n para un mtodo es una forma de definir un contrato que liga al mtodo con quienes lo llaman. *l asociar una precondici'n pre y una postcondici'n p+st con un mtodo m la clase le est! diciendo a sus clientes: *+i usted me promete llamar a m con pre satisfec,o entonces -o le prometo entregar un estado final en el que post es satisfec,o). 9n par pre1postcondici'n de un mtodo describe el contrato que el mtodo 1el proveedor de un cierto servicio1 define para los que lo llaman 1los clientes del servicio1. 9n buen contrato entra+a tanto obligaciones como beneficios para ambas partes, ya que lo que es una obligaci'n para uno se convierte en un beneficio para el otro. *s: La precondici'n compromete al cliente: define las condiciones bajo las cuales es legtima la llamada a un mtodo. "s una obligaci'n para el cliente y un beneficio para el proveedor. La postcondici'n compromete a la clase: define las condiciones que debe asegurar el mtodo al retornar. "sto es un beneficio para el cliente y una obligaci'n para el proveedor. Los beneficios son para el cliente la garanta de que ciertas propiedades se van a cumplir despus de la llamada, y para el proveedor que se puede suponer que determinados presupuestos se van a cumplir cada ve que se llame a la rutina. Las obligaciones para los clientes son satisfacer los requisitos que establecen las precondiciones y para los proveedores cumplir con la tarea que establecen las postcondiciones. La precondici'n es un beneficio para el proveedor porque si la parte del cliente no se cumple, es decir, si la llamada no satisface la precondici'n, entonces la clase no est! obligada a cumplir la postcondici'n. "n este caso, el mtodo puede $acer lo que quiera: retornar cualquier valor, caer en un bucle infinito sin retornar valor alguno o incluso acabar con la ejecuci'n de una manera dr!stica. Gste es el caso en el cual %el cliente est! equivocado&. La primera ventaja de esta convenci'n es que simplifica considerablemente el estilo de programaci'n. 7abiendo especificado como precondici'n las restricciones bajo las cuales se puede llamar a un mtodo, el que desarrolla la clase puede suponer, cuando escribe el cuerpo del mtodo, que las restricciones se satisfacen, por lo que no es necesario verificar stas en el cuerpo del mtodo8 de $ec$o, el dise+o por contrato va m!s all!: no solamente es innecesario, sino que es inaceptable. "s lo que se conoce como principio de no redundancia: /ajo ninguna circunstancia debe el cuerpo del mtodo verificar el cumplimiento de la precondicin del mtodo) "sta regla es contraria a lo que se conoce a menudo con el nombre de pr+2ramaci4n de0ensiva. Gsta establece que para obtener soft)are fiable $ay que dise+ar componentes que se protejan a s mismos lo m!s posible. "s mejor comprobar demasiado, seg#n este enfoque, que demasiado poco: uno nunca es demasiado cuidadoso cuando tiene que tratar con e/tra+os. 9na comprobaci'n redundante puede no ayudar, pero al menos no $ace da+o. "l dise+o por contrato proviene de la observaci'n opuesta: las comprobaciones redundantes pueden $acer da+o. (or supuesto que esto al principio puede parecer raro: la reacci'n natural es la de pensar que una comprobaci'n adicional, como por ejemplo una instrucci'n condicional para comprobar si el argumento de un mtodo es un n#mero negativo, pudiera ser in#til, pero posiblemente no cause ning#n da+o. ,in embargo, un comentario como ste proviene de una comprensi'n microsc'pica de lo que es fiabilidad, que se centra en los elementos individuales de soft)are. ,i se restringe el panorama al estrec$o mundo de un #nico mtodo, entonces puede parecer que dic$o mtodo es m!s robusto con una comprobaci'n adicional que sin ella. (ero el mundo de un sistema soft)are no est! restringido a un mtodo: contiene una multitud de mtodos en una multitud de clases. (ara obtener sistemas soft)are fiables, se debe pasar del enfoque microsc'pico a una visi'n macrosc'pica que considere la arquitectura completa. ,i se considera esta visi'n global, la sencille se convierte en un criterio crucial. Aomo ya se sabe, la complejidad es el mayor enemigo de la calidad. Auando se tiene esto en cuenta, las posibles comprobaciones redundantes >ya no aparecen tan inocuas? "/trapoladas a miles de mtodos de un sistema soft)are de tama+o medio 1o decenas o cientos de miles de mtodos en uno muy grande1, la comprobaci'n adicional anterior basada en una #nica instrucci'n condicional, que es inocua a primera vista, comiena a parecer un monstruo de complejidad in#til. *l a+adir comprobaciones posiblemente redundantes se a+ade m!s soft)are, m!s soft)are significa m!s complejidad y en particular m!s fuentes de condiciones que pueden ser err'neas8 de aqu la necesidad de m!s comprobaciones, lo que significa m!s soft)are y as $asta el infinito. ,i arrancamos en este camino s'lo una cosa es cierta: nunca se obtendr! fiabilidad. Auanto m!s se escriba, m!s se tendr! que escribir. (ara evitar esta persecuci'n infinita, >nunca se debera empear? "l dise+o por contrato invita a identificar las condiciones de consistencia que son necesarias para el funcionamiento correcto de cada cooperaci'n cliente1proveedor 1es decir, cada contrato1 y a especificar, para cada una de estas condiciones, de quin es la responsabilidad de asegurar la misma: del cliente o del proveedor. 9na ve que se $a tomado una decisi'n, $ay que basarse en ella: si en una prec+ndici4n aparece un re1uisit+ de c+rrecci4n' l+ cual indica 1ue el re1uisit+ es parte de la resp+nsabilidad del cliente' n+ debe 9aber una c+mpr+baci4n c+rresp+ndiente en el m:t+d+; y si n+ est< en una prec+ndici4n' ent+nces el m:t+d+ debe c+mpr+bar el re1uisit+. ,eg#n se acaba de decir, la idea que se e/presa como principio de no redundancia indica que, para cualquier condici'n de consistencia que pudiera $acer peligrar el funcionamiento apropiado del mtodo, se le debe asignar el asegurar esta condici'n a una sola de las dos partes del contrato. -* cu!l de las dos0 La respuesta puede variar, y es en parte un asunto de estilo de dise+o. 7ay dos posibilidades obvias: F se le asigna la responsabilidad a los clientes, en cuyo caso la condici'n aparecer! como parte de la precondici'n del mtodo, y recibe el nombre de dise!o exigente de las precondiciones. F se le pasa al proveedor en cuyo caso la condici'n aparecer! en una instrucci'n condicional en el cuerpo del mtodo, y recibe el nombre de dise!o tolerante de las precondiciones. -Au!l es el mejor estilo0 7asta cierto punto es un asunto de criterio personal, al contrario que el principio de no redundancia, que es absoluto cuando establece que nunca es aceptable tratar una condici'n de correcci'n desde ambos lados, el del cliente y el del proveedor. *rgumentos fuertes pudieran tenerse, sin embargo, para el estilo e/igente, especialmente en el caso de que se quiera que el soft)are sea reutiliable, y en el desarrollo orientado a objetos siempre se debiera escribir el soft)are con el objetivo final de $acerlo reutiliable. * primera vista el estilo tolerante pudiera parecer mejor tanto para la reutiliaci'n como para la fiabilidad8 despus de todo el enfoque e/igente parece pasar m!s responsabilidad a los clientes y tpicamente $ay muc$os clientes para un mismo proveedor, incluso m!s en el caso de una clase reutiliable. -No es preferible entonces dejar que sea el proveedor el que se ocupe de las condiciones de correcci'n de una ve por todas, en lugar de estar requirindole a cada cliente que lo $aga por s mismo0 ,i se mira m!s de cerca esta cuesti'n, este raonamiento no se cumple. Las condiciones de correcci'n describen lo que requieren las rutinas para ser capaces de $acer su trabajo correctamente. :eamos un contraejemplo. Hmaginemos un mtodo desapila tolerante para una clase que implementa las pilas: -qu puede $acer un pobre mtodo para quitar un elemento de la pila si sta est! vaca0 Gsta puede $acer un intento rebelde de dar como salida un mensaje de error, pero esto es claramente inadecuado: un m'dulo cliente especialiado tal como un manejador de pila no $ace nada con un mensaje al usuario. ,e debiera tratar de $acer algo m!s sofisticado, pero simplemente desapila no se encuentra en el conte/to apropiado para ello8 el foco de la clase que implementa las pilas es demasiado estrec$o para determinar qu $acer en caso de una pila vaca. ,'lo el cliente 1un m'dulo que est! usando pilas en alguna aplicaci'n1 tiene suficiente informaci'n para decidir qu es lo que significa realmente un intento de quitar un elemento si la pila est! vaca: -es sta una solicitud normal aunque in#til que simplemente se debiera ignorar ejecutando una operaci'n nula0 -F por el contrario es un error y por tanto $ay que tratarlo: lanar una e/cepci'n, corregir la situaci'n antes de intentarlo de nuevo o 1la respuesta menos probable1 dar como salida un mensaje de error visible para el usuario0 "n el espritu del dise+o por contrato, el enfoque e/igente en el dise+o de la precondici'n no intenta producir mtodos que $agan todas las cosas para todos los clientes. "n lugar de esto, se insiste en que cada mtodo realice una tarea bien definida y la $aga bien <correctamente, eficientemente, lo suficientemente general para que sea reutiliable por muc$os clientes...= y que se especifique claramente cu!les son los casos que el mtodo no puede manejar. De $ec$o no se puede esperar que el mtodo $aga bien su trabajo a menos que se $aya circunscrito cuidadosamente su misi'n. 9n mtodo fact'tum, que quiera $acer un c!lculo, verificar los casos anormales y tomar acciones correctivas, notificar a los clientes y a su ve producir de todas maneras un resultado, tiene grandes posibilidades de no llegar a satisfacer correctamente ninguno de estos objetivos. "l autor de un mtodo no tiene que ser m!s listo que los clientes8 si no est! seguro de lo que tiene que $acer el mtodo en una cierta situaci'n anormal, debe e/cluir sta e/plcitamente en la precondici'n. *$ora bien, el dise+o e/igente de las precondiciones s'lo es aplicable si las precondiciones se mantienen raonables. -Qu es lo que significa %raonable& para la precondici'n de un mtodo0 * continuaci'n se da una caracteriaci'n m!s precisa, mediante el principio de la precondicin razonable: 0a precondicin de todo mtodo en el dise!o exigente de las precondiciones debe satisfacer los siguientes requisitos1 0a precondicin aparece en la documentacin oficial distribuida a los autores de los mdulos clientes) 2s posible justificar la necesidad de una precondicin exclusivamente en trminos de la especificacin) "l segundo requisito e/cluye restricciones que sean s'lo para conveniencia del proveedor al implementar el mtodo. (or ejemplo, cuando se quiere quitar un elemento de una pila la precondici'n que e/ige que la pila no est vaca es un requisito l'gico que puede ser justificado en trminos de la especificaci'n solamente, mediante la simple observaci'n de que en una pila vaca no $ay nada que quitar8 y, por ejemplo, cuando se computa la ra cuadrada de un n#mero real, la precondici'n que e/ige que el n#mero sea mayor o igual que cero es un resultado directo de la propiedad matem!tica de que los n#meros reales negativos no tienen races cuadradas reales. *lgunas restricciones pueden surgir debido a la forma general de implementaci'n que se seleccione. (or ejemplo, utiliar un array para implementar las pilas tendr! como conscuencia que el mtodo apila tenga una precondici'n que e/ija que la pila no est llena. (ero un caso como ste no viola el principio porque la naturalea acotada de dic$a implementaci'n se $ace parte de la especificaci'n: la clase no se anunciar! para representar pilas arbitrarias, sino s'lo pilas de una capacidad m!/ima finita. "l tipo abstracto de datos que sirve de especificaci'n a esta clase no es la noci'n m!s general de pila, sino la noci'n de pila acotada. "s importante $acer notar que los contratos que aqu se discuten ocurren entre un mtodo 1el proveedor1 y otro mtodo 1el cliente que lo llama18 lo que nos concierne es la comunicaci'n de soft)are con soft)are, no la comunicaci'n de soft)are con $umano ni la comunicaci'n de soft)are con mundo e/terior. 9na precondici'n no se ocupa de corregir la entrada del usuario. "n este caso no $ay sustituto para las estructuras condicionales $abituales de verificaci'n de condiciones. Las aserciones no tienen ning#n papel que jugar en la soluci'n del problema de la validaci'n de la entrada del mundo e/terior 1de sensores, de entradas del usuario, de una red...1, de modo que en la obtenci'n de informaci'n del mundo e/terno no se puede basar uno en precondiciones. "n este conte/to, el dise+o tolerante de las precondiciones es #til para los elementos soft)are que tienen que ver no con otros elementos soft)are sino con datos que provienen del mundo e/terior, tales como entradas del usuario o datos provenientes de un sensor8 sin embargo, para m'dulos cuyos clientes son otros m'dulos soft)are, el dise+o e/igente de las precondiciones suele ser el adecuado. 9na confusi'n com#n es pensar en las aserciones como estructuras de control para manejar casos especiales. Debe quedar claro que ste no es su papel. ,i se quiere escribir un mtodo que calcule la ra cuadrada de un n#mero real y trate los argumentos negativos de cierta manera y los argumentos no negativos de otra manera, entonces no se necesita una precondici'n sino las cl!sicas estructuras de control condicionales. Las aserciones son otra cosa. "/presan las condiciones de correcci'n. ,i dic$o mtodo que calcula la ra cuadrada de un n#mero real tiene una precondici'n que e/ige que el argumento sea mayor o igual que cero, una llamada a dic$o mtodo con un argumento negativo no es un caso especial: es un error simple y llano. 2 dada la visi'n de las aserciones como contrato, podemos enunciar la regla de violacin de las aserciones: 0a violacin en tiempo de ejecucin de una asercin es la manifestacin de un error en el softare) 0a violacin de una precondicin es la manifestacin de un error en el cliente) 0a violacin de una postcondicin es la manifestacin de un error en el proveedor) 9na violaci'n de una precondici'n significa que el mtodo que llama, aunque est! obligado por el contrato a satisfacer un cierto requisito, no lo $a $ec$o. "sto es un error del cliente como tal, la rutina a la que se llama no tiene la culpa. 9n observador e/terno pudiera por supuesto criticar un contrato porque e/ige demasiado, pero es demasaido tarde para argumentar en contra del contrato: ste es el contrato y el cliente no $a cumplido su parte del trato. (or tanto, $ay un mecanismo para monitoriar las aserciones durante la ejecuci'n y si ste detecta una violaci'n de la precondici'n, el mtodo no se ejecutar!. ,e $an establecido las condiciones bajo las cuales puede funcionar y estas condiciones no se $an cumplido: tratar de ejecutar el mtodo no tendra sentido. La violaci'n de una postcondici'n significa que el mtodo, presumiblemente invocado en condiciones correctas, no $a sido capa de cumplir con su contrato. *qu tambin est! clara la distribuci'n de la culpa y la inocencia, aunque es la inversa de lo anterior: el error est! en el mtodo, el que llama es el inocente. ,.3.- *nvariantes de clase Las precondiciones y las postcondiciones describen las propiedades sem!nticas de los mtodos individuales. ;ambin es necesario e/presar las propiedades sem!nticas globales de todas las instancias de una clase, que deben ser preservadas por todos los mtodos. ;ales propiedades sem!nticas constituyen el invariante de la clase y capturan las restricciones de integridad que caracterian a una clase. 9n invariante de clase es una aserci'n que e/presa restricciones de consistencia generales que se aplican a cada instancia de la clase como un todo8 por tanto, es diferente de las precondiciones y las postcondiciones, que caracterian a mtodos individuales. 9n invariante de una clase es una aserci'n que debe satisfacer cada instancia de la clase en todos los momentos estables. Los momentos estables de una instancia de una clase son aquellos en los que el objeto es observable desde fuera, en el sentido de que un cliente le puede aplicar una caracterstica. "stos momentos estables son: "l estado resultante de la creaci'n del objeto. "l estado inmediatamente antes y despus de una llamada ejecutada por un cliente a un mtodo de la clase de ese objeto. (ese a su nombre, el invariante no tiene que satisfacerse en todo momento. "s perfectamente aceptable que un mtodo empiece a intentar alcanar su objetivo 1es decir, su postcondici'n1 y que durante ese proceso destruya el invariante8 de este modo, en algunas etapas intermedias el invariante no se cumplir!, lo que est! bien siempre y cuando el mtodo restableca el invariante antes de terminar su ejecuci'n. La obligaci'n de mantener el invariante s'lo se aplica al cuerpo de los mtodos que se e/portan, ya que estos mtodos que se ejecutan por parte de un cliente siempre deben partir de un estado que satisfaga al invariante y terminar en un estado que tambin satisfaga al invariante. 9n mtodo privado o secreto 1y que, por tanto, no est! disponible para ning#n cliente1 no est! afectado por el invariante, ya que estos mtodos no son ejecutados directamente por los clientes sino que sirven s'lo como $erramientas au/iliares para llevar a cabo las necesidades de los mtodos e/portados. *$ora podemos preguntarnos: -qu significara que un invariante se viole durante la ejecuci'n de un sistema soft)are0 La respuesta es la de considerar a los invariantes en el mismo caso que las postcondiciones: la violaci'n de un invariante es la manifestaci'n de un error en el proveedor. 9na ve que ya sabemos qu son las precondiciones, las postcondiciones y los invariantes, podemos definir lo que significa que una clase sea correcta. La base de la respuesta ya $a sido estudiada: una clase, como cualquier otro elemento soft)are, es correcta o incorrecta no por s misma sino con respecto a una especificaci'n. Hntroduciendo las precondiciones, postcondiciones e invariantes se tiene una forma de incluir la especificaci'n en el propio te/to de la clase. "sto proporciona una base para precisar la correcci'n: la clase es correcta si y s'lo si su implementaci'n, seg#n se da en los cuerpos de los mtodos, es consistente con las precondiciones, las postcondiciones y los invariantes. ,ea C una clase e inv el invariante de la clase. (ara cada mtodo m de la clase, se llamar! pre m &( m ) y p+st m &( m ) a su precondici'n y su postcondici'n respectivamente, donde ( m denota a los posibles argumentos de m, a los cuales se pueden referir tanto la precondici'n como la postcondici'n. ,i la precondici'n o la postcondici'n no aparecen en el te/to del mtodo quiere decir que pre m o p+st m son ,erdader+. Llamemos Cuerp+ m al cuerpo del mtodo m. (or #ltimo, sea P+r=de0ect+ C la aserci'n que e/presa que los atributos de C tienen los valores por defecto de sus tipos respectivos. Aon estas notaciones podemos definir la regla de correccin de una clase: (na clase es correcta con respecto a sus aserciones si - slo si1 %ara cada conjunto vlido de argumentos x p de un constructor p1 $%or3defecto " and pre p 4x p 5& "uerpo p $post p 4x p 5 and inv& %ara cada mtodo exportado r - cualquier conjunto x r de argumentos vlidos1 $pre r 4x r 5 and inv& "uerpo r $post r 4x r 5 and inv& :amos a estudiar con detenimiento esta regla: "l estado de un objeto est! definido por los valores de los atributos de la clase para esta instancia en particular. "l estado inicial de un objeto es el estado que tiene dic$o objeto inmediatamente antes de una llamada ejecutada por un cliente a un mtodo e/portado por la clase de ese objeto. "l estado final de un objeto es el estado que tiene dic$o objeto inmediatamente despus de una llamada ejecutada por un cliente a un mtodo e/portado por la clase de ese objeto. ,e considera que toda clase tiene al menos un constructor. ,i ning#n constructor $a sido definido e/plcitamente, se puede considerar que la clase tiene un constructor predeterminado implcito que tiene un cuerpo vaco. *plicar la primera condici'n al constructor predeterminado significa entonces que los valores por defecto de los atributos de la clase deben satisfacer el invariante. (or otra parte, para cualquier constructor que se defina e/plcitamente, la primera condici'n establece que cuando se llama con argumentos que satisfacen su precondici'n y en un estado inicial donde los atributos tienen sus valores por defecto, produce un estado final que satisface el invariante de la clase y la postcondici'n del constructor. La precondici'n de un mtodo puede involucrar al estado inicial y a los argumentos de ese mtodo. La postcondici'n puede involucrar al estado final, al estado inicial y, en el caso de que el mtodo devuelva un valor, al valor proporcionado por el mtodo. "l invariante s'lo puede involucrar el estado del objeto. La segunda condici'n de la regla establece que todo mtodo e/portado de la clase, cuando se llama con argumentos que satisfacen su precondici'n y en un estado inicial que satisface tanto el invariante como la precondici'n del mtodo, termina y produce un estado final que satisface el invariante y la postcondici'n del mtodo. Aomo ya $emos visto, las f'rmulas de correcci'n no comprometen al elemento soft)are de ninguna forma en los casos en lo que la precondici'n no se satisface con antelaci'n. *s, el contrato no es vinculante para el mtodo si el cliente fall' al cumplir con su parte del trato. De acuerdo con esto, la definici'n de correcci'n de una clase deja a los mtodos de la clase la libertad de $acer lo que quieran en una llamada que viole la precondici'n o el invariante. ,eg#n esta regla de correcci'n, se puede considerar el invariante como una aserci'n que se a+ade implcitamente a la precondici'n y a la postcondici'n de cada mtodo que se e/porte. De modo que en principio la noci'n de invariante es superflua: se puede pasar sin l si se enriquecen las precondiciones y las postcondiciones de todos los mtodos de la clase. 9na transformaci'n como sta, por supuesto, no es deseable. Aomplicara los te/tos de los mtodos y, lo que es m!s importante, se perdera el significado m!s profundo de los invariantes, que trasciende a los mtodos individuales y se aplica a la clase como un todo. ,e podra considerar de $ec$o que el invariante se aplica no s'lo a los mtodos que est!n escritos realmente en la clase, sino a todo lo que se pueda a+adir m!s tarde, de modo que servira como control sobre la evoluci'n futura de la clase. "n el desarrollo del soft)are el cambio es inevitable e intentamos controlarlo. Aabe esperar que algunos aspectos de los sistemas soft)are y de sus componentes individuales 1las clases1 cambien m!s r!pidamente que otros. "n particular a+adir, quitar o cambiar caractersticas de de una clase es un suceso frecuente y normal. "n este proceso desearemos basarnos en aquellas propiedades que, aunque pudieran cambiar tambin, cambiar!n con muc$a menos frecuencia. Los invariantes, debido a que capturan las restricciones fundamentales que se aplican a una clase, juegan este papel. Aomo $emos visto, desde el punto de vista l'gico se puede considerar al invariante como algo a+adido a toda precondici'n y a toda postcondici'n de todo mtodo e/portado. :amos a reproducir la segunda condici'n de la regla de una manera simplificada. ,ea cuerp+ el cuerpo de un mtodo, pre su precondici'n, p+st su postcondici'n e inv el invariante de la clase. "l requisito de correcci'n de un mtodo se puede e/presar mediante la siguiente f'rmula de correcci'n: 7inv and pre8 cuerp+ 7inv and p+st8 "sta f'rmula de correcci'n significa que cualquier ejecuci'n de cuerp+ que comience en un estado inicial en el cual inv y pre se cumplen, terminar! en un estado final en el que inv y p+st se cumplen. Lo que queremos preguntarnos a$ora es: para el proveedor 1la persona que escribe cuerp+1 -el invariante es una buena o una mala noticia, es decir, le $ace la tarea m!s f!cil o m!s difcil0 La respuesta es: ambas cosas. *l a+adir inv se fortalece tanto a la pre como a la postcondici'n ya que, de las reglas de la l'gica, a and b implica siempre a, es decir, a and b es m!s fuerte que a. (or tanto, si se est! a cargo de implementar el cuerpo, el invariante: Jacilita esta tarea: adicionalmente a la precondici'n oficial pre se puede suponer que el estado inicial satisface inv, lo que restringe m!s el conjunto de casos que $ay que manejar. Dificulta la tarea: adicionalmente a la postcondici'n oficial p+st, $ay que asegurar a$ora tambin que el estado final satisface inv. "stas observaciones son consistentes con el punto de vista de que el invariante es una condici'n general de consistencia que se aplica a la clase como un todo y por consiguiente a todos sus mtodos. Aomo autor de uno de estos mtodos, uno se beneficia de poder suponer que esta condici'n se cumple al comieno del mtodo, pero se tiene la obligaci'n de asegurar que se siga satisfaciendo al terminar el mtodo, de modo que el pr'/imo mtodo que sea aplicado al mismo objeto pueda dar por supuesto su cumplimiento. "stas refle/iones sobre los invariantes producen tambin una mejor comprensi'n de los constructores. 9n invariante de clase e/presa el conjunto de propiedades que los objetos 1las instancias de la clase1 deben satisfacer en lo que se $a denominado momentos estables de su e/istencia. "n particular, estas propiedades se debn cumplir despus de crearse la instancia. "l mecanismo est!ndar de asignaci'n de objetos en memoria inicialia los atributos d!ndoles los valores por defecto de los tipos correspondientes de los atributos8 a$ora bien, estos valores pueden o no satisfacer el invariante. ,i no lo satisfacen, se requiere un constructor e/plcito que debe dar valores a los atributos de modo que se satisfaga el invariante. *s que el papel de un constructor debe verse coomo el medio para asegurar que una instancia de una clase, cuando comiena su vida, ya satisface la regla fundamental de su casta 1 el invariante de su clase. De este modo, la construcci'n debe verse como la operaci'n que asegura que todas las instancias de una clase comienan sus vidas de modo correcto 1uno en el que se cumple el invariante de la clase. "l mtodo orientado a objetos utilia un modelo de ejecuci'n que es muy fle/ible porque $ace un uso e/tensivo de las referencias. Desafortunadamente, este modelo de ejecuci'n puede ocasionar conflictos cuando se junta con la noci'n de invariante de clase. ,i ( e y son referencias a objetos e y es no vaco, la asignaci'n ( > y da lugar a que tanto ( como y estn conectados al mismo objeto8 es decir, el resultado es ligar ( e y de una forma duradera, $asta que se produca alguna asignaci'n posterior a cualquiera de ellos. La cone/i'n de ( al mismo objeto que y produce una compartici'n de estructura y se conoce como alias dinmico 1en ingls dynamic aliasin21: alias porque la asignaci'n $ace que se pueda acceder a un objeto a travs de dos referencias, y din!mico porque el alias ocurre en tiempo de ejecuci'n. *s, realiar la llamada (?0&), donde 0 es un mtodo de la clase correspondiente, tendr! el mismo efecto que y?0&) puesto que afectan al mismo objeto. "s decir, (?0&) afecta a y a#n a pesar de que y es una entidad a la cual no $ace referencia. "l problema es que, debido al alias din!mico, no es posible comprobar la correcci'n de una clase sobre la base de la clase solamente. ,e $a visto la correcci'n de una clase en trminos de dos condiciones que e/presan 1concentr!ndonos en el invariante inv e ignorando las precondiciones y las postcondiciones que no juegan un papel directo aqu1: la primera, (6, que cada constructor produce objetos que satisfacen inv y la segunda, (B, que cada mtodo e/portado preserva inv. "stas dos condiciones parecen suficientes para garantiar que inv es realmente invariante. La prueba es aparentemente trivial: puesto que inv ser! satisfec$o inicialmente y preservado por cada llamada a un mtodo e/portado, por inducci'n debera satisfacerse en todos los momentos estables. ,in embargo, esta prueba informal no es v!lida en presencia de alias din!micos. "l problema es que un atributo de un objeto podra ser modificado por una operaci'n sobre otro objeto. De modo que aun cuando todas las operaciones a?r preserven inv sobre el objeto OA de la clase A conectado con a, las propiedades de * pueden involucrar instancias de otras clases 1por ejemplo, de la clase D1 y la prueba de correcci'n anterior no dice nada sobre el efecto de estas caractersticas de otras clases sobre el invariante de * de modo que una cierta operaci'n b?s 1para un b conectado a otro objeto O* de la clase *1 podra destruir el invariante inv de OA. De modo que aun cumplindose las condiciones (6 y (B, inv pudiera no ser un invariante. "ste problema tiene un nombre: 2fecto 6ndirecto del 6nvariante. (uede aparecer tan pronto como se permitan los alias din!micos, mediante los cuales una operaci'n podra modificar un objeto aun sin involucrar a ninguna entidad asociada a l mediante una referencia. (or ello, si se desea monitoriar las aserciones en tiempo de ejecuci'n para garantiar que se cumplen, es necesario comprobar que se cumple el invariante de clase al entrar y al salir de un mtodo e/portado. -(or qu al entrar y al salir0 ,in el efecto indirecto del invariante sera suficiente comprobar el invariante s'lo al salir de las llamadas a constructores y a mtodos e/portados. (ero a$ora $ay que ser m!s cuidadoso, ya que entre la culminaci'n de una llamada y el comieno de otra llamada aplicada al mismo objeto, otra llamada pudiera $aber afectado a dic$o objeto aun cuando el receptor $aya sido otro objeto distinto. "s tambin responsabilidad del proveedor tener en cuenta el alias din!mico para garantiar que el invariante de clase se satisface a la entrada del mtodo y no s'lo a la salida. (or ello, la violaci'n del invariante es responsabilidad suya y no del cliente. ,.$.- Epleo del DpC en 0ava 9na ve establecidos los principios b!sicos de c'mo aplicar en la pr!ctica el DpA, es necesario que los pongamos en pr!ctica abordando el estudio de un caso pr!ctico para conocer y resolver las dificultades que se puedan presentar. Aomo ya comentamos en su momento, vamos a usar Iava como lenguaje de programaci'n orientado a objetos. Iava no tiene directamente integrado de forma nativa el DpA, as que simularemos ste mediante los mecanismos del lenguaje. "l objetivo es desarrollar una clase que implemente el ;*D Pila[G] que se especific' formalmente con anterioridad. La clase ser! genrica, bajo la forma: pac/a0e or012omave0er1d3c4 566 6 6 7a$"8or 2omave0er 6 93r: 93r: 6 7descrip"ion Pilas: $na es"r$c"$ra dispensadora con pol"ica ;<(=: el 6 >l"imo elemen"o en en"rar es el primero en salir1 ?ienen capacidad 6 ilimi"ada1 65 p$3lic class Pila9G: + 111 , Los puntos suspensivos indican que completaremos lo que falta despus. 7agamos una observaci'n sobre las clases genricas. ,eg#n $emos visto, una clase es un tipo de datos. Desde un punto de vista formal, se puede afirmar que, con la genericidad, esta afirmaci'n no es literalmente verdadera, aunque la diferencia sea peque+a. 9na clase genrica C@$A es, en lugar de un tipo de datos, un patr'n de tipos de datos que abarca un conjunto infinito de posibles tipos de datos8 se puede obtener uno de estos tipos de datos al proporcionar un par!metro genrico real o actual 1que es a su ve un tipo de datos1 que corresponde a $. "sto es completamente an!logo a lo que se e/plic' en su momento sobre ;*Ds genricos. ;odo esto nos lleva a una noci'n m!s general y fle/ible. (ero para ganar en potencia $ay que pagar un peque+o precio en sencille: s'lo mediante un peque+o abuso del lenguaje se puede seguir $ablando, si ( se $a declarado de tipo T, de las %caractersticas de T& o de los %clientes de T&8 m!s que una clase, T puede ser a$ora un tipo C@UA derivado genricamente de alguna clase genrica C y alg#n tipo U. (or supuesto que sigue estando involucrada una clase 1la clase C1, por lo que este abuso del lenguaje es aceptable. Auando se necesite ser riguroso la terminologa debe ser la siguiente. ;odo tipo T est! asociado con una clase, la clase base de T, de modo que siempre es correcto $ablar de las caractersticas o los clientes de la clase base de T. ,i T es una clase no genrica, entonces ; es su propia clase base. ,i T es una derivaci'n genrica de la forma C@UA entonces la clase base de T es C. No obstante, esta e/plicaci'n, que desde un punto de vista formal es correcta, no es aplicable a Iava porque en este lenguaje la genericidad se implementa mediante borrado de tipos 1en ingls type erasure1, de modo que para la m!quina virtual todos los objetos pertenecen a clases no genricas, por lo que e/iste un #nico tipo de datos asociado a una clase genrica8 en este caso, una clase s que es siempre un tipo de datos y nunca es realmente un patr'n de tipos de datos. Auando en Iava se define una clase genrica, se proporciona autom!ticamente su tipo de datos asociado, que se denomina tipo de datos puro, y cuyo nombre es simplemente el nombre de la clase genrica despus de eliminar los par!metros genricos formales. Aontinuemos con nuestra clase genrica. *ntes de considerar cuestiones de implementaci'n es importante observar que los mtodos est!n caracteriados por fuertes propiedades sem!nticas que son independientes de una representaci'n especfica. (or ejemplo: Los mtodos desapila y cima s'lo son aplicables si la pila no est! vaca. "l mtodo apila $ace que la pila deje de estar vaca en caso de que lo estuviera antes de aplicar el mtodo. ;ales propiedades son parte de la especificaci'n de un tipo abstracto de datos e incluso la gente que no use ning#n enfoque remotamente tan formal como los ;*Ds las contempla implcitamente8 pero en los enfoques m!s comunes de construcci'n de soft)are los te/tos soft)are no revelan rastro de ellas. Cediante las precondiciones y postcondiciones de los mtodos se puede convertirlas en elementos e/plcitos del soft)are. (artiendo de la especificaci'n del ;*D desarrollada con anterioridad, es evidente que a la funci'n constructora crea le corresponder! un mtodo constructor, a cada una de las funciones de consulta cima y vaca les corresponder! un mtodo de acceso con el mismo nombre y a cada una de las funciones de orden apila y desapila les corresponder! un mtodo de modificaci'n con el mismo nombre. *$ora bien, imaginemos que encontramos #til a+adir una nueva operaci'n a la clase, que se llama cuenta, que devuelve el n#mero de elementos que est!n actualmente apilados en la pila. -"s esto un problema0 Fbviamente no. La adici'n de m!s operaciones a la clase no es una diferencia importante debido a que pueden especificarse algebraicamente y, por tanto, pueden incluirse en la especificaci'n del tipo abstracto de datos. *s, la operaci'n cuenta se especificara mediante los siguientes a/iomas: c$en"a: Pila[G] @n"ero Para c$al%$ier &:G, p:Pila[G], c$en"a(crea) # 0 c$en"a(apila(p, &)) # ! A c$en"a(p) "stos a/iomas son bastante evidentes. "l primero afirma que el n#mero de elementos actualmente apilados en una pila vaca es cero. "l segundo a/ioma afirma que el n#mero de elementos actualmente apilados en una pila es uno 1el que corresponde a la cima de la pila1 m!s el n#mero de elementos apilados en esa pila $abindosele quitado la cima puesto que sta ya $a sido contada. :eamos a continuaci'n la clase completamente implementada: pac/a0e or012omave0er1d3c4 impor" 2ava1io1BB"eCrraB<np$"D"ream4 impor" 2ava1io1BB"eCrraB=$"p$"D"ream4 impor" 2ava1io1=32ec"<np$"D"ream4 impor" 2ava1io1=32ec"=$"p$"D"ream4 impor" 2ava1$"il1CrraB;is"4 566 6 6 7a$"8or 2omave0er 6 93r: 93r: 6 7descrip"ion Pilas: $na es"r$c"$ra dispensadora con pol"ica 6 ;<(=: el >l"imo elemen"o en en"rar es el primero en salir1 6 ?ienen capacidad ilimi"ada1 6 93r: 93r: 6 7invarian" 6 c$en"a() :) 0 6 93r:93r: 6 7invarian"Priva"e 6 c$en"a() )) represen"a"ion1siEe() 93r: 6 (c$en"a() : 0) implies (represen"a"ion10e"(c$en"a() - !) )) cima()) 65 p$3lic class Pila9G: + priva"e CrraB;is"9G: represen"a"ion4 priva"e 3oolean 0$arda ) False4 priva"e void invarian"() + "8is10$arda ) "r$e4 asser" ("8is1c$en"a() :) 0) GG ("8is1c$en"a() )) "8is1represen"a"ion1siEe()) GG (H("8is1c$en"a() : 0) II "8is1represen"a"ion10e"("8is1c$en"a() - !) )) "8is1cima()) : J'iolaciKn del <nvarian"e de la LlaseJ4 "8is10$arda ) False4 ,
566 6 Lompara en proF$ndidad si el o32e"o ac"$al es i0$al al o32e"o %$e 6 reci3e como parSme"ro real1 65 7=verride p$3lic 3oolean e%$als(=32ec" o32) + iF (o32 )) n$ll) + re"$rn False4 , iF (0e"Llass() H) o3210e"Llass()) + re"$rn False4 , Final Pila9G: o"8er ) (Pila9G:) o324 re"$rn "8is1represen"a"ion1e%$als(o"8er1represen"a"ion)4 , 566 6 Rev$elve el cKdi0o de dispersiKn del o32e"o ac"$al 65 7=verride p$3lic in" 8as8Lode() + in" res$l" ) !.4 res$l" ) 3! 6 res$l" A "8is1represen"a"ion18as8Lode()4 re"$rn res$l"4 , 566 6 WealiEa $na copia en proF$ndidad del o32e"o ac"$al1 65 7=verride p$3lic Pila9G: clone() + "rB + BB"eCrraB=$"p$"D"ream 3o$" ) neM BB"eCrraB=$"p$"D"ream()4 =32ec"=$"p$"D"ream o$" ) neM =32ec"=$"p$"D"ream(3o$")4 o$"1Mri"e=32ec"("8is)4 o$"1close()4 BB"eCrraB<np$"D"ream 3in ) neM BB"eCrraB<np$"D"ream(3o$"1"oBB"eCrraB())4 =32ec"<np$"D"ream in ) neM =32ec"<np$"D"ream(3in)4 Pila9G: res$l" ) (Pila9G:) in1read=32ec"()4 in1close()4 re"$rn res$l"4 , ca"c8 (@&cep"ion e) + re"$rn n$ll4 , , , La etiqueta descripti+n se $a utiliado para $acer una descripci'n en lenguaje natural del prop'sito general que tiene la clase. ,'lo es necesario pasar a la $erramienta Bavad+c el argumento Cta2 descripti+n para que dic$a etiqueta sea procesada por dic$a $erramienta y apareca, por tanto, en la documentaci'n de la clase. Las precondiciones, postcondiciones e invariante de clase se e/presan como cl!usulas introducidas por las etiquetas pre 1precondici'n1, pos" 1postcondici'n1 e invarian" 1invariante1, respectivamente, en la secci'n de comentarios Bavad+c de los mtodos. De nuevo, s'lo es necesario pasar a la $erramienta Bavad+c los argumentos Cta2 pre Cta2 p+st Cta2 invariant para que las citadas cl!usulas aparecan en la documentaci'n generada por dic$a $erramienta. La etiqueta pre es opcional, de modo que puede $aber mtodos que no tengan precondiciones 1o m!s precisamente, que tengan "r$e como precondici'n1. ;ambin es opcional la etiqueta pos", de modo que puede $aber mtodos que no tengan postcondiciones: entonces estos mtodos tienen "r$e como postcondici'n, lo que no implica ausencia de obligaciones dado que tienen que satisfacer el invariante. ,int!cticamente, las aserciones son simplemente e/presiones l'gias escritas en Iava con unas pocas e/tensiones. Auando las cl!usulas aparecen en lneas separadas, se debe considerar que e/iste un and implcito entre lneas sucesivas de cl!usulas, de modo que se facilita la identificaci'n de los componentes individuales de una aserci'n. :amos a analiar la clase, los detalles de implementaci'n y tambin cada una de las aserciones, qu e/presan, c'mo lo e/presan y c'mo se relacionan con la especificaci'n del ;*D subyacente. "mpecemos por el mtodo cima(), el cual devuelve el elemento que est! en la cima. ,u precondici'n es: 7pre Hvacia() que establece, como es l'gico, que el mtodo no se puede invocar a menos que la pila no est vaca, dado que si est! vaca no e/iste la cima. "sta precondici'n se corresponde directamente con la precondici'n siguiente de la especificaci'n del ;*D: cima(p:Pila[G]) require vaca(p) ) (also ,igamos con el mtodo desapila(), el cual quita el elemento que est! en la cima. De forma semejante al caso anterior, su precondici'n es: 7pre Hvacia() que establece, como es l'gico, que el mtodo no se puede invocar a menos que la pila no est vaca, dado que si est! vaca no $ay elemento en la cima que se pueda desapilar. "sta precondici'n se corresponde directamente con la precondici'n siguiente de la especificaci'n del ;*D: desapila(p:Pila[G]) require vaca(p) ) (also La postcondici'n del mtodo desapila() es: 7pos" c$en"a() )) old c$en"a() - ! la cual presenta una notaci'n especial, old. Los mtodos la utilian para e/presar cambios8 as, en este caso, el mtodo desapila() la utilia para e/presar los cambios de c$en"a(). La notaci'n old e, en donde e es una e/presi'n, denota el valor de e antes de entrar en el mtodo. "n una postcondici'n toda aparici'n de e que no est precedida por old denota el valor de esa e/presi'n al salir del mtodo. Dic$o esto, est! claro que esta postcondici'n no se corresponde directamente con ninguna ecuaci'n de la especificaci'n. Hntuitivamente, su certea es evidente puesto que, si la especificaci'n de la funci'n cuenta nos dice que apilar un nuevo elemento en una pila incrementa en uno el valor de cuenta, parece raonable concluir que desapilar un elemento de la pila decrementar! en uno dic$o valor. *$ora bien, -se puede demostrar que es cierta0 La respuesta es que s. :eamos c'mo. ;odo ;*D tiene propiedades que se deducen de su especificaci'n pero que no coinciden directamente con una de las ecuaciones. 7ay dos tipos de propiedades distintas, que e/igen demostraciones tambin distintas: Pr+piedades ecuaci+nales: son nuevas ecuaciones que se deducen de las ecuaciones de la especificaci'n mediante el c!lculo ecuacional, del cual ya $ablamos en su momento. Pr+piedades inductivas: son nuevas ecuaciones que se demuestran aplicando el principio de inducci'n estructural sobre los valores del ;*D. "s estructural el principio de inducci'n aplicado debido a que, dado que los valores del ;*D son generados por trminos construidos a partir de un conjunto finito de operaciones generadoras, se realia una inducci'n sobre la estructura de dic$os trminos. "l principio de inducci'n se aplica del modo siguiente: *ase de la inducci4n: se demuestra la propiedad para los valores b!sicos del ;*D, que son los generados por las operaciones generadoras constantes o por generadoras en cuyos argumentos no figuran valores del ;*D. Dip4tesis de inducci4n: para cada valor no b!sico, cuyo patr'n tiene como operaci'n m!s e/terna una generadora con argumentos del ;*D, se supondr! que dic$os argumentos satisfacen la propiedad. Pas+ de inducci4n: para cada valor no b!sico, se demostrar! que satisface la propiedad. :amos a demostrar que la postcondici'n es correcta demostrando que la siguiente ecuaci'n es cierta: Para "oda pila p:Pila[G] no vaca, c$en"a(desapila(p)) # c$en"a(p) ! (ara ello, se aplica el principio de inducci'n estructural: Base de la ind$cciKn Dea p # apila(crea, &) Xna Forma de ac"$ar es compro3ar, dado el valor de p an"erior B aplicando cSlc$lo ec$acional, %$e los dos lados de la ec$aciKn %$e se %$iere demos"rar son e%$ivalen"es al mismo valor1 Cs:
al"$ra(desapila(p)) # al"$ra(desapila(apila(crea, &) # al"$ra(crea) # 0 al"$ra(p) ! # al"$ra(apila(crea, &)) ! # al"$ra(crea) A ! ! # 0 A! ! # 0 PipK"esis de ind$cciKn Dea p # apila(%, &) donde % no es vaca, se p$ede aFirmar %$e c$en"a(desapila(%)) # c$en"a(%) ! Paso de ind$cciKn Dea p # apila(%, &) Re n$evo, $na Forma de ac"$ar es compro3ar, dado el valor de p an"erior B aplicando cSlc$lo ec$acional, %$e los dos lados de la ec$aciKn %$e se %$iere demos"rar son e%$ivalen"es al mismo valor1 Cs: al"$ra(desapila(p)) # al"$ra(desapila(apila(%, &) # al"$ra(%) al"$ra(p) ! # al"$ra(apila(%, &)) ! # ! A al"$ra(%) ! # al"$ra(%) (or tanto, queda demostrada que la postcondici'n es correcta puesto que se corresponde con una ecuaci'n deducida de la especificaci'n del ;*D mediante inducci'n. ,igamos con el mtodo vacia(), el cual informa si la pila est! vaca o no. La postcondici'n del mtodo vacia() es: 7pos" res$l" )) (c$en"a() )) 0) la cual presenta una notaci'n especial, res$l", que $ace referencia al resultado proporcionado por el mtodo. "n este caso, de nuevo nos encontramos con una postcondici'n no se corresponde directamente con ninguna ecuaci'n de la especificaci'n. Hntuitivamente, su certea es evidente puesto que la pila est! vaca si y s'lo si su n#mero de elementos es cero. *$ora bien, -se puede demostrar que esto es cierto0 La respuesta de nuevo es que s. :eamos c'mo aplicando de nuevo el principio de inducci'n estructural. :amos a demostrar que la postcondici'n es correcta demostrando que la siguiente ecuaci'n es cierta: Para "oda pila p:Pila[G], vacia(p) # c$en"a(p) ) 0 Base de la ind$cciKn Dea p # crea Xna Forma de ac"$ar es compro3ar, dado el valor de p an"erior B aplicando cSlc$lo ec$acional, %$e los dos lados de la ec$aciKn %$e se %$iere demos"rar son e%$ivalen"es al mismo valor1 Cs: vacia(crea) # 'erdadero c$en"a(crea) ) 0 # 0 ) 0 # 'erdadero PipK"esis de ind$cciKn Dea p # apila(%, &), se p$ede aFirmar %$e vacia(%) # c$en"a(%) ) 0 Paso de ind$cciKn Dea p # apila(%, &) Re n$evo, $na Forma de ac"$ar es compro3ar, dado el valor de p an"erior B aplicando cSlc$lo ec$acional, %$e los dos lados de la ec$aciKn %$e se %$iere demos"rar son e%$ivalen"es al mismo valor1 Cs: vacia(p) # vacia(apila(%, &)) # (also c$en"a(p) ) 0 # c$en"a(apila(%, &)) ) 0 # ! A c$en"a(%) ) 0 # (also (or tanto, queda demostrada que la postcondici'n es correcta puesto que se corresponde con una ecuaci'n deducida de la especificaci'n del ;*D mediante inducci'n. Las aserciones ilustran un concepto fundamental: la diferencia entre el punto de vista imperativo y el aplicativo. Mecordemos la postcondici'n de vacia(): 7pos" res$l" )) (c$en"a() )) 0) y a$ora la instrucci'n del cuerpo del mtodo que computa el valor requerido: 3oolean res$l" ) "8is1c$en"a() )) 04 (udiera uno preguntarse cu!l es la ra'n de esta postcondici'n si en el cuerpo del mtodo se tiene e/actamente lo mismo, con la #nica diferencia de que en ste se usa el operador de asignaci'n mientras que en la postcondici'n se usa el operador de igualdad. -No es redundante la postcondici'n0 Mealmente $ay una gran diferencia entre las dos construcciones y no $ay ninguna redundancia. La instrucci'n del cuerpo del mtodo es una orden que se le da al computador virtual <la m!quina $ard)are1soft)are= para cambiar su estado de una cierta manera y llevar a cabo una acci'n. La aserci'n no $ace nada: especifica una propiedad del estado final esperado y que es visible al mtodo que llama. La instrucci'n es prescriptiva y la aserci'n es descriptiva. La instrucci'n describe el c4m+ y la aserci'n describe el 1u:. La instrucci'n es parte de la implementaci'n8 la aserci'n es un elemento de especificaci'n. La instrucci'n es imperativa8 la aserci'n es aplicativa. Que esas dos notaciones sean tan parecidas no debe oscurecer su diferencia fundamental. La aserci'n describe la intenci'n de un resultado y la instrucci'n 1el cuerpo de la rutina1 describe una forma particular de alcanar dic$o resultado. *lguien que est usando una clase para escribir una clase cliente estar! interesado tpicamente en la aserci'n pero no en la implementaci'n. La ra'n de la similitud entre las notaciones de la asignaci'n y de la igualdad es que la asignaci'n es en muc$os casos la forma elemental de lograr la igualdad. (or tanto, la presencia de los elementos respectivos en el cuerpo y la postcondici'n no es una evidencia de redundancia, sino que es una evidencia de la consistencia entre la implementaci'n y la especificaci'n 1es decir, de la correcci'n tal y como fue definido este concepto anteriormente. ,igamos con el mtodo apila(), el cual a+ade un elemento a la cima de la pila. Dado que no tiene precondici'n e/plcitamente definida, esto quiere decir que su precondici'n es "r$e, como ya se e/plic' anteriormente. La postcondici'n de este mtodo presenta una caracterstica especial. 7ay dos etiquetas en este mtodo que definen la postcondici'n, la etiqueta 7pos" que ya conocemos, formada por varias cl!usulas, y la etiqueta 7pos"Priva"e. :amos a estudiar en primer lugar esta #ltima antes de analiar las cl!usulas de la primera. La etiqueta 7pos"Priva"e define una postcondici'n privada, en concreto: 7pos"Priva"e represen"a"ion10e"(c$en"a() - !) )) i"em c8ec/NliFo(old "8is) -Qu es una postcondici'n privada0 D!sicamente, una postcondici'n que no aparece en la documentaci'n p#blica de la clase que se entrega a los autores de las clases clientes. Dien, $ay dos raones posibles por las que una postcondici'n puede ser privada. "studiemos la primera de ellas. "/iste un requisito suplementario para las precondiciones que no figura en el principio de la precondici'n raonable: para que una precondici'n pueda ser satisfec$a por un cliente, la precondici'n no debe utiliar caractersticas de la clase que debido a restricciones de e/portaci'n estn ocultas a los clientes. Llegamos as a la regla de disponibilidad de la precondicin: Toda caracterstica que aparezca en la precondicin de un mtodo debe estar disponible para cualquier cliente para el que est disponible dic,o mtodo) Aon esta regla todo cliente que est en situaci'n de llamar a una caracterstica tambin estar! en posici'n de verificar su precondici'n, lo cual es l'gico: no tiene sentido incluir en la precondici'n de un mtodo, por ejemplo, caractersticas secretas de la clase que ning#n cliente puede utiliar para saber si est! en condiciones de invocar correctamente a dic$o mtodo. ,in embargo, no $ay una regla similar para las postcondiciones. No es un error el que algunas cl!usulas de una cl!usula de postcondici'n se refieran a caractersticas secretas, o a caractersticas que no se e/porten con tanta amplitud como el mtodo al que pertenecen dic$as cl!usulas8 esto significa simplemente que se est!n e/presando propiedades del efecto del mtodo que no son utiliables directamente por los clientes. Gste es el caso de la primera cl!usula de la postcondici'n privada del mtodo apila() que nos ocupa: represen"a"ion10e"(c$en"a() - !) )) i"em "sta cl!usula indica que el elemento que se acaba de a+adir a la pila est! situado al final del CrraB;is" represen"a"ion. ,e trata de una propiedad de implementaci'n. Las propiedades de implementaci'n no se corresponden directamente con ecuaci'n alguna de la especificaci'n del ;*D, ni tampoco se corresponden con una ecuaci'n que sea una propiedad ecuacional o inductiva obtenida a partir de la especificaci'n del ;*D. *s, aun cuando apila() es p#blico y por tanto se e/porta a todo el mundo, el atributo represen"a"ion es secreto. (ero no $ay nada incorrecto con esta postcondici'n8 se limita a a+adir, a las otras propiedades que son #tiles para los clientes y que vienen e/presadas en la etiqueta 7pos", una que s'lo es significativa para alguien que lea el te/to de la clase completa. ;ales cl!usulas que forman parte de postcondiciones privadas no aparecer!n en la documentaci'n de la clase que se pone a disposici'n de los autores de las clases cliente. "n este punto, es conveniente remarcar algo. Aomo es l'gico y se $a e/plicado, a los desarrolladores se les entrega #nicamente la documentaci'n de la clase que necesitan para escribir las clases clientes, ya que no es necesario proporcionarles informaci'n e/tra que los sumerja en un mar de detalles que para ellos son innecesarios y a la larga les pueda $acer m!s difcil su trabajo. No obstante, la ocultaci'n de la informaci'n no versa sobre ocultar el c'digo fuente al cliente 1es decir, al autor de las clases cliente1, sino sobre que ste no pueda escribir su c'digo bas!ndose en caractersticas secretas, incluyendo entre ellas la representaci'n interna de la clase. (or ello, las precondiciones deben usar siempre caractersticas p#blicas, que son visibles para el cliente, de modo que ste pueda comprobar que se cumplen. ,in embargo, las postcondiciones 1y los invariantes, como veremos pronto1 no tienen que cumplir este requisito: en este caso no es un error incluir caractersticas secretas porque ello no causa problemas al cliente. "n cualquier caso, las aserciones informan al cliente qu $ace la clase pero no le informan de los detalles de c'mo lo $ace aun cuando las postcondiciones y el invariante puedan eventualmente mostrar caractersticas secretas. *unque el cliente pueda leer las cl!usulas de las postcondiciones y del invariante que muestran propiedades de implementaci'n de la clase, del mismo modo que aunque el cliente pueda leer el te/to fuente completo de la clase, no se viola la ocultaci'n de la informaci'n porque al cliente no se le permite escribir una clase cliente bas!ndose en esas caractersticas secretas, incluida entre ellas la representaci'n interna de la clase, por la simple ra'n de que no puede acceder a ellas: el cliente s'lo puede acceder a las caractersticas p#blicas para escribir el c'digo de sus clases cliente, que es al fin y al cabo el objetivo perseguido por la ocultaci'n de la informaci'n. (or ello, una ve m!s remarcamos que ocultar las propiedades de implementaci'n de la clase al cliente tiene como #nico objetivo no despistarle con informaci'n innecesaria para su trabajo y as proporcionarle s'lo la informaci'n que necesita de verdad para escribir sus clases clientes. (or tanto, la primera ra'n posible para que una postcondici'n sea privada es que e/prese una propiedad de implementaci'n. *$ora vamos a ver la segunda ra'n por la que una postcondici'n puede ser privada. "sta segunda ra'n se presenta en la segunda cl!usula de la postcondici'n privada del mtodo apila() que nos ocupa: c8ec/NliFo(old "8is) "sta cl!usula se corresponde con el siguiente a/ioma de la especificaci'n del ;*D: desapila(apila(p, &)) # p No obstante, es f!cil ver que la correspondencia en este caso no es directa, debido a que no $ay una manera directa de e/presar mediante una aserci'n dic$o a/ioma. -(or qu0 "l lenguaje de aserciones que se $a utiliado es esencialmente el lenguaje de las e/presiones booleanas, e/tendido con unos pocos conceptos tales como old. Aomo resultado, puede resultar e/cesivamente restrictivo cuando se quieren incluir en las clases algunas de las propiedades que eran f!ciles de e/presar en la notaci'n matem!tica de los tipos abstractos de datos. *$ora bien, la limitaci'n no es tan estricta como puede parecer a simple vista, debido a que en las e/presiones booleanas puede $aber llamadas a funciones 1naturalmente, cuando $ablamos de funciones nos referimos a mtodos que proporcionan un resultado1. De $ec$o, lo que $ace la aserci'n de esta #ltima cl!usula es precisamente eso: invocar a una funci'n privada que comprobar! que la pila verifica la poltica LHJF que la caracteria, que es al fin y al cabo lo que e/presa dic$o a/ioma que no puede e/presarse directamente mediante una aserci'n. (or tanto, debido a una limitaci'n en el lenguaje de aserciones, se $a necesitado definir una funci'n privada para as poder definir una aserci'n8 dado que esa funci'n privada no aporta nada al cliente, dic$a aserci'n forma parte de una postcondici'n privada y, por tanto, no aparecer! en la documentaci'n de la clase que se le proporcionar! al autor de las clases clientes de la nuestra. Aomo es l'gico, si la funci'n no fuera privada, como ya $emos visto en otras aserciones, s que aparecera la aserci'n en la documentaci'n p#blica de la clase. Mesumiendo: tenemos dos raones distintas para $acer que una postcondici'n sea privada y que por tanto no apareca en la documentaci'n p#blica de la clase, para as no despistar con detalles innecesarios al autor de las clases clientes de aquella clase. @racias a las funciones, que nos dan la posibilidad de computar un valor booleano en la forma que se quiera, podemos e/presar conceptos que antes no nos era posible enunciar con la frrea disciplina del c!lculo proposicional de nuestro lenguaje de aserciones. *dem!s, utiliar funciones es una forma evidente de obtener aserciones m!s abstractas. No obstante, $ay un riesgo: tan pronto como se permitan funciones en las aserciones, se est!n introduciendo elementos potencialmente imperativos en el mundo puramente aplicativo de las aserciones. (or ello, cualquier funci'n que se utilice en una aserci'n para especificar las propiedades de un elemento soft)are debe ser imperativamente intac$able, es decir, no debe causar ning#n cambio permanente en el estado del objeto8 por ello, como se puede ver en la implementaci'n de la funci'n c8ec/NliFo(), se trabaja con copias idnticas en profundidad de los objetos de modo que el objeto actual no se vea modificado de ninguna forma. De $ec$o, la e/istencia del mtodo c8ec/NliFo() es la ra'n de que se $ayan implementado clone() y e%$als(), y debido a que se implementa este #ltimo mtodo se $a implementado tambien 8as8Lode(). "n concreto, clone() implementa una clonaci'n profunda utiliando serialiaci'n, que es una tcnica lenta pero simple y efica. Aomo se $a comentado, c8ec/NliFo() trabaja con clones para evitar modificar el objeto actual dado que nuestra clase no es inmutable. *s, lo que $ace este mtodo es comprobar que, al desapilar un clon del objeto actual, obtenemos un objeto que es igual al clon del objeto que e/ista antes de sufrir el apilamiento del nuevo elemento. Lo cual como es l'gico permite verificar que la clase cumple la propiedad lifo. 7ay un asunto tcnico que puede $aber llamado la atenci'n. 9na funci'n 0 utiliada en una aserci'n para un mtodo m 1o utiliada en el invariante de la clase que contiene a m1 puede en s misma tener aserciones. "sto plantea un problema potencial en el control de las aserciones en tiempo de ejecuci'n: si como parte de una llamada a m se eval#a una aserci'n y esto causa una llamada a 0, no se quiere que la llamada eval#e ninguna aserci'n que 0 a su ve pueda tener. (or una parte, es f!cil construir ejemplos que podran causar una recursividad infinita. (ero incluso sin este riesgo sera incorrecto evaluar las aserciones de 0. "sto significara que se tratan como iguales los mtodos para computar los servicios propios de la clase, tales como m, y las funciones de sus aserciones, tales como 0 1lo que contradice la regla de que las aserciones debieran estar en un plano m!s alto que el soft)are que protegen y que su correcci'n debe ser tan clara como el agua1. La regla entonces es simple y se llama regla de evaluacin de aserciones: Durante el proceso de evaluacin de una asercin en tiempo de ejecucin7 las llamadas a mtodos deben ejecutarse sin evaluar las aserciones asociadas) ,i una llamada a 0 se produce como parte de una comprobaci'n de aserciones para m, es muy tarde para preguntar si 0 satisface sus aserciones. "l momento adecuado para $acer esto es cuando se decide utiliar a 0 en las aserciones aplicables a m. ,e puede utiliar una analoga. (iense en 0 como en un guarda de seguridad a la entrada de una planta nuclear, a cargo de inspeccionar las credenciales de los visitantes. ;ambin puede $aber requisitos sobre los guardas. (ero stos $abr! que comprobarlos con antelaci'n, no mientras estn controlando las credenciales de los visitantes. :olviendo al c'digo de nuestra clase, se puede ver en el te/to que cada precondici'n de un mtodo p#blico tiene asociado un mtodo privado que verifica el cumplimiento de la precondici'n empleando para dic$a verificaci'n la instrucci'n assert, la cual lana una e/cepci'n que detiene la ejecuci'n del programa si la e/presi'n booleana e/aminada no es cierta. De igual modo se $ace para cada postcondici'n de un mtodo p#blico. *dem!s, e/iste un mtodo privado que verifica que se cumple el invariante de la clase. Aomo se puede comprobar en el c'digo, el invariante se verifica tanto a la entrada como a la salida de cada mtodo p#blico. ;al y como $emos implementado en nuestra clase el control de aserciones en tiempo de ejecuci'n, es muy simple $acer que se cumpla la regla de evaluaci'n de aserciones. (ara garantiar que se cumple dic$a regla, la primera tarea que realia cada mtodo privado encargado de verificar una aserci'n es poner a true un atributo de la clase llamado 2uarda. * continuaci'n, se verifica si se cumple o no la aserci'n. "n dic$a verificaci'n, cualquier mtodo invocado comprueba en primer lugar el valor del atributo 2uarda, de modo que si dic$o valor es true no verifica sus aserciones asociadas. 9na ve que el mtodo privado $a terminado de verificar la aserci'n correspondiente, pone a 0alse el atributo 2uarda, de modo que cuando un cliente invoque un mtodo p#blico de la clase, ste comprobar! que 2uarda tiene valor 0alse y por tanto verificar! sus aserciones. 9na ve e/plicado el concepto de postcondici'n privada, recordemos cu!les son las cl!usulas de la postcondici'n p#blica de apila(). La cl!usula cima() )) i"em se corresponde directamente con la ecuaci'n siguiente de la especificaci'n del ;*D: cima(apila(p, &)) # & La cl!usula Hvacia() se corresponde directamente con la ecuaci'n siguiente de la especificaci'n del ;*D: vaca(apila(p, &)) # (also La cl!usula c$en"a() )) old c$en"a() A ! se corresponde directamente con la ecuaci'n siguiente de la especificaci'n del ;*D: c$en"a(apila(p, &)) ) ! A c$en"a(p) ,igamos con el mtodo constructor pila(), el cual crea una pila vaca. Nos encontramos de nuevo con que la postcondici'n de este mtodo presenta una parte p#blica y una parte privada. La cl!usula de la postcondici'n privada es: 7pos"Priva"e represen"a"ion H) n$ll "sta cl!usula indica que el atributo privado represen"a"ion $a sido inicialiado a un valor no nulo. ,e trata, como corresponde a una postcondici'n privada, de una propiedad de implementaci'n que, por tanto, no se corresponde con ecuaci'n alguna de la especificaci'n del ;*D. *nalicemos a$ora el resto de cl!usulas de la postcondici'n, las que corresponden a la postcondici'n p#blica. La cl!usula vacia() se corresponde directamente con la ecuaci'n siguiente de la especificaci'n del ;*D: vacia(crea) # 'erdadero 2 la cl!usula c$en"a() ) 0 se corresponde directamente con la ecuaci'n siguiente de la especificaci'n del ;*D: c$en"a(crea) # 0 (or #ltimo, nos queda analiar el invariante de la clase. "l invariante de la clase presenta una parte p#blica y una parte privada. La cl!usula que constituye el invariante p#blico, que es visible a los autores de las clases clientes, es: 7invarian" c$en"a() :) 0 la cual no se corresponde directamente con ninguna ecuaci'n de la especificaci'n del ;*D. Hntuitivamente, su certea es evidente puesto que el n#mero de elementos de la pila siempre $a de ser mayor o igual que cero. *$ora bien, -se puede demostrar que esto es cierto0 (ues de nuevo la respuesta es que s, aplicando otra ve el principio de inducci'n estructural. :amos a demostrar que esta cl!usula es correcta demostrando que la siguiente ecuaci'n es cierta: Para "oda pila p:Pila[G], c$en"a(p) Y 0 # 'erdadero Base de la ind$cciKn Dea p # crea c$en"a(crea) Y 0 # 0 Y 0 # 'erdadero PipK"esis de ind$cciKn Dea p # apila(%, &), se p$ede aFirmar %$e c$en"a(%) Y 0 # 'erdadero Paso de ind$cciKn Dea p # apila(%, &) c$en"a(p) Y 0 # c$en"a(apila(%, &)) Y 0 # ! A c$en"a(%) Y 0 # 'erdadero (or tanto, queda demostrada que la cl!usula es correcta puesto que se corresponde con una ecuaci'n deducida de la especificaci'n del ;*D mediante inducci'n. *nalicemos a$ora el invariante privado, que es: 7invarian"Priva"e c$en"a() )) represen"a"ion1siEe() (c$en"a() : 0) implies (represen"a"ion10e"(c$en"a() - !) )) cima()) La primera cl!usula e/presa que el n#mero de elementos apilados en la pila, que es el resultado que devuelve el mtodo c$en"a(), se corresponde con el resultado que devuelve el mtodo siEe() del atributo privado represen"a"ion. La segunda cl!usula establece que el $ec$o de que el n#mero de elementos apilados en la pila sea mayor que cero implica que el elemento que se $aya en la cima de la pila es el que est! situado al final del atributo privado CrraB;is" represen"a"ion. "n esta segunda cl!usula, la notaci'n implies describe la implicaci'n definida en la l'gica matem!tica8 as: a implies 3 se define como no" a or 3. *l igual que ocurre con las postcondiciones privadas, ciertas aserciones aparecen en el invariante de clase aunque no se corresponden directamente con ecuaci'n alguna de la especificaci'n del ;*D, ni tampoco se corresponden con una ecuaci'n que sea una propiedad ecuacional o inductiva obtenida a partir de la especificaci'n del ;*D. "stas aserciones son propiedades de implementaci'n que involucran atributos secretos que por definici'n no seran significativos en el tipo abstracto de datos. Aomo ejemplos tenemos las dos cl!usulas anteriores del invariante privado. "l invariante privado, al igual que las postcondiciones privadas, no aparece en la documentaci'n p#blica que se entrega a los autores de las clases cliente. ,in embargo, lo m!s importante, y que qui! el lector ya $aya supuesto, es que el invariante de la clase es el invariante de implementaci'n o invariante de representaci'n, del que $ablamos largo y tendido en su momento. Las aserciones del invariante de clase sirven para e/presar la consistencia de la representaci'n escogida en la clase en consonancia con el tipo abstracto de datos correspondiente. *lgunas de ellas ser!n visibles al cliente y otras 1las que involucran atributos secretos1 no lo ser!n. *$ora es el momento de enfrentarnos en su totalidad a la pregunta %-cu!l es el efecto de las aserciones en tiempo de ejecuci'n0&. ,i el control de aserciones en tiempo de ejecuci'n est! activado al nivel m!s alto 1como en el c'digo fuente de nuestra clase1, no tiene efecto visible 1salvo en los ciclos de A(9 que son necesarios para evaluarlas1 mientras las aserciones controladas tengan el valor verdadero. (ero el que un aserci'n tome el valor falso al evaluarse es un suceso bastante serio que normalmente conducir! a terminar la ejecuci'n. Aomo ya se $a comentado anteriormente, en realidad se disparar! una e/cepci'n pero, a menos que se $ayan tomado medidas especiales para capturar la e/cepci'n, todo se detendr!. -Qu nivel de seguimiento de las aserciones se debe activar0 La respuesta es un compromiso entre las consideraciones siguientes: cu!nto se debe confiar en la correcci'n del soft)are8 qu crucial es obtener la m!/ima eficiencia8 qu consecuencias serias puede tener un error no detectado durante la ejecuci'n. "n los casos e/tremos la situaci'n est! clara: Auando se est! depurando un sistema, o m!s generalmente cuando se est! probando antes de su distribuci'n, se debe activar el control de las aserciones al nivel m!s alto. ,i se tiene un sistema completamente fiable en un !rea de aplicaci'n en la que sea crucial la eficiencia 1del tipo en que cada microsegundo cuenta1 se puede considerar quitar todos los controles. "n este caso, se convertiran en comentarios todas aquellas lneas del c'digo fuente dedicadas solamente a controlar aserciones. "sta #ltima sugerencia es en parte parad'jica ya que no suele ser posible confiar plenamente en un sistema salvo que se controlen sus aserciones. Gste es un caso especial de una observaci'n general efectuada con su elocuencia caracterstica por A.*.M. 7oare: Es absurd+ 9acer c+mpr+baci+nes elab+radas en las eBecuci+nes de depuraci4n' cuand+ nadie c+n0a en l+s resultad+s y lue2+ 1uitarlas en las eBecuci+nes de pr+ducci4n' en las 1ue un resultad+ err4ne+ p+dra ser c+st+s+ y desastr+s+? 36u: pensaram+s de un mariner+ entusiasta 1ue se pusiera el c9alec+ salvavidas cuand+ entrenase en tierra 0irme per+ se l+ 1uitase al 9acerse a la mar5 9na soluci'n de compromiso interesante es verificar en tiempo de ejecuci'n #nicamente las precondiciones. "n este caso, se convertiran en comentarios todas aquellas lneas del c'digo fuente dedicadas solamente a controlar postcondiciones e invariantes. "n ejecuciones del soft)are en producci'n 1es decir, pasado la depuraci'n y el control de calidad1 esto tiene la ventaja de evitar cat!strofes que podran producirse por llamadas no detectadas a rutinas sin cumplir sus requisitos, al tiempo que cuesta significativamente menos durante la ejecuci'n que comprobar tambin que se verifican las postcondiciones y los invariantes. (ara terminar, veamos c'mo queda, medianta la $erramienta Bavad+c, la documentaci'n que recibe el autor de las clases cliente de la nuestra: org)jomaveger)dbc "lass %ila89: java.lang.Object |_ org.jomaveger.dbc.Pila<G> public class Pila<G> extends java.lang.Object Aut,or1 jomaveger Description1 (ilas: una estructura dispensadora con poltica LHJF: el #ltimo elemento en entrar es el primero en salir. ;ienen capacidad ilimitada. 6nvariant1 cuenta<= NO 4 "onstructor +ummar- Pila() Area una pila vaca ;et,od +ummar- void apila(G item) *+ade un elemento a la cima G cima() Devuelve el elemento que est! en la cima Pila<G> clone() Mealia una copia en profundidad del objeto actual. int cuenta() Devuelve el n#mero de elementos que $ay en la pila void desapila() Quita el elemento que est! en la cima boolean equals(java.lang.Object obj) Aompara en profundidad si el objeto actual es igual al objeto que recibe como par!metro real. int hashCode() Devuelve el c'digo de dispersi'n del objeto actual boolean vacia() -7ay elementos en la pila0 ;et,ods in,erited from class java)lang)<bject finalize, getClass, notify, notifyAll, toString, wait, wait, wait "onstructor Detail
%ila public Pila() Area una pila vaca %ost1 vacia<= cuenta<= OO 4 ;et,od Detail vacia public boolean vacia() -7ay elementos en la pila0 %ost1 result OO <cuenta<= OO 4= cima public G cima() Devuelve el elemento que est! en la cima %re1 ?vacia<= desapila public void desapila() Quita el elemento que est! en la cima %re1 ?vacia<= %ost1 cuenta<= OO old cuenta<= 1 6 apila public void apila(G item) *+ade un elemento a la cima %ost1 cima<= OO item ?vacia<= cuenta<= OO old cuenta<= P 6 cuenta public int cuenta() Devuelve el n#mero de elementos que $ay en la pila equals public boolean equals(java.lang.Object obj) Aompara en profundidad si el objeto actual es igual al objeto que recibe como par!metro real. <verrides1 equals in class java.lang.Object ,as,"ode public int hashCode() Devuelve el c'digo de dispersi'n del objeto actual <verrides1 hashCode in class java.lang.Object clone public Pila<G> clone() Mealia una copia en profundidad del objeto actual. <verrides1 clone in class java.lang.Object Agradecimientos1 * D. Micardo (e+a Car, Aatedr!tico de Lenguajes y ,istemas Hnform!ticos de la 9niversidad Aomplutense de Cadrid, por sus encomiables paciencia y atenci'n a la $ora de resolver mis dudas. * D. Dertrand Ceyer, creador del lenguaje "iffel, por su generosa dedicaci'n a la $ora de contestar mis preguntas, lo que apareci' reflejado en este documento. /ibliografa1 C+nstrucci4n de S+0tEare Orientad+ a ObBet+s, Dertrand Ceyer, "d. (renctice 7all, BQ "dici'n, 6RRR. DiseF+ de Pr+2ramasG F+rmalism+ y Abstracci4n, Micardo (e+a Car, "d. (rentice 7all K (earson "ducaci'n, SQ "dici'n, B44T C+re Hava . ,+l? - I Fundament+s, Aay 7orstmann U @ary Aornell, "d. (rentice 7all 1 (earson "ducaci'n, 3Q "dici'n, B44T. ObBectCOriented Pr+2rammin2 in Ei00el, (ete ;$omas U May Veedom, "d. *ddison1Vesley, BQ "dici'n, 6RRW. Pr+2ramaci4n met4dica, Ios Luis Dalc!ar, "d. Cc@ra)17ill, 6RRS. Estructuras de dat+s y m:t+d+s al2+rtmic+s I EBercici+s resuelt+s, Narciso Cart Fliet U 2olanda Frtega Calln U Ios *lberto :erdejo L'pe, "d. (rentice 7all K (earson "ducaci'n, B44S. Desi2n by C+ntract' by E(ample, Mic$ard Citc$ell U Iim CcXim, "d. *ddison1Vesley, B44B. Data Structures And S+0tEare Devel+pment In An ObBectCOriented D+main I Hava Editi+n, Iean1(aul ;remblay U @rant *. A$eston, "d. (rentice 7all, B44S Data Structures And S+0tEare Devel+pment In An ObBectCOriented D+main I Ei00el Editi+n, Iean1(aul ;remblay U @rant *. A$eston, "d. (rentice 7all, B446 Jos Mara Vegas Gertrudix