¿Está desnudo el emperador?
En los comentarios del post Gestores de proyectos, Juanjo plantea un asunto interesante:
Mi opinión sobre estos temas, en general, es bastante singular. Estoy convencido de que "el emperador está desnudo", en la mayoría de los temas mencionados. Ocurre, sin embargo, que durante todos estos años, he gritado eso mismo unas cuantas veces, refiriéndome a distintos "emperadores", y ha resultado que, con las inevitables excepciones, tenía razón. Esto puede inducir a pensar que me he aficionado al deporte de detectar emperadores en bolas. Estas actitudes son adictivas, hay que reconocerlo. Por estos motivos, tanto por vosotros como por mí, quiero explicar mis razones de mi escepticismo. Prometo enlazar el tema con cualquier refutación que tengáis a bien escribir. Porque en definitiva, si estoy equivocado, soy el primer interesado en saberlo.
Voy a centrarme en UML. ¿Qué es UML? Se supone que es un convenio gráfico para representar determinados aspectos de sistemas. Hasta ahí, todos de acuerdo. Ahora viene la parte que la gente deduce por su cuenta. En realidad, según la persona, se pueden dar por asumidas ciertas "verdades", no necesariamente equivalentes o compatibles entre sí. Por ejemplo:
- UML debería ser utilizado sistemáticamente en la fase de análisis.
- Los gráficos, en general, y UML en particular, tienen un "nosequé" que lo hacen más potente que cualquier formalismo basado en texto.
Ocurre, además, que UML, como formalismo, cojea. Preguntas retóricas para una calurosa tarde de mayo:
- ¿Cuántos tipos de gráficos ofrece UML?
- ¿Cuántos de estos tipos suele usted ver en libros de Informática (excepto en los que se dedican a explicar el propio UML)?
- ¿Cuántos de ellos son verdaderamente útiles?
¿Verdaderamente útiles? Los diagramas de clases. Sin embargo, la gente suele confundirse con las cardinalidades de las relaciones, o se centra exclusivamente en la herencia. De todos modos, un diagrama de clases es útil, aunque al final... cuando se trate de bases de datos, la gente termine prefiriendo los clásicos diagramas de "patas de gallo".
¿Qué otro tipo de diagrama ofrece UML que realmente merezca la pena usar? Un servidor suele incluir algunos diagramas de secuencia en libros y cursos. ¿Sabe por qué lo hago? ¡Porque son tan raros y complicados que estoy seguro de que, cuando el lector se rompe la cabeza para descifrarlos, está repensando el contenido que ya he contado en el texto! Decían los antiguos romanos que, quien escribe, lee dos veces. Digo yo que, quien escudriña un diagrama de secuencias, piensa en el problema subyacente unas cuarenta veces más.
Seamos sinceros: ¿qué entiende usted mejor? ¿Cuatro líneas de pseudo código, o un intrincado diagrama de secuencias?
Otros tipos de gráficos, de tan triviales, terminan por parecer infantiles. Estoy pensando en los "use cases": un muñeco hecho con palotes y óvalos con textos encerrados. Los diagramas de estados tienen un poco más de sentido, pero esta vez, las reglas y convenios de UML son tan enrevesadas, y los propios gráficos tan parecidos a otros gráficos de UML, que al final la gente termina por dibujarlos como le da la gana, y guiándose por la dirección desde donde sopla el viento.
Hay otro problema importantísimo: UML fue diseñado por gente que usaba C++ como lenguaje de programación. C++ es muy potente, muy eficiente... pero su expresividad y claridad, sinceramente, dejan mucho que desear. Luego esa misma gente se aficionó a Java. Cuando alguien que trabaja en C# (¡o incluso en Delphi!) se enzarza con un diagrama UML en la fase de diseño, descubre importantes carencias. ¿Cómo se representa un evento en un diagrama de secuencias, por ejemplo? Claro, se puede alegar que UML no debería trabajar en ese nivel de detalles. Bravo. Estupendo. Pero entonces, ¿qué utilidad me puede proporcionar en la fase de diseño, una vez que el jefe lego en programación se ha encerrado en su despacho a jugar al Solitario?
Seguramente a esta explicación le faltan argumentos. Lo bueno de una bitácora es que no te obliga a vaciarte los bolsillos en un único mensaje. Me he centrado en UML para simplificar... pero algo parecido, y en ocasiones incluso peor, ocurre en otras áreas del mundillo de la "ingeniería de software".
Por ejemplo, la mayoría del contenido de la nueva moda, eso que llaman extreme programming, método Agile, etc, etc, es, o reglas triviales que nada aportan como novedad... o simplemente disparates. A mí se me cayó el alma al suelo hace un par de años cuando vi que Borland comenzaba a publicar en la página de su community sesudos artículos sobre la conveniencia... ¡de usar colores en los diagramas de software! Otra moda: la idea de la test-driven programming. Esta vez, hay un núcleo importante de verdad detrás del método. Pero para que la gente compre libros y software, y para que sus propagadores ganen dinero, el núcleo verdadero de la metodología test driven (que tiene mucha relación con la programación por contrato, la verificabilidad, etc, etc) se ha recubierto con capas y capas de fundamentalismo y tontería. Hay aplicaciones que admiten la metodología test driven, es cierto. También es cierto que en otros tipos de aplicaciones, es un disparate plantear que el desarrollo vaya guiado por pruebas sobre las especificaciones.
¿Un ejemplo? Intente escribir un ray tracer o un compilador con esta metodología. No avanzaría, se lo aseguro. ¿Por qué? Porque en el fondo, el método test-driven exige pequeños cambios incrementales en la funcionalidad y estructura del código. Sin embargo, los dos modelos de aplicaciones que he mencionado exigen el correcto funcionamiento de subsistemas realmente grandes antes de que usted pueda conectar algo y que se puedan hacer pruebas. Incluso después de ese momento, hay ciertos cambios que exigen que el programador tenga la mayor parte del modelo teórico en su cabeza para que la cosa funcione. ¡Esto es trivial, por Júpiter! Pero quien te cuenta las virtudes del test driving nunca te lo cuenta.
... y, sin embargo, de las cosas que realmente tiene que conocer el programador, pocas veces se habla. ¿Sabía usted que es más difícil comprender qué hace una aplicación orientada a objetos a partir de su código fuente, que comprender el funcionamiento de una aplicación basada en la vieja programación estructurada? ¿No me cree? Mírelo de este modo: la metodología object oriented consiste en realizar la división modular utilizando la clasificación de entidades como principal criterio, mientras que antes se primaban los criterios funcionales. Cuando usted abre el código de XSight RT, por ejemplo, se encuentra con una clase Sphere que "ofrece" los métodos y propiedades tales y cuales. Vale, ¿y quién usa estos métodos y propiedades? ¿Cómo empieza a rodar la bola que debe luego provocar la avalancha? ¡Ah, amigo mío, para conectar los puntos estará obligado a comprobar detenidamente el funcionamiento de la jerarquía de clases basada en BaseSampler, y seguir las vías secundarias que conectan los samplers con el código asociado a escenas y cámaras. Por el contrario, si XSight RT fuese una aplicación con descomposición modular funcional, habría un método Main muy claro y visible, y usted podría entender qué hace la aplicación en un plis plas. Es un trozo de conocimiento clásico: mientras que la programación estructura se centraba en el cómo, la POO enfoca el quién. Y no se puede estar en misa y repicando a la vez. ¿Se lo ha escuchado decir a alguien? Sin embargo, es de sentido común...
Sé que éste es un tema polémico. Llevo quince minutos tecleado como un poseso, y todavía me quedan explicaciones y ejemplos. Es interesante analizar por qué existe un mercado para este tipo de cosas: para las "metodologías de salvación del alma del programador" y para los remedios homeopáticos (buena comparación, por cierto). Voy a dejarlo aquí por hoy. Creo que es un debate interesante, y os animo a que os suméis y deis vuestra opinión.
29 Comments:
Estimado Dr Marteens. Su razonamiento de como es mas "entendible" un trozo de codigo a la vieja usanza "estructurada" que orientado a objetos, es algo que de vez en cuan habia experimentado. Lo que sucede es que incoscientemente mi cabeza trataba de no pensar en ello, pues tenia la certeza de que si lo comentaba con alguien seguro que se producia un linchamiento popular contra mi persona. ¿Como osa usted decir semejante barbarida..?, hubiera dicha el juez en mi juicio.
Saludos
El emperador está en pelota picada y el niño está de vacaciones.
La gran mayoría de lo que se publica sobre informática es basura, sobre todo lo relacionado con bases de datos. Las buenas ideas son mucho más difíciles de producir que las malas y hay muchas páginas que llenar y hay que vender productos como sea. Cuando no hay nada mejor que ofrecer se ofrece algo igual o peor a lo que ya había diciendo que va a hacer maravillas.
El que no conoce la historia está condenado a repetirla, y la gran mayoría de los programadores no la conocen. La mayoría de las supuestas nuevas técnicas no son más que viejas técnicas que fracasaron en el pasado y que vuelven con otros nombres para volver a fracasar. Por ejemplo el caso de UML se estudia aquí:
http://citeseer.ist.psu.edu/386839.html
No creo que el tema de UML genere mucha polémica. La mayoría de los que lo hemos probado nos hemos dado cuenta rápidamente de que es solo una chorradita. En seguida te cansas de perder el tiempo con diagramas que nadie mira y vuelves a lo de siempre. Lo único que cambia es que cuando de verdad necesitas hacer un dibujito para explicar algo usas si puedes las convenciones de UML por que las conoce todo el mundo y tampoco cuesta nada.
Hay casos aun más claros que UML, por ejemplo XML y el análisis y diseño orientados al objeto (que no hay que confundir con la programación orientada al objeto).
Hay mucho caradura que no tiene ni idea que consigue hacerse pasar por un gurú, y esto es un círculo vicioso que crea nuevas generaciones de "gurús" de pacotilla.
La misma programación a orientada al objeto es un enorme caos donde habría mucho que limpiar.
Como muchos otros, creo que el campo del software está en decadencia. La programación atrae cada vez menos a las personas inteligentes, y el nivel académico también está bajando. Por ejemplo el avance de los lenguajes de programación en los últimos 15 años ha sido mínimo, y no es por que no quede nada que mejorar ni mucho menos.
Yo recomiendo con todas mis fuerzas leer al viejo Dijkstra.
http://www.cs.utexas.edu/users/EWD/
Es sorprendente la cantidad de cosas escritas hace 20 o 30 años que siguen completamente vigentes.
Con respecto a lo de que el código OO es más dificil que leer que el código estructurado clásico, eso lo tengo bien claro desde que intenté leer por primera vez los viejos ejemplos OO del Turbo Pascal 5.5
El único dibujito del que no puedo prescindir es el diagrama de la BD. Todo lo demás es una forma de justificar el sueldo de alguien que no sabe lo que es un compilador, no ha escrito un programa más complicado que "Hello World" y cada vez que habla, se le llena la boca de "metodología".
El único libro interesante y del que he podido sacar alguna idea es Ship it!
A Practical Guide to Successful Software Projects, que lo bueno que tiene es que no propone ninguna metodología en particular, sólo una serie de buenas prácticas bastante sencillas de seguir.
Pero para diagramas de bases de datos mejor usar el ER de toda la vida.
Hace poco tube que hacer una funcion para buscar un fichero por todo el disco duro y como soy un aprendiz (y encima casero) no acababa de conseguir lo que queria, mi mente sabia que tendría que hacer recursividad pero no me salia el código. Mi cerebro tenía todo el esquema montado (sin UML ni gaitas) pero no había forma. Recordé unos viejas fotocopias de apuntes de FP sobre busquedas , ordenacion de arrays y cosas con ficheros de Pascal. Busqué y encontre un código de busqueda de 1984 (creo) en TurboPascal que con dos retoques para adaptarlo a codigo Delphi me ha funcionado a la perfección. El tipo ese que hizo la función si que sabia y no algunos programadores de ahora.
Yo siempre he dicho que en la programación estamos reinventando la rueda continuamente sin motivo.
Y leer estructurado es muuuucho más sencillo que OOP hombrepordios.. :)
Ups, perdón por no especificarlo, pero me estaba refiriendo, como tu dices, al ER de siempre.
Leer este comentario me ha producido una sacudida. Es algo que en el fondo sabía pero no quería reconocer.
Yo fuí de los primeros en quedar fascinado por la programación orientada a objetos, al menos en mi entorno. La he encontrado muy útil a lo largo de más de 10 años en ciertos casos. Últimamente andaba emperrado en entender eso de los patrones. Pero siempre me quedaba la duda de si el uso limitado que le suelo hacer de la OO no era más que una programación tradicional en las que sustituía módulos por clases.
De todas formas, no estoy deacuerdo completamente con el planteamiento de que la programación estructurada es más legible que la OO. Creo que la programación OO llevada al extremo de academicismo puede no hay quien la entienda. Pero usando la OO sin llevarla a esos extremos si que clarifica el código. Utilizada para separar conceptualmente las funciones en torno a las clases (vale, no deja de ser los clásicos módulos de siempre), la herencia y los interfaces, ambos tomados con moderación, te dejan un código la mar de limpito y fácil de entender . En una aplicación siempre tendremos trozos de códigos "estructurado", que definirán el flujo de la aplicación y se encargarán de hacer las llamadas a los métodos de clases. Y parte de ese flujo será controlado por los eventos (¿Acaso se hacen muchas aplicaciones que no sean interactivas?)
Respecto al UML, poco he visto usarlo. Yo también estoy de acuerdo que lo único que se acaba usando como modelo gráfico son los diagramas ER. Un compañero me apunta que para lo que sirve el UML es para enseñarsele los diagramas al cliente y que entienda la aplicación. No sé si es lo más apropiado para el caso.
En fin, es mi modesta opinión.
Creo que el problema no es el UML o cualquier otra herramienta, sino el uso que se hace de ella. Como siempre que intento explicar algo de informática, lo voy a sacar de contexto.
Tenemos una herramienta para clavar clavos, llamada martillo, lleva mucho tiempo funcionando y funcionando bien. Hay grupos que les gusta mucho y lo utilizan para clavar clavos muy bien, incluso algunos son tan manitas que pueden desabollar el coche con el mismo martillo.
Como la ciencia avanza que es una barbaridad, unos tipos pensaron que podían clavar los clavos con aire comprimido, diseñan la pistola de aire, la prueban y se dan cuenta que clava clavos mucho mejor y más rápido que el martillo. Y aquí es cuando entra el fallo, le comentan al comercial que la pistola puede substituir al martillo. El comercial lo ve apasionante y prepara ruedas de prensa, publica artículos, otros "expertos" publican artículos basándose en esa publicidad. "¡¡Se acabaron los martillos!! ¡¡Comenzó la epoca del aire comprimido!!"
Los montadores de marcos para cuadros están encantados, mucho más rápido y sin peligro para tus deditos. El carpintero a domicilio también está contento, pero se tuvo que comprar una furgoneta mucho más grande para poder llevar su compresor de aire. El taller de chapa y pintura todavía está buscando al consultor que tras cobrarles un pastizal les cambió sus martillos por pistolas de clavos...
¿A que cuando encuenteras un simil fuera de la informática se encuentran las soluciones antes? La culpa no es del UML o del OOD o de lo que sea, es su mala utilización. Vamos, digo yo....
A mi me parece una mala analogía. Un consultor informático es el que te quiere convencer de que tienes que ponerte una plancha de titanio en la frente y clavar los clavos con la cabeza en vez de con un martillo.
Hago la precisión, de todos modos, por si alguien se suma a última hora y no se lee todos los mensajes: no hay nada malo en la POO, ni hay que tirarla. Lo que ocurre es que hay excesos. Hay gente, por ejemplo, que si no sabes recitar en orden ascendente y descendente los nombres de los "patrones", no te da trabajo. Y está todo este mareo constante con las metodologías. Lo del Agile es sólo la gota que colma el vaso... pero ha sido una gota bastante gruesa.
Aquí ha ocurrido una cosa: la implantación de la POO, en su momento, fue difícil. No sólo porque mucha gente no lo veía claro al principio, porque eso tenía solución... sino precisamente por toda la gente que se subió al carro para vender que lo que ellos hacían era "orientado a objetos", aún sin serlo. Claro, hay mucha gente que se puso de uñas entonces, y desde entonces no ha bajado la guardia. Es lógico.
Lo malo de obsesionarse con la presunta ortodoxia de la POO es que se corre el riesgo de no ver las soluciones que van llegando a algunos problemas. O peor aún, no ver que existen problemas y por lo tanto, que jamás se ideen las correspondientes soluciones.
Problemas que veo, por ejemplo:
1- Esto no es sólo un problema de la POO: la composición modular puede ser muy ineficiente. De esto es de lo que me quejaba en un post anterior sobre XSight RT. Para resolver esto habría que mejorar bastante la labor de los compiladores: el código de un componente debe poder adaptarse al contexto en que se usa. Pero también requiere colaboración por parte del lenguaje.
Un ejemplo de esto: uno programa una pila (vale, ejemplo muy gastado, pero sirve). El método Pop se programa comprobando que la pila no está vacía. Si está vacía, el método genera una excepción. Luego, el método se usa en otro lugar en un bucle: mientras no esté vacía la pila, Pop. La comprobación del Pop es innecesaria, y el compilador debería encontrar una forma de ejecutar una versión de Pop sin ella. Esto tiene solución sencilla cuando existen aserciones al estilo Eiffel en el lenguaje, y es, por consiguiente, un ejemplo muy fácil. Pero hay muchas otras situaciones en que un compilador realmente inteligente podría mejorar mucho la calidad del código final... y de paso, detectar posibles fallos semánticos.
2- Segundo problema: no todo es "encapsulable". El tratamiento de errores suele dispersarse a lo largo de todo el código. El control de transacciones, idem. La verificación de la identidad de quien ejecuta el código: tres cuartos de lo mismo. Ciertos patrones de manejo de memoria también.
Estos problemas son los que presuntamente resuelve la programación por Aspectos.
3- Lo que mencionaba sobre legibilidad. Imaginad dos dimensiones: la primera, de tipo espacial, la segunda de tipo temporal. Me temo que esto va a ser un poco "metafórico" e impreciso, pero no encuentro una forma breve de explicarlo mejor. En POO, el código se agrupa según un criterio espacial. En un fichero tienes todo el código perteneciente a un mismo tipo de objeto (vulgo, clase). Cuesta seguir la línea de evolución temporal del programa, es decir, ver qué hace. En una descomposición funcional (estructurada clásica), en un mismo fichero se agrupan funciones relacionadas, aunque pertenezcan a distintas entidades conceptuales. Es fácil "tracear" el código. Es difícil predecir todos los puntos que debes tocar del código para añadir soporte para una nueva entidad. Es decir, tenemos criterios de agrupación del código fuente que son mutuamente excluyentes.
Aquí la solución podría ser sencilla: ¿y si es el software de desarrollo el que se encarga de presentar la vista que necesite el programador en cada momento? Es que todavía, a estas alturas del siglo XXI, seguimos tratando el código fuente como una secuencia lineal de caracteres. En determinado nivel (muy pedestre), se puede decir aproximadamente que la POO es simplemente una forma de organizar el código (es mucho más que eso, por supuesto, pero TAMBIEN es esto). ¿Y si inventamos una forma nueva, más flexible, de organizar el código? Ni siquiera se trata de cambiar la forma de almacenamiento, sino la forma en que el IDE te presentase las clases y sus métodos. Eso no lo hace ni el IDE de Microsoft ni el de Borland. No sé tampoco si al desarrollar la idea, ésta seguiría teniendo sentido.... Pero observad una cosa interesante: la forma en que se plantea la programación por Aspectos en la mayoría de los lenguajes experimentales tiene bastante que ver con esto. La mayoría de estos lenguajes trabaja sobre la idea de "inyección de código".
Claro, la limitación entraría en escena violentamente cuando intentases llevarte un listado impreso del programa. Pero estamos en el siglo XXI, ¿no? ¿Por qué imprimir? ¿No existen ya papel y tinta electrónicos? ¿No podría ocuparse el software del lector de realizar estas mismas transformaciones, respetando todos los grados de libertad del texto en su conjunto?
Tengo plena consciencia de que un planteamiento así de vago sólo es una gigantesca paja mental (dicho sea con perdón). Pero hay que entrenar la imaginación para que no se atrofie, ¿no?
Una nota aparte: luego prepararé un artículo con ideas para lo del grupo de usuarios, para tener un núcleo de propuesta que se pueda modelar luego según haga falta. Se me han ido ocurriendo algunas posibilidades, pero voy a necesitar ayuda para muchas cosas.
Lo que es triste es que a estas alturas del siglo XXI sigamos anclados a la programación procedimental (C# es un lenguaje tan procedimental como el que más).
Poca gente duda de que la POO haya sido un avance, pero no es ni muchísimo menos el final del camino, y además ha enturbiado muchos conceptos que en la programación estructurada estaban claros. En general la terminología OO es un desastre. El OOAD si que no sirve para casi nada, y mucho menos para cualquier cosa relacionada con bases de datos.
El problema con lo de hacer más inteligentes los compiladores es que la POO no da mucho margen para eso por lo primitivo y "ad hoc" que es su modelo computacional. Esto sería mucho más efectivo si nos moviesemos hacia la programación declarativa y lógica, en donde los compiladores se convierten en verdaderos programadores automáticos y la productividad sube de forma exponencial. El problema es el pánico que le tienen la mayoría de los programadores a cualquier cosa que suene a matemáticas. Sobre todo los americanos, que al final son los que crean los lenguajes y las herramientas. Dijkstra ha escrito muchas cosas interesantes sobre esto.
Respecto a lo del grupo de usuarios me parece bien. La mayoría de grupos de usuarios de .Net en España están bastante muertos. Lo malo es que nunca he sabido muy bien para que sirven este tipo grupos además de para quedar de vez en cuando para tomar unas cervezas.
A veces leo los foros de programación .Net de M$, y la mayoría de las preguntas son de gente que no se ha molestado en leer la ayuda y quieren que otros les hagan su trabajo.
Yo también he pensado alguna vez que suy un "bicho raro": no me gustan ni UML ni Merisse ni... y utilizo la notación matemática para las fases de analisis de un desarrollo.
Saludos,
ParadiseL
Leyendo algunos de los comentarios, y uniendo también mi propia experiencia, me pregunto: ¿No será que, los que decimos que no sacamos "todo el jugo" a la POO es porque seguimos programando más o menos igual que cuando empezamos? Decían por ahí arriba, y creo que con acierto, que para muchos de nosotros el "paso" de la programación estructurada (Pascal, Clipper) a la POO, casi se ha limitado a cambiarle el nombre a algunos conceptos (Módulo=Clase, Subrutina=Procedimiento), pero la utilización que hacemos de esos "nuevos" recursos es más o menos la misma.
En mi caso particular, que empecé en esto de la programación hace la friolera de 21 años con el BASIC del Spectrum y he visto lenguajes y metodologías de todos los colores, si me pongo a analizarlo fríamente encuentro que efectivamente las "primitivas" ideas y conceptos que aprendí a la tierna edad de 14 añitos son las mismas que hoy en día aplico a mis aplicaciones en Delphi y C#. Evolucionadas, eso sí, pero las mismas al fin y al cabo.
Y es que por mucho que nos quieran meter en la cabeza lo contrario, un programa no es otra cosa que "una serie de instrucciones ejecutadas de manera secuencial".
Así me lo aprendí yo.
Es que la POO casi se ha limitado a cambiar los nombres de la programación estructurada por otros mucho más imprecisos. Por ejemplo a las variables les llama objetos, a los valores les llama objetos y también ejemplares "instances" (por cierto, llamarle "instancia" a un ejemplar de un tipo es una burrada), a los operadores se les llama métodos, a la invocación de operadores se le llama pasar mensajes (menuda chorrada), cada uno le llama clase a lo que le da la gana, etc, etc.
Al final POO = programación estructurada + herencia + un primitivo mecanismo de ocultación de la información.
Y la herencia es poco más que un mecanismo para encapsular la creación de tablas de saltos.
Y esto se quiso vender como el no va más, cuando no es más que un pequeño y sucio avance dentro de la programación imperativa procedimental. Uno de los tipos de programación más primitivos.
Sharq, "una serie de instrucciones ejecutadas de manera secuencial" es lo que se conoce como un programa procedimental, pero hay más formas de programar.
Perdón, eso se llama programa procedimental. Hay lenguages procedimentales no imperativos como Logo
Alfredo: Todo se ejecuta secuencialmente, sea un programa "procedimental", o el mismísimo kernel del SO. Una aplicación "idle" tiene su turno dentro de un ciclo secuencial en el que el gestor de Mensajes de Windows (poniendo como ejemplo este SO) va notificando a las aplicaciones los mensajes (o Eventos) que se van produciendo.
Quizás en el sentido estrictamente académico, sólo se pueda aplicar lo de "sucesión de instrucciones secuenciales" a los programas puramente lineales; pero es que entonces, eso el vetusto BASIC ya lo superaba cuando se introdujo el GoSub (no deja de ser un "salto" en la secuencia, no?).
Si hablamos de programas multi-hilo, pues sí, vale que al haber dos hebras ejecutándose "pseudo-simultáneamente" puede haber tentación de decir que la ejecución no es lineal... Sin embargo a lo que yo me refiero realmente es al orden de ejecución de un determinado procedimiento o función, nada más.
Si me apuras podríamos discutir si en los sistemas multiprocesador y con ejecución paralela de instrucciones hay o no una "secuencia" u "orden" definido de ejecución (que en mi modesto entender sería lo lógico, no me imagino un sistema ejecutando código arbitrariamente), pero en los sistemas Windows que funcionan por colas de mensajes, las cosas van "una primero y la otra después".
De hecho si algún día inventan un lenguaje en el que los procedimientos o funciones (o módulos, o subrutinas, llamémosle como queramos) NO se ejecuten secuencialmente... a ver quién es el guapo que entiende un programa ;)
Sharq, una cosa es un programa y otra como se ejecuta una vez compilado.
Los lenguajes procedimentales son aquellos en los que se especifica de forma explícita una secuencia de instrucciones. En los lenguajes declarativos esto no es así.
http://foldoc.org/?procedural+language
Los lenguajes no procedimentales lógicamente no tienen procedimientos, se inventaron hace mucho tiempo y con frecuencia los programas son mucho más fáciles de leer. Aunque es verdad que hay programas en Prolog que no los entiende ni su madre :)
Todo se ejecuta secuencialmente
No necesariamente. Incluso en un "dual core" que ahora se compra con cuatro duros, hay dos hilos verdaderos. Y existen arquitecturas "masivamente paralelas". Además, un cerebro es inheremente paralelo, y lo mismo ocurre con una red neural analógica.
Si me apuras podríamos discutir si en los sistemas multiprocesador
Sí, es paralelo de verdad.
Otra cosa es la comprensibilidad, pero ahí es donde entran lenguajes como Prolog o los lenguajes funcionales. En principio, para programar en estos programas no te planteas comprenderlos "traceándolos".
Ahora bien, otra cosa diferente más es que estos lenguajes sean inherentemente "mejores" en todos los sentidos:
- Los lenguajes paralelos tienen problemas con los sistemas secuenciales... y la entrada y salida es un problema secuencial, básicamente. La E/S siempre fue un problema para Prolog, y había que escuchar a los puristas de aquel entonces tronar contra las extensiones para interfaces gráficas.
- Los lenguajes funcionales tienen sus limitaciones propias. El mecanismo básico de discriminación en un lenguaje funcional es el "match"... que es una especie evolucionada de "case/switch", y que presenta todos los problemas de extensibilidad del "case/switch". Yo me estuve planteando añadir un "match" a Freya, pero al final no me decidí porque estaba metiendo al mismísimo Satanás por la puerta trasera del lenguaje.
En mi humilde opinión, el planteamiento de Alfredo es demasiado reduccionista. Ese mismo argumento se puede extender y decir que para qué hace falta un IF si existe el GOTO. Aunque haya una equivalencia, en muchos casos merece la pena pasar a una abstracción superior. Y la gran ventaja de los lenguajes orientados a objetos no es el encapsulamiento, o encapsulación, o como se llame... sino la extensibilidad. Puedes añadir un nuevo jugador sin necesidad de reescribir las reglas del sistema. Eso, por ejemplo, no es tan sencillo en un lenguaje funcional que se basa en "match". Tienes que ir revisando todos los puntos del sistema donde se produce tal discriminación, y nunca tienes la garantía de haber mirado todos.
Mi queja no es tanto contra la técnica: la técnica fue cojonuda en su momento (se asume que la gente la aprovechó) y no hay que tirarla por la borda. Lo que hay es que resolver nuevos problemas. Y aquí es donde te encuentras a los "puristas" de la OOP, que casi siempre son gente que llegó tarde al partido, vendiéndote cepillos de dientes orientados a objetos y, lo peor, retirándote el carné de programador si no le compras el puñetero cepillo.
Esa es también mi "teoría" (que ni es mía ni es una teoría en sí) de las olas. Hubo una primera ola que introdujo, o más bien popularizó, las que ahora se ven como características clásicas: encapsulamiento/herencia/polimorfismo. Una segunda ola la provocó Visual Basic: el concepto de componente. Esto todavía hay gente que no lo entiende: ahí está la tribu de Scott McNeally (Java no soporta componentes y así le va). La tercera ola discurrió en paralelo: fue Java quien se cargó definitivamente la idea de herencia múltiple como desideratum, y popularizó el concepto de tipo de interfaz. Y la cuarta ola está todavía en camino: reflexión a tutiplén, aspectos declarativos (en el sentido técnico de "aspecto", no en el genérico) y quizás una flexibilización de la idea de componentes. El próximo paso podrían ser "componentes con esteroides". ¿Cuánta "inteligencia" se puede empaquetar dentro de un componente?
Y claro, es difícil hacer de profeta: ¿quién sabe dónde terminará la historia de LINQ? ¿Tendrán futuro otras formas de composición modular, como los "traits"? Por ejemplo, si uno abría el API del IDE de Borland, se encontraba con un puñado de interfaces. ¿Cuáles venían implementadas para que uno las usase, y a cuáles había que darles un cuerpo material? Eso no te lo dice el lenguaje: ahora mismo te lo tienen que decir los comentarios. ¿Qué subsistemas necesita un ToolStrip para funcionar? No te lo dice el lenguaje: tienes que tener fe en que el programador siempre se monte todo lo necesario... y eso funciona cuando el "grano" es grueso, no en un nivel "fine-grained". Y todas estas son cosas que se podrían resolver mediante "traits".
...pero es sólo una opinión personal, o más bien, un estado de ánimo :)
No entiendo lo que que quiere decir Ian con lo del argumento reduccionista. Los lenguajes declarativos tienen un nivel de abstracción muy superior a los de los lenguajes procedimentales sean OO o no. Es cierto que tienen limitaciones, pero en esos casos podríamos recurrir a extensiones procedimentales.
Por ejemplo, cuando estás programando en Delphi, que es un 3GL a veces (muy pocas) se recurre a incrustar código en ensamblador 2GL. Se podría hacer algo parecido cuando estás escribiendo código declarativo 4GL y recurrir a código procedimental en casos puntuales.
Con respecto a LINQ, es un paso tremendamente torpe y chapucero hacia la programación declarativa. La sintaxis es como para salir corriendo, pero por lo menos va por el buen camino. Aunque de novedoso tampoco tiene nada por que no es muy diferente al viejo SQL incrustado.
Lo del "reduccionismo" está mal usado por mi parte, pero me di cuenta después de enviar el comentario: no es el caso, porque lo que entiendo de tu argumento es que habría que pasar a un paradigma declarativo. ¿Es eso?
Pues más o menos. Para mi está claro que el futuro va por ahí. Es la evolución natural de los lenguajes de programación. Lo de la POO fue solo un avance más y hay que seguir adelante.
¿Qué te parecería un Prolog sobre .NET con lenguaje propio procedimental dependiente? Cuando anunciaron LINQ empecé a mirar, pero en la otra dirección: un motor de inferencias acoplado dentro de un lenguaje procedimental (Freya): me hubiera hecho falta algo así para el propio compilador de Freya.
O, por el contrario, ¿conoces un modelo de integración mejor? He estado buscando libros sobre implementaciones de Prolog, pero... están todos out of stock.
Los lenguajes funcionales son interesantes teóricamente, pero no me convencen para tirar código "de verdad", por lo que decía antes: el "match" no es más potente que la llamada polimórfica, sólo un poco más conveniente que el discriminador procedimental. Y por supuesto, tampoco llega a ser tan potente como la unificación.
Prolog no me interesa mucho, es muy potente pero es un lenguaje para aplicaciones muy específicas. No lo conozco demasiado bien, pero me parece bastante horroroso.
Por cierto yo si he encontrado libros de Prolog como por ejemplo "The Art of Prolog".
Yo estoy más interesado en algo tipo LINQ pero bien hecho y mucho más potente. Me refiero a la parte relacional, por que XML es una tontería.
Es algo parecido a lo que dices tu. Para mi un lenguaje procedimental con un "motor de inferencias" bien integrado es la misma cosa que un lenguaje declarativo con extensiones procedimentales.
El "motor de inferencias" debería de ser capaz de garantizar cualquier regla de negocio, apoyandose en las extensiones procedimentales cuando fuese necesario. Es decir que el "motor de inferencias" sería el nucleo del sistema.
Lo que tengo claro es que el "motor de inferencias", debe de estar basado en la lógica matemática, y aquí la apuesta segura es el Modelo Relacional (ese gran desconocido).
Basar la lógica de negocio en la lógica matemática es algo que cae de cajón.
Podría hablar durante horas sobre esto con muchísimo más detalle (tengo mucho código ya hecho), pero este no es el sitio. Lo malo es que no se cual es el sitio :)
Con respecto a los lenguajes funcionales puros a mi tampoco me convencen demasiado. Como la mayoría, yo desarrollo software de gestión, y ahí lo que interesa es precisamente el estado de las variables (tablas), que son conceptos (estado y variable) que los lenguajes funcionales eliminan.
Pero hay lenguajes funcionales con llamadas polimórficas, y por supuesto las extensiones procedimentales de las que hablaba antes deberían incluir las llamadas polimórficas los subtipos, los operadores genéricos y todas esas cosas.
Yo creo que enfocais el tema hacia la programación y la mayoría de metodologías están más orientadas hacia el análisis y estudio del sistema objeto del sistema de información (requerimientos, modelaje de procesos y modelaje de datos).
Las metodologías (como UML y muchas otras) tienen su razón de ser cuando queremos analizar un sistema de información del que aún no tenemos clara su implementación final y que hay que consensuar con un colectivo no necesariamente técnico.
Nos permiten avanzar en el diseño, tomar decisiones y establecer un lenguaje común con cualquier interlocutor : informático o no.
Esta es mi opinión, romántica y utópica si quereis, pero esa es.
Otro cantar son las modas tipo MDA (Model Driven Architecture) que prentenden llevar el modelado hasta la última coma de la última línea de código. Ahí sí estoy con la mayoría de que hay que "desnudar emperadores".
Saludos.
Nos permiten avanzar en el diseño, tomar decisiones y establecer un lenguaje común con cualquier interlocutor : informático o no.
Hummm, mi problema para aceptar este punto de vista es que asume un "metanivel" sobre el lenguaje. Sé que hay quienes creen que ese "metanivel" existe y no es trivial... pero es precisamente lo que no termino de ver.
Te pongo un ejemplo que aparentemente no tiene mucho que ver: cuando Delphi 3, se me ocurrió programar un "asistente para crear componentes". Motivación: cuando dices que una clase A tiene una propiedad B de tipo C en Delphi, te estás dejando mucha información en el tintero. C puede ser TFont, que no hereda de TComponent, y eso significa que la clase A es "propietaria" de la instancia en B (debe existir un valor por omisión, la asignación sobre la propiedad procede por copia, no por referencia...). Es decir: detecté toda una serie de características que no se reflejaban en el lenguaje. Al llegar a este punto, hay dos actitudes posibles:
1- Decir que existe un lenguaje con un nivel de abstracción mayor, del que Delphi sería una especie de ensamblador. A continuación, se define ese lenguaje y los componentes se empiezan a programar en él.
2- Por el contrario, asumir que se trata de carencias del lenguaje original para resolverlas en el propio lenguaje.
Por regla, prefiero la segunda vía. De lo contrario, terminas distribuyendo tus esfuerzos en N niveles, con N compiladores diferentes... y esto provoca problemas similares a los que surgen en C++ con las macros: es extraordinariamente difícil implementar Intellisense, por ejemplo.
En este sentido, UML plantea aún muchos más problemas: aunque presuntamente suplementa los lenguajes "de implementación", no se trata de un lenguaje completo. No se puede (ni tiene mucho sentido) programar en UML. Y esa "metainformación" que se especifica a nivel UML es muy pobre: cardinalidad y pertenencia, básicamente.
Claro, entonces entra en escena el puñetero OCL... y de repente te encuentras manejando dos lenguajes de expresiones diferentes e incompatibles.
Es la navaja de Ockam aplicada a la programación...
Una cosa es lo que UML pretende y otra lo que consigue.
Si alguien lee con atención las especificaciones de UML verá que los conceptos básicos no están nada claros. Está todo muy liado. El OCL no hay por donde cogerlo y la mayoría de la gente no sabe ni que existe.
Puedes encontrar perlas como esta:
"Valid model types are the types, classes, interfaces, association classes, actors, use cases, and datatypes defined in the UML model. "
Un diagrama de clases es casi igual a un diagrama de entidades y relaciones, pero las entidades conceptuales y las clases de un lenguaje OO son cosas muy diferentes . UML confunde totalmente estos dos conceptos llamando "clase" a los dos. Hacer una conversión uno a uno de entidades a clases C# suele llevar a resultados desastrosos.
No estoy seguro de cómo dejar un "trackback", así que lo hago "manualmente". Tengo una historia contestando a ésta en: mi bitácora. Era un poco excesiva como respuesta para colgarla aquí.
Hola yo creo que se deveria crear una nueva tecnica creada por programadores para programadores y no por psicologos, cientificos o el marketing informatico
Atte MAT
Publicar un comentario
<< Home