12.07.2015 Views

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

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<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!