Introducción a la metodología de diseño descendente

Introducción a la metodología de diseño descendente Introducción a la metodología de diseño descendente

12.07.2015 Views

Introduccióna la metodologíade diseñodescendenteJosep Vilaplana PastóM. Jesús Marco GalindoP05/75062/00112

<strong>Introducción</strong>a <strong>la</strong> <strong>metodología</strong><strong>de</strong> <strong>diseño</strong><strong>de</strong>scen<strong>de</strong>nteJosep Vi<strong>la</strong>p<strong>la</strong>na PastóM. Jesús Marco GalindoP05/75062/00112


© FUOC • P05/75062/00112 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteÍndice<strong>Introducción</strong>............................................................................................... 5Objetivos ...................................................................................................... 81. Diseño <strong>de</strong>scen<strong>de</strong>nte.............................................................................. 91.1. Análisis <strong>de</strong> problemas complejos ...................................................... 91.2. ¿Análisis ascen<strong>de</strong>nte o <strong>de</strong>scen<strong>de</strong>nte? ................................................ 101.3. Orientaciones <strong>de</strong> <strong>la</strong>s abstracciones .................................................... 121.4. Formas <strong>de</strong> trabajar y presentar el <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte...................... 131.5. Herramientas <strong>de</strong> <strong>la</strong> notación para abstraer datos.............................. 161.6. Herramientas <strong>de</strong> <strong>la</strong> notación para abstraer código ............................ 191.7. Trabajando con profundidad el ejemplo........................................... 211.8. Valoración final <strong>de</strong> <strong>la</strong> <strong>metodología</strong> ................................................... 261.9. Últimas observaciones ....................................................................... 28Resumen....................................................................................................... 29Ejercicios <strong>de</strong> autoevaluación .................................................................. 37Solucionario................................................................................................ 41Glosario........................................................................................................ 56Bibliografía................................................................................................. 56


© FUOC • P05/75062/00112 5 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte<strong>Introducción</strong>En este módulo apren<strong>de</strong>remos a <strong>de</strong>sarrol<strong>la</strong>r algoritmos para problemas máscomplicados que los que hemos visto hasta ahora. No introduciremos ningúnelemento más <strong>de</strong>l lenguaje algorítmico. Lo que haremos, en todo caso, es madurarel uso que daremos a algunos <strong>de</strong> los elementos, como por ejemplo <strong>la</strong> <strong>de</strong>c<strong>la</strong>ración<strong>de</strong> acciones, <strong>la</strong>s funciones y <strong>la</strong> <strong>de</strong>finición <strong>de</strong> nuevos tipos. Dicho <strong>de</strong>otro modo, aquí propondremos una <strong>metodología</strong> por <strong>la</strong> cual llegaremos, si <strong>la</strong>seguimos, al <strong>diseño</strong> <strong>de</strong> algoritmos correctos e inteligibles que solucionan enunciadosmás complejos.Pensad que...... el seguimiento <strong>de</strong> <strong>la</strong> <strong>metodología</strong>que propondremos servirápara que nuestros <strong>diseño</strong>s sehagan en un tiempo <strong>de</strong> <strong>de</strong>sarrollomínimamente razonable,<strong>de</strong> modo que aumente nuestrogrado <strong>de</strong> eficacia al producir algoritmoscorrectos. Recordadlos objetivos que nos habíamospropuesto en el módulo “<strong>Introducción</strong>a <strong>la</strong> programación”.Hasta ahora nos hemos <strong>de</strong>dicado, por un <strong>la</strong>do, a apren<strong>de</strong>r <strong>la</strong> sintaxis y <strong>la</strong> semántica<strong>de</strong> los elementos <strong>de</strong>l lenguaje algorítmico. Con <strong>la</strong> resolución <strong>de</strong> problemassencillos hemos <strong>de</strong>sarrol<strong>la</strong>do <strong>la</strong> <strong>de</strong>streza al expresar nuestros algoritmos <strong>de</strong> formac<strong>la</strong>ra y no ambigua. A pesar <strong>de</strong> ello, para diseñar nuestros primeros algoritmoshemos estudiado unas pautas metodológicas basadas en <strong>la</strong> aplicación <strong>de</strong> losesquemas <strong>de</strong> tratamiento secuencial. El uso <strong>de</strong> estos esquemas nos ayuda a evitarerrores típicos en los que po<strong>de</strong>mos caer, así como a formu<strong>la</strong>r algoritmos inteligibles.Así pues, <strong>la</strong> <strong>metodología</strong> que se imparte en este curso no es exclusiva <strong>de</strong> estemódulo, sino que en los módulos anteriores ya se ha propuesto <strong>de</strong> forma progresivauna <strong>metodología</strong> que hay que seguir para problemas más sencillos quelos que encontraremos a partir <strong>de</strong> este momento. Sin embargo, todo lo que hemosaprendido gracias a estos problemas más sencillos nos servirá tambiénpara los problemas complejos que propondremos más a<strong>de</strong><strong>la</strong>nte.Los problemas sencillos que hemos estado resolviendo se caracterizan por teneruna solución que utiliza un número razonable <strong>de</strong> elementos básicos <strong>de</strong>llenguaje algorítmico.Los enunciados <strong>de</strong> los problemas sencillos hacen referencia a objetosque están muy cercanos a los tipos elementales <strong>de</strong> lenguaje o que sondirectamente representables por éstos.El tratamiento que hay que aplicar a estos objetos se pue<strong>de</strong> alcanzar con unaspocas asignaciones y con algunas construcciones algorítmicas. El resultado finales un algoritmo comprensible y legible en términos <strong>de</strong> los elementos básicos<strong>de</strong>l lenguaje algorítmico.


© FUOC • P05/75062/00112 6 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteAl <strong>de</strong>sarrol<strong>la</strong>r aplicaciones más reales, nos encontramos con problemas gran<strong>de</strong>sy complejos.Los enunciados <strong>de</strong> problemas complejos hacen referencia a objetos queno tienen una correspon<strong>de</strong>ncia directa con los tipos elementales <strong>de</strong> <strong>la</strong>notación algorítmica.El tratamiento <strong>de</strong> estos objetos pue<strong>de</strong> no ser elemental y, asimismo, tambiénpue<strong>de</strong> llevar a un número <strong>de</strong> sentencias y <strong>de</strong>c<strong>la</strong>raciones excesivamente elevado,si expresamos todo lo que hay que hacer como una composición secuencial<strong>de</strong> asignaciones, iteraciones y/o alternativas.El resultado es un algoritmo <strong>de</strong> muchas páginas, difícil <strong>de</strong> seguir y, por lo tanto,también <strong>de</strong> saber si funciona, y lleno <strong>de</strong> <strong>de</strong>talles (algunas veces repetidos)que lo hacen prácticamente ilegible. El número <strong>de</strong> <strong>de</strong>talles que hay que teneren cuenta es excesivo, y nuestra capacidad <strong>de</strong> ser conscientes <strong>de</strong> todos los <strong>de</strong>talleses limitada. Pensar estos enunciados en términos <strong>de</strong> los elementos básicos<strong>de</strong>l lenguaje, sin unas pautas que seguir, nos pue<strong>de</strong> comportar muchosquebra<strong>de</strong>ros <strong>de</strong> cabeza y bastante dispersión mental, <strong>de</strong> forma que disminuyenuestra capacidad <strong>de</strong> comprensión sobre lo que hacemos y, por lo tanto,nuestra seguridad sobre si estamos realizando un algoritmo correcto y legible(mantenible). Con estas circunstancias, llegamos a <strong>la</strong> conclusión <strong>de</strong> que <strong>la</strong> notaciónalgorítmica es tan elemental que hace incómodo y poco práctico el <strong>de</strong>sarrollo<strong>de</strong> aplicaciones reales, y <strong>de</strong> que haría falta un lenguaje más cómodoque comprendiese objetos más reales.¿Os imagináis...... lo que conseguiríamos si expusiésemosel funcionamiento<strong>de</strong> un programa en términos<strong>de</strong>l movimiento <strong>de</strong> electronesque hay por <strong>la</strong>s pistas <strong>de</strong> cobre<strong>de</strong> <strong>la</strong> p<strong>la</strong>ca <strong>de</strong> circuito impresoy en el silicio <strong>de</strong> vuestro or<strong>de</strong>nador?Acabaríamos confundidosy distraídos por el exceso<strong>de</strong> información en <strong>la</strong> exposición,y per<strong>de</strong>ríamos toda referenciaa aquello <strong>de</strong> lo queestamos hab<strong>la</strong>ndo.Si este apreciado lenguaje existiese, con <strong>la</strong> cantidad y <strong>la</strong> variedad <strong>de</strong> problemasque hay por resolver, tendría un número tan gran<strong>de</strong> <strong>de</strong> acciones y tipos quenunca acabaríamos <strong>de</strong> conocerlo a fondo. Se pue<strong>de</strong>n encontrar algunos lenguajesespecíficos para algunas aplicaciones concretas, pero cuando no los encontramos,¿qué hacemos?La notación algorítmica tiene los suficientes elementos para construircualquier algoritmo que <strong>de</strong>seemos a partir <strong>de</strong> los tipos elementales, <strong>la</strong>asignación y <strong>la</strong>s composiciones algorítmicas. El lenguaje algorítmicotambién permite ampliar el propio lenguaje <strong>de</strong>finiendo y construyendotipos más complejos y <strong>de</strong>finiendo <strong>la</strong>s acciones y/o funciones que másnos convengan.Con <strong>la</strong>s características <strong>de</strong>l lenguaje algorítmico, todo lo que nos hace falta essaber qué <strong>metodología</strong> <strong>de</strong>bemos seguir para llevar a buen fin el <strong>diseño</strong> <strong>de</strong> unproblema complejo. Esta <strong>metodología</strong> consistirá en <strong>de</strong>scomponer un proble-


© FUOC • P05/75062/00112 7 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntema complejo en subproblemas más sencillos e in<strong>de</strong>pendientes entre sí. La solución<strong>de</strong> estos subproblemas implicará <strong>la</strong> solución <strong>de</strong>l problema. Por otro<strong>la</strong>do, <strong>la</strong> <strong>de</strong>scomposición <strong>de</strong>l problema se hace mediante <strong>la</strong> abstracción.La abstracción es el resultado <strong>de</strong> ais<strong>la</strong>r ciertos aspectos (cualidad, atributos,etc.) <strong>de</strong> un todo para po<strong>de</strong>r razonar o pensar <strong>de</strong> forma más cómoday menos dispersa (en nuestro caso, para <strong>la</strong> solución <strong>de</strong> problemas).En el fondo, se trata <strong>de</strong> simplificar alguna realidad y reducir<strong>la</strong> sólo a los aspectosque tengan una especial relevancia o un interés <strong>de</strong>terminado para lo queestamos pensando o haciendo.Hemos estado utilizando <strong>la</strong> abstracción prácticamente <strong>de</strong>s<strong>de</strong> el inicio <strong>de</strong>l curso:el mo<strong>de</strong>lo <strong>de</strong> secuencia, los esquemas (que podríamos consi<strong>de</strong>rar como algoritmosabstractos), etc. A partir <strong>de</strong> este módulo, sin embargo, tendremos queapren<strong>de</strong>r a abstraer <strong>de</strong> forma más a<strong>de</strong>cuada problemas más complejos que losque hemos trabajado hasta ahora. Deberemos <strong>de</strong>scomponer el problema ensubproblemas más sencillos. Este módulo os proporcionará <strong>la</strong>s técnicas necesariaspara hacerlo (herramientas <strong>de</strong> <strong>la</strong> notación para abstraer datos y abstraercódigo) y una <strong>metodología</strong> a seguir (<strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte).


© FUOC • P05/75062/00112 8 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteObjetivosCuando hayáis estudiado este módulo, seréis capaces <strong>de</strong>:• Analizar problemas <strong>de</strong> cierta complejidad y <strong>de</strong>scomponerlos en subproblemasmás sencillos, aplicando <strong>la</strong> técnica <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte por refinamientossucesivos.• Saber que hay <strong>de</strong>scomposiciones <strong>de</strong> problemas más convenientes y efectivasque otras para el <strong>diseño</strong>. La elección <strong>de</strong> abstracciones convenientes al problemay el seguimiento <strong>de</strong> <strong>la</strong>s pautas indicadas en este módulo os llevarán a<strong>de</strong>scomposiciones efectivas.• Aplicar los conceptos estudiados en los módulos anteriores para resolvercada uno <strong>de</strong> los subproblemas sencillos, utilizando <strong>la</strong> abstracción <strong>de</strong> códigoy datos.• Desarrol<strong>la</strong>r algoritmos <strong>de</strong> forma efectiva y en un tiempo razonable para resolverproblemas más reales.


© FUOC • P05/75062/00112 9 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte1. Diseño <strong>de</strong>scen<strong>de</strong>nte1.1. Análisis problemas complejosComo ya hemos a<strong>de</strong><strong>la</strong>ntado en <strong>la</strong> introducción, <strong>la</strong> forma <strong>de</strong> enfrentarse a unproblema complejo consiste en <strong>de</strong>scomponerlo en una colección <strong>de</strong> subproblemasmás sencillos e in<strong>de</strong>pendientes, <strong>de</strong> forma que <strong>la</strong> solución <strong>de</strong> estos subproblemasimplique <strong>la</strong> solución <strong>de</strong>l problema en cuestión. Al mismo tiempo, lossubproblemas se pue<strong>de</strong>n <strong>de</strong>scomponer en otros subproblemas si los primerosno son suficientemente sencillos. Estamos hab<strong>la</strong>ndo <strong>de</strong> niveles <strong>de</strong> <strong>de</strong>scomposición.Es <strong>de</strong>cir, el primer nivel <strong>de</strong>scompondrá el problema en los subproblemasque sea necesario; el segundo, <strong>de</strong>scompondrá cada uno <strong>de</strong> los subproblemas resultantes<strong>de</strong> <strong>la</strong> <strong>de</strong>scomposición <strong>de</strong>l primero en otros, etc. El número <strong>de</strong> niveles<strong>de</strong> <strong>de</strong>scomposición en subproblemas <strong>de</strong>pen<strong>de</strong>rá <strong>de</strong> <strong>la</strong> complejidad <strong>de</strong>l problema.En el último nivel encontraremos los subproblemas más sencillos <strong>de</strong> resolver,es <strong>de</strong>cir, los más concretos y elementales. La solución <strong>de</strong> cada subproblemacontribuye parcialmente a <strong>la</strong> solución global <strong>de</strong>l problema. Observad <strong>la</strong> siguientefigura:Sólo mediante <strong>la</strong> práctica seremos capaces <strong>de</strong> realizar buenas <strong>de</strong>scomposiciones.No todas <strong>la</strong>s <strong>de</strong>scomposiciones <strong>de</strong> un problema en subproblemas son a<strong>de</strong>cuadaspara <strong>de</strong>sarrol<strong>la</strong>r un buen <strong>diseño</strong>. La <strong>de</strong>scomposición se <strong>de</strong>bería basar


© FUOC • P05/75062/00112 10 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteen algún criterio guiado por <strong>la</strong>s abstracciones que creyésemos convenientes<strong>de</strong>l problema.Para ilustrar los conceptos que se dan en este apartado, os proponemos el siguienteproblema:Una editorial está interesada en analizar los errores <strong>de</strong> un texto presentado por un autor<strong>de</strong> materiales. Nos encarga diseñar un algoritmo, que, una vez realizado el análisis <strong>de</strong> errores<strong>de</strong> un texto, nos indique el porcentaje <strong>de</strong> frases, <strong>la</strong> media <strong>de</strong> pa<strong>la</strong>bras por frase y elmáximo <strong>de</strong> pa<strong>la</strong>bras por frase que <strong>de</strong>ben ser corregidos. Si no es necesario hacerlo, no sedice nada en <strong>la</strong> salida.En <strong>la</strong> entrada <strong>de</strong>l algoritmo tendremos un texto como secuencia <strong>de</strong> caracteres. Cada frasetermina con una pa<strong>la</strong>bra que finaliza, a su vez, con un punto.Cada pa<strong>la</strong>bra está separada <strong>de</strong> <strong>la</strong> siguiente por un único espacio. En el caso <strong>de</strong> que <strong>la</strong> pa<strong>la</strong>braacabe en punto, el espacio aparece a continuación <strong>de</strong>l punto. En el inicio <strong>de</strong>l textono hay espacios. Las pa<strong>la</strong>bras que <strong>de</strong>ben ser corregidas contienen uno o más signos <strong>de</strong>asterisco “*”. Si <strong>la</strong> pa<strong>la</strong>bra consiste sólo en el carácter asterisco, se trata también <strong>de</strong> unacorrección que es preciso hacer (una pa<strong>la</strong>bra que se tiene que añadir, por ejemplo).Se ha convenido en que el final <strong>de</strong>l texto original se marcará por una frase que no tieneninguna pa<strong>la</strong>bra; simplemente aparecerá el carácter <strong>de</strong> punto <strong>de</strong> final <strong>de</strong> frase.Por ejemplo, si en <strong>la</strong> entrada tenemos:Ho<strong>la</strong> qu* tal. Como B*a to*o. .En <strong>la</strong> salida tendremos:100 1.5 2El <strong>diseño</strong> pue<strong>de</strong> llegar a ser complicado si pensamos en <strong>la</strong> aplicación a partir <strong>de</strong><strong>la</strong> secuencia <strong>de</strong> caracteres. En cambio, si lo p<strong>la</strong>nteamos proponiendo un conjunto<strong>de</strong> abstracciones que son naturales y convenientes para el problema, el <strong>de</strong>sarrolloresultará más sencillo <strong>de</strong> hacer. Aquí nos resulta útil pensar que el textoes una secuencia <strong>de</strong> frases y proponer un algoritmo que vaya obteniendo y tratandocada una. Después nos ocuparíamos <strong>de</strong>l siguiente nivel, que consiste enp<strong>la</strong>ntear el subproblema <strong>de</strong> cómo obtener una frase, el subproblema <strong>de</strong> cómotratar<strong>la</strong>, y cómo i<strong>de</strong>ntificar también que se trata <strong>de</strong> <strong>la</strong> última frase. La consi<strong>de</strong>ración<strong>de</strong> una frase como una secuencia <strong>de</strong> pa<strong>la</strong>bras nos será conveniente y darálugar a <strong>la</strong> creación <strong>de</strong> los subproblemas <strong>de</strong>dicados a <strong>la</strong>s pa<strong>la</strong>bras, que se resolveránen el último nivel como problemas <strong>de</strong> secuencia <strong>de</strong> caracteres.El uso <strong>de</strong> <strong>la</strong>s abstracciones frase y pa<strong>la</strong>bra es propio <strong>de</strong>l problema y natural a éste;su correspon<strong>de</strong>ncia en un nivel <strong>de</strong> <strong>de</strong>scomposición hace que nos podamos concentraren los <strong>de</strong>talles más concretos <strong>de</strong> una abstracción, y que <strong>de</strong>jemos paramás a<strong>de</strong><strong>la</strong>nte los <strong>de</strong>talles <strong>de</strong> <strong>la</strong>s abstracciones que estén pendientes <strong>de</strong> resolver.Debemos procurar que cada nivel tenga un número <strong>de</strong> <strong>de</strong>talles que lo haga fácil<strong>de</strong> seguir y que asegure <strong>la</strong> corrección <strong>de</strong> <strong>la</strong>s soluciones p<strong>la</strong>nteadas.1.2. ¿Análisis ascen<strong>de</strong>nte o <strong>de</strong>scen<strong>de</strong>nte?El primer nivel <strong>de</strong> <strong>de</strong>scomposición es el más abstracto, mientras que los siguienteslo son menos o, dicho <strong>de</strong> otro modo, son más concretos, hasta llegar


© FUOC • P05/75062/00112 11 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteal último, que es el que presenta un mayor nivel <strong>de</strong> concreción. En el caso <strong>de</strong>lejemplo, el más concreto es <strong>la</strong> secuencia elemental <strong>de</strong> caracteres.A <strong>la</strong> hora <strong>de</strong> p<strong>la</strong>ntear un problema complejo, tenemos dos posibles direccionespara su análisis:• Resolver los problemas más concretos, para resolver <strong>de</strong>spués los más abstractos.Es <strong>de</strong>cir, vamos <strong>de</strong>l más concreto al más abstracto. Esta forma <strong>de</strong> p<strong>la</strong>ntearlorecibirá el nombre <strong>de</strong> análisis ascen<strong>de</strong>nte.• Resolver el primer nivel más abstracto, para proseguir <strong>de</strong>spués con los nivelesque lo son menos, hasta llegar al nivel más concreto. Esta segunda direcciónrecibirá el nombre <strong>de</strong> análisis <strong>de</strong>scen<strong>de</strong>nte. Esta dirección es <strong>la</strong> sugerida en elejemplo.El análisis ascen<strong>de</strong>nte está repleto <strong>de</strong> dificulta<strong>de</strong>s y no resulta a<strong>de</strong>cuado parallevar a buen término un <strong>diseño</strong> en un tiempo razonable <strong>de</strong> <strong>de</strong>sarrollo. La dificultadprincipal consiste en que, si no se resuelven en primer lugar los nivelesmás abstractos, no sabemos realmente qué problemas concretos tenemosque solucionar. De este modo, po<strong>de</strong>mos estar resolviendo problemas concretosque <strong>de</strong>spués no se utilizarán o que no están convenientemente <strong>de</strong>finidospara ser usados en los niveles más abstractos. Esto llevaría a rediseñar el nivelmás concreto y, en consecuencia, a retroce<strong>de</strong>r en el <strong>diseño</strong>, para <strong>de</strong>spués volveral otro nivel. Imaginad, en el ejemplo <strong>de</strong>l que nos estamos ocupando, queno tenéis <strong>de</strong>masiado c<strong>la</strong>ro el tratamiento que <strong>de</strong>béis aplicar; por este motivo,os <strong>de</strong>dicáis a <strong>de</strong>sarrol<strong>la</strong>r una acción que lea una pa<strong>la</strong>bra y <strong>la</strong> guar<strong>de</strong> en una estructura<strong>de</strong> datos, para <strong>de</strong>spués <strong>de</strong>scubrir en el nivel más abstracto que <strong>la</strong> utilizaque no es necesario el contenido exacto <strong>de</strong> <strong>la</strong> pa<strong>la</strong>bra, ya que sólo hay quesaber si es preciso corregir<strong>la</strong>, y contar<strong>la</strong> en el caso <strong>de</strong> que así sea. La estructura<strong>de</strong> datos pue<strong>de</strong> sobrar y servir <strong>de</strong> muy poco al problema, sobre todo si ponelimitaciones al enunciado, como veremos más a<strong>de</strong><strong>la</strong>nte.En el análisis <strong>de</strong>scen<strong>de</strong>nte, <strong>la</strong>s cosas van mejor. Al empezar en el nivel másabstracto, i<strong>de</strong>ntificamos y <strong>de</strong>finimos los subproblemas que hay que resolveren el siguiente nivel menos abstracto (fijamos los objetivos para el siguientenivel <strong>de</strong> menor abstracción); en consecuencia, no haremos más trabajo <strong>de</strong>lque realmente hace falta para resolver el problema global, por lo que acortaremosel tiempo <strong>de</strong> <strong>de</strong>sarrollo y evitaremos retrocesos. El ejemplo en el quenos centraremos seguirá esta línea. El inconveniente <strong>de</strong> esta estrategia, cuandose tiene poca experiencia práctica en el método y en el <strong>diseño</strong> <strong>de</strong> algoritmos,es que no se tiene <strong>la</strong> seguridad <strong>de</strong> que se pueda resolver más a<strong>de</strong><strong>la</strong>nte alguno <strong>de</strong>los subproblemas propuestos en el nivel abstracto; entonces se prefiere p<strong>la</strong>ntearel problema <strong>de</strong> forma ascen<strong>de</strong>nte, para tener <strong>la</strong> seguridad <strong>de</strong> que se dispone <strong>de</strong>una base <strong>de</strong> problemas concretos resueltos que ayudarán a resolver, a su vez, losniveles más abstractos. Sin embargo, si lo hacemos así, iremos saltando <strong>de</strong> nivelesy llegando a confusiones innecesarias. La única forma <strong>de</strong> asimi<strong>la</strong>r el métodoEl <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte es unmétodo más eficaz y rápido para<strong>de</strong>sarrol<strong>la</strong>r problemas complejosque el ascen<strong>de</strong>nte u otro métodoque combine ambos.


© FUOC • P05/75062/00112 12 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte<strong>de</strong>scen<strong>de</strong>nte y superar este inconveniente inicial es su práctica en distintos problemas,ya que el análisis ascen<strong>de</strong>nte o <strong>la</strong> combinación <strong>de</strong>l análisis ascen<strong>de</strong>ntey <strong>de</strong>scen<strong>de</strong>nte hace que el <strong>de</strong>sarrollo sea un proceso más lento, a menudo confuso,disperso y que presente incoherencias en los resultados.1.3. Orientaciones <strong>de</strong> <strong>la</strong>s abstraccionesDisponemos <strong>de</strong> dos orientaciones para hacer abstracciones <strong>de</strong> un problema osubproblema y, <strong>de</strong> este modo, guiar su <strong>de</strong>scomposición en subproblemas:• Orientación funcional: en el enunciado <strong>de</strong>l problema se pi<strong>de</strong> un tratamientomuy amplio <strong>de</strong> <strong>de</strong>talles y pasos. Descubrimos que este tratamiento ampliose pue<strong>de</strong> <strong>de</strong>scomponer en varias etapas conceptualizadas para que cada unarealice una función parcial que contribuya a <strong>la</strong> solución global <strong>de</strong>l problema.Una vez i<strong>de</strong>ntificadas estas etapas, proce<strong>de</strong>mos a expresar su composición algorítmica,para más a<strong>de</strong><strong>la</strong>nte <strong>de</strong>sarrol<strong>la</strong>r cada etapa por separado.• Orientación a objetos: un objeto real <strong>de</strong>l problema no es directamente representablepor los tipos elementales <strong>de</strong>l lenguaje algorítmico. En primerlugar <strong>de</strong>finiremos un tipo conveniente para el objeto; a lo <strong>la</strong>rgo <strong>de</strong> todo el<strong>diseño</strong>, para hacer cualquier cambio <strong>de</strong> estado o acceso <strong>de</strong> este objeto, seránecesario llevar a cabo unas acciones y/o funciones diseñadas expresamentepor el tipo <strong>de</strong> objeto <strong>de</strong>finido. Es <strong>de</strong>cir, asociamos unas acciones y/o funcionesal tipo, y sólo estas acciones y/o funciones serán <strong>la</strong>s que modificaráno consultarán el estado <strong>de</strong> un objeto <strong>de</strong>l tipo <strong>de</strong>finido.Po<strong>de</strong>mos encontrar un ejemplo <strong>de</strong> abstracción funcional en el siguiente problema:Se dispone <strong>de</strong> <strong>la</strong>s temperaturas medias diarias <strong>de</strong> un mes en una tab<strong>la</strong>. Se quiere diseñarun algoritmo que nos <strong>de</strong>vuelva el día <strong>de</strong>l mes en estudio que tiene <strong>la</strong> temperatura máspróxima a <strong>la</strong> media.Es necesario recorrer toda <strong>la</strong> tab<strong>la</strong> para calcu<strong>la</strong>r <strong>la</strong> temperatura media <strong>de</strong>l mes; una vezcalcu<strong>la</strong>da, se <strong>de</strong>be buscar el valor <strong>de</strong> temperatura diaria que más se acerca a el<strong>la</strong>. De estemodo, hemos dividido el problema en dos subproblemas más concretos según su función,que son:1)Cálculo <strong>de</strong> <strong>la</strong> media <strong>de</strong> temperaturas <strong>de</strong> un mes.2)Búsqueda <strong>de</strong>l día <strong>de</strong> temperatura más próxima a <strong>la</strong> media <strong>de</strong>l mes.Ambos problemas trabajan sobre el mismo objeto, que es una tab<strong>la</strong> <strong>de</strong> temperaturas mediasdiarias <strong>de</strong> un mes.En el ejemplo propuesto para ser trabajado a lo <strong>la</strong>rgo <strong>de</strong>l apartado, se han hechoabstracciones orientadas a objetos. Hemos interpretado parte <strong>de</strong> <strong>la</strong> informaciónimplícita que guarda <strong>la</strong> secuencia <strong>de</strong> caracteres como frases y pa<strong>la</strong>bras.Notad que po<strong>de</strong>mos consi<strong>de</strong>rar un texto <strong>de</strong> distintas formas; por ejemplo, eltexto como una secuencia <strong>de</strong> capítulos <strong>de</strong> un libro, el capítulo como una secuencia<strong>de</strong> apartados, etc. Pasamos por alto el hecho <strong>de</strong> que el texto que nos


© FUOC • P05/75062/00112 13 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntedan en <strong>la</strong> entrada estuviese organizado por párrafos, ya que <strong>la</strong> consi<strong>de</strong>ración<strong>de</strong> párrafos no tiene ninguna utilidad en <strong>la</strong> resolución <strong>de</strong> nuestro problema.La fuerza <strong>de</strong> <strong>la</strong> abstracción resi<strong>de</strong> en esta afirmación: sólo consi<strong>de</strong>ramos aquelloque es relevante para nuestro problema. En cada nivel <strong>de</strong>finiremos <strong>la</strong> representaciónque <strong>de</strong>be tener cada abstracción elegida, y qué acciones y/o funcionesasociaremos a cada una.1.4. Formas <strong>de</strong> trabajar y presentar el <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteAhora necesitamos expresar <strong>de</strong> algún modo nuestro <strong>de</strong>sarrollo, siguiendo <strong>la</strong><strong>metodología</strong> <strong>de</strong>l <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte. Una forma <strong>de</strong> hacerlo podría consistiren proponer en el primer nivel un borrador <strong>de</strong> algoritmo informal.Observemos qué suce<strong>de</strong> en nuestro ejemplo si resolvemos el primer nivel. Enprimer lugar, <strong>de</strong>bemos establecer los objetivos <strong>de</strong>l <strong>diseño</strong> mediante <strong>la</strong> especificación,manteniendo el nivel <strong>de</strong> abstracción que nos hayamos propuesto. Ennuestro caso, consiste en imaginarnos el texto como una secuencia <strong>de</strong> frases.De este modo, una vez examinado el enunciado, escribimos <strong>la</strong> siguiente especificación:Dicho <strong>de</strong> otro modo,...... p<strong>la</strong>nteamos el nivel comosi dispusiésemos <strong>de</strong> un procesadorvirtual (o un lenguajevirtual) que sabe lo que es unasecuencia <strong>de</strong> frases y cómoobtener<strong>la</strong>s y tratar<strong>la</strong>s.{ Pre: en <strong>la</strong> entrada tenemos una secuencia <strong>de</strong> frases, T, que pue<strong>de</strong> estar vacía. Cada frase<strong>de</strong> T contiene información para saber si hace falta corregir<strong>la</strong> o no }AnalisisCorrecciones{ Post: en el caso <strong>de</strong> que no sea necesario corregir T, no se escribe nada. En el caso <strong>de</strong> queT sea un texto que haya que corregir, se generará en <strong>la</strong> salida una secuencia R, formadapor tres elementos:R1 Representa <strong>la</strong> media <strong>de</strong> pa<strong>la</strong>bras que hay que corregir por frase <strong>de</strong> T.R2 Representa el porcentaje <strong>de</strong> frases que hay que corregir en T.R3 Representa el máximo <strong>de</strong> pa<strong>la</strong>bras que hay que corregir por frase <strong>de</strong> T }Se pi<strong>de</strong> un análisis <strong>de</strong>l texto, para e<strong>la</strong>borar una estadística <strong>de</strong> <strong>la</strong>s correccionesque se <strong>de</strong>ben llevar a cabo. Hay que hacerlo mediante <strong>la</strong> aplicación <strong>de</strong>l esquema<strong>de</strong> recorrido, ya que los datos <strong>de</strong>l análisis <strong>de</strong>l texto <strong>de</strong>pen<strong>de</strong>rán <strong>de</strong> los datosparciales que aportará cada una <strong>de</strong> sus frases. Las acciones <strong>de</strong>l análisis, asícomo <strong>la</strong> obtención <strong>de</strong> <strong>la</strong> secuencia, irían a cargo <strong>de</strong> nuestro procesador virtualo nuestro lenguaje virtual inteligente. De este modo, si aplicamos el esquema<strong>de</strong> recorrido, obtenemos informalmente:algoritmo AnalisisCorreccionesvar ... fvar“Inicializar los resultados <strong>de</strong>l análisis <strong>de</strong>l texto.”“Obtener <strong>la</strong> primera frase.”mientras “<strong>la</strong> frase obtenida no sea <strong>la</strong> última frase” hacer“Actualizar los resultados <strong>de</strong>l análisis <strong>de</strong>l texto a partir <strong>de</strong> <strong>la</strong> frase actual.”“Obtener <strong>la</strong> siguiente frase.”fmientras“Escribir los resultados <strong>de</strong>l análisis <strong>de</strong>l texto.”falgoritmoEn el siguiente nivel, refinaríamos cada una <strong>de</strong> <strong>la</strong>s acciones o funciones expresadasinformalmente con posibles nuevos nombres informales. Seguiríamos


© FUOC • P05/75062/00112 14 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte<strong>de</strong> este modo hasta completar un algoritmo completamente formal y concreto.Podéis notar que esta forma <strong>de</strong> expresar <strong>la</strong> resolución tiene el inconveniente<strong>de</strong> que en cada nivel <strong>de</strong>bemos reescribir el algoritmo y al final <strong>de</strong>l <strong>de</strong>sarrollo,si tenemos muchos niveles, po<strong>de</strong>mos encontrarnos con un algoritmo muy <strong>la</strong>rgoy muy difícil <strong>de</strong> compren<strong>de</strong>r a causa <strong>de</strong> los numerosos <strong>de</strong>talles que abarca.Esta técnica<strong>de</strong> refinamiento...... es <strong>la</strong> que hemos utilizadopara aplicar los esquemas.Una forma más a<strong>de</strong>cuada <strong>de</strong> expresar nuestro <strong>diseño</strong> se basa en <strong>la</strong>s herramientasque nos proporciona <strong>la</strong> notación algorítmica. Po<strong>de</strong>mos encapsu<strong>la</strong>r medianteacciones y/o funciones parametrizadas cada subproblema a resolver. Por otro<strong>la</strong>do, po<strong>de</strong>mos encapsu<strong>la</strong>r cada objeto complejo mediante los constructores <strong>de</strong>tipos, o <strong>de</strong>c<strong>la</strong>rando nuevos tipos (enumerativos, etc.). De este modo, en cadanivel escribimos ya un algoritmo y una acción y/o función con total precisióny formalidad, y no reescribimos <strong>la</strong>s partes ya resueltas <strong>de</strong>l <strong>diseño</strong>. El uso <strong>de</strong> parámetrosnos permitirá alcanzar <strong>la</strong> máxima in<strong>de</strong>pen<strong>de</strong>ncia entre niveles y entrelos subproblemas p<strong>la</strong>nteados, pues nos concentraremos en una parce<strong>la</strong> limitada<strong>de</strong>l problema global.La especificación <strong>de</strong> acciones y/o funciones tendrá una doble utilidad: por un<strong>la</strong>do, servirá <strong>de</strong> puente entre niveles para verificar <strong>la</strong> corrección <strong>de</strong> <strong>la</strong>s solucionesp<strong>la</strong>nteadas, asumiendo que <strong>la</strong>s acciones y/o funciones utilizadas en el nivel <strong>de</strong>estudio cumplen <strong>la</strong> especificación dada, y por otro <strong>la</strong>do, <strong>la</strong> especificación <strong>de</strong> unaacción y/o función es en sí el enunciado formalizado <strong>de</strong>l subproblema que hayque resolver en el nivel que corresponda. Si en el <strong>diseño</strong> <strong>de</strong> <strong>la</strong> acción y/o funciónse respeta <strong>la</strong> especificación, el <strong>diseño</strong> global funcionará como se espera.Reflejaremos el análisis <strong>de</strong>scen<strong>de</strong>nte <strong>de</strong>l problema mediante los mecanismos<strong>de</strong> encapsu<strong>la</strong>do que nos ofrece <strong>la</strong> notación algorítmica (<strong>de</strong>finición<strong>de</strong> tipos, constructores <strong>de</strong> tipos y acciones y/o funciones).Siguiendo nuestro ejemplo <strong>de</strong> trabajo, el resultado <strong>de</strong>l primer nivel queda <strong>de</strong><strong>la</strong> siguiente forma:algoritmo AnalisisCorreccionesvarResultadosAnalisisTexto: tDatosAnalisis;Frase: tFrase;fvar{ Pre: en <strong>la</strong> entrada tenemos una secuencia <strong>de</strong> frases, T, que pue<strong>de</strong> estar vacía. Cadafrase <strong>de</strong> T contiene información para saber si es necesario corregir<strong>la</strong> o no }InicioResultadosAnalisis(ResultadosAnalisisTexto);ObtenerFrase(frase);mientras no UltimaFrase(Frase) hacerActualizaResultadosAnalisis(frase, ResultadosAnalisisTexto);ObtenerFrase(frase)fmientrasEn esta solución...... sólo aparecen los comentarios<strong>de</strong> <strong>la</strong> precondición y <strong>la</strong>postcondición. La elección<strong>de</strong> unos nombres apropiadosa <strong>la</strong>s acciones, funciones yvariables hace que no seannecesarios más comentarios,si <strong>de</strong>spués especificamos cadauna <strong>de</strong> <strong>la</strong>s acciones y/o funciones.Esto lo veremos más a<strong>de</strong><strong>la</strong>nte,y completará el nive<strong>la</strong>ctual <strong>de</strong> trabajo.


© FUOC • P05/75062/00112 15 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteescribirResultadosAnalisis(ResultadosAnalisisTexto);{ Post: en el caso <strong>de</strong> que no sea necesario corregir T no se escribe nada. En el caso <strong>de</strong>que T sea un texto por corregir, se generará en <strong>la</strong> salida una secuencia R formadapor tres elementos:R1 representa <strong>la</strong> media <strong>de</strong> pa<strong>la</strong>bras que hay que corregir por frase <strong>de</strong> T.R2 representa el porcentaje <strong>de</strong> frases que hay que corregir en T.R3 representa el máximo <strong>de</strong> pa<strong>la</strong>bras que hay que corregir por frase <strong>de</strong> T }falgoritmoObservad que <strong>la</strong> última solución presentada por el primer nivel tiene <strong>la</strong> particu<strong>la</strong>ridad<strong>de</strong> ser sintácticamente correcta. Sin embargo, no es completa porque faltapor <strong>de</strong>finir el tipo tFrase y un conjunto <strong>de</strong> acciones y/o funciones (obtenerFrase, yultimaFrase), y el tipo tDatosAnalisis con sus acciones (inicioResultadosAnalisis, actualizaResultadosAnalisis,y escribirResultadosAnalisis), que se <strong>de</strong>berán <strong>de</strong>finir en unsegundo nivel.A pesar <strong>de</strong> que no es completa, hay otra ventaja que po<strong>de</strong>mos aprovechar: po<strong>de</strong>mosrazonar <strong>la</strong> corrección <strong>de</strong> <strong>la</strong> solución hasta ahora formu<strong>la</strong>da sin necesidad<strong>de</strong> conocer los <strong>de</strong>talles <strong>de</strong> los tipos aún no <strong>de</strong>finidos, ni <strong>de</strong> cómo <strong>la</strong>sacciones y/o funciones realizarán el efecto que se espera <strong>de</strong> el<strong>la</strong>s, que todavíaestán por <strong>de</strong>sarrol<strong>la</strong>r. La especificación <strong>de</strong> cada una <strong>de</strong> <strong>la</strong>s acciones o funcionesque hay que <strong>de</strong>sarrol<strong>la</strong>r nos indica cuál es su efecto; a partir <strong>de</strong> aquí po<strong>de</strong>mosrazonar <strong>la</strong> corrección <strong>de</strong> <strong>la</strong> solución formu<strong>la</strong>da. Cuando se <strong>de</strong>sarrolle el siguientenivel, si <strong>la</strong>s acciones o funciones <strong>de</strong>sarrol<strong>la</strong>das respetan sus precondiciones ypostcondiciones, se mantendrá <strong>la</strong> corrección <strong>de</strong>l nivel actual. La especificaciónjuega aquí un papel importante <strong>de</strong> puente entre niveles, ya que ayuda a separarel qué <strong>de</strong>l cómo.La corrección <strong>de</strong> <strong>la</strong> solución nos viene asegurada por el hecho <strong>de</strong> que hemosaplicado el esquema <strong>de</strong> recorrido a una secuencia <strong>de</strong> frases. En <strong>la</strong> solución propuestahemos consi<strong>de</strong>rado una última frase que actúa como marca <strong>de</strong> final <strong>de</strong>secuencia. Es preciso averiguar si esta frase es sólo una marca o si es al mismotiempo una frase que se <strong>de</strong>be tratar y una marca.Si examinamos el enunciado, observamos que al final <strong>de</strong>l texto tendremos doscaracteres “.”. El primer punto pertenece a <strong>la</strong> última frase “real” <strong>de</strong>l texto. El segundopunto pue<strong>de</strong> verse como un punto que cierra una frase vacía (no tieneninguna pa<strong>la</strong>bra) y sólo sirve para marcar el final <strong>de</strong>l texto. La frase vacía indicaráel fin <strong>de</strong> <strong>la</strong> secuencia <strong>de</strong> frases; por lo tanto, no es necesario tratar<strong>la</strong> (analizar<strong>la</strong>,en este caso). Sólo hay que analizar cada frase leída no vacía, acumu<strong>la</strong>ndolos resultados <strong>de</strong> su análisis en el objeto ResultadosAnalisisTexto. Cuando salgamos<strong>de</strong> <strong>la</strong> iteración mientras , habremos analizado todas <strong>la</strong>s frases “reales” <strong>de</strong>ltexto (es <strong>de</strong>cir, con caracteres y, por lo tanto, con contenido), y ResultadosAnalisisTextotendrá el resultado <strong>de</strong>l análisis global <strong>de</strong>l texto.Uno <strong>de</strong> los puntos...... fuertes <strong>de</strong> los esquemas resi<strong>de</strong>en que conocemos todos los<strong>de</strong>talles <strong>de</strong> su funcionamiento ocomportamiento, que nos sirven<strong>de</strong> base para razonar cómodamentesobre <strong>la</strong> corrección<strong>de</strong>l algoritmo o fragmento <strong>de</strong>algoritmo resultante <strong>de</strong> <strong>la</strong> aplicación<strong>de</strong> los esquemas.A<strong>de</strong>más, el hecho <strong>de</strong> que el algoritmo no entre en <strong>de</strong>talles <strong>de</strong>l tipo no <strong>de</strong>finido,pues <strong>la</strong> responsabilidad <strong>de</strong> estos <strong>de</strong>talles pertenece a <strong>la</strong>s acciones y/o funcionesque tratan el tipo, hace que <strong>la</strong> <strong>de</strong>finición concreta <strong>de</strong> tFrase sea irrelevanteLa orientación a objetos nos facilitauna separación <strong>de</strong> los problemasmuy efectiva para <strong>de</strong>scomponerlosen subproblemas in<strong>de</strong>pendientes.


© FUOC • P05/75062/00112 16 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntepara razonar <strong>la</strong> corrección <strong>de</strong> esta etapa <strong>de</strong> <strong>diseño</strong>. En el segundo nivel <strong>de</strong>beremos<strong>de</strong>finir los tipos tFrase, para trabajar con los <strong>de</strong>talles que creamos convenientes.Podremos estudiar <strong>la</strong> mejor alternativa, que no tendrá ningún efectosobre el primer nivel, siempre que se respete el significado, implícito en estosmomentos, <strong>de</strong> <strong>la</strong>s acciones y/o funciones que utiliza el algoritmo <strong>de</strong>l primer nivel,y que se <strong>de</strong>sarrol<strong>la</strong>rán en el segundo. Podremos comprobar que cada funcióno acción haga lo que tiene que hacer, sin tener que retroce<strong>de</strong>r a etapas anteriores<strong>de</strong>l <strong>diseño</strong>.Antes <strong>de</strong> proseguir con el problema que nos ilustra este apartado, vamos a hacerotras observaciones. La notación algorítmica nos permite <strong>de</strong>finir accionesy/o funciones y encapsu<strong>la</strong>r subproblemas, tal y como hemos hecho en <strong>la</strong> últimasolución <strong>de</strong>l ejemplo. Los constructores <strong>de</strong> tipos y <strong>la</strong> <strong>de</strong>c<strong>la</strong>ración <strong>de</strong> nuevostipos nos permiten encapsu<strong>la</strong>r <strong>la</strong>s abstracciones <strong>de</strong> datos. De este modo, <strong>la</strong> notaciónnos da todos los elementos necesarios para po<strong>de</strong>r reflejar en el <strong>diseño</strong><strong>la</strong>s abstracciones que hemos realizado y <strong>la</strong> <strong>metodología</strong> seguida en <strong>la</strong>s <strong>de</strong>scomposiciones.Si seguimos <strong>la</strong>s pautas, también podremos evitar reescribir o modificarcada una <strong>de</strong> <strong>la</strong>s etapas previas.1.5. Herramientas <strong>de</strong> <strong>la</strong> notación para abstraer datosComencemos por hab<strong>la</strong>r sobre cómo encapsu<strong>la</strong>r nuestras abstracciones <strong>de</strong> datos.Por ejemplo, intentemos <strong>de</strong>finir <strong>la</strong> abstracción <strong>de</strong> frase <strong>de</strong> nuestro ejemplo.Po<strong>de</strong>mos ver <strong>la</strong> frase como una secuencia <strong>de</strong> pa<strong>la</strong>bras o vocablos, y tambiéncomo una secuencia <strong>de</strong> caracteres. Imaginemos que en <strong>la</strong> aplicación que estamos<strong>de</strong>sarrol<strong>la</strong>ndo nos pi<strong>de</strong>n <strong>de</strong>tectar frases capicúas. Cuando llegásemos alnivel que trata <strong>la</strong> abstracción <strong>de</strong> frase, nos daríamos cuenta <strong>de</strong> que nos hacefalta guardar toda <strong>la</strong> frase para comparar el último carácter con el primero, elpenúltimo con el segundo, etc., aplicando un esquema <strong>de</strong> búsqueda <strong>de</strong>ntro <strong>de</strong>una función que seña<strong>la</strong>ría si una frase es capicúa o no. Para <strong>de</strong>finir los tipos,po<strong>de</strong>mos utilizar los constructores <strong>de</strong> tipos que nos ofrece el lenguaje: tab<strong>la</strong>sy tup<strong>la</strong>s.Por ejemplo, <strong>la</strong> frase“Dábale arroz a <strong>la</strong> zorra el abad”es capicúa.En nuestro caso, puesto que <strong>la</strong> frase consiste en datos homogéneos (caracteres),utilizaríamos <strong>la</strong>s tab<strong>la</strong>s. Por ejemplo:tipoftipotFrase = tab<strong>la</strong> [maxCarFrase + 1] <strong>de</strong> caracter;don<strong>de</strong> maxCarFrase es el máximo <strong>de</strong> caracteres que preveíamos que tendríacada frase. El elemento <strong>de</strong> más es para el centine<strong>la</strong>, ya que a priori no sabemos


© FUOC • P05/75062/00112 17 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteel número <strong>de</strong> caracteres. Dado que nos interesa comparar el último con el primero,etc., siempre nos pue<strong>de</strong> ser más útil tener <strong>la</strong> longitud <strong>de</strong> <strong>la</strong> frase en lugar<strong>de</strong>l centine<strong>la</strong>. Sin embargo, si <strong>de</strong>c<strong>la</strong>ramos lo siguiente:varncaracteresFrase: entero;Frase: tFrase;fvarestamos dispersando <strong>la</strong> abstracción <strong>de</strong> frase en dos conceptos: su longitud y <strong>la</strong>frase en sí. Esta dispersión pue<strong>de</strong> parecer ridícu<strong>la</strong>, pero si <strong>de</strong>spués nos vemosobligados a guardar más <strong>de</strong> una frase, <strong>de</strong>beremos <strong>de</strong>c<strong>la</strong>rar más contadores <strong>de</strong>caracteres para <strong>la</strong>s diferentes tab<strong>la</strong>s. A<strong>de</strong>más, tendríamos que cambiar los parámetros<strong>de</strong> <strong>la</strong>s acciones y/o funciones en <strong>la</strong>s que no lo hayamos previsto, paraconsi<strong>de</strong>rar los nuevos contadores. Es <strong>de</strong>cir, vamos <strong>de</strong> un nivel a otro reescribiendoel código ya resuelto, y esto no nos interesa. Lo mejor es encapsu<strong>la</strong>rcompletamente todo lo que haga referencia a <strong>la</strong> abstracción que estamos implementando:tipotFrase = tup<strong>la</strong>nCaracteres: entero;c: tab<strong>la</strong> [maxCarFrase] <strong>de</strong> caracter;ftup<strong>la</strong>ftipoDe este modo, tenemos <strong>de</strong>ntro <strong>de</strong>l tipo <strong>de</strong>c<strong>la</strong>rado los <strong>de</strong>talles que nos interesan<strong>de</strong> <strong>la</strong> abstracción que trabajamos; en el nivel más abstracto no es necesariohacer ningún cambio, ya que los <strong>de</strong>talles serán trabajados en el nivel <strong>de</strong> <strong>la</strong> abstracción<strong>de</strong> frase.Imaginemos ahora que lo que nos pi<strong>de</strong>n es averiguar si una frase <strong>de</strong>l texto tiene<strong>la</strong>s mismas pa<strong>la</strong>bras que una frase dada, pero con distinto or<strong>de</strong>n. De formamás breve, si po<strong>de</strong>mos <strong>de</strong>cir que una frase es permutación <strong>de</strong> otra. Sin entraren <strong>de</strong>talles <strong>de</strong>l problema, parece c<strong>la</strong>ro que es necesario ver <strong>la</strong> frase como unasecuencia <strong>de</strong> pa<strong>la</strong>bras; por lo tanto, <strong>la</strong> anterior <strong>de</strong>finición <strong>de</strong> tFrase no nos serviría,ya que necesitamos estructurar <strong>la</strong> frase en una colección <strong>de</strong> pa<strong>la</strong>bras paracomparar<strong>la</strong>s entre sí. Una estructura que no resulta nada útil es <strong>la</strong> siguiente:Por ejemplo, <strong>la</strong> frase “La mar estabaserena” es una permutación <strong>de</strong> <strong>la</strong>frase “serena estaba <strong>la</strong> mar”.tipotFrase = tup<strong>la</strong>nPa<strong>la</strong>bras: entero;c: tab<strong>la</strong> [maxPa<strong>la</strong>brasFrase, maxCarPa<strong>la</strong>bra + 1] <strong>de</strong> caracter;ftup<strong>la</strong>ftipo


© FUOC • P05/75062/00112 18 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntedon<strong>de</strong> maxPa<strong>la</strong>brasFrase es el número máximo <strong>de</strong> pa<strong>la</strong>bras que pue<strong>de</strong> tener unafrase, maxCarPa<strong>la</strong>bra es el máximo <strong>de</strong> caracteres que pue<strong>de</strong> tener una pa<strong>la</strong>bra, ycada una <strong>de</strong> <strong>la</strong>s fi<strong>la</strong>s <strong>de</strong> <strong>la</strong> matriz <strong>de</strong> caracteres guarda un centine<strong>la</strong> para cada pa<strong>la</strong>bra.A pesar <strong>de</strong> que <strong>la</strong> información esté estructurada, es críptico tratar esta estructuraporque no refleja <strong>de</strong>l todo <strong>la</strong> abstracción <strong>de</strong> pa<strong>la</strong>bra que nos convienepara resolver <strong>de</strong> forma más cómoda el nuevo problema, sin dispersión <strong>de</strong> abstracciones.En cambio, <strong>la</strong> siguiente <strong>de</strong>finición es mucho más apropiada y menosproblemática a <strong>la</strong> hora <strong>de</strong> tratar<strong>la</strong>:tipotFrase = tup<strong>la</strong>nPa<strong>la</strong>bras: entero;m: tab<strong>la</strong> [maxPa<strong>la</strong>brasFrase] <strong>de</strong> tPa<strong>la</strong>bra;ftup<strong>la</strong>ftipoDon<strong>de</strong> tPa<strong>la</strong>bra se <strong>de</strong>finirá en el nivel correspondiente a <strong>la</strong>s acciones y funcionesasociadas que le hagan falta.De este modo, po<strong>de</strong>mos observar que <strong>la</strong> abstracción <strong>de</strong> datos se pue<strong>de</strong> hacermediante los constructores <strong>de</strong> tipos, pero no es necesario olvidar que en <strong>la</strong> abstracciónreunimos aquello que nos interesa y que nos conviene porque es relevantepara el problema que estamos resolviendo. ¿Habéis encontrado ya <strong>la</strong>solución que <strong>de</strong>be aplicarse al tipo tFrase <strong>de</strong> nuestro problema inicial?Pensad <strong>la</strong> solución antes<strong>de</strong> continuar.Pues aquí <strong>la</strong> tenéis:tipotFrase = tup<strong>la</strong>nPa<strong>la</strong>brasC: entero;final: booleano;ftup<strong>la</strong>ftipoPara nuestro ejercicio inicial, todo lo que nos interesa <strong>de</strong> una frase es saber elnúmero <strong>de</strong> pa<strong>la</strong>bras que tiene por corregir, a<strong>de</strong>más <strong>de</strong> saber también si se trata<strong>de</strong> <strong>la</strong> frase final. De este modo, <strong>la</strong> tup<strong>la</strong> <strong>de</strong>finida cumple los objetivos que noshemos propuesto para el problema.Tal vez penséis que alguno <strong>de</strong> los tipos en los que se guarda el contenido <strong>de</strong> <strong>la</strong>frase también sirve para nuestro objetivo, ya que <strong>de</strong>spués po<strong>de</strong>mos <strong>de</strong>sarrol<strong>la</strong>r<strong>la</strong>s acciones y/o funciones que contabilizan el número <strong>de</strong> caracteres y pa<strong>la</strong>brasa partir <strong>de</strong>l cual está guardado. Sin embargo, si pensamos así nos olvidamos <strong>de</strong>los objetivos que perseguimos al llevar a cabo un <strong>diseño</strong>. En primer lugar, tenemosuna razón <strong>de</strong> sentido común: ¿por qué <strong>de</strong>bemos guardar cosas que <strong>de</strong>spuésno utilizaremos? La abstracción <strong>de</strong> datos consiste en simplificar los <strong>de</strong>talles <strong>de</strong>lobjeto sometido a estudio para poner aquellos datos que son relevantes para el


© FUOC • P05/75062/00112 19 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteproblema, <strong>de</strong>scartando todo lo que no resulta útil. Por ejemplo, si hiciésemosun estudio consistente en una estadística <strong>de</strong> estaturas <strong>de</strong> un grupo <strong>de</strong> individuos,¿nos serviría <strong>de</strong> algo el color <strong>de</strong> sus ojos para <strong>la</strong> finalidad <strong>de</strong>l estudio?También hay razones técnicas que ayudan a los objetivos <strong>de</strong> <strong>diseño</strong> que perseguimos.En primer lugar, es necesario llevar a cabo un algoritmo que cump<strong>la</strong>los objetivos propuestos (postcondición) por el enunciado, a partir <strong>de</strong> <strong>la</strong>s condicionesiniciales que establezca (precondición). En <strong>la</strong> entrada tenemos untexto que es una secuencia <strong>de</strong> caracteres. ¿Cuántos caracteres y cuántas pa<strong>la</strong>braspue<strong>de</strong> haber en una secuencia? En principio, no lo sabemos. Si <strong>de</strong>c<strong>la</strong>ramostab<strong>la</strong>s, <strong>de</strong>bemos <strong>de</strong>finir máximos y, en consecuencia, restringir <strong>la</strong> entrada(texto) <strong>de</strong>l enunciado a condiciones que, si se satisfacen, harán que el algoritmofuncione correctamente. Si no se satisfacen, <strong>de</strong>bemos modificar <strong>la</strong>s constantes<strong>de</strong>l algoritmo. Todo este embrollo sólo sirve para formu<strong>la</strong>r un algoritmoque no será <strong>de</strong>l todo correcto, pues no admite cualquier frase, como pi<strong>de</strong> elenunciado. A<strong>de</strong>más, para contar los vocablos <strong>de</strong> una frase, no nos hace falta tenerpreviamente <strong>la</strong> frase guardada y, por lo tanto, es un capricho poner restriccionesen el enunciado que, en el fondo, no son necesarias. Debemos ajustarnosal enunciado, y no al revés.Otra razón es <strong>la</strong> cuestión <strong>de</strong> eficiencia: guardar una frase para nuestro problemaocupa un espacio <strong>de</strong> memoria innecesario, así que abusamos sin justificación<strong>de</strong> dicho recurso.En los problemas sugeridos anteriormente <strong>de</strong> <strong>la</strong> frase capicúa y <strong>la</strong> permutación<strong>de</strong> frases tiene sentido que <strong>la</strong> frase se guar<strong>de</strong>, ya que para resolverlos nos hacefalta el acceso directo que nos proporcionan <strong>la</strong>s tab<strong>la</strong>s. En estos problemas escorrecto exigir límites al enunciado don<strong>de</strong> sea necesario, y el espacio que ocupanlos datos está plenamente justificado por su necesidad.1.6. Herramientas <strong>de</strong> <strong>la</strong> notación para abstraer códigoUna vez resuelta <strong>la</strong> abstracción <strong>de</strong> datos en el nivel correspondiente, es necesariodiseñar <strong>la</strong>s acciones y/o funciones que se han propuesto en el nivel anterioral hacer una abstracción <strong>de</strong> código. De hecho, el primer nivel todavía se <strong>de</strong>becompletar dando significado a cada una <strong>de</strong> <strong>la</strong>s acciones y/o funciones que sehan propuesto. El medio es <strong>la</strong> especificación, y <strong>de</strong> este modo establecemos unpuente entre niveles que asegura <strong>la</strong> coherencia entre sí. Para <strong>la</strong> frase tenemos:accion obtenerFrase(sal f: tFrase){ Pre: en <strong>la</strong> entrada tenemos un texto T representado como una secuencia <strong>de</strong> frases t.En <strong>la</strong> parte <strong>de</strong>recha <strong>de</strong> t, DT, hay una secuencia <strong>de</strong> frases o <strong>la</strong> frase vacía }{ Post: en f tenemos representada <strong>la</strong> primera frase <strong>de</strong> DT. La frase representada estáen <strong>la</strong> parte izquierda <strong>de</strong> t }funcion ultimaFrase(f: tFrase): booleano{ Pre: f = F }{ Post: ultimaFrase(F) es cierto si F es una frase vacía. Retornará falso en caso contrario }


© FUOC • P05/75062/00112 20 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntePara el análisis <strong>de</strong>l texto, a partir <strong>de</strong>l objeto <strong>de</strong> tipo tAnalisisDatos, <strong>de</strong>bemoscentrarnos en <strong>la</strong> postcondición <strong>de</strong>l problema. Recordad que <strong>de</strong>bemos obtenerel porcentaje <strong>de</strong> frases que hay que corregir, y <strong>la</strong> media <strong>de</strong> pa<strong>la</strong>bras y el máximo<strong>de</strong> pa<strong>la</strong>bras a corregir por frase. Los dos primeros datos se obtienen a partir<strong>de</strong> los elementos siguientes:• El número <strong>de</strong> frases <strong>de</strong>l texto (nfrases).• El número <strong>de</strong> frases que hay que corregir (nfrasesC) <strong>de</strong>l texto.• El número <strong>de</strong> pa<strong>la</strong>bras que hay que corregir <strong>de</strong>l texto (npa<strong>la</strong>brasC).Hemos puesto entre paréntesis unos nombres que nos servirán para abreviar<strong>la</strong> especificación. Abreviaremos también el máximo <strong>de</strong> pa<strong>la</strong>bras por frase medianteel nombre mx. Si seguimos estos nombres, <strong>la</strong> especificación nos queda<strong>de</strong> <strong>la</strong> siguiente forma:accion InicioResultadosAnalisis(sal a: tDatosAnalisis){ Pre: }{ Post: en a tenemos nfrases, nfrasesC, npa<strong>la</strong>brasC y mx <strong>de</strong> un texto vacío }accion actualizaResultadosAnalisis(ent f: tFrase; entsal a: tDatosAnalisis){ Pre: a = A y f = F }{ Post: en a tenemos nfrases, nfrasesC, npa<strong>la</strong>brasC y mx <strong>de</strong>l texto que resulta <strong>de</strong> añadir e<strong>la</strong>nálisis <strong>de</strong> <strong>la</strong> frase F al texto ya analizado en A }accion escribirResultadosAnalisis(ent A: tDatosAnalisis){ Pre: a = A }{ Post: si los datos <strong>de</strong> A son <strong>de</strong> un texto a corregir, se escribe por el canal <strong>de</strong> salida unasecuencia R formada por tres elementos:R1 representa <strong>la</strong> media <strong>de</strong> pa<strong>la</strong>bras a corregir por frase presente en el texto analizado en A.R2 representa el porcentaje <strong>de</strong> frases a corregir en el texto analizado en A.R3 representa el máximo <strong>de</strong> pa<strong>la</strong>bras a corregir por frase existente en el texto analizadoen A }En el caso <strong>de</strong> que A tenga los datos <strong>de</strong> un texto vacío, no se escribe nada }Notad que mediante <strong>la</strong> especificación establecemos <strong>la</strong> separación entre niveles:1) Con <strong>la</strong> especificación en <strong>la</strong> mano po<strong>de</strong>mos comprobar si el primer nivel escorrecto, sin tener que saber los <strong>de</strong>talles internos <strong>de</strong> cada acción o función.2) Cada tripleta (encabezamiento acción o función)-(precondición)-(postcondición)es el enunciado formalizado <strong>de</strong> un subproblema que hay que resolveren el segundo nivel, y marca los objetivos que se tienen que trabajar.De este modo, <strong>la</strong>s acciones y funciones <strong>de</strong> <strong>la</strong> notación algorítmica nos permitenencapsu<strong>la</strong>r los subproblemas que necesitamos, sin que tengamos que reescribirel algoritmo, ya que una vez que se hayan diseñado <strong>la</strong>s acciones y funciones queprecisamos, el <strong>diseño</strong> estará completo. Como herramientas <strong>de</strong> abstracción <strong>de</strong>Notad que...... <strong>la</strong> especificación tambiénnos permite dividir entre ungrupo <strong>de</strong> personas el trabajo<strong>de</strong> <strong>la</strong> aplicación que hay que<strong>de</strong>sarrol<strong>la</strong>r, <strong>de</strong> forma que cadapersona no <strong>de</strong>penda <strong>de</strong> <strong>la</strong> otraen el momento <strong>de</strong> llevara cabo el <strong>de</strong>sarrollo.


© FUOC • P05/75062/00112 21 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntecódigo, permiten separar el qué <strong>de</strong>l cómo en el p<strong>la</strong>nteamiento <strong>de</strong> un nivel. Es<strong>de</strong>cir, permiten escribir en el lugar propicio <strong>de</strong>l texto <strong>de</strong>l algoritmo qué queremosmediante el nombre <strong>de</strong> una acción o función con los parámetros a<strong>de</strong>cuados,sin pensar en cómo <strong>la</strong> acción o función llegará a cumplir su propósito. Deesta forma po<strong>de</strong>mos mantener <strong>la</strong>s abstracciones que consi<strong>de</strong>remos convenientesen el nivel <strong>de</strong>l que nos ocupamos.Notad también que <strong>la</strong> parametrización <strong>de</strong> acciones y funciones es <strong>la</strong> responsable<strong>de</strong> que los entornos <strong>de</strong> cada problema o subproblema estén convenientementeseparados. De hecho, los parámetros nos ayudan a formalizar <strong>la</strong>s entradas y salidas<strong>de</strong>l subproblema en cuestión. Con los parámetros establecemos el contactocon el exterior <strong>de</strong> <strong>la</strong> acción o función. Mediante los parámetros actuales usamos<strong>la</strong> acción en el entorno que hemos <strong>de</strong>cidido que se <strong>de</strong>be modificar y/o consultar.Con los parámetros formales diseñamos <strong>la</strong> acción o función sin pensarquién <strong>la</strong> utilizará, y simplemente <strong>de</strong>cidimos qué parámetros nos son necesariospara llegar al objetivo propuesto por el subproblema.Con los parámetros...... <strong>la</strong>s acciones o funciones sepue<strong>de</strong>n ver como cajas negrasque interactúan con el exteriora partir <strong>de</strong> una entrada <strong>de</strong> datos,y que producen datos en <strong>la</strong>salida. Lo que hay <strong>de</strong>ntro <strong>de</strong> <strong>la</strong>caja no importa cuando <strong>la</strong> usamos.A<strong>de</strong>más,<strong>la</strong> po<strong>de</strong>mos movera cualquier lugar, porqueaparte <strong>de</strong> sus propios parámetrosno <strong>de</strong>pen<strong>de</strong> <strong>de</strong> ningúnotro elemento externo para sufuncionamiento interno.1.7. Trabajando con profundidad el ejemploPasemos a resolver el siguiente nivel <strong>de</strong> <strong>de</strong>scomposición <strong>de</strong>l problema, en elque nos enfrentaremos a dos abstracciones: <strong>la</strong>s frases y los resultados <strong>de</strong>l análisis<strong>de</strong>l texto que hemos conceptualizado como objetos <strong>de</strong>l problema resueltoen el primer nivel.Empezamos por los resultados <strong>de</strong>l análisis <strong>de</strong>l texto. Si queremos saber el porcentaje<strong>de</strong> frases a corregir, nos es necesario saber también cuántas frases hayen el texto, y cuántas <strong>de</strong>ben ser corregidas. Nos hará falta, por lo tanto, dos contadores(nfrases, nFrasesCor respectivamente) para calcu<strong>la</strong>r el porcentaje cuandohayamos acabado <strong>de</strong> procesar el texto.Si queremos saber <strong>la</strong> media <strong>de</strong> pa<strong>la</strong>bras por frase corregida, necesitaremos uncontador <strong>de</strong> <strong>la</strong>s pa<strong>la</strong>bras a corregir, que, junto con el número <strong>de</strong> frases a corregir,nos proporcionará <strong>la</strong> media. También necesitaremos registrar el máximo <strong>de</strong> pa<strong>la</strong>brasque hay que corregir por frase. Encapsulemos los datos:tDatosAnalisis = tup<strong>la</strong>nFrases: entero;nFrasesCor: entero;nPa<strong>la</strong>brasPorCorregir: entero;maximoPa<strong>la</strong>brasPorCorregir: entero;ftup<strong>la</strong>El <strong>diseño</strong> <strong>de</strong> <strong>la</strong>s acciones, <strong>de</strong> acuerdo con <strong>la</strong>s especificaciones que perseguimos,es el siguiente:


© FUOC • P05/75062/00112 22 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteaccion inicioResultadosAnalisis(sal A: tDatosAnalisis)A.nFrases := 0;A.nFrasesCor := 0;A.nPa<strong>la</strong>brasPorCorregir := 0;A.maximoPa<strong>la</strong>brasPorCorregir := 0faccionaccion actualizaResultadosAnalisis(ent F: tFrase; entsal A: tDatosAnalisis)varnPa<strong>la</strong>brasPorCorFrase: entero;fvarA.nFrases := A.nFrases + 1;nPa<strong>la</strong>brasPorCorFrase := pa<strong>la</strong>brasPorCorregir(F);si nPa<strong>la</strong>brasPorCorFrase > 0 entoncesfsiA.nFrasesCor := A.nFrasesCor + 1;A.nPa<strong>la</strong>brasPorCorregir := A.nPa<strong>la</strong>brasPorCorregir + nPa<strong>la</strong>brasPorCorFrasesi nPa<strong>la</strong>brasPorCorFrase > A.maximoPa<strong>la</strong>brasPorCorregir entoncesA.maximoPa<strong>la</strong>brasPorCorregir := nPa<strong>la</strong>brasPorCorFrasefsifaccionaccion escribirResultadosAnalisis(ent A: tDatosAnalisis)si A.nFrasesCor > 0 entoncesfsifaccionescribirReal(enteroAReal(A.nFrasesCor) / enteroAReal(A.nFrases) ∗ 100.0);escribirReal(enteroAReal(A.nPa<strong>la</strong>brasPorCorregir) / enteroAReal(A.nFrasesCor));escribirEntero(A.maximoPa<strong>la</strong>brasPorCorregir)Notad que <strong>de</strong>bemos prever el error <strong>de</strong> dividir por 0 en <strong>la</strong> última acción. El enunciadopi<strong>de</strong> que no se genere salida si no hay errores.En <strong>la</strong> acción actualizaResultadosAnalisis se utiliza <strong>la</strong> función pa<strong>la</strong>brasPorCorregirque añadiremos al grupo <strong>de</strong> acciones y/o funciones <strong>de</strong>l tipo tFrase. A pesar <strong>de</strong>que, por razones <strong>de</strong> exposición, ya habíamos a<strong>de</strong><strong>la</strong>ntado el tipo tFrase, <strong>la</strong> funciónnos resulta útil para mantener <strong>la</strong> in<strong>de</strong>pen<strong>de</strong>ncia entre <strong>la</strong>s dos abstracciones:para resolver los resultados <strong>de</strong>l análisis <strong>de</strong>l texto no nos hace falta conocerlos <strong>de</strong>talles <strong>de</strong> cómo se representa una frase; <strong>de</strong> esta forma, cuando resolvemos<strong>la</strong> abstracción <strong>de</strong> frase, llevaremos a cabo esta acción in<strong>de</strong>pendientemente <strong>de</strong> loque se ha hecho en <strong>la</strong> abstracción <strong>de</strong> datos <strong>de</strong>l análisis. Si hacemos modificacionesen tFrase (con los respectivos cambios que hay que realizar en su conjunto<strong>de</strong> acciones y funciones), no tendremos que examinar el código referente a <strong>la</strong>abstracción <strong>de</strong> datos <strong>de</strong> análisis. La especificación <strong>de</strong> <strong>la</strong> función será <strong>la</strong> siguiente:funcion pa<strong>la</strong>brasPorCorregir(f: tFrase): entero;{ Pre: f = F }{ Post: pa<strong>la</strong>brasPorCorregir(F) nos da el número <strong>de</strong> pa<strong>la</strong>bras por corregir en <strong>la</strong> frase F }Vamos a resolver el segundo nivel <strong>de</strong> abstracción: <strong>la</strong> abstracción <strong>de</strong> frases. Empezaremospor el subproblema <strong>de</strong> obtener una frase. La mejor forma <strong>de</strong> p<strong>la</strong>ntearsu obtención es consi<strong>de</strong>rar que, en <strong>la</strong> entrada, <strong>la</strong> frase que se <strong>de</strong>be obteneres una secuencia <strong>de</strong> pa<strong>la</strong>bras:m 1 m 2 m 3 m 4 ...


© FUOC • P05/75062/00112 23 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteDecidimos hacer <strong>la</strong> abstracción <strong>de</strong> pa<strong>la</strong>bra para resolver este nivel. Por lo tanto,expresaremos todas <strong>la</strong>s soluciones <strong>de</strong> este nivel en términos <strong>de</strong> pa<strong>la</strong>bras, sihace falta, y más a<strong>de</strong><strong>la</strong>nte ya trabajaremos los <strong>de</strong>talles <strong>de</strong> los pa<strong>la</strong>bras en otraetapa.Al reconocer una secuencia <strong>de</strong>l problema, sea ésta real o abstracta, es necesarioi<strong>de</strong>ntificar el primer elemento, cómo se obtiene el siguiente y qué elemento esel último o marca el final <strong>de</strong> <strong>la</strong> secuencia. Al repasar el enunciado, observamosque no hay ninguna diferencia entre obtener <strong>la</strong> primera pa<strong>la</strong>bra y obtener <strong>la</strong> siguiente;también observamos que <strong>la</strong> propiedad que i<strong>de</strong>ntifica <strong>la</strong> última pa<strong>la</strong>braes que finaliza con un punto. En nuestro caso, el mantenimiento <strong>de</strong> <strong>la</strong> abstracción<strong>de</strong> pa<strong>la</strong>bra convierte <strong>la</strong> i<strong>de</strong>ntificación <strong>de</strong> <strong>la</strong>s operaciones que hay que efectuaren <strong>la</strong> secuencia en abstracciones <strong>de</strong> código, como veremos a continuación.Reconocemos <strong>la</strong> obtención <strong>de</strong> una frase como un problema <strong>de</strong> recorrido, consistenteen contar el número <strong>de</strong> pa<strong>la</strong>bras por corregir; esto nos lleva al siguienteborrador que hay que completar:accion obtenerFrase(sal f: tFrase)var m: tPa<strong>la</strong>bra;fvar“Iniciar el tratamiento”obtenerPrimeraPa<strong>la</strong>bra(m);mientras no ultimaPa<strong>la</strong>bra(m) hacer“Tratar el elemento” { tratamiento <strong>de</strong> <strong>la</strong> pa<strong>la</strong>bra m }obtenerPa<strong>la</strong>bra(m)fmientras“Tratamiento final”faccionObservamos también que <strong>la</strong> última pa<strong>la</strong>bra no sólo marca el final <strong>de</strong> <strong>la</strong> frase,sino que resulta válida para tratar, al igual que <strong>la</strong>s <strong>de</strong>más. Esta posibilidad noestá contemp<strong>la</strong>da en el esquema <strong>de</strong> recorrido que <strong>de</strong>beremos modificar convenientementepara que sea tenida en cuenta.Debemos prever <strong>la</strong> posibilidad <strong>de</strong> que <strong>la</strong> frase esté vacía. Es <strong>de</strong>cir, que sólo contengael punto. En este caso, tendremos que contar con <strong>la</strong> pa<strong>la</strong>bra vacía, queno tiene ningún carácter y acaba en punto.El tratamiento que hay que aplicar para cada pa<strong>la</strong>bra consiste en saber si hayque corregir o no aquél<strong>la</strong> a <strong>la</strong> que se ha accedido, y en el caso <strong>de</strong> que así sea,contabilizar<strong>la</strong> para saber cuántas pa<strong>la</strong>bras <strong>de</strong>bemos corregir en <strong>la</strong> frase. Porotro <strong>la</strong>do, contamos el número <strong>de</strong> pa<strong>la</strong>bras que hay en <strong>la</strong> frase para saber siésta está vacía o no. Debemos recordar que <strong>la</strong> frase vacía (y, por lo tanto, quecontiene una pa<strong>la</strong>bra vacía) representa el final <strong>de</strong>l texto y no forma parte <strong>de</strong>lmismo. Obviamente, <strong>la</strong> pa<strong>la</strong>bra vacía no es una pa<strong>la</strong>bra real, y por ello no hay


© FUOC • P05/75062/00112 24 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteque contar<strong>la</strong>. Tendremos que distinguir si <strong>la</strong> última pa<strong>la</strong>bra está vacía o no,para hacerle, en consecuencia, un tratamiento distinto. La solución queda <strong>de</strong><strong>la</strong> siguiente forma:accion obtenerFrase(sal f: tFrase)var m: tPa<strong>la</strong>bra; nPa<strong>la</strong>bras: entero;fvar{ Pre: en <strong>la</strong> entrada tenemos un texto T representado como una secuencia <strong>de</strong> frases t. En<strong>la</strong> parte <strong>de</strong>recha <strong>de</strong> t, DT, hay una secuencia <strong>de</strong> frases o <strong>la</strong> frase vacía }nPa<strong>la</strong>bras := 0;f.nPa<strong>la</strong>brasC := 0;obtenerPa<strong>la</strong>bra(m);mientras no ultimaPa<strong>la</strong>bra(m) hacersi hayQueCorregirPa<strong>la</strong>bra(m) entonces f.nPa<strong>la</strong>brasC := f.nPa<strong>la</strong>brasC + 1 fsinPa<strong>la</strong>bras := nPa<strong>la</strong>bras + 1;ObtenerPa<strong>la</strong>bra(m)fmientrassi no pa<strong>la</strong>braVacia(m) entoncessi hayQueCorregirPa<strong>la</strong>bra(m) entonces f.nPa<strong>la</strong>brasC := f.nPa<strong>la</strong>brasC + 1 fsinPa<strong>la</strong>bras:= NPa<strong>la</strong>bras + 1fsif: final := nPa<strong>la</strong>bras = 0{ Post: en f tenemos representado <strong>la</strong> primera frase <strong>de</strong> DT. La frase representada está en <strong>la</strong>parte izquierda <strong>de</strong> t }faccionLa función hayQueCorregirPa<strong>la</strong>bra nos dirá si <strong>la</strong> pa<strong>la</strong>bra m <strong>de</strong>be corregirse o no.Por el momento, <strong>la</strong> tarea que hay que realizar en el siguiente nivel es:Fijaros que...... en <strong>la</strong> última estructura condicional(si … fsi) estamostratando <strong>la</strong> pa<strong>la</strong>bra que actúacomo marca.accion obtenerPa<strong>la</strong>bra(sal m: tPa<strong>la</strong>bra){ Pre: en <strong>la</strong> entrada tenemos <strong>la</strong> secuencia <strong>de</strong> pa<strong>la</strong>bras, t, <strong>de</strong>l texto T, <strong>de</strong> <strong>la</strong> que sólo po<strong>de</strong>mosobtener su parte <strong>de</strong>recha DT, y ésta no ha llegado al final <strong>de</strong>l texto }{ Post: m representa <strong>la</strong> primera pa<strong>la</strong>bra que hay en DT. La pa<strong>la</strong>bra obtenida estará en<strong>la</strong> parte izquierda <strong>de</strong> <strong>la</strong> secuencia t }funcion ultimaPa<strong>la</strong>bra(m: tPa<strong>la</strong>bra): booleano{ Pre: m = M }{ Post: ultimaPa<strong>la</strong>bra(M) es cierto si m representa <strong>la</strong> última pa<strong>la</strong>bra <strong>de</strong> una frase }funcion pa<strong>la</strong>braVacia(m: tPa<strong>la</strong>bra): booleano{ Pre: m = M }{ Post: pa<strong>la</strong>braVacia( M) es cierto si m representa una pa<strong>la</strong>bra vacía }funcion hayQueCorregirPa<strong>la</strong>bra(m: tPa<strong>la</strong>bra): booleano{ Pre: m = M }{ Post: hayQueCorregirPa<strong>la</strong>bra(M) es cierto si <strong>la</strong> pa<strong>la</strong>bra M <strong>de</strong>be ser corregida. hayQue-CorregirPa<strong>la</strong>bra(M) es falso si no hace falta corregir M }El resto <strong>de</strong> los subproblemas <strong>de</strong> <strong>la</strong> abstracción frase son evi<strong>de</strong>ntes; se muestrana continuación <strong>la</strong>s respectivas soluciones:funcion ultimaFrase(f: tFrase): booleanoretorna f.finalffuncion{ Pre: f = F , y F es una frase válida }{ Post: ultimaFrase(F) es cierto si F es una frase vacía. Retornará falso en caso contrario }funcion pa<strong>la</strong>brasPorCorregir(f: tFrase): enteroretorna f.nPa<strong>la</strong>brasCffuncion{ Pre: f = F }{ Post: pa<strong>la</strong>brasPorCorregir(F) nos da el número <strong>de</strong> pa<strong>la</strong>bras que hay que corregir para <strong>la</strong>frase F }


© FUOC • P05/75062/00112 25 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteOs pue<strong>de</strong>n parecer exageradas estas funciones excesivamente breves, pero <strong>la</strong>ventaja es c<strong>la</strong>ra: puesto que el primer nivel no se preocupa <strong>de</strong> los <strong>de</strong>talles <strong>de</strong>tFrase, no se <strong>de</strong>berá modificar nunca si en el segundo nivel elegimos otra representaciónpara tFrase y diseñamos <strong>la</strong>s acciones y funciones <strong>de</strong> acuerdo con<strong>la</strong> nueva representación. Sólo hemos cambiado el nivel don<strong>de</strong> concentramos <strong>la</strong>abstracción, sin cambiar el resto <strong>de</strong> los niveles, don<strong>de</strong> están <strong>la</strong>s otras abstraccionessin concretar. Por lo tanto, <strong>la</strong>s posibles modificaciones que hay que realizaren el algoritmo sólo tienen lugar en <strong>la</strong>s abstracciones o <strong>la</strong> abstracción cuyarepresentación nos hemos propuesto cambiar.Pasemos ahora al tercer nivel correspondiente a <strong>la</strong> abstracción <strong>de</strong> pa<strong>la</strong>bras. Po<strong>de</strong>mosconsi<strong>de</strong>rar una pa<strong>la</strong>bra como una secuencia <strong>de</strong> caracteres acabada enb<strong>la</strong>nco, a excepción <strong>de</strong> <strong>la</strong> última <strong>de</strong> <strong>la</strong> frase, que acaba en punto antes <strong>de</strong> llegaral espacio. En este nivel, entonces, <strong>la</strong> expresaremos en términos <strong>de</strong> caracteres,que afortunadamente son entendidos por nuestro lenguaje algorítmico; se trata,por lo tanto, <strong>de</strong>l último nivel <strong>de</strong> abstracción, ya que el <strong>diseño</strong> estará ya suficientementeconcretado.Lo que nos interesa <strong>de</strong> <strong>la</strong> pa<strong>la</strong>bra aquí es saber si sería necesario corregir<strong>la</strong> ono. Por lo tanto, tenemos que <strong>de</strong>tectar <strong>la</strong> presencia <strong>de</strong>l carácter “*” una vezpara saber si <strong>la</strong> pa<strong>la</strong>bra se <strong>de</strong>be corregir o no. Si <strong>la</strong> pa<strong>la</strong>bra consiste sólo en elNotad que...... expresar <strong>la</strong>s soluciones quetratan una pa<strong>la</strong>bra en términos<strong>de</strong> caracteres es convenientepara el problema que estamostrabajando, pero no en general.Por ejemplo, si tuviésemos quecontar <strong>la</strong>s sí<strong>la</strong>bas <strong>de</strong> una pa<strong>la</strong>brao un vocablo, tal vez seríaconveniente consi<strong>de</strong>rar esta pa<strong>la</strong>bracomo una secuencia <strong>de</strong>sí<strong>la</strong>bas y no <strong>de</strong> caracteres.carácter “*”, se interpretará que hace falta añadir una pa<strong>la</strong>bra para corregir <strong>la</strong>frase. Por otro <strong>la</strong>do, también nos interesa conocer si se trata <strong>de</strong> una pa<strong>la</strong>bra finalválida o es vacía. Por lo tanto:tipotPa<strong>la</strong>bra = tup<strong>la</strong>final: booleano;vacio: booleano;hayQueCorregir: booleano;ftup<strong>la</strong>ftipo{ Pre: en <strong>la</strong> entrada tenemos <strong>la</strong> secuencia <strong>de</strong> pa<strong>la</strong>bras, t, <strong>de</strong>l texto T, <strong>de</strong> <strong>la</strong> que sólo po<strong>de</strong>mosobtener su parte <strong>de</strong>recha DT, y ésta no ha llegado al final <strong>de</strong>l texto }accion obtenerPa<strong>la</strong>bra(sal m: tPa<strong>la</strong>bra)varc: caracter;caracteresLeidos: entero;fvarcaracteresLeido := 0;c := leerCaracter();mientras c ≠ ‘*’ y c ≠ ‘ ’ y c ≠ ‘.’ hacer { buscamos asterisco }caracteresLeidos := caracteresLeidos + 1;c := leerCaracter()fmientrasm.hayQueCorregir := c = ‘*’;mientras c ≠ ‘ ’ y c ≠ ‘.’ hacer { pasamos resto pa<strong>la</strong>bra }caracteresLeidos := caracteresLeidos + 1;c := leerCaracter()fmientrasm.vacio := caracteresLeidos = 0;m.final := c = ‘.’;faccion{ Post: m representa <strong>la</strong> primera pa<strong>la</strong>bra que hay en DT. La pa<strong>la</strong>bra obtenida estará en <strong>la</strong>parte izquierda <strong>de</strong> <strong>la</strong> secuencia t }


© FUOC • P05/75062/00112 26 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteEl resto <strong>de</strong> funciones son obvias:funcion ultimaPa<strong>la</strong>bra(m: tPa<strong>la</strong>bra): booleanoretorna m.final o m.vacioffuncionfuncion pa<strong>la</strong>braVacia(m: tPa<strong>la</strong>bra): booleanoretorna m.vaciaffuncionfuncion hayQueCorregirPa<strong>la</strong>bra(m: tPa<strong>la</strong>bra): booleanoretorna m.hayQueCorregirffuncionCon esto llegamos al final <strong>de</strong> <strong>la</strong> solución <strong>de</strong>l ejercicio. Habréis notado <strong>la</strong> cantidad<strong>de</strong> <strong>de</strong>talles que han sido necesarios para llegar a <strong>la</strong> solución. El análisisha sido complicado a causa <strong>de</strong> los <strong>de</strong>talles que se <strong>de</strong>bían tener en cuenta, sobretodo en <strong>la</strong> etapa en que trabajábamos con frases como secuencias <strong>de</strong> pa<strong>la</strong>bras.Sin embargo, <strong>la</strong> separación <strong>de</strong> los problemas nos ha ayudado a concentrarnos<strong>de</strong> forma más cómoda en estos <strong>de</strong>talles, algo que no hubiese ocurrido si hubiéramostenido en cuenta todos los <strong>de</strong>talles <strong>de</strong>l problema al mismo tiempo.1.8. Valoración final <strong>de</strong> <strong>la</strong> <strong>metodología</strong>¿Realmente es tan útil el método propuesto? Si lo hubiésemos pensado sólo encaracteres, sin utilizar ninguna abstracción ni separación <strong>de</strong> problemas, podríamoshaber llegado a una solución como ésta:algoritmo churrovarc: caracter;N1, N2, N3, N4, Mx: entero;FF, A, DP: booleano;fvarN1 := 0;Mx := 0;N2 := 0;N3 := 0;N4 := 0;A := falso;FF := cierto;c := leerCaracter();mientras (no FF) o (c ≠ ‘.’) hacersi (c ≠ ‘ ’) entoncesFF := falso;si no A entoncesA := c = ‘*’fsic := leerCaracter();si (c = ‘ ’) entoncessi A entoncesN2 := N2 + 1;A := falsofsiDP := c = ‘.’;c := LeerCaracter()fsisinoDP := c = ‘.’;c := LeerCaracter()fsi


© FUOC • P05/75062/00112 27 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntesi DP entoncesfsifalgoritmoFF := cierto;N3 := N3 + 1;si N2 > 0 entoncesN4 := N4 + 1fsiN1:= N1 + N2;si N2 > Mx entoncesMx := N2fsiN2 := 0fmientrassi N3 > 0 entoncesescribirReal(enteroAReal(N4) / enteroAReal(N3) ∗ 100.0);escribirReal(enteroAReal(N1) / enteroAReal(N4));escribirEntero(Mx);fsiAhora <strong>la</strong> discusión consiste en saber si vale <strong>la</strong> pena llegar a este tipo <strong>de</strong> solución.Es conveniente que os preguntéis:• ¿Os es fácil tener <strong>la</strong> certeza <strong>de</strong> que esta solución funciona sin probar<strong>la</strong> en elor<strong>de</strong>nador, e incluso probándo<strong>la</strong>?• ¿Creéis que, al ser un texto más corto, <strong>de</strong>be ser más eficiente cuando sea procesado?• ¿Creéis que, al ser un texto más corto, harán falta menos horas <strong>de</strong> <strong>de</strong>sarrollo?• ¿Creéis que con muchos comentarios sería más inteligible que <strong>la</strong> soluciónanterior, basada en el método que hemos propuesto?• ¿Creéis que es fácil <strong>de</strong> modificar, <strong>de</strong> mantener o <strong>de</strong> enten<strong>de</strong>r por alguien opor vosotros mismos <strong>de</strong>spués <strong>de</strong> un tiempo?Esta serie <strong>de</strong> preguntas, en el caso <strong>de</strong> que consi<strong>de</strong>réis lo que hemos ido proponiendoa lo <strong>la</strong>rgo <strong>de</strong>l curso, tiene una respuesta única: no.Los numerosos <strong>de</strong>talles que aparecen en el algoritmo lo hacen muy poco prácticopara que nos convenzamos <strong>de</strong> que funciona. Debemos estar muy concentradosy atentos para estar seguros: ¿avanza bien <strong>la</strong> secuencia?, ¿acabará bien?¿están bien <strong>la</strong>s inicializaciones?, etc. Si alguien propone un algoritmo <strong>de</strong> estetipo posiblemente lo haya ido probando en el or<strong>de</strong>nador, modificándolo continuamente<strong>de</strong>s<strong>de</strong> una versión inicial, hasta que algunas pruebas le han dado <strong>la</strong>confianza <strong>de</strong> que es correcto, pero no <strong>la</strong> absoluta certeza. “¿Qué prueba le falta?”,es su duda. Se habrán hecho múltiples relecturas (entre otras cosas, podríaPensad...... a<strong>de</strong>más, que es más fácilrealizar pruebas si el problemaestá <strong>de</strong>scompuesto en accionesy/o funciones para que podamoscomprobar qué tarearealiza cada función.


© FUOC • P05/75062/00112 28 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteser más explícito con el nombre <strong>de</strong> <strong>la</strong>s variables, por ejemplo), intentando verloparcialmente a partir <strong>de</strong> algunas abstracciones que no están expresadas.A pesar <strong>de</strong> todo, <strong>la</strong> confusión pue<strong>de</strong> existir por el hecho <strong>de</strong> que <strong>la</strong>s abstraccionesno están separadas. Cuando más a<strong>de</strong><strong>la</strong>nte (una semana o más) haya que revisarlopor el motivo que sea, se <strong>de</strong>berá hacer <strong>de</strong> nuevo este ejercicio olímpico <strong>de</strong>concentración. Si se ha comentado ampliamente, seguro que se encontrará quealgunos comentarios <strong>de</strong>spistan, porque no se ha seguido un or<strong>de</strong>n concreto, asícomo tampoco se han separado ni mantenido <strong>la</strong>s abstracciones que en su momentose han realizado para enten<strong>de</strong>r el algoritmo. A<strong>de</strong>más, con comentarios,el algoritmo “churro” podría ser tan <strong>la</strong>rgo como el <strong>diseño</strong> hecho metodológicamente.La mayoría <strong>de</strong> <strong>la</strong>s veces, un <strong>de</strong>sarrollo <strong>de</strong> este tipo es muy lento, a pesar<strong>de</strong> que el texto final <strong>de</strong>l algoritmo sea re<strong>la</strong>tivamente corto.En ocasiones, <strong>la</strong> intuición nos juega ma<strong>la</strong>s pasadas. La longitud <strong>de</strong>l texto en elque se expresa un algoritmo no tiene corre<strong>la</strong>ción con su posible eficiencia entiempo al ser procesado. El coste <strong>de</strong> introducir encapsu<strong>la</strong>do (acciones y/o funciones,constructores, etc.) es mínimo y <strong>de</strong>spreciable. Recordad que otro <strong>de</strong> losobjetivos <strong>de</strong> los algoritmos es que puedan ser leídos fácilmente, ya que el coste<strong>de</strong> mantenimiento y mejoras se pue<strong>de</strong> disparar en una empresa si otros programadoresse ven obligados a per<strong>de</strong>r el tiempo leyendo algoritmos confusos<strong>de</strong> programadores no metódicos. Por ejemplo, <strong>la</strong> editorial nos acaba <strong>de</strong> avisarque se ha introducido un nuevo carácter corrector, el “/”, que sirve para indicarque <strong>la</strong>s pa<strong>la</strong>bras que lo tengan no se cuenten como pa<strong>la</strong>bras por corregir,a pesar <strong>de</strong> que vayan acompañadas <strong>de</strong> asterisco. ¿Dón<strong>de</strong> haréis los cambios <strong>de</strong>forma más cómoda, en el algoritmo “churro” o en el que hemos <strong>de</strong>sarrol<strong>la</strong>dosiguiendo el método <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte?A lo <strong>la</strong>rgo <strong>de</strong> todo el apartado nos hemos ocupado <strong>de</strong> un ejemplo. Una aplicaciónreal presenta una complejidad mucho mayor, y todas <strong>la</strong>s observacioneshechas son todavía más evi<strong>de</strong>ntes; por ello se hace más necesario trabajar con<strong>la</strong> <strong>metodología</strong> que aquí se propone.1.9. Últimas observacionesPara asimi<strong>la</strong>r <strong>la</strong> <strong>metodología</strong> es necesario practicar mucho y vencer los miedosiniciales. En cada ejercicio que hagáis, tenéis que potenciar vuestra capacidadintelectual para encontrar <strong>la</strong>s abstracciones más convenientes al problema, asícomo también potenciar vuestra capacidad <strong>de</strong> expresión (<strong>la</strong> elección <strong>de</strong> unosbuenos nombres en <strong>la</strong>s <strong>de</strong>finiciones forma también parte <strong>de</strong>l juego). El restoes verificar que <strong>la</strong> composición <strong>de</strong> sentencias y expresiones <strong>de</strong>l algoritmo y <strong>de</strong> <strong>la</strong>sacciones y/o funciones que diseñáis sigue <strong>la</strong> lógica correcta y prevista, <strong>de</strong> modoque ampliéis <strong>la</strong>s técnicas más trabajadas a lo <strong>la</strong>rgo <strong>de</strong> <strong>la</strong> asignatura.


© FUOC • P05/75062/00112 29 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteResumenEn este último módulo hemos introducido <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntepara refinamientos sucesivos, que nos permite diseñar algoritmos queresuelven problemas más complejos y cercanos a <strong>la</strong> realidad.Como hemos observado, <strong>la</strong> base <strong>de</strong> aplicación <strong>de</strong> esta <strong>metodología</strong> consiste en<strong>de</strong>scomponer el problema complejo, mediante <strong>la</strong> abstracción, en subproblemasin<strong>de</strong>pendientes y más sencillos <strong>de</strong> resolver.Ahora, por lo tanto, po<strong>de</strong>mos construir a<strong>de</strong>cuadamente los algoritmos que resuelvanproblemas complejos. Ya disponemos <strong>de</strong> todos los recursos necesarios:por un <strong>la</strong>do, tenemos <strong>la</strong>s herramientas –el lenguaje algorítmico–, y por otro, <strong>la</strong><strong>metodología</strong> que nos enseña cómo utilizar<strong>la</strong>s.En cuanto consigamos <strong>la</strong> suficiente <strong>de</strong>streza en <strong>la</strong> aplicación <strong>de</strong> <strong>la</strong> <strong>metodología</strong>y el uso <strong>de</strong> <strong>la</strong>s herramientas <strong>de</strong>l lenguaje algorítmico, habremos alcanzado uno<strong>de</strong> los objetivos básicos que proponemos al principio <strong>de</strong> <strong>la</strong> asignatura: apren<strong>de</strong>ra diseñar e implementar algoritmos correctos, inteligibles, eficientes y generalesque resuelvan los problemas p<strong>la</strong>nteados. O, dicho <strong>de</strong> otro modo, apren<strong>de</strong>r a programar<strong>de</strong> forma profesional; es <strong>de</strong>cir, con eficiencia (en un tiempo razonable) yeficacia (que el resultado responda a los objetivos pedidos). A medida que vayamosresolviendo problemas, iremos adquiriendo esta <strong>de</strong>streza.Cada vez que nos enfrentemos al <strong>diseño</strong> <strong>de</strong> un algoritmo que <strong>de</strong>be resolver unproblema, será necesario seguir <strong>la</strong>s pautas que os hemos recomendado y que recordamosahora: enten<strong>de</strong>r el enunciado, p<strong>la</strong>ntear <strong>la</strong> solución, formu<strong>la</strong>r<strong>la</strong> y, finalmente,evaluar<strong>la</strong>.Notad que...... dado el carácter incremental<strong>de</strong> <strong>la</strong> materia, estas pautasson al mismo tiempo unasíntesis <strong>de</strong> todo lo que hemosaprendido mediante los módulosy, por lo tanto, un buenresumen final.1. Enten<strong>de</strong>r el enunciadoCuando leamos por primera vez el enunciado, sabremos si correspon<strong>de</strong> a unproblema al que es necesario aplicar <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte,cuando los objetos <strong>de</strong>l problema o los objetivos que el enunciado proponealcanzar no se pue<strong>de</strong>n expresar fácilmente en términos <strong>de</strong> tipos, acciones yfunciones elementales <strong>de</strong> <strong>la</strong> notación algorítmica, posiblemente a causa <strong>de</strong>una cantidad excesiva <strong>de</strong> <strong>de</strong>talles que hay que tener en cuenta. Si éste es elcaso, <strong>de</strong>beremos encontrar <strong>la</strong>s abstracciones que hacen más abordable unenunciado tan lleno <strong>de</strong> <strong>de</strong>talles, y a partir <strong>de</strong> aquí lo releeremos teniendopresente <strong>la</strong>s abstracciones elegidas, sin consi<strong>de</strong>rar los <strong>de</strong>talles que están por<strong>de</strong>bajo <strong>de</strong> estas abstracciones y <strong>de</strong> los que ya nos ocuparemos en posterioresniveles <strong>de</strong> <strong>de</strong>scomposición.


© FUOC • P05/75062/00112 30 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteComo ya sabemos, lo primero que hay que hacer siempre es saber qué queremosconseguir: si no tenemos c<strong>la</strong>ro cuál es el problema que se <strong>de</strong>be resolver, no encontraremossu solución. Debemos interpretar correctamente el enunciado y<strong>de</strong>finir <strong>de</strong> forma c<strong>la</strong>ra y sin ambigüeda<strong>de</strong>s qué es necesario hacer. Por ello especificaremosel algoritmo que hay que diseñar. Si es necesario usar abstracciones,<strong>la</strong> especificación se expresará en términos <strong>de</strong> <strong>la</strong>s abstracciones convenidas. Enotros niveles <strong>de</strong> <strong>de</strong>scomposición más concretos ya se especificarán los <strong>de</strong>tallesque ahora ocultan <strong>la</strong>s abstracciones.Recordad que...… cuando especificamos, sólopensamos en qué es necesariohacer, y no en cómo hay quehacerlo.La especificación nos indica cuál es el problema que se <strong>de</strong>be resolver; por lotanto, <strong>de</strong>bemos especificar <strong>la</strong> precondición y <strong>la</strong> postcondición <strong>de</strong> cada algoritmo,acción y función que queramos diseñar.A pesar <strong>de</strong> que <strong>la</strong> especificaciónse redacta en lenguaje natural, esnecesario que procuremos hacerlocon precisión.La precondición <strong>de</strong>scribe el estado inicial en el que se encuentra el entorno<strong>de</strong>l que partimos.La postcondición <strong>de</strong>scribe el estado final <strong>de</strong>l entorno al que <strong>de</strong>bemos llegar<strong>de</strong>spués <strong>de</strong> que el algoritmo resuelva el problema.2. P<strong>la</strong>ntear el problemaLa etapa <strong>de</strong> p<strong>la</strong>nteamiento empieza una vez establecidas <strong>la</strong> precondición y <strong>la</strong>postcondición <strong>de</strong> un algoritmo, una acción o función. La especificación correspon<strong>de</strong>ráal problema en sí o a una parte <strong>de</strong>l problema (subproblema). Ahora hayque <strong>de</strong>cidir cómo se <strong>de</strong>be resolver el problema, y por lo tanto, cómo po<strong>de</strong>mosseguir y aplicar gran parte <strong>de</strong> <strong>la</strong> <strong>metodología</strong> que conocemos.En primer lugar, <strong>de</strong>bemos ver si po<strong>de</strong>mos resolver el problema directamentecon facilidad. Es <strong>de</strong>cir, si para resolverlo po<strong>de</strong>mos aplicar directamente <strong>la</strong>s estructurasy los esquemas que conocemos sobre los datos reales <strong>de</strong>l problema.En este caso nos encontramos ante un problema concreto y re<strong>la</strong>tivamente sencillo<strong>de</strong> resolver. A pesar <strong>de</strong> ello, para realizar con unas ciertas garantías <strong>de</strong> correcciónun problema que se correspon<strong>de</strong> a un seguimiento <strong>de</strong> una secuencia,<strong>de</strong>beremos utilizar <strong>la</strong>s pautas que os hemos ido proponiendo y que sintetizamosahora:• Reconocer <strong>la</strong> secuencia que se <strong>de</strong>be tratar. En algunos casos será sencillo,porque trabajaremos directamente con <strong>la</strong> secuencia explícita que sigue losdatos <strong>de</strong>l enunciado. En otros casos, tendremos que reconocer que para resolverel problema nos hace falta generar una secuencia. La i<strong>de</strong>ntificación<strong>de</strong>l primer elemento, <strong>de</strong>l siguiente y <strong>de</strong>l que <strong>de</strong>termina el final <strong>de</strong> <strong>la</strong> secuenciaconcretará <strong>la</strong> secuencia que se <strong>de</strong>be tratar.Recordad que…… <strong>la</strong> secuencia pue<strong>de</strong> venirdada por el enunciado <strong>de</strong>lproblema, o bien, pue<strong>de</strong> ocurrirque los propios objetivos<strong>de</strong>l problema nos pidan generar<strong>la</strong>.


© FUOC • P05/75062/00112 31 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte• Decidir el esquema que se <strong>de</strong>be aplicar. Es necesario averiguar cuál <strong>de</strong> los esquemasque conocemos (búsqueda y recorrido) nos ayudará a resolver el problema.• Aplicar el esquema elegido al problema concreto, llevando a cabo <strong>la</strong>s adaptacionesconvenientes en cada caso.Es preciso ir con pies <strong>de</strong> plomo a <strong>la</strong> hora <strong>de</strong> aplicar el esquema elegido. Paraestar seguros, es conveniente reflexionar sobre <strong>la</strong>s siguientes cuestiones:• Cómo obtenemos los diferentes elementos <strong>de</strong> <strong>la</strong> secuencia.– Cómo obtener el primer elemento.– Cómo obtener los siguientes.– Cómo <strong>de</strong>tectar el final <strong>de</strong> <strong>la</strong> secuencia.• Cómo hacemos el tratamiento.– I<strong>de</strong>ntificar el tratamiento que correspon<strong>de</strong> para cada elemento.– Definir <strong>la</strong>s variables necesarias.Con frecuencia <strong>de</strong>bemos <strong>de</strong>finir variables para acumu<strong>la</strong>r los resultados que vamosobteniendo a medida que vamos tratando los elementos; estas variables se <strong>de</strong>ben inicializarconvenientemente en el tratamiento inicial.– Decidir si es necesario trabajar con tab<strong>la</strong>s.Si po<strong>de</strong>mos hacer el tratamiento secuencialmente, no <strong>de</strong>finiremos tab<strong>la</strong>s para almacenar(<strong>de</strong> forma parcial o total) los datos <strong>de</strong> <strong>la</strong> secuencia, ya que esto nos limitaría los datosque <strong>de</strong>bemos tratar, y ocuparíamos espacio innecesario. Sin embargo, en caso <strong>de</strong>que tengamos que hacer algún acceso directo sobre (algunos o todos) los datos, <strong>de</strong>beremos<strong>de</strong>finirlos convenientemente.– Determinar si hay que tratar el último elemento.A veces, el último elemento es un elemento no válido que sólo sirve <strong>de</strong> marca para<strong>de</strong>tectar el final <strong>de</strong> <strong>la</strong> secuencia. No obstante, en otros casos, a<strong>de</strong>más <strong>de</strong> ser <strong>la</strong> marcafinal, también es un elemento válido más <strong>de</strong> <strong>la</strong> secuencia y, por lo tanto, hay queprestar atención y aplicarle el mismo tratamiento que al resto. Entonces el esquema<strong>de</strong>be contener este tratamiento haciendo los cambios a<strong>de</strong>cuados.– Decidir si es necesario un tratamiento final.Observar si todavía se <strong>de</strong>be llevar a cabo un tratamiento final para llegar a <strong>la</strong> postcondición,una vez ya tratados todos los elementos <strong>de</strong> <strong>la</strong> secuencia.En el caso <strong>de</strong> que el problema no siga ninguna secuencia, no po<strong>de</strong>mos aplicarlos esquemas <strong>de</strong> recorrido y búsqueda que conocemos; a<strong>de</strong>más, dado que notenemos ningún esquema previo que aplicar, p<strong>la</strong>ntear <strong>la</strong> resolución <strong>de</strong>l problemaconsistirá en <strong>de</strong>scubrir cuáles son <strong>la</strong>s acciones y funciones necesarias


© FUOC • P05/75062/00112 32 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteque se <strong>de</strong>ben diseñar con el fin <strong>de</strong> que, combinadas <strong>de</strong> forma conveniente, alcancenel objetivo final. En estos casos, cada acción o función (elemental ono) resuelve un subobjetivo, y compuestas a<strong>de</strong>cuadamente resolverán el objetivofinal <strong>de</strong>l algoritmo.Las pautas expuestas hasta ahora son también aplicables a problemas complejosque no pue<strong>de</strong>n ser expresados directamente con los elementos <strong>de</strong> <strong>la</strong> notaciónalgorítmica. Ahora ampliaremos <strong>la</strong>s indicaciones que nos servirán parap<strong>la</strong>ntear estos tipos <strong>de</strong> problemas más complejos.Cuando nos hal<strong>la</strong>mos ante un problema complejo, <strong>de</strong>bemos encontrar abstraccionesconvenientes que simplifiquen los <strong>de</strong>talles que hay que tener en cuentaen el p<strong>la</strong>nteamiento <strong>de</strong>l problema, y que por ello nos permitan resolverlo concomodidad y con suficiente c<strong>la</strong>ridad (por ejemplo, que facilite <strong>la</strong> aplicación <strong>de</strong>los esquemas). Una vez que hemos elegido estas abstracciones, <strong>de</strong>bemos mantener<strong>la</strong>sa lo <strong>la</strong>rgo <strong>de</strong>l p<strong>la</strong>nteamiento <strong>de</strong>l problema; es <strong>de</strong>cir, no <strong>de</strong>bemos entraren <strong>de</strong>talles que correspon<strong>de</strong>rán a otro nivel <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte.Recordad que…... los esquemas algorítmicosno imponen ninguna restricciónrespecto <strong>de</strong>l tipo <strong>de</strong> loselementos <strong>de</strong> <strong>la</strong> secuencia y,por lo tanto, se pue<strong>de</strong>n aplicara secuencias <strong>de</strong> tipos no elementales<strong>de</strong>finidos mediantetup<strong>la</strong>s y tab<strong>la</strong>s, para resolverproblemas más complejos.Estamos haciendo una abstracción<strong>de</strong> datos.Al aplicar <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte, i<strong>de</strong>ntificaremos <strong>la</strong> secuencia<strong>de</strong> elementos abstractos; cuando apliquemos el esquema elegido, <strong>de</strong>beremos <strong>de</strong>finiracciones y/o funciones correspondientes a <strong>la</strong> i<strong>de</strong>ntificación <strong>de</strong>l primer elemento,el siguiente y <strong>la</strong> marca <strong>de</strong> elemento. De este modo, en lugar <strong>de</strong> concretar<strong>la</strong>s operaciones anteriores con sentencias y tipos elementales <strong>de</strong>l lenguaje, <strong>la</strong>sencapsu<strong>la</strong>mos mediante acciones y/o funciones con tipos no elementales queescon<strong>de</strong>n los <strong>de</strong>talles concretos <strong>de</strong> <strong>la</strong> abstracción o <strong>la</strong>s abstracciones realizadas.Suponer <strong>la</strong> existencia <strong>de</strong> un tipo no elemental con un conjunto <strong>de</strong> acciones y/o funciones que no existen no nos <strong>de</strong>be comportar ningún problema: siemprelos podremos diseñar más a<strong>de</strong><strong>la</strong>nte.En el momento <strong>de</strong> formu<strong>la</strong>r un esquema sobre los datos abstractos, <strong>de</strong>beremosintroducir tantas acciones y funciones y tipos nuevos como sea necesario. Deeste modo, <strong>la</strong> aplicación <strong>de</strong> <strong>la</strong> <strong>metodología</strong> <strong>de</strong>l <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte comporta<strong>la</strong> creación <strong>de</strong> nuevos enunciados <strong>de</strong> subproblemas (tipos, acciones y funciones),que se <strong>de</strong>berán p<strong>la</strong>ntear en su nivel correspondiente (y, por lo tanto, porcada subproblema <strong>de</strong>beremos enten<strong>de</strong>r el enunciado, p<strong>la</strong>ntearlo, formu<strong>la</strong>rlo yevaluarlo; si el subproblema no es suficientemente concreto, dará lugar a otrossubproblemas que habrá que resolver). Iremos siguiendo este proceso <strong>de</strong> formasucesiva, hasta que sea posible aplicar los esquemas directamente sobre los datosreales <strong>de</strong>l problema.Estamos haciendo una abstracción<strong>de</strong> código.Por lo tanto, en cada nivel más concreto <strong>de</strong>l <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte tendremos quehacer primero un p<strong>la</strong>nteamiento <strong>de</strong>l nivel, y a continuación el p<strong>la</strong>nteamiento,<strong>la</strong> formu<strong>la</strong>ción y <strong>la</strong> evaluación <strong>de</strong> cada uno <strong>de</strong> los subproblemas para resolveren el nivel <strong>de</strong> trabajo.


© FUOC • P05/75062/00112 33 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte• Para cada abstracción correspondiente al nivel <strong>de</strong> <strong>de</strong>scomposición es necesariorepresentar los tipos que hay que trabajar en <strong>de</strong>talle y que todavía nose han <strong>de</strong>finido.• Para cada acción y/o función ya especificada (subproblema) que se <strong>de</strong>be <strong>de</strong>sarrol<strong>la</strong>ren este nivel, hay que:– Reconocer, si hace falta, <strong>la</strong> secuencia que hay que tratar. En estos casoses más complicado, ya que los datos abstractos a<strong>de</strong>cuados que forman<strong>la</strong> secuencia <strong>de</strong>ben ser i<strong>de</strong>ntificados.– Decidir el esquema que se <strong>de</strong>be aplicar sobre <strong>la</strong> secuencia abstracta. Comosiempre, es necesario observar cuál <strong>de</strong> los esquemas que conocemos (búsqueday recorrido) nos ayudará a resolver el problema.– Aplicar el esquema elegido al problema concreto, efectuando <strong>la</strong>s variacionesque convengan en cada caso. La aplicación se <strong>de</strong>be hacer respetando<strong>la</strong>s abstracciones que correspondan a otro nivel más concreto, enel caso <strong>de</strong> que existan.– Especificar <strong>la</strong>s acciones y funciones auxiliares que hayan aparecido enel paso anterior.El punto c<strong>la</strong>ve en <strong>la</strong> abstracción <strong>de</strong> código consiste en <strong>de</strong>terminar cuálesson los niveles <strong>de</strong> abstracción a<strong>de</strong>cuados. Normalmente, los objetos quetrata el problema son el criterio que seguimos en el momento <strong>de</strong> <strong>de</strong>terminarlos niveles y <strong>de</strong>scomponer el problema.Notad que…… normalmente hacemosuna <strong>de</strong>scomposición orientadaa objetos.En cada nivel <strong>de</strong> <strong>de</strong>scomposición expresamos los algoritmos en función <strong>de</strong>unos tipos, acciones y funciones que <strong>de</strong>sarrol<strong>la</strong>remos en el siguiente nivel. Laabstracción que hemos hecho en cada nivel nos permite concentrarnos sóloen <strong>la</strong> resolución <strong>de</strong> un subproblema concreto; no tenemos por qué preocuparnos<strong>de</strong> cómo se diseñan los tipos, acciones y funciones que necesitamos; simplementelos utilizamos sabiendo qué hacen y, más a<strong>de</strong><strong>la</strong>nte, en otros niveles,ya los iremos diseñando.La <strong>de</strong>scomposiciónen niveles...... se pue<strong>de</strong> enten<strong>de</strong>r como situviésemos un procesador distintopara cada uno que fuesecapaz <strong>de</strong> enten<strong>de</strong>r todos lostipos, <strong>la</strong>s acciones y <strong>la</strong>s funcionesque aún esperan a ser <strong>de</strong>sarrol<strong>la</strong>dos.Recordad que para cada nivel <strong>de</strong> abstracción <strong>de</strong> <strong>diseño</strong> iría bien releer el enunciado,con el fin <strong>de</strong> captar los <strong>de</strong>talles que son relevantes.Notad que, a pesar <strong>de</strong> toda <strong>la</strong> exposición que acabamos <strong>de</strong> hacer sobre <strong>la</strong> tipología<strong>de</strong> problemas que po<strong>de</strong>mos resolver en este curso, todavía nos faltaría añadir uncaso. Nos po<strong>de</strong>mos encontrar ante un problema en el que no reconozcamos oi<strong>de</strong>ntifiquemos ninguna secuencia que nos convenga al p<strong>la</strong>ntearlo. En este caso,<strong>de</strong>beremos <strong>de</strong>scubrir el or<strong>de</strong>n <strong>de</strong> <strong>la</strong>s acciones que pue<strong>de</strong>n alcanzar el objetivo queque preten<strong>de</strong> el algoritmo.En ocasiones el número <strong>de</strong> acciones elementales que se <strong>de</strong>ben proponer paraconseguir un objetivo pue<strong>de</strong> ser excesivo; en este caso conviene reconocer <strong>la</strong>s


© FUOC • P05/75062/00112 34 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntediferentes etapas que alcanzan subobjetivos parciales que, al componerse, proporcionanel objetivo final. Cada una <strong>de</strong> estas etapas se encapsu<strong>la</strong> mediante accionesy funciones. De este modo obtenemos legibilidad e inteligibilidad en <strong>la</strong>ssoluciones formu<strong>la</strong>das. La orientación <strong>de</strong> <strong>la</strong> <strong>de</strong>scomposición es funcional. Notadque esto que acabamos <strong>de</strong> comentar es aplicable a subproblemas provenientes<strong>de</strong> una <strong>de</strong>scomposición orientada a objetos (por ejemplo, el tratamiento <strong>de</strong>un elemento abstracto <strong>de</strong> una secuencia).3. Formu<strong>la</strong>r <strong>la</strong> soluciónUna vez que ya sabemos cómo queremos resolver el problema, sólo nos haráfalta formu<strong>la</strong>r <strong>la</strong> solución en <strong>la</strong> notación algorítmica que hemos <strong>de</strong>finido. Deeste modo, podremos expresar con precisión y rigor el algoritmo que resuelveel problema.Recordad que…... cuando formuléis vuestrosalgoritmos, <strong>de</strong>béis seguirestrictamente <strong>la</strong> notaciónalgorítmica que hemos <strong>de</strong>finidopara evitar ambigüeda<strong>de</strong>s.Ya conocemos <strong>la</strong> sintaxis y <strong>la</strong> semántica <strong>de</strong> cada uno <strong>de</strong> los elementos y, en elsiguiente cuadro, se sintetizan <strong>la</strong>s construcciones <strong>de</strong>l lenguaje algorítmico.


© FUOC • P05/75062/00112 35 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte4. Evaluar <strong>la</strong> soluciónDe momento no hemos introducido ningún método formal para verificar <strong>la</strong> corrección<strong>de</strong> un algoritmo. Es <strong>de</strong>cir, <strong>de</strong>bemos hacerlo informalmente, medianteel razonamiento sobre <strong>la</strong> semántica <strong>de</strong> los elementos y <strong>la</strong>s construcciones <strong>de</strong>llenguaje algorítmico que hayamos utilizado, y mediante <strong>la</strong> comprobación, pasoa paso, <strong>de</strong> que los hemos ido componiendo <strong>de</strong> modo a<strong>de</strong>cuado para conseguirfinalmente <strong>la</strong> postcondición <strong>de</strong>seada.Los comentarios que hayamosinsertado en el momento <strong>de</strong> hacerel <strong>diseño</strong>, como ya sabéis, nosayudarán a llevar a cabo estareflexión.De todas formas, el uso <strong>de</strong> <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> y aplicación a<strong>de</strong>cuada <strong>de</strong>los esquemas <strong>de</strong> recorrido y búsqueda nos asegura <strong>la</strong> corrección <strong>de</strong> los tratamientossecuenciales que hayamos hecho. Recordad que un esquema es una especie<strong>de</strong> p<strong>la</strong>ntil<strong>la</strong> cuyo funcionamiento conocemos muy bien, y que utilizamospara solucionar un tipo concreto <strong>de</strong> problemas; por lo tanto, si lo aplicamos correctamente,nos conducirá a resultados también correctos.El uso combinado <strong>de</strong>l <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte y <strong>de</strong> los mecanismos <strong>de</strong> abstracciónno sólo beneficia al <strong>diseño</strong>, sino que también favorece otras etapas <strong>de</strong>l <strong>de</strong>sarrollo<strong>de</strong> programas:Como vimos en el módulo“<strong>Introducción</strong> a <strong>la</strong> programación”<strong>la</strong>s etapas <strong>de</strong> <strong>de</strong>sarrollo <strong>de</strong> un programason el análisis <strong>de</strong> requerimientos,el <strong>diseño</strong>, <strong>la</strong> implementación, <strong>la</strong>s pruebasy el mantenimiento.• El proceso <strong>de</strong> <strong>de</strong>sarrollo: gracias al hecho <strong>de</strong> parce<strong>la</strong>r <strong>la</strong> complejidad <strong>de</strong> losproblemas y <strong>de</strong> <strong>de</strong>scomponerlos sucesivamente en fragmentos menores,nos ocupamos en cada momento <strong>de</strong> <strong>la</strong> resolución <strong>de</strong> un único problema <strong>de</strong>dimensiones más manejables.• La puesta a punto: los fragmentos que componen los programas se pue<strong>de</strong>nprobar por separado (individualmente cada acción y función), y poco a poco.• El mantenimiento: <strong>la</strong>s modificaciones posteriores que será necesario realizardurante <strong>la</strong> vida útil <strong>de</strong> un programa, normalmente, tienen un impactolocalizado sólo en unas pocas acciones; el resto <strong>de</strong>l programa no se ve afectadoy, por lo tanto, el hecho <strong>de</strong> tenerlo <strong>de</strong>scompuesto facilita su modificación.Por otro <strong>la</strong>do, si los programas tienen una estructura más c<strong>la</strong>ra, resultamás fácil y seguro modificarlos.• La reutilización <strong>de</strong>l código: si se <strong>de</strong>sarrol<strong>la</strong>n programas que tratan con objetossimi<strong>la</strong>res, seguramente podremos aprovechar estos <strong>diseño</strong>s <strong>de</strong> tiposya hechos por otros programas, así como <strong>la</strong>s funciones y <strong>la</strong>s acciones quetraten.• La legibilidad: los programas que nos resultan <strong>de</strong>spués <strong>de</strong> aplicar <strong>la</strong>s técnicas<strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte y los esquemas están estructurados, por lo queson más fáciles <strong>de</strong> leer y analizar.


© FUOC • P05/75062/00112 37 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteEjercicios <strong>de</strong> autoevaluación1. Diseñar un algoritmo que <strong>de</strong>scubra cuántas veces aparece “LA” en una frase escrita enmayúscu<strong>la</strong>s y terminada con un punto en el canal <strong>de</strong> entrada. Por ejemplo, en <strong>la</strong> entrada tenemos<strong>la</strong> frase siguiente:BLANCA REGALA A LAIA UNA MANTA.El programa <strong>de</strong>berá dar como resultado: 3, ya que encontramos ‘LA’ en los siguientes casos:BLA 1 NCA REGALA 2 A LA 3 IA UNA MANTA.2. Dado un polígono especificado por una secuencia <strong>de</strong> vértices en el or<strong>de</strong>n <strong>de</strong> <strong>la</strong> serie <strong>de</strong> sucontorno, diseñad un algoritmo que encuentre su área. La secuencia termina con el primervértice con el que ha empezado. Como mínimo, en <strong>la</strong> entrada están los datos <strong>de</strong> un triángulo.Cada vértice se especifica por dos coor<strong>de</strong>nadas reales. Por ejemplo, si <strong>la</strong> secuencia es:3.0 3.0 2.0 6.0 7.0 11.0 12.0 9.0 3.0 3.0El polígono que representa es:Un amigo a quien le gusta <strong>la</strong> geometría nos dice que el cálculo <strong>de</strong>l área <strong>de</strong> un polígono, <strong>de</strong>scritopor sus vértices y el contorno que <strong>de</strong>limitan, se pue<strong>de</strong> calcu<strong>la</strong>r mediante <strong>la</strong> fórmu<strong>la</strong>:n( x i + 1 – x∑i ) ( y i + 1 + y i )-------------------------------------------------------2i = 1don<strong>de</strong> n es el número <strong>de</strong> aristas y cuando i = n, i + 1 es en realidad 1 (utilizar el módulo es <strong>la</strong>manera correcta <strong>de</strong> hacerlo, pero no lo ponemos para que <strong>la</strong> fórmu<strong>la</strong> tenga una mayor c<strong>la</strong>ridad).En nuestro ejemplo, el área A <strong>de</strong>l polígono sería:A = 1/2 ((2 − 3) (6 + 3) + (7 − 2) (11 + 6) + (12 − 7)(9 + 11) + (3 − 12)(3 + 9))A = 1/2 (−9 + 85 + 100 − 108) = 68/2 = 34Podría darse el caso <strong>de</strong> que el resultado fuese negativo, pero si le cambiásemos el signo el valor<strong>de</strong>l área continuaría siendo correcto. Disponemos <strong>de</strong> <strong>la</strong> función abs(r), que da el valor absoluto


© FUOC • P05/75062/00112 38 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte<strong>de</strong> un número real r. De hecho, cada término <strong>de</strong>l sumatorio calcu<strong>la</strong> el área <strong>de</strong>l trapecio que formauna arista <strong>de</strong>l polígono sobre el eje x, tal como se aprecia en <strong>la</strong> siguiente figura:Para quienes tengáis curiosidad por el tema (no es necesario que leáis esto para diseñar el algoritmo,ya que el enunciado dice muy c<strong>la</strong>ramente qué se <strong>de</strong>be resolver), podéis ver en <strong>la</strong>figura que el trapecio está compuesto por un triángulo y un rectángulo; entonces, el área A tserá:A t=y i ( x 2 – x 1 )⎧ ⎪⎨⎪⎩rectángulo+( x 2 – x 1 ) ( y 2 – y 1 )----------------------------------------------2⎧ ⎪⎪⎪⎨triángulo⎪⎪⎪⎩2y i ( x 2 – x 1 ) + ( x 2 – x 1 ) ( y 2 – y 1 )A t = ------------------------------------------------------------------------------------2( xA 2 – x 1 ) ( y 2 + y 1 )t = ----------------------------------------------2Observemos que el área tiene signo positivo o negativo <strong>de</strong>pendiendo <strong>de</strong> si x 2 > x 1 o no.Si los vértices <strong>de</strong> <strong>la</strong>s aristas <strong>de</strong> un polígono se dan respetando el sentido <strong>de</strong>l contorno (horarioo antihorario), <strong>la</strong>s áreas <strong>de</strong> los trapecios se podrán sumar <strong>de</strong> forma algebraica, <strong>de</strong>modo que obtendremos como resultado el área neta <strong>de</strong>l polígono, una vez que hayamosrecorrido todas <strong>la</strong>s aristas.De este modo, el área <strong>de</strong>l polígono se representará <strong>de</strong> <strong>la</strong> forma siguiente:n( x i + 1 – x∑i ) ( y i + 1 + y i )-------------------------------------------------------2i = 1Don<strong>de</strong> n es el número <strong>de</strong> aristas, y cuando i es igual a n + 1, n + 1 es 1.3. Dada una frase acabada con un punto, contad el número <strong>de</strong> pa<strong>la</strong>bras capicúa. Entre pa<strong>la</strong>brashay uno o más caracteres separadores como espacios, comas o puntos y coma. Cada pa<strong>la</strong>bra<strong>de</strong> <strong>la</strong> frase tiene como mucho 15 caracteres.4. Una empresa <strong>de</strong> publicidad tiene un servidor <strong>de</strong> Internet y quiere facturar a sus clientes <strong>la</strong>spáginas <strong>de</strong> HTML insta<strong>la</strong>das. Con este propósito, <strong>la</strong> empresa quiere que diseñemos un programaque indique lo que cada cliente tiene que pagar a partir <strong>de</strong>l contenido <strong>de</strong> <strong>la</strong>s páginas insta<strong>la</strong>das.


© FUOC • P05/75062/00112 39 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteEn <strong>la</strong> entrada <strong>de</strong>l programa habrá una secuencia <strong>de</strong> caracteres organizada <strong>de</strong> <strong>la</strong> forma siguiente:m 11 · m 12 · ... · m 1n1 · FinTextoHTML · m 21 · m 22 · m 2n2 · FinTextoHTML · ... ·· ... · m n1 · m n2 · m nn n· FinTextoHTML · FinPaginasDon<strong>de</strong> m ij son ca<strong>de</strong>nas <strong>de</strong> caracteres sin separadores que pue<strong>de</strong>n tener cualquier número <strong>de</strong>caracteres. FinTextoHTML es <strong>la</strong> pa<strong>la</strong>bra “FinTextoHTML” e indica el final <strong>de</strong> <strong>la</strong> página HTML.FinPaginas indica el final <strong>de</strong> <strong>la</strong> secuencia y es <strong>la</strong> pa<strong>la</strong>bra “FinPaginas” acabada con un b<strong>la</strong>nco.Se consi<strong>de</strong>ra que un carácter es separador si éste es un espacio (“ ”), un “=”, o se trata <strong>de</strong> uncontrol <strong>de</strong> línea (retorno <strong>de</strong> carro o salto <strong>de</strong> línea).De entre <strong>la</strong>s pa<strong>la</strong>bras que hay en cada página, interesa reconocer <strong>la</strong> pa<strong>la</strong>bra “propiedad”, yaque a continuación <strong>de</strong> ésta aparecerá el nombre <strong>de</strong>l cliente que ha puesto <strong>la</strong> página y, por lotanto, a quien se le <strong>de</strong>be facturar. Para facturar <strong>la</strong> página a <strong>la</strong> empresa propietaria, el programa<strong>de</strong>berá tener en cuenta lo siguiente:• Las pa<strong>la</strong>bras “propiedad”, “FinTextoHTML” y “FinPaginas” son obviamente gratuitas, yaque sólo sirven para contro<strong>la</strong>r <strong>la</strong> secuencia.• Toda pa<strong>la</strong>bra en <strong>la</strong> cual el primer carácter sea “” no contará, ya que setrata <strong>de</strong> controles <strong>de</strong>l lenguaje HTML que <strong>la</strong> empresa consi<strong>de</strong>ra gratuitos (sólo pa<strong>la</strong>bras, <strong>la</strong>sfrases entre los caracteres “” no serán gratuitas).• Si se encuentra <strong>la</strong> pa<strong>la</strong>bra “ La última innovación pue<strong>de</strong>s encontrar <strong>la</strong> página enFinTextoHTMLFinPaginas


© FUOC • P05/75062/00112 40 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteEn <strong>la</strong> salida tendremos:VagonesPopu<strong>la</strong>res 7.2 UOC 2.1Hay 42 pa<strong>la</strong>bras contabilizadas a 5 euros. Para el caso <strong>de</strong> VagonesPopu<strong>la</strong>res: La última innovación .


© FUOC • P05/75062/00112 41 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteSolucionario1. Tenemos que diseñar un algoritmo que calcule cuantas veces aparece “LA” en una fraseescrita en mayúscu<strong>la</strong>s y acabada en punto y final.EspecificaciónLa frase se pue<strong>de</strong> ver como una secuencia <strong>de</strong> caracteres acabada con un punto; necesitaremosun contador que <strong>de</strong>nominaremos nuDeLA para indicar el número <strong>de</strong> ‘‘LA” que aparecen en<strong>la</strong> secuencia. De este modo, entonces,varnuDeLA: enterofvar{ Pre: f = F, f es una frase acabada con un punto y f sólo contiene mayúscu<strong>la</strong>s }contarLA{ Post: nuDeLA indica el número <strong>de</strong> ‘LA’ que hay en F }P<strong>la</strong>nteamiento general 1Al principio pue<strong>de</strong> parecer que sea posible pensar el problema directamente a partir <strong>de</strong> <strong>la</strong> secuencia<strong>de</strong> caracteres aplicando un esquema <strong>de</strong> recorrido. Pero, tener que trabajar carácterpor carácter dificulta nuestra perspectiva <strong>de</strong>l problema, ya que necesitaremos ver dos caracteresal mismo tiempo para <strong>de</strong>cidir si es una pareja “LA” o no. Si se piensa carácter a carácter,nos po<strong>de</strong>mos encontrar con los siguientes casos:1. El carácter leído es diferente <strong>de</strong> ‘L’ → Pasamos a consultar el siguiente carácter.2. El carácter leído es igual a ‘L’ → Debemos verificar que el carácter siguiente sea una ‘A’.Para el carácter siguiente, nos encontraremos con los siguientes casos:(a) Es una ‘A’→ Incrementamos el contador <strong>de</strong> ‘LA’.(b) Es una ‘L’→ Debemos continuar verificando el carácter que sigue al actual, ya que se podríadar el caso <strong>de</strong>, por ejemplo, ‘ELLA’.(c) Es diferente <strong>de</strong> ‘L’ y ‘A’ → No tenemos en cuenta el carácter actual, ya que no dará ‘LA’.Solución 1algoritmo contarLAvarc: caracter;nuDeLA: entero;fvar{ f = F , f es una frase acabada en punto y f sólo contiene mayúscu<strong>la</strong>s }nuDeLA := 0;c := leerCaracter();mientras c ≠ ‘.’ hacersi c = ‘L’ entonces {Carácter actual es una ‘L’}c := leerCaracter();si c = ‘A’ entonces { el carácter anterior fue una ‘L’ y el actual, una ‘A’ }nuDeLA := nuDeLA + 1;c := leerCaracter()fsi{En caso <strong>de</strong> quec = ‘A’→ ya habremos avanzado y contado.c = ‘.’ → mejor no avanzar.c = ‘L’→ aprovecharemos el primer condicional y, por lo tanto, no avanzamos.c ≠ ‘L’→ ya avanzaremos con el sino <strong>de</strong>l primer condicional.}sino {c ≠ ‘.’}c:= leerCaracter()


© FUOC • P05/75062/00112 42 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntefsifmientras{nuDeLA indica el número <strong>de</strong> ‘LA’ que hay en F}escribirEntero(nuDeLA)falgoritmoEvaluación 1La corrección <strong>de</strong> <strong>la</strong> solución presentada es muy difícil <strong>de</strong> evaluar. Por ejemplo, <strong>de</strong>bemos resolvercuestiones <strong>de</strong>l siguiente tipo:1. ¿Tiene en cuenta <strong>la</strong> secuencia vacía formada sólo por el punto?2. ¿Tiene en cuenta casos como ‘ELLA’?3. ¿Avanza siempre <strong>la</strong> secuencia, o se queda estancada en algún punto?Si seguís bien el algoritmo, os daréis cuenta <strong>de</strong> que todas <strong>la</strong>s cuestiones están bien cubiertas.A pesar <strong>de</strong> ello, es muy difícil verlo.P<strong>la</strong>nteamiento general 2El hecho <strong>de</strong> pensar este problema en términos <strong>de</strong> caracteres ha creado un cierto <strong>de</strong>sor<strong>de</strong>n. Encambio, si convenimos en <strong>la</strong> abstracción <strong>de</strong> pareja <strong>de</strong> caracteres, veremos que el problema esmás fácil <strong>de</strong> analizar y <strong>de</strong>sarrol<strong>la</strong>r. Lo primero que <strong>de</strong>bemos hacer es imaginarnos que tenemosuna secuencia <strong>de</strong> parejas <strong>de</strong> caracteres. Esto nos conduce a particu<strong>la</strong>rizar el esquema <strong>de</strong>recorrido teniendo en cuenta <strong>la</strong> abstracción convenida:1)Primer nivelSoluciónalgoritmo contarLAvarnuDeLA: entero;Pareja: tPareja;fvar{ f = F, f es una frase acabada en punto y f sólo contiene mayúscu<strong>la</strong>s}nuDeLA := 0;obtenerPrimeraPareja(pareja);mientras no ultimaPareja(pareja) hacersi esLA(pareja) entoncesnuDeLA := nuDeLA + 1fsiobtenerPareja(pareja)fmientras{ nuDeLA indica el número <strong>de</strong> ‘LA’que hay en F }escribirEntero(nuDeLA)falgoritmoAhora tenemos una parte <strong>de</strong> <strong>la</strong> solución expresada, y el nivel se completará con <strong>la</strong> especificación<strong>de</strong> <strong>la</strong>s acciones y funciones que quedan por <strong>de</strong>sarrol<strong>la</strong>r:accion obtenerPrimeraPareja (sal p: tPareja);{ Pre: s = S, s es una frase acabada en punto y <strong>la</strong> parte izquierda <strong>de</strong> s está vacía }{ Post: p contendrá <strong>la</strong> primera pareja <strong>de</strong> <strong>la</strong> secuencia <strong>de</strong> parejas y <strong>la</strong> parte izquierda <strong>de</strong> scontendrá un carácter }accion obtenerPareja (entsal p: tPareja);{ Pre: s = S, s es una frase acabada en punto y <strong>la</strong> parte izquierda <strong>de</strong> S no está vacía, <strong>la</strong> parte<strong>de</strong>recha <strong>de</strong> s tampoco está vacía y p = P y P es <strong>la</strong> anterior pareja obtenida }{ Post: p contendrá <strong>la</strong> pareja siguiente <strong>de</strong> <strong>la</strong> secuencia <strong>de</strong> parejas, y <strong>la</strong> parte izquierda <strong>de</strong> scontendrá un carácter más }funcion ultimaPareja(p: tPareja): booleano{ Pre: p = P }{ Post: ultimaPareja(p) es cierto si P es <strong>la</strong> última pareja <strong>de</strong> <strong>la</strong> secuencia }


© FUOC • P05/75062/00112 43 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntefuncion EsLA(P: tPareja): booleano;{ Pre: p = P }{ Post: esLA(P) es cierto si P es <strong>la</strong> pareja LA }Notad que para verificar esta parte no necesitamos conocer <strong>la</strong> <strong>de</strong>finición <strong>de</strong>l tipo tPareja, ydado que disponemos <strong>de</strong> <strong>la</strong> especificación <strong>de</strong> acciones y funciones que hay que <strong>de</strong>sarrol<strong>la</strong>r,po<strong>de</strong>mos comprobar si es correcta <strong>la</strong> solución formu<strong>la</strong>da hasta ahora.2)Segundo nivelP<strong>la</strong>nteamientoPara continuar el <strong>diseño</strong> se necesita <strong>de</strong>finir <strong>la</strong> representación que tendrá una pareja <strong>de</strong> caracteres.Una posibilidad consiste en <strong>de</strong>finir <strong>la</strong> tup<strong>la</strong>, y otra en <strong>de</strong>finir una tab<strong>la</strong>. Elegiremos unatab<strong>la</strong> (elegir una tup<strong>la</strong> también habría sido una buena solución para este problema).tipotPareja = tab<strong>la</strong> [2] <strong>de</strong> caracter;ftipoAhora <strong>de</strong>bemos p<strong>la</strong>ntear el problema <strong>de</strong> cómo hacer que nuestra secuencia <strong>de</strong> caracteres se puedaver como <strong>la</strong> secuencia <strong>de</strong> parejas que nos conviene. Veamos <strong>la</strong> correspon<strong>de</strong>ncia que existe:<strong>la</strong> secuencia f está formada por c 1 c 2 c 3 c 4 c 5 …c f , don<strong>de</strong> c f es el carácter final ‘.’, y queremos veruna secuencia <strong>de</strong> parejas p 1 p 2 …p f tal que p 1 = c 1 c 2 , p 2 = c 2 c 3 , y p f tenga como segundo carácterel punto.Observamos que se trata <strong>de</strong> parejas so<strong>la</strong>padas <strong>de</strong> caracteres: cada pareja que no sea <strong>la</strong> primeracomparte un carácter con <strong>la</strong> anterior.La primera pareja entendida como los dos primeros caracteres <strong>de</strong> <strong>la</strong> secuencia (c 1 c 2 ), obligaríaa que <strong>la</strong> secuencia <strong>de</strong> caracteres tuviese como mínimo un carácter diferente al punto (c 1 ‘.’).Para ajustarnos a <strong>la</strong> precondición (como mínimo, <strong>la</strong> secuencia tiene el punto final) <strong>de</strong>beremoshacer que el primer carácter <strong>de</strong> <strong>la</strong> primera pareja sea un carácter arbitrario que no forme parte<strong>de</strong> <strong>la</strong> secuencia y que el segundo carácter sea el primero <strong>de</strong> <strong>la</strong> secuencia. Elegiremos el carácterarbitrario <strong>de</strong> modo que no nos estropee el tratamiento (que no sea una ‘L’). Por ejemplo, elcarácter espacio. De este modo, <strong>la</strong> secuencia que nos conviene es:que tenga como segundo carácter el punto.Por lo tanto:p 1 = ‘ ’ c 1 , p 2 = c 1 c 2 , y p fSoluciónaccion obtenerPrimeraPareja(sal p: tPareja)p[1]:= ‘ ’ ;p[2]:= leerCaracter()faccionaccion obtenerPareja(entsal p: tPareja)p[1]:= p[2];p[2]:= leerCaracter()faccionfuncion ultimaPareja(p: tPareja): booleanoretorna p[2] = ‘.’ffuncionfuncion esLA(p: tPareja): booleanoretorna p[1] = ‘L’ y p[2] = ‘A’ffuncion2. Tenemos que diseñar un algoritmo que calcule al área <strong>de</strong> un polígono a partir <strong>de</strong> <strong>la</strong>s coor<strong>de</strong>nadas<strong>de</strong> sus vértices.


© FUOC • P05/75062/00112 44 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteEspecificaciónPasemos a especificarlo. Para hacerlo, abreviaremos <strong>la</strong>s especificaciones <strong>de</strong>nominando <strong>la</strong> secuencia<strong>de</strong> entrada <strong>de</strong> datos pol.var area: real fvar;{ Pre: pol = POL y POL es una secuencia <strong>de</strong> reales que representa como mínimo un triángulo }areaPoligono{ Post: en area se encuentra el área <strong>de</strong>l polígono representado en <strong>la</strong> secuencia POL }1)Primer nivelP<strong>la</strong>nteamientoPara afrontar bien el problema es necesario i<strong>de</strong>ntificar los objetos que pue<strong>de</strong>n ser convenientespara nuestro análisis. Éstos son:• aristas• vértices• realesEn <strong>la</strong> primera etapa <strong>de</strong>l <strong>diseño</strong>, es conveniente hacer <strong>la</strong> formu<strong>la</strong>ción <strong>de</strong>l algoritmo en términos<strong>de</strong> arista, a pesar <strong>de</strong> que en <strong>la</strong> entrada disponemos <strong>de</strong> una secuencia <strong>de</strong> reales. Imaginemos,entonces, el tipo arista y que en <strong>la</strong> entrada tenemos una secuencia <strong>de</strong> arista. En estecaso, <strong>la</strong>s cuestiones clásicas <strong>de</strong> cómo se obtiene el primero, el siguiente y el último elementoestarán encapsu<strong>la</strong>das mediante <strong>la</strong>s acciones y <strong>la</strong>s funciones que encontraréis más a<strong>de</strong><strong>la</strong>nte.Repasando el enunciado, vemos que cada término <strong>de</strong>l sumatorio es el área <strong>de</strong>l trapecio correspondientea cada arista. El tratamiento que hay que aplicar consistiría, <strong>de</strong> este modo, en ir acumu<strong>la</strong>ndoestas áreas para tener al final el sumatorio. Obviamente, esto correspon<strong>de</strong> al esquema<strong>de</strong> recorrido sobre una secuencia <strong>de</strong> aristas y también <strong>de</strong>beremos reflexionar sobre el esquema.Por ejemplo, es necesario tratar <strong>la</strong> última arista que hace <strong>de</strong> marca <strong>de</strong> fin <strong>de</strong> secuencia; por lotanto, <strong>de</strong>beremos modificar ligeramente el esquema para conseguir este efecto.Otra observación es que <strong>de</strong>l sumatorio po<strong>de</strong>mos extraer factor común <strong>de</strong> <strong>la</strong> división por dos,y posponer<strong>la</strong> para el tratamiento final. El tratamiento final consistirá en dividir por dos <strong>la</strong>sáreas acumu<strong>la</strong>das y encontrar su valor absoluto. Así, para cada arista calcu<strong>la</strong>remos el área doble,y <strong>de</strong> este modo ahorraremos algunos cálculos. Notad, en <strong>la</strong> solución que tenéis más a<strong>de</strong><strong>la</strong>nte,que <strong>la</strong> última asignación es el tratamiento final, pero <strong>la</strong> expresión en <strong>la</strong> parte <strong>de</strong>recha<strong>de</strong> <strong>la</strong> asignación incluye el tratamiento <strong>de</strong> <strong>la</strong> última arista.Tenemos, pues, todos los elementos para pasar a expresar una solución centrada en <strong>la</strong>s aristas<strong>de</strong>l polígono y <strong>la</strong>s áreas <strong>de</strong> los trapecios correspondientes; así, no entraremos en <strong>de</strong>talles másconcretos.algoritmo areaPoligonovararea: real;a: arista;fvar{ Pre: pol = POL y POL es una secuencia <strong>de</strong> reales que representa como mínimo un triangulo }obtenerPrimeraArista(a);area := 0;mientras no ultimaArista(a) hacerarea := area + areaTrapecio(a);obtener Arista(a)fmientrasarea := abs ((area + areaTrapecio(a)) / 2.0){ Post : en area tenemos el area <strong>de</strong>l polígolno representado en <strong>la</strong> secuencia POL }falgoritmoaccion obtenerPrimeraArista(sal a: arista){ Pre: en <strong>la</strong> entrada tenemos una secuencia <strong>de</strong> aristas pol y pol = POL y pol tiene como mínimotres aristas en <strong>la</strong> parte <strong>de</strong>recha, mientras que <strong>la</strong> parte izquierda está vacía }{ Post: a será <strong>la</strong> primera arista <strong>de</strong> POL y en <strong>la</strong> parte izquierda <strong>de</strong> pol hay una arista }


© FUOC • P05/75062/00112 45 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteaccion obtenerArista(entsal a: arista){ Pre: pol = POL y <strong>la</strong> parte <strong>de</strong>recha <strong>de</strong> pol, PDPol, no está vacía y tiene como mínimo unaarista; <strong>la</strong> parte izquierda <strong>de</strong> pol tiene como mínimo una arista, a = A y A es <strong>la</strong> última aristaobtenida }{ Post: a tiene <strong>la</strong> primera arista <strong>de</strong> PDPol, y el valor <strong>de</strong> a es <strong>la</strong> última arista <strong>de</strong> <strong>la</strong> parte izquierda<strong>de</strong> pol }funcion ultimaArista(a: arista): booleano{ Pre: a = A }{ Post: ultimaArista (A) es cierto si A es <strong>la</strong> última arista <strong>de</strong> POL }funcion areaTrapecio (a: arista): real;{ Pre: a = A }{ Post: areaTrapecio(A) es el área doble <strong>de</strong>l trapecio formado por <strong>la</strong> arista A y el eje x }2)Segundo nivelConvencidos <strong>de</strong>l primer nivel, pasemos al siguiente, que consiste en <strong>de</strong>finir <strong>la</strong>s acciones y <strong>la</strong>sfunciones y tipos que han quedado pendientes. En este nivel es conveniente pensar en términos<strong>de</strong> vértices, y consi<strong>de</strong>rar nuestra secuencia como una secuencia <strong>de</strong> vértices.Para el p<strong>la</strong>nteamiento <strong>de</strong> <strong>la</strong> secuencia <strong>de</strong> vértices, es necesario observar que <strong>la</strong> abstracción <strong>de</strong>arista está formada por dos parejas <strong>de</strong> vértices so<strong>la</strong>padas en <strong>la</strong> secuencia:a 1 a 3v 1, v 2, v 3, v 4 , v 5 , ...a 2 a 4Así pues, <strong>la</strong>s i<strong>de</strong>as que hay que aplicar al p<strong>la</strong>nteamiento (primer elemento, siguiente y último)son <strong>la</strong>s mismas que nos encontramos cuando solucionábamos el problema <strong>de</strong> contar‘LA’, y por ello no <strong>la</strong>s representaremos aquí. La última arista merece una atención especial.Si examinamos el enunciado, vemos que <strong>la</strong> última arista es aquél<strong>la</strong> cuyo extremo final, v f , esidéntico al vértice inicial <strong>de</strong> <strong>la</strong> primera arista (v 1 ), que es a<strong>de</strong>más el primer elemento <strong>de</strong> <strong>la</strong>secuencia. Con estas observaciones pasamos directamente a <strong>la</strong> solución.Cuando <strong>de</strong>finamos el tipo arista <strong>de</strong>beremos tener en cuenta que necesitaremos sus dos vérticespara po<strong>de</strong>r aplicar <strong>la</strong> fórmu<strong>la</strong> <strong>de</strong>l área <strong>de</strong>l trapecio, y también saber cuál es el últimovértice <strong>de</strong> <strong>la</strong> secuencia:tipoarista = tup<strong>la</strong> vi, vf, dv: vertice;ftup<strong>la</strong>ftipo{ Pre: en <strong>la</strong> entrada tenemos una secuencia <strong>de</strong> aristas pol y pol = POL y pol, como mínimo tienetres aristas en <strong>la</strong> parte <strong>de</strong>recha y <strong>la</strong> parte izquierda está vacía }accion obtenerPrimeraArista(sal A: arista)obtenerPrimerVertice(A.vi); { por <strong>la</strong> precondición sabemos que como mínimo hay cuatrovértices }obtenerVertice(A.vf); { contando el que marca el final }A.dv := A.vifaccion{ Post: A tiene <strong>la</strong> primera arista <strong>de</strong> pdPol y el valora <strong>de</strong> A es <strong>la</strong> última arista <strong>de</strong> <strong>la</strong> parte izquierda<strong>de</strong> Pol }{ Pre: pol = POL y <strong>la</strong> parte <strong>de</strong>recha <strong>de</strong> pol, pDPol, no está vacía y tiene como mínimo una arista;<strong>la</strong> parte izquierda <strong>de</strong> pol tiene como mínimo una arista; a = A y A es <strong>la</strong> última arista obtenida }accion obtenerArista( entsal a: arista)a.vi:= a.vf;obtenerVertice(a.vf)faccion{ Post: A tiene <strong>la</strong> primera arista <strong>de</strong> pDPol y el valor <strong>de</strong> A es <strong>la</strong> última arista <strong>de</strong> <strong>la</strong> parte izquierda<strong>de</strong> pol }


© FUOC • P05/75062/00112 46 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte{ Pre: a = A }funcion ultimaArista(a: arista): booleanoretorna verticesIguales(a.vf, a.dv)ffuncion{ Post: ultimaArista (A) es cierto si A es <strong>la</strong> última arista <strong>de</strong> POL }{ Pre: a = A }funcion areaTrapecio(a: arista): realretorna areaTrapecioVertices (a.vi,a.vf)ffuncion{ Post: areaTrapecio(A) es el área doble <strong>de</strong>l trapecio formado por <strong>la</strong> arista A y el eje x }3)Tercer nivelFinalizado el segundo nivel, es necesario <strong>de</strong>finir <strong>la</strong> secuencia <strong>de</strong> vértices a partir <strong>de</strong> <strong>la</strong> secuencia<strong>de</strong> reales. En este caso, po<strong>de</strong>mos observar que los vértices son parejas <strong>de</strong> realesdisyuntas:v 1 v 2x 1, y 1, x 2, y 2, ...tipovertice = tup<strong>la</strong> x, y: real;ftup<strong>la</strong>ftipo{ Pre: v1 = V1 y v2 = V2 }funcion areaTrapecioVertices (v1, v2: vertice): realretorna (v2.x – v1.x) ∗ (v2.y + v1.y)ffuncion{ Post: areaTrapecioVertices(V1,V2) es el área doble <strong>de</strong>l trapecio formado por <strong>la</strong> arista que va<strong>de</strong> V1 a V2 y el eje x }{ Pre: pol = POL y pol tiene como mínimo dos reales (un vértice) en su parte <strong>de</strong>recha }accion obtenerPrimerVertice(sal v: vertice)v.x:= leerReal();v.y:= leerReal()faccion{ Post: <strong>la</strong> parte izquierda <strong>de</strong> pol tiene un vértice más y v tiene el vértice que antes estaba en<strong>la</strong> parte <strong>de</strong>recha }{ Pre: pol = POL y pol como mínimo tiene dos reales (un vértice) en su parte <strong>de</strong>recha }accion obtenerVertice(sal v: vertice)v.x:= leerReal();v.y:= leerReal()faccion{ Post: <strong>la</strong> parte izquierda <strong>de</strong> pol tiene un vértice más y v tiene el vértice que antes estaba en <strong>la</strong><strong>de</strong>recha }{ Pre: v1 = V1 y v2 = V2 }funcion verticesIguales(v1, v2: vertice): booleanoretorna (v1.x = v2.x) y (v1.y = v2.y)ffuncion{ verticesIguales(v1, v2) es cierto si V1 y V2 son el mismo vértice }3.Especificaciónvar nPa<strong>la</strong>brasC: entero;fvar{ en <strong>la</strong> entrada hay <strong>la</strong> secuencia <strong>de</strong> pa<strong>la</strong>bras f <strong>de</strong> <strong>la</strong> frase F. F no está vacía }cuentaCapicuasFrase{ nPa<strong>la</strong>brasC tiene el número <strong>de</strong> pa<strong>la</strong>bras capicúa <strong>de</strong> F }


© FUOC • P05/75062/00112 47 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte1)Primer nivel: fraseP<strong>la</strong>nteamiento– Abstracciones utilizadas: pa<strong>la</strong>bra.– I<strong>de</strong>ntificación <strong>de</strong> <strong>la</strong> secuencia: frase vista como secuencia <strong>de</strong> pa<strong>la</strong>bras. La obtención <strong>de</strong> <strong>la</strong>spa<strong>la</strong>bras primera y siguiente y el reconocimiento <strong>de</strong> <strong>la</strong> marca se encapsu<strong>la</strong>n mediante accionesy funciones.– I<strong>de</strong>ntificación <strong>de</strong>l esquema: recorrido. Hay que tratar <strong>la</strong> pa<strong>la</strong>bra que hace <strong>de</strong> marca <strong>de</strong> final.Aplicación directa <strong>de</strong>l algoritmoalgoritmo cuentaCapicuasFrasevarpa<strong>la</strong>bra: tPa<strong>la</strong>bra;nPa<strong>la</strong>brasC: entero;fvarnPa<strong>la</strong>brasC := 0;obtenerPrimeraPa<strong>la</strong>bra(pa<strong>la</strong>bra);mientras no pa<strong>la</strong>braFinal(pa<strong>la</strong>bra) hacersi pa<strong>la</strong>braCapicua(pa<strong>la</strong>bra) entonces nPa<strong>la</strong>brasC := nPa<strong>la</strong>brasC + 1;fsiobtenerPa<strong>la</strong>bra(pa<strong>la</strong>bra)fmientrassi pa<strong>la</strong>braCapicua(pa<strong>la</strong>bra) entonces nPa<strong>la</strong>brasC := nPa<strong>la</strong>brasC + 1fsiescribirEntero(nPa<strong>la</strong>brasC)falgoritmoAcciones pendientes <strong>de</strong> <strong>de</strong>sarrol<strong>la</strong>rEl algoritmo funcionará si <strong>la</strong>s acciones y funciones que se <strong>de</strong>ben <strong>de</strong>sarrol<strong>la</strong>r cumplen <strong>la</strong>s especificacionessiguientes:accion obtenerPrimeraPa<strong>la</strong>bra(sal m: tPa<strong>la</strong>bra){ Pre: en <strong>la</strong> entrada hay <strong>la</strong> secuencia <strong>de</strong> pa<strong>la</strong>bras f <strong>de</strong> <strong>la</strong> frase F. La parte izquierda <strong>de</strong> f estávacía. La parte <strong>de</strong>recha, DF, no está vacía }{ Post: m representa <strong>la</strong> primera pa<strong>la</strong>bra <strong>de</strong> DF. La pa<strong>la</strong>bra obtenida estará en <strong>la</strong> parte izquierda<strong>de</strong> <strong>la</strong> secuencia f }accion obtenerPa<strong>la</strong>bra(entsal m: tPa<strong>la</strong>bra){ Pre: en <strong>la</strong> entrada hay <strong>la</strong> secuencia <strong>de</strong> pa<strong>la</strong>bras f <strong>de</strong> <strong>la</strong> frase F. La parte <strong>de</strong>recha, DF, no estávacía. La anterior pa<strong>la</strong>bra leída está en m }{ Post: m representa <strong>la</strong> primera pa<strong>la</strong>bra <strong>de</strong> DF. La pa<strong>la</strong>bra obtenida estará en <strong>la</strong> parte izquierda<strong>de</strong> <strong>la</strong> secuencia f }funcion pa<strong>la</strong>braFinal(ent m: tPa<strong>la</strong>bra): booleano{ Pre: m = M }{ Post: pa<strong>la</strong>braFinal(M) es cierto si m es <strong>la</strong> última pa<strong>la</strong>bra <strong>de</strong> una frase }funcion pa<strong>la</strong>braCapicua( ent m: tPa<strong>la</strong>bra): booleano{ Pre: m = M }{ Post: pa<strong>la</strong>braCapicua (M) es cierto sólo si m es una pa<strong>la</strong>bra capicúa }2)Segundo nivel: pa<strong>la</strong>bra– Abstracciones utilizadas: ninguna.– I<strong>de</strong>ntificación <strong>de</strong> <strong>la</strong> secuencia: pa<strong>la</strong>bra vista como una secuencia <strong>de</strong> caracteres. La obtención<strong>de</strong> <strong>la</strong>s pa<strong>la</strong>bras primera y siguiente se hará mediante <strong>la</strong> función pre<strong>de</strong>finida leerCaracter() yel reconocimiento <strong>de</strong>l carácter que marca el final será el carácter espacio o <strong>la</strong> coma, o el puntoy coma, o el punto.


© FUOC • P05/75062/00112 48 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteDefinición <strong>de</strong>l tipoNecesitaremos guardar los elementos siguientes:– El contenido <strong>de</strong> <strong>la</strong> pa<strong>la</strong>bra: <strong>la</strong> tab<strong>la</strong> c y long, ya que <strong>la</strong> tab<strong>la</strong> pue<strong>de</strong> estar parcialmente llena.– El último carácter leído <strong>de</strong> <strong>la</strong> secuencia: caracterLeido será siempre el carácter <strong>de</strong> <strong>la</strong> siguientepa<strong>la</strong>bra que se lee en el caso <strong>de</strong> que no se haya llegado al final <strong>de</strong> <strong>la</strong> secuencia.– Un indicador <strong>de</strong> final: final será cierto si se trata <strong>de</strong> <strong>la</strong> última pa<strong>la</strong>bra.const maxCar: entero = 15;fconsttipotPa<strong>la</strong>bra = tup<strong>la</strong>long: entero;c: tab<strong>la</strong>[maxCar] <strong>de</strong> caracter;caracterLeido: caracter;final: booleano;ftup<strong>la</strong>ftipoP<strong>la</strong>nteamiento y soluciones <strong>de</strong> <strong>la</strong>s acciones y funciones <strong>de</strong>l nivelI<strong>de</strong>ntificación esquema: recorrido.accion obtenerPrimeraPa<strong>la</strong>bra(sal m: tPa<strong>la</strong>bra)var c: caracter;fvarm.long := 0;c := leerCaracter();mientras separador(c) y c ≠ ‘.’ hacer { saltamos los primeros separadores }c := leerCaracter()fmientrasm.caracterLeido := c;obtenerPa<strong>la</strong>bra(m)faccionI<strong>de</strong>ntificación <strong>de</strong>l esquema: recorrido.accion obtenerPa<strong>la</strong>bra (entsal m: tPa<strong>la</strong>bra)var c: caracter;fvarm.long := 0;c := m.caracterLeido;mientras no separador(c) y c ≠ ‘.’ hacer { obtenemos <strong>la</strong> pa<strong>la</strong>bra }m.long := m.long + 1;m.c[m.long] := c;c := leerCaracter()fmientrasmientras separador (c) y c ≠ ‘.’ hacer { saltamos los separadores }c := leerCaracter()fmientrasm.caracterLeido := c;m.final := c = ‘.’faccionAplicación directa <strong>de</strong>l algoritmofuncion pa<strong>la</strong>braFinal(m: tPa<strong>la</strong>bra): booleanoretorna m.finalffuncion


© FUOC • P05/75062/00112 49 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteI<strong>de</strong>ntificación <strong>de</strong>l esquema: búsqueda.funcion pa<strong>la</strong>braCapicua(m: tPa<strong>la</strong>bra): booleanovari, j; entero;encontrado: booleano;fvari := 1; j := m.long;encontrado := falso;mientras (no encontrado) y (i < j) hacersi m.c[i] ≠ m.c[j] entoncesencontrado := ciertosino i := i + 1; j := j – 1fsifmientrasretorna no encontradoffuncionfuncion separador(ent c: caracter): booleanoretorna (c= ‘ ’) o (c = ‘,’) o (c = ‘;’)ffuncion4. Del enunciado <strong>de</strong>ducimos que po<strong>de</strong>mos organizar los niveles <strong>de</strong> <strong>de</strong>scomposición <strong>de</strong>l <strong>diseño</strong>a partir <strong>de</strong> los objetos <strong>de</strong>l problema. En <strong>la</strong> entrada <strong>de</strong>l programa tenemos una secuencia<strong>de</strong> páginas. Una página es una secuencia <strong>de</strong> pa<strong>la</strong>bras separadas por espacios y controles <strong>de</strong>línea. Una pa<strong>la</strong>bra es una secuencia <strong>de</strong> caracteres sin espacios ni controles <strong>de</strong> línea. La secuencia<strong>de</strong> entrada es <strong>de</strong> tipo carácter. Po<strong>de</strong>mos distinguir, pues, tres niveles <strong>de</strong> <strong>de</strong>scomposición<strong>de</strong>l <strong>diseño</strong>:a) Secuencia <strong>de</strong> páginas <strong>de</strong> web acabada con “FinPaginas”.b) Página: secuencia <strong>de</strong> pa<strong>la</strong>bras acabada con <strong>la</strong> pa<strong>la</strong>bra “FinTextoHTML”.c) Pa<strong>la</strong>bra: secuencia <strong>de</strong> caracteres terminada con separador (espacio, símbolo =, caracteres<strong>de</strong> control <strong>de</strong> línea).1)Primer nivel: secuencia <strong>de</strong> páginasEspecificaciónReleemos el enunciadoy lo adaptamos siguiendo<strong>la</strong> abstracción <strong>de</strong> página.El objetivo es confeccionar una lista <strong>de</strong> <strong>la</strong>s empresas clientes que participan en el servidor y,para cada empresa participante, obtener <strong>la</strong> cantidad que se les <strong>de</strong>be facturar. Para cada página,po<strong>de</strong>mos obtener el nombre <strong>de</strong> <strong>la</strong> empresa cliente a <strong>la</strong> cual pertenece y valorar su precioa partir <strong>de</strong>l contenido. En un primer nivel, formu<strong>la</strong>mos el algoritmo en términos <strong>de</strong> una secuencia<strong>de</strong> páginas. De este modo, por lo tanto, <strong>la</strong> entrada se pue<strong>de</strong> ver como una secuencia<strong>de</strong> páginas:s = S = ‘FinPaginas’ indica el final <strong>de</strong> <strong>la</strong> secuencia y se pue<strong>de</strong> consi<strong>de</strong>rar como una página especial yúnica que sólo tiene <strong>la</strong> pa<strong>la</strong>bra “FinPaginas”.La precondición se pue<strong>de</strong> expresar como:{ Pre: s = S = y (toda P i , 1 ≤ i ≤ n, es una página) }La postcondición consistirá en tener una secuencia t <strong>de</strong> empresas clientes con el importe facturado.La secuencia t tendrá <strong>la</strong> forma siguiente:t = Don<strong>de</strong> E i es el nombre <strong>de</strong> una empresa cliente presente en <strong>la</strong> secuencia S, y F i es el importe<strong>de</strong> <strong>la</strong> facturación que se <strong>de</strong>be aplicar a <strong>la</strong> empresa E i . La especificación <strong>de</strong>l algoritmo será, porlo tanto:{ Pre: en <strong>la</strong> entrada se tiene una secuencia s = S = y (toda P i,1 ≤ i ≤ n, es una página) }


© FUOC • P05/75062/00112 50 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntefacturaPaginas{ Post: crea <strong>la</strong> secuencia <strong>de</strong> salida t = y (si E i ≠ ‘NoI<strong>de</strong>ntificados’, E i es un nombre <strong>de</strong> empresa cliente que hay en S)y (F i es el importe correspondiente a <strong>la</strong> empresa E i <strong>de</strong> todas <strong>la</strong>s pa<strong>la</strong>bras no gratuitas quehay en <strong>la</strong>s páginas <strong>de</strong> S que pertenecen a E i )y (todas <strong>la</strong>s E i presentes en t son diferentes)y (si no hay ningún E i que sea igual a “NoI<strong>de</strong>ntificados”,m es el número <strong>de</strong> empresas diferentes <strong>de</strong> S) }y (si existe una E i igual a “NoI<strong>de</strong>ntificados”,m – 1 es el número <strong>de</strong> empresas i<strong>de</strong>ntificadas diferentes <strong>de</strong> S) }P<strong>la</strong>nteamiento <strong>de</strong>l algoritmo principalLa solución consistirá en hacer que por cada página que obtenemos <strong>de</strong> <strong>la</strong> secuencia, i<strong>de</strong>ntifiquemosa <strong>la</strong> empresa cliente, calculemos el importe <strong>de</strong> su factura y lo acumulemos en unaestructura <strong>de</strong> datos que guarda a <strong>la</strong>s empresas clientes i<strong>de</strong>ntificadas con los importes facturadoshasta el momento. Se trata, pues, <strong>de</strong> aplicar el esquema <strong>de</strong> recorrido sobre <strong>la</strong> secuencia<strong>de</strong> páginas. El tratamiento para cada página consistirá en actualizar una estructura <strong>de</strong> datosque mantiene <strong>la</strong> facturación <strong>de</strong> todas <strong>la</strong>s empresas clientes que han ido apareciendo o apareceránmás a<strong>de</strong><strong>la</strong>nte en S a medida que vayamos progresando. Denominaremos a este objetoFacturas, y ya veremos sus <strong>de</strong>talles en el nivel <strong>de</strong>l <strong>diseño</strong> correspondiente.I<strong>de</strong>ntificamos el esquema que hayque aplicar, y hacemosabstracciones nuevas.Enten<strong>de</strong>mos que <strong>la</strong> última página consistirá sólo en <strong>la</strong> pa<strong>la</strong>bra gratuita ‘FinPaginas’ y, portanto, no será necesario tratar<strong>la</strong>.Aplicación directa <strong>de</strong>l algoritmoCon todo esto, el algoritmo principal resulta <strong>de</strong> <strong>la</strong> forma siguiente:Particu<strong>la</strong>rizamos <strong>la</strong> solución<strong>de</strong>l esquema <strong>de</strong> recorridopara este problema.algoritmo facturaPaginas;varfacturas: tFacturas;pagina: tPagina;fvarinicializarFacturas(Facturas);obtenerPagina(Pagina);mientras no ultimaPagina(Pagina) hacerfacturaPagina(Pagina, Facturas);obtenerPagina(Pagina)fmientrasescribirFacturas(Facturas);falgoritmoEspecificación <strong>de</strong> <strong>la</strong>s accionesaccion obtenerPagina(sal p: tPagina){ Pre: <strong>la</strong> parte <strong>de</strong>recha <strong>de</strong> S contiene una subsecuencia que es una página, como mínimo, o<strong>la</strong> página especial “FinPaginas”. Denominamos página E a esta subsecuencia. }{ Post: P representa <strong>la</strong> página E }funcion ultimaPagina (p: tPagina): booleano{ Pre: p = P }{ Post: ultimaPagina (p) es cierto cuando P representa <strong>la</strong> última página }accion inicializarFacturas(sal F: tFacturas){ Pre: }{ Post: hay 0 empresas propietarias en F }accion facturaPagina (sal p: tPagina; entsal f: tFacturas){ Pre: p = P y f = F y F contiene el importe total por propietarios <strong>de</strong> páginas procesadas anteriormentepor facturaPagina }{ Post: en f se ha acumu<strong>la</strong>do el importe <strong>de</strong> P correspondiente al propietario <strong>de</strong> P. Si P no tienepropietario, el importe se ha acumu<strong>la</strong>do en el propietario especial “NoI<strong>de</strong>ntificados” }


© FUOC • P05/75062/00112 51 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteaccion escribirFacturas(sal f: tFacturas){ Pre: f = F }{ Post: crea una secuencia <strong>de</strong> salida con <strong>la</strong> estructura , don<strong>de</strong> n i es unasubsecuencia <strong>de</strong> caracteres que representa a un propietario <strong>de</strong> páginas F y acaba en b<strong>la</strong>nco, ei i es una subsecuencia <strong>de</strong> caracteres dígitos acabada en b<strong>la</strong>nco que representa el importe totalque hay en F para el propietario n i }2)Segundo nivel: Páginas y FacturasEn este nivel tenemos dos abstracciones: pagina y facturas.a) Pasemos primero a trabajar <strong>la</strong> abstracción página:– Abstracciones utilizadas: pa<strong>la</strong>bra.– I<strong>de</strong>ntificación secuencia: página vista como una secuencia <strong>de</strong> pa<strong>la</strong>bras. La obtención <strong>de</strong>los elementos primero y siguiente se hará por medio <strong>de</strong> <strong>la</strong>s acciones leerPrimeraPa<strong>la</strong>bra yleerPa<strong>la</strong>bra, y el reconocimiento <strong>de</strong> <strong>la</strong> pa<strong>la</strong>bra que marca el final será <strong>la</strong> pa<strong>la</strong>bra “FinTexto-HTML”. En el caso especial <strong>de</strong> estar en <strong>la</strong> última página, ésta contendrá sólo “FinPáginas”.Definición <strong>de</strong> los tiposLo único que interesa <strong>de</strong> una página es conocer a su propietario y el importe <strong>de</strong> <strong>la</strong> factura.En el caso <strong>de</strong> <strong>la</strong> última página, lo único que interesa es saber que se trata <strong>de</strong> <strong>la</strong> última. Definiríamos,pues, el tipo tPagina <strong>de</strong> <strong>la</strong> forma siguiente:tipotPagina = tup<strong>la</strong>propietario: tPa<strong>la</strong>bra;importe: real;final: booleano;ftup<strong>la</strong>ftipoP<strong>la</strong>nteamientos y solucionesI<strong>de</strong>ntificación <strong>de</strong>l esquema: recorrido con i<strong>de</strong>ntificación previa <strong>de</strong> si se trata <strong>de</strong> <strong>la</strong> última página.accion obtenerPagina (sal p: tPagina)varpa<strong>la</strong>bra, pa<strong>la</strong>braNoI<strong>de</strong>ntificados, pa<strong>la</strong>braFinPaginas, pa<strong>la</strong>braFinTextoHTML, pa<strong>la</strong>bra-Propiedad: tPa<strong>la</strong>bra;fvarinicializaPa<strong>la</strong>braNoI<strong>de</strong>ntificados(pa<strong>la</strong>braNoI<strong>de</strong>ntificados);inicializaPa<strong>la</strong>braFinPaginas(pa<strong>la</strong>braFinPaginas);inicializaPa<strong>la</strong>braFinTextoHTML(pa<strong>la</strong>braFinTextoHTML);inicializaPa<strong>la</strong>braPropiedad(pa<strong>la</strong>braPropiedad);p.Importe := 0.0;p. Propietario := pa<strong>la</strong>braNoI<strong>de</strong>ntificadas; { Lo inicializamos en “NoI<strong>de</strong>ntificados” por siacaso no tiene propietario }leerPrimeraPa<strong>la</strong>bra(pa<strong>la</strong>bra);si pa<strong>la</strong>brasIguales(pa<strong>la</strong>bra, pa<strong>la</strong>braFinPaginas) entoncesp.final := ciertosinop.final := falsomientras no pa<strong>la</strong>brasIguales(pa<strong>la</strong>bra, pa<strong>la</strong>braFinTextoHTML) hacersi pa<strong>la</strong>brasIguales(pa<strong>la</strong>bra,pa<strong>la</strong>braPropiedad) entoncesleerPa<strong>la</strong>bra(pa<strong>la</strong>bra);p.Propietario := pa<strong>la</strong>brasinocontabilizaPa<strong>la</strong>bra(pa<strong>la</strong>bra, p.Importe);leerPa<strong>la</strong>bra(pa<strong>la</strong>bra)fsifmientrasfsifaccion { obtenerPagina }


© FUOC • P05/75062/00112 52 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteAunque en el enunciado se ha <strong>de</strong>jado c<strong>la</strong>ro que <strong>la</strong> secuencia <strong>de</strong> entrada está bien formada,podéis observar que en <strong>la</strong> solución dada, en el caso peor en que <strong>de</strong>spués <strong>de</strong> “propietario” nohubiese el nombre <strong>de</strong>l propietario y se llegase al final <strong>de</strong> <strong>la</strong> secuencia, el propietario sería“FinTextoHTML”.funcion ultimaPagina(P: tPagina): booleanoretorna p.finalffuncion { ultimaPagina }b) Consi<strong>de</strong>remos ahora <strong>la</strong> facturación <strong>de</strong> empresas. Aquí el objetivo es que el objeto Facturascontenga el nombre <strong>de</strong> <strong>la</strong>s empresas clientes presentes en <strong>la</strong> secuencia S, y para cada empresacliente, el importe acumu<strong>la</strong>do <strong>de</strong> <strong>la</strong>s facturaciones <strong>de</strong> todas <strong>la</strong>s páginas <strong>de</strong> S que pertenecena <strong>la</strong> empresa cliente en cuestión.Definición <strong>de</strong>l tipoHay que mantener una tab<strong>la</strong> don<strong>de</strong> conste el nombre <strong>de</strong> cada empresa cliente y el valor <strong>de</strong>limporte <strong>de</strong> <strong>la</strong> factura. El enunciado nos asegura que no habrá más <strong>de</strong> 50 empresas distintas.Debemos tener en cuenta que pue<strong>de</strong> haber páginas sin i<strong>de</strong>ntificación <strong>de</strong> propietario queserán para <strong>la</strong> empresa fantasma “NoI<strong>de</strong>ntificados”. Así pues, tenemos 51 empresas diferentes.Dado el propietario <strong>de</strong> una página, tendremos que buscar en <strong>la</strong> tab<strong>la</strong> si ya está o si se le <strong>de</strong>beañadir. La búsqueda que utilizaremos para saber si una empresa cliente ya está necesitará unaposición más <strong>de</strong> <strong>la</strong> tab<strong>la</strong>, como veremos más a<strong>de</strong><strong>la</strong>nte. De este modo, <strong>la</strong> <strong>de</strong>c<strong>la</strong>ración <strong>de</strong> tiposerá <strong>la</strong> siguiente:constmaxEmpresas: entero = 51;fconsttipotFactura = tup<strong>la</strong>nombreCliente; tPa<strong>la</strong>bra;importe: real;ftup<strong>la</strong>tFacturas =tup<strong>la</strong>nEmpresas: entero;f: tab<strong>la</strong>[ maxEmpresas + 1] <strong>de</strong> tFactura;ftup<strong>la</strong>ftipoP<strong>la</strong>nteamiento y solucionesI<strong>de</strong>ntificación <strong>de</strong>l esquema: búsqueda.Notad que...... hemos utilizado un esquema<strong>de</strong> búsqueda por centine<strong>la</strong>. Poreste motivo, hemos necesitadouna posición <strong>de</strong> más. El centine<strong>la</strong>es siempre <strong>la</strong> empresaque buscamos en <strong>la</strong> tab<strong>la</strong>.accion facturaPagina(sal p: tPagina, entsal f: tFacturas)var i: entero;fvar{ Buscamos <strong>la</strong> empresa por centine<strong>la</strong> }f.f[F.nEmpresas + 1].nombreCliente := p.propietario;i := 1;mientras no pa<strong>la</strong>brasIguales(f.f[i].nombreCliente, p.propietario) haceri := i + 1fmientrassi i = f.nEmpresas + 1 entonces{ Damos <strong>de</strong> alta a <strong>la</strong> empresa e inicializamos el importe }f.nEmpresas := f.nEmpresas + 1;f.f[i].importe := p.importesino { Añadimos el nuevo importe }f.f[i].importe := f.f[i].importe + p.importe;fsifaccion { facturaPagina }


© FUOC • P05/75062/00112 53 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteAplicación directaaccion inicializarFacturas(sal f:tFacturas)f.nEmpresas := 0faccionI<strong>de</strong>ntificación <strong>de</strong>l esquema: recorrido.accion escribirFacturas(ent f: tFacturas)var i: entero;fvari := 1;mientras i ≤ f.nEmpresas hacerescribePa<strong>la</strong>bra(f.f[i].nombreCliente);escribirReal(f.f[i].importe);i := i + 1;fmientrasfaccion { escribirFacturas }Acciones pendientes <strong>de</strong> <strong>de</strong>sarrol<strong>la</strong>raccion inicializaPa<strong>la</strong>braFinPaginas(sal m: tPa<strong>la</strong>bra){ Pre: }{ Post: m es <strong>la</strong> pa<strong>la</strong>bra “FinPaginas” }accion inicializaPa<strong>la</strong>braFinTexto(sal m: tPa<strong>la</strong>bra){ Pre: }{ Post: m es <strong>la</strong> pa<strong>la</strong>bra “FinTexto HTML” }accion inicializaPa<strong>la</strong>braPropiedad( sal m: tPa<strong>la</strong>bra){ Pre: }{ Post: m es <strong>la</strong> pa<strong>la</strong>bra “propiedad”}accion inicializaPa<strong>la</strong>braNoI<strong>de</strong>ntificados(sal m:tPa<strong>la</strong>bra){ Pre: }{ Post: m es <strong>la</strong> pa<strong>la</strong>bra “NoI<strong>de</strong>ntificados” }accion leerPrimeraPa<strong>la</strong>bra( sal m: tPa<strong>la</strong>bra){ Pre: en <strong>la</strong> entrada hay <strong>la</strong> secuencia <strong>de</strong> pa<strong>la</strong>bras s <strong>de</strong> <strong>la</strong> frase S. La parte izquierda <strong>de</strong> s estávacía. La parte <strong>de</strong>recha, DF, no está vacía }{ Post: m representa <strong>la</strong> primera pa<strong>la</strong>bra <strong>de</strong> DF. La pa<strong>la</strong>bra obtenida estará en <strong>la</strong> parte izquierda<strong>de</strong> <strong>la</strong> secuencia s }accion obtenerPa<strong>la</strong>bra (entsal m: tPa<strong>la</strong>bra){ Pre: En <strong>la</strong> entrada tenemos <strong>la</strong> secuencia <strong>de</strong> pa<strong>la</strong>bras s <strong>de</strong> <strong>la</strong> frase S. La parte <strong>de</strong>recha, DF, noestá vacía. La última pa<strong>la</strong>bra leída está en m }{ Post: m representa <strong>la</strong> primera pa<strong>la</strong>bra <strong>de</strong> DF. La pa<strong>la</strong>bra obtenida estará en <strong>la</strong> parte izquierda<strong>de</strong> <strong>la</strong> secuencia s }accion contabilizaPa<strong>la</strong>bra( ent pa<strong>la</strong>bra:tPa<strong>la</strong>bra; entsal importe: real){ Pre: pa<strong>la</strong>bra = M e importe = I y l es el número <strong>de</strong> caracteres <strong>de</strong> M }{ Post: pa<strong>la</strong>bra = M e importe = I + 50 si M es “ 1 y M ≠ ‘


© FUOC • P05/75062/00112 54 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte3)Tercer nivel: pa<strong>la</strong>bra– Abstracciones utilizadas: ninguna.– I<strong>de</strong>ntificación <strong>de</strong> secuencia: pa<strong>la</strong>bra vista como una secuencia <strong>de</strong> caracteres. La obtención<strong>de</strong> los elementos primero y siguiente se hará por medio <strong>de</strong> <strong>la</strong> función pre<strong>de</strong>finida leerCaracter()y el reconocimiento <strong>de</strong>l carácter que marca el final será el carácter espacio, o eligual, o el salto <strong>de</strong> línea.Definición <strong>de</strong> los tiposEn este nivel trabajamos con los tipos pre<strong>de</strong>finidos <strong>de</strong>l lenguaje y con el tipo tPa<strong>la</strong>bra que<strong>de</strong>finimos a continuación:Podéis ver <strong>la</strong> solución <strong>de</strong>l ejercicioanterior para los comentariossobre el tipo.constmaxCar: entero = 40;fconsttipotPa<strong>la</strong>bra = tup<strong>la</strong>long: entero;c: tab<strong>la</strong> [maxCar] <strong>de</strong> caracter;caracterLeido: caracter;ftup<strong>la</strong>ftipoP<strong>la</strong>nteamientos y solucionesaccion inicializaPa<strong>la</strong>braFinPaginas(sal m: tPa<strong>la</strong>bra)m.long := 10;m.c[1] := ‘F’; m.c[2] := ‘i’; m.c[3] := ‘n’;m.c[4] := ‘P’; m.c[5] := ‘a’; m.c[6] := ‘g’; m.c[7] := ‘i’m.c[8] := ‘n’; m.c[9] := ‘e’; m.c[10] := ‘s’faccionaccion inicializaPa<strong>la</strong>braFinTextoHTML(sal m: tPa<strong>la</strong>bra)m.long := 12;m.c[1] := ‘F’; m.c[2] := ‘i’; m.c[3] := ‘n’;m.c[4] := ‘T’; m.c[5] := ‘e’; m.c[6] := ‘x’; m.c[7] := ‘t’; m-c[8] := ‘0’;m.c[9] := ‘H’; m.c[10] := ‘T’; m.c[11] := ‘M’; m.c[12] := ‘L’faccionaccion inicializaPa<strong>la</strong>braPropiedad(sal m: tPa<strong>la</strong>bra)m.long := 9;m.c[1] := ‘p’; m.c[2] := ‘r’; m.c[3] := ‘o’;m.c[4] := ‘p’; m.c[5] := ‘i’; m.c[6] := ‘e’;m.c[7] := ‘d’; m.c[8] := ‘a’; m.c[9] := ‘d’accion inicializaPa<strong>la</strong>braNoI<strong>de</strong>ntificados(sal m: tPa<strong>la</strong>bra)m.long := 15;m.c[1] := ‘N’; m.c[2] := ‘o’; m.c[3] := ‘I’m.c[4] := ‘d’; m.c[5] := ‘e’; m.c[6] := ‘n’m.c[7] := ‘t’; m.c[8] := ‘i’; m.c[9] := ‘f’;m.c[10] := ‘i’; m.c[11] := ‘c’; m.c[12] := ‘a’;m.c[13] := ‘d’; m.c[14] := ‘o’; m.c[15] := ‘S’faccionI<strong>de</strong>ntificación <strong>de</strong>l esquema: recorrido.accion leerPrimeraPa<strong>la</strong>bra( sal m: tPa<strong>la</strong>bra)var c: caracter;fvarm.long := 0;c := leerCaracter();


© FUOC • P05/75062/00112 55 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>ntemientras separador(c) y c ≠ ‘.’ hacer { saltamos los primeros separadores }c := leerCaracter()fmientrasm.caracterLeido := c;obtenerPa<strong>la</strong>bra(m)faccionI<strong>de</strong>ntificación <strong>de</strong>l esquema: recorrido.accion leerPa<strong>la</strong>bra(sal m: tPa<strong>la</strong>bra)vari: entero; cNoSeparador: booleano;c: caracter;fvarm.long := 0;c := m.caracterLeido;mientras no (separador(c) y (m.long < maxCar)) hacer { obtenemos <strong>la</strong> pa<strong>la</strong>bra }m.long := m.long + 1;m.c[m.long] := c;c := leerCaracter()fmientrasmientras no separador(c) hacer { saltamos los caracteres que sobran }c := leerCaracter()fmientrasmientras separador(c) hacer { saltamos los separadores }c := leerCaracter()fmientrasm.caracterLeido := cfaccionObservad que...... <strong>la</strong> acción leerPa<strong>la</strong>bra tiene encuenta <strong>la</strong> posibilidad <strong>de</strong> que <strong>la</strong>pa<strong>la</strong>bra leída sea más <strong>la</strong>rga quemaxCar. La pa<strong>la</strong>bra se lee, perolos caracteres <strong>de</strong> <strong>la</strong> pa<strong>la</strong>bra queestán más allá <strong>de</strong> maxCar en <strong>la</strong>tab<strong>la</strong> no se guardan. Dado quesólo nos interesa comprobar <strong>la</strong>spa<strong>la</strong>bras que tienen maxCar caracteres,como mucho, el truncamiento<strong>de</strong> <strong>la</strong> pa<strong>la</strong>bra no tieneningún efecto en el resto <strong>de</strong>l algoritmoy permite aceptarpa<strong>la</strong>bras tan <strong>la</strong>rgas como sequiera.Aplicación directa <strong>de</strong> <strong>la</strong> alternativaaccion contabilizaPa<strong>la</strong>bra( ent pa<strong>la</strong>bra: tPa<strong>la</strong>bra; entsal importe: real)var pa<strong>la</strong>braImagen: tPa<strong>la</strong>bra;fvarinicializaPa<strong>la</strong>braImagen(pa<strong>la</strong>braImagen);si pa<strong>la</strong>brasIguales(pa<strong>la</strong>bra, pa<strong>la</strong>braImagen) entoncesimporte:= importe + 50sinosi no(pa<strong>la</strong>braEntreMenoresMayores(pa<strong>la</strong>bra) y longitudPa<strong>la</strong>bra(pa<strong>la</strong>bra) > 1) entoncesimporte := importe + 5;fsifsifaccionI<strong>de</strong>ntificación <strong>de</strong>l esquema: búsqueda.funcion pa<strong>la</strong>brasIguales(m1: tPa<strong>la</strong>bra, m2: tPa<strong>la</strong>bra): booleanovari: entero;iguales: booleano;fvarsi m1.long = m2.long entoncessi m1.l > 0 entoncesi := 1;mientras (m1.c[i] = m2.c[i]) y (i < m1.l) hacer i := i + 1fmientrasiguales := m1.c[i] = m2.c[i]sino iguales := ciertofsisino iguales := falsofsiretorna igualesffuncion { pa<strong>la</strong>brasIguales }


© FUOC • P05/75062/00112 56 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteI<strong>de</strong>ntificación esquema: recorrido.accion escribePa<strong>la</strong>bra(ent m: tPa<strong>la</strong>bra)var i : entero;fvari := 1;mientras i ≤ m.long hacerescribirCaracter(m.c[i]);i := i + 1fmientrasescribirCaracter(‘ ’)faccion { escribePa<strong>la</strong>bra }Acciones pendientes <strong>de</strong> <strong>de</strong>sarrol<strong>la</strong>rEl <strong>diseño</strong> <strong>de</strong> este nivel ha dado pie a unas funciones auxiliares que <strong>de</strong>tal<strong>la</strong>mos a continuación.accion inicializaPa<strong>la</strong>braImagen(sal m: tPa<strong>la</strong>bra){ Pre: }{ Post: m es <strong>la</strong> pa<strong>la</strong>bra }funcion longitudPa<strong>la</strong>bra(m: tPa<strong>la</strong>bra): entero{ Pre: m = M}{ Post: longitudPa<strong>la</strong>bra(m) da el número <strong>de</strong> caracteres que tiene M }funcion separador(c: caracter): booleano{ Pre: c = C }{ Post: separador(c) es cierto si C es espacio o C es un igual o C es algún carácter <strong>de</strong> retorno o<strong>de</strong> salto <strong>de</strong> línea }accion inicializaPa<strong>la</strong>braImagen(sal m: tPa<strong>la</strong>bra)m.long := 4;m.c[1] := ‘


© FUOC • P05/75062/00112 57 <strong>Introducción</strong> a <strong>la</strong> <strong>metodología</strong> <strong>de</strong> <strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nte<strong>diseño</strong> <strong>de</strong>scen<strong>de</strong>nteMetodología que <strong>de</strong>scompone un problema complejo en subproblemas menos complejosque el original. La <strong>de</strong>scomposición es guiada por abstracciones naturales y convenientes alproblema, y da como resultado un conjunto <strong>de</strong> subproblemas in<strong>de</strong>pendientes y más concretos.Se proce<strong>de</strong> <strong>de</strong> idéntica forma para cada uno <strong>de</strong> los subproblemas, hasta llegar a subproblemaslo suficientemente concretos y elementales.nivel <strong>de</strong> abstracciónNivel en el que se concreta una abstracción utilizada para <strong>de</strong>scomponer un problema o subproblema.Nivel <strong>de</strong> abstracción y nivel <strong>de</strong> <strong>de</strong>scomposición son dos conceptos distintos y quepue<strong>de</strong>n coincidir en <strong>la</strong> mayoría <strong>de</strong> los casos, pero no necesariamente.nivel <strong>de</strong> <strong>de</strong>scomposiciónNivel propio <strong>de</strong> una etapa <strong>de</strong> <strong>la</strong> <strong>de</strong>scomposición <strong>de</strong> subproblemas en subproblemas más concretos.El primer nivel correspon<strong>de</strong> al <strong>de</strong>sarrollo <strong>de</strong>l problema original. La <strong>de</strong>scomposición<strong>de</strong> los subproblemas generados en el primer nivel se <strong>de</strong>sarrol<strong>la</strong>rá en un segundo nivel, y asísucesivamente.BibliografíaCastro, J.; Cucker, F.; Messeguer; Rubio, A.; So<strong>la</strong>no, L.; Vallés, B. (1992). Curso <strong>de</strong>Programación. Madrid: McGraw Hill.Sebastià Vi<strong>la</strong>, M. (1995). Programació Fonamental. Problemes. Barcelona: Edicions UPC.Wirth, N. (1982). <strong>Introducción</strong> a <strong>la</strong> Programación Sistemática. Buenos Aires: El Ateneo.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!