Tras hablar brevemente de la Programación Procedural (PP), ahora toca lo propio con la Programación Orientada a Objetos (POO). Que quede claro antes de nada que voy a tratar de explicarlo para completos “ignorantes” del tema, así que mis definiciones pueden no ser completamente formales. Sólo intentaré que se entienda el concepto.
La Programación Orientada a Objetos (POO)
¡No veáis qué cambio supone esto con respecto a la PP! El concepto es totalmente diferente y, viniendo de la PP, cuesta cambiar esa mentalidad (se hace más fácil para alguien que no ha visto esto nunca).
Primeramente, la definición formal (me vale la de la Wikipedia): “La programación orientada a objetos o POO es un paradigma de programación que usa objetos y sus interacciones, para diseñar aplicaciones y programas de ordenador. Está basado en varias técnicas, incluyendo herencia, abstracción, polimorfismo y encapsulamiento“. Toma del frasco, Carrasco. ¿Alguien ha entendido algo, así, a bote pronto?
Si en la PP únicamente teníamos que pensar en qué funciones queríamos realizar y codificarlas, para poder llamarlas luego desde cualquier parte del programa, ahora la cosa es como sigue: tienes un mundo real, así que lo que vayas a programar debería encajar lo mejor posible con ese mundo. En el mundo hay cosas, objetos, y sobre ellos haces operaciones. Por lo tanto, cuando diseñes el programa, no pienses en qué debe hacer esta operación o aquella otra, piensa que un objeto debe transformarse mediante sus operaciones y de él podrás extraer un resultado o usarlo para otros menesteres.
Esto, visto así de forma abstracta, parece que se entiende, pero luego, a la hora de ponerlo en práctica, no es tan fácil. Veamos un ejemplo sencillo:
Tengo un coche, que está formado por 3 partes: ruedas, motor y chasis. El programa que necesitas debe comprar piezas para tener coches y venderlos. Bien, en un programa estilo PP podrías hacer esto (lo que pongo es pseudocódigo, una descripción natural de lo que haría el programa, no código fuente):
Variable coche1; Variable ListaPiezas;
Procedimiento ComprarPieza(tipo de pieza); Procedimiento MontarPiezas(lista de piezas); Procedimiento VenderCoche(coche);
Función Principal ( ComprarPieza(rueda); ComprarPieza(rueda); ComprarPieza(rueda); ComprarPieza(rueda); ComprarPieza(motor); ComprarPieza(chasis); MontarPiezas(ListaPiezas);
VenderCoche(coche1); )La variable coche1 de arriba es global al programa, por tanto accesible para cualquier función que quiera vender el coche o añadirle piezas. Lo mismo le pasa a la variable ListaPiezas, que es una lista con las piezas que vamos comprando. No hay que hacer nada más que usarlas. Asumimos que las funciones trabajan sobre estas variables.
Esto, con POO, no es tan fácil como lo que aparece ahí arriba. Primero, debemos definir una “entidad” (el objeto) genérica de la que se puedan “extraer” variables que sí podemos usar, es decir, debe existir un objeto genérico coche del que sacaremos, cada vez que lo necesitemos, las variables coche1, coche2, etc. que será con las que podemos tratar para añadirles piezas y venderlos. Ese objeto coche debe tener sus propias funciones (se llaman métodos) con las que operar, porque si no, no podremos hacer nada con él. Y esto es así porque, por definición, los objetos son cerrados y nada puede acceder a sus propiedades o funciones, salvo que nosotros queramos que así sea (definiéndolos de esa forma, como públicos). Esto se hizo así en parte para evitar que los malos programadores abusasen de las variables globales y que otras funciones pudiesen tocar los valores del objeto. De esa forma, si mi objeto es sólo mío, sólo yo puedo manipular los valores de mis variables, así que siempre las tendré controladas y no habrá la posibilidad de que un error en una llamada a una función con el mismo nombre que la mía me cambie el objeto sin darme cuenta.
Por lo tanto, debemos definir el objeto y las funciones posibles del mismo (no lo voy a complicar en demasía, sólo para hacerse una idea). Podría quedar algo así:
Definición de Objeto Coche; Variable Privada rueda (es un tipo de pieza); Variable Privada motor (es un tipo de pieza); Variable Privada chasis (es un tipo de pieza);
Procedimiento Público ComprarPieza(tipo de pieza); Procedimiento Público MontarPiezas(); Procedimiento Público Vender(); Fin de la definición;
Mis variables: Variable coche1 de tipo coche;
Función Principal ( coche1.ComprarPieza(rueda); coche1.ComprarPieza(rueda); coche1.ComprarPieza(rueda); coche1.ComprarPieza(rueda); coche1.ComprarPieza(motor); coche1.ComprarPieza(chasis); coche1.MontarPiezas(); coche1.Vender(); )En este caso, el objeto real coche1 (que proviene del objeto general “coche”) está formado por 3 piezas diferentes y, para poder montarlas (la función de montar las piezas, como es propia del objeto, ya sabe como montarlas), hay que usar su propia función de MontarPieza. No vale otra, debe ser esa.
Bien, parece fácil a priori… Sí, bueno, la teoría es sencilla hasta que te enfrentas a un programa real con multitud de objetos que tienen que interactuar entre sí. Entonces te das cuenta de que, de serie, todo es privado, así que aquello que era tan fácil, como llamar a una función para hacer una serie de cálculos sin mayor importancia, ahora se transforma en una mezcla de objetos que tienen que tener bien “configuradas” sus variables y funciones para ser accesibles desde otros objetos. Luego tienes el añadido de que si trabajas, por ejemplo, con Java, es tan estricto en sus definiciones que a la mínima te da un error de “incongruencia” cuando intentas llamar a una función o usar una variable que es de otro tipo (no es que esto sea malo, sólo que es muy exigente, a veces demasiado). Encima, si quieres realizar alguna función “general” para todo el programa, algo tan simple como “Sumar(numero 1, numero2)”, no hay una “sección” donde puedas colocar funciones generales globales, aquí todo son objetos y deben estar dentro de un objeto, por lo que toca crear un objeto “FuncionesGenerales“, y dentro definir las funciones que quieras. Esto no casa con eso de “objetos reales del mundo” del que hablaba este modelo, pero para ser coherentes con el mismo, debe ser así.
Bueno, en el ejemplo se ve bonito y hasta fácil de entender, pero como digo, eso es lo que parece cuando sólo tienes un objeto. Y además, esto es sólo lo básico, aún falta ver la otra parte de la definición: “… herencia, abstracción, polimorfismo y encapsulamiento” decía, ¿no? Aquí es donde se lía todo.
Herencia, abstracción, polimorfismo y encapsulamiento… ¿ein?
¿Pero… esto qué es lo que es? Con lo feliz que era yo con mis variables y mis funciones… pero chico, las cosas evolucionan. Realmente esto es lo que le da la potencia real a los objetos, lo anterior es tan sólo una organización más estricta de los datos y funciones. Os recuerdo que, para no liar al personal, seguiré hablando de funciones (para los métodos) y variables (para los atributos):
Herencia
Pues es una propiedad por la que un objeto “hijo” hereda de su “padre” todas sus funciones y variables, de forma que no tenga que volver a codificarlas. Ejemplo: teníamos un coche, ¿verdad? Le tuve que decir al coche que tenía chasis, motor y ruedas. Si ahora vendo también motos, tendré que volver a definir todas las piezas de la moto, que al fin y al cabo son las mismas (pero solo hacen falta 2 ruedas). ¿Qué tal si en vez de definir un objeto coche y otro moto, defino uno más genérico (el padre) llamado vehículo? Si sus hijos heredan sus propiedades, ya no tendré que definir dos veces lo mismo, me vale con decir que coche y moto son vehículos. Esto sería algo tal que así:
Definición de Objeto vehículo; Variable Privada rueda (es un tipo de pieza); Variable Privada motor (es un tipo de pieza); Variable Privada chasis (es un tipo de pieza);
Procedimiento Público ComprarPieza(tipo de pieza); Procedimiento Público MontarPiezas(); Procedimiento Público Vender(); Fin de la definición;
Mis variables: Variable coche1 de tipo vehículo; Variable moto1 de tipo vehículo;Et voilà!! Ya tenemos todas las funciones del vehículo en coche1 y moto1, podemos hacer ahora coche1.ComprarPieza(chasis) y funcionará automáticamente. Lo mismo con moto1, sólo que para poder venderla, nos llegará con llamar dos veces a moto1.ComprarPieza(rueda). Es útil, ¿verdad? Se escribe menos, cierto, pero obliga a pensar más en el diseño del programa completo, buscar puntos en común para hacer objetos lo más abstractos posibles (de forma que podamos heredar y heredar y heredar…) y… ahí empiezan los problemas. Cuanto más perfeccionas esta técnica, más liosos se vuelven los programa, sobre todo para entenderlos. De repente te encuentras un programa desconocido que pone:
motoHonda4cil600ccDobleFaro.ComprarPieza(motor4cil600cc)
Y dices tu: vaya, esto me suena a algo. Y empiezas a investigar. Primero miras qué funciones tiene motoHonda4cil600ccDobleFaro y te das cuenta de que tiene 1 ó 2, pero no es ésa. Pero ves que este objeto es hijo de motoHonda4cil600cc. Vas a buscar a ese objeto a ver si está allí la función y… tampoco, pero ves que es hijo de motoHonda4cil y crees que estará allí. Vaya, tampoco, pero es hijo de motoHonda y crees que ahora sí que sí. Error, éste es hijo de vehículo. ¡Vaya, por fin veo la función original, ya puedo seguir el flujo del programa! Afortunadamente, los entornos de programación actuales buscan la función por ti y siguen ese flujo, pero si ves el programa en papel es para llorar… Igual te preguntas por qué salieron tantos hijos. Sencillo: el programador quería heredar todas las características de cada uno de los padres, ya que cada padre agregaba una característica única al objeto final. Hay motos, algunas son marca Honda, algunas son de 2 cilindros y otras de 4, la cilindrada es variable (600 en este caso) y además, el chasis puede ser de doble faro o simple. ¿Alguna duda?
Abstracción
Que palabra más fea, pero, en resumen, viene a decir que tú puedes usar las funciones de los objetos sin necesidad de que sepas qué hacen o cómo lo hacen. Si total, para qué lo quieres saber, con tal de que hagan lo que prometen (no como los políticos). Esto ayuda a que no te entrometas en sus funciones y así no puedas modificar su comportamiento. Por ejemplo, a tí te basta con saber que coche1.MontarPiezas(); hace que el coche se monte con las piezas que compraste. Te da igual cómo lo haga, con tal que lo haga bien. Esa función posiblemente calcule si tiene las piezas necesarias y realice el montaje, pero en realidad a ti todo eso te da igual.
Polimorfismo
Si la palabra de antes era fea, ésta mete miedo y todo. Y sin embargo es muy útil y fácil de comprender. Lo que significa es que puedes tener la misma función con el mismo nombre en objetos hijos, pero que internamente hacen cosas diferentes a la misma función que hay en el padre. Con el ejemplo se ve claro: resulta que tienes tres formas (o más) de montar un coche, por ejemplo un cocheNormal (un vehículo), un cocheHondaCupe y un cocheHonda5Puertas. Pero tú lo que quieres es que todo el mundo use el mismo método de montar las piezas, de forma que el proceso sea siempre el mismo (es decir, que obtengas el coche montado y listo para su venta), eso sí, sólo cambia la forma de hacerlo. Con PP tendrías que definir tres funciones, ya que no podrían llamarse igual: MontarPiezas, MontarPiezasCupe y MontarPiezas5Puertas. O bien, si más del 50% del código es igual, hacer una función con un parámetro que indicase la forma de montaje: MontarPiezas(Puertas) y, según eso, en el código hacer una cosa u otra.
Pero llega el polimorfismo para arreglar esto de tener tres funciones diferentes (ya digo, si el código es igual en más de un 50% no merece la pena, lo arreglas con una variable que decida qué hacer). Como quieres que siempre se use la función MontarPiezas, pues defines en cada uno de los hijos de un objeto vehículo la función MontarPiezas, solo que el código de cada función será diferente y realizará las operaciones que necesite para obtener el coche montado:
Variable cocheNormal de tipo vehículo;
Variable cocheHondaCupe de tipo vehículo; Procedimiento Privado MontarPiezas() { Acciones abc... };
Variable cocheHonda5Puertas de tipo vehiculo; Procedimiento Privado MontarPiezas() { Acciones xyz... };Como vemos, cocheNormal no define su propia función MontarPiezas() (viene heredada y no está aplicando el polimorfismo). Cada función definida sustituirá la del padre y realizará unas tareas propias, sin embargo, yo solo tengo que llamar a la función del objeto concreto que, gracias al polimorfismo, puede llamarse igual en cada hijo. La llamada sería así:
código para montar un coche normal...; cocheNormal.MontarPiezas(); código para montar un coche cupe... cocheHondaCupe.MontarPiezas(); código para montar un coche de 5 puertas cocheHonda5Puertas.MontarPiezas();Se puede apreciar que el nombre de la función es el mismo en todos los hijos, pero el código de cada función es diferente, obteniendo todas las funciones el mismo resultado: un coche montado y listo para vender.
Encapsulamiento
Bonito palabro, suena futurista y todo, pero simplemente quiere decir que unes todo lo referente a un objeto dentro de él, es decir, no deberías necesitar, para trabajar con ese objeto, nada externo. Como vimos con el coche, en la PP todo era libre y cualquiera podía hurgar en él. De hecho, el pobre coche1 no tenía forma de evitar que nadie tocase cosas de él, era un simple títere. En la POO tenemos todas las variables y funciones dentro del objeto coche. Es, como si dijéramos, autosuficiente.
Conclusiones
No voy a ahondar más en este tema, porque hay abundante literatura de él. Tan sólo trato de dar una vista general del mismo. Como todo en esta vida, hay que buscar el compromiso adecuado entre organización y comprensión. Ni la PP ni la POO son siempre lo mejor, depende del caso que trates y de tus conocimientos.
Yo, por ejemplo, prefiero la PP porque:
- Suelo hacer programas pequeños y simples.
- Es más rápido.
- Es más fácil de mantener.
- Sólo los hago yo.
Sin embargo, entiendo que para ciertas tareas es mejor usar POO. Por ejemplo, si más de una persona va a trabajar en el proyecto, o si hay varios proyectos abiertos y muchas partes son comunes: puedes aprovechar tus objetos ya definidos para el otro programa. Un ejemplo sería, tengo un programa de gestión de almacén de vehículos y otro de venta: si defino el objeto vehículo en uno, es posible que tenga muchas cosas en común con el otro programa, y por tanto mucho código que tenga escrito de uno me valdrá para el otro. Esto lo facilita el encapsulamiento, ya que se supone que el objeto es “autosuficiente”.
Podemos decir también que la PP facilita una programación más “libre” o más “sobre la marcha”: es ideal para los improvisadores. Si en un momento determinado se te ocurre una novedad a incorporar, la flexibilidad que tiene permite meterla en “ná y menos“. La POO es lo contrario, deberías haber analizado bien el problema antes, reconocido y separado sus objetos, para luego definirlos y empezar a operar con ellos. Agregar una función nueva a un objeto es sencillo si la operación es “interna”, pero interactuar entre objetos ya no es tan sencillo si no lo habías planificado.
La ventaja de libertad de la PP es también su mayor problema: hay miles de desastrosos programas que han dado la mala fama a los lenguajes que emplean esta metodología (como Visual Basic). Sólo hay que buscar programas de ejemplo, y en más del 50% de los realizados con VB se podrán apreciar varias faltas (no obligatoriedad de declarar variables, código spaguetti, funciones sin ton ni son, etc.) Y, derivado de esto, viene la “fama” de que los que usan POO son unos fieras porque para eso “hay que saber”, en cambio para usar PP hasta el vecino puede… pero para usarla bien hay que ser más fiera que los de la POO, porque para eso necesitas buenos conocimientos, disciplina y orden (en la POO se te obliga a hacer las cosas, con lo que si no eres disciplinado, la metodología lo es por tí).
Por poner un ejemplo real, yo digo que suelo hacer programas pequeños, pero con VB tengo realizados (y en producción) tres programas empresariales de gestión (uno para un almacén de ropa, otro para gestión de lotes avícolas y otro para una academia a nivel autonómico), con más de 20.000 líneas de código y que llevan más de 10 años funcionando cada uno sin la menor incidencia, más allá de las típicas “nuevas funcionalidades” que demandan los clientes. Trabajan con ellos más de 20 usuarios simultaneos. Ya véis, PP con Visual Basic, ni un objeto, y funcionando sin problemas, con fácil mantenimiento y relativamente fácil ampliación de funcionalidades. Es decir, la POO no es la panacea, es sólo… otra metodología.
¿Cuál interesa más? Pues como dice “Jarabe de Palo” en su canción… ¡depende!
Bueno, finalmente comentar que he tratado de que el tema se haga de la forma más abstracta y alejada de tecnicismos posible para entender las bases. No se pretende explicar en profundidad cada metodología, para eso imagino que hay miles de páginas centradas en cada cosa. Esto pretende ser solo una orientación de “por donde van los tiros”. No sé si lo he conseguido, pero es la intención. Espero que os haya gustado este breve VS. Ahora toca empezar con el próximo combate: Sistemas cliente-servidor vs Sistemas multi-capa
The Informática: esos locos, con sus locos cacharros – Programación procedural clásica (PP) vs Programación orientada a objectos (POO) (2 de 2) by Manuel Conde Vendrell, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 2.5 Spain License.
{ 21 } Comentarios
Un par de errores:
1-
Procedimiento Privado ComprarPieza(tipo de pieza); Procedimiento Privado MontarPiezas(); Procedimiento Privado Vender();
Si lo declaras así no vas a poder usarlo como pones más abajo. Tendrías que declararlos como públicos pues los métodos privados solo se pueden usar dentro de otros métodos del objeto.
2-
El polimorfismo no va de eso: eso es sobrecarga de métodos y operadores (y C lo tiene, si no me acuerdo mal, y es un bonito lenguaje procedimental).
El polimorfismo es cuando un objeto padre y otro hijo tienen el MISMO método con los MISMOS parámetros pero tienen distinto código (aunque hagan la misma cosa, o deberían). Esto es así porque probablemente (siguiendo tu ejemplo) no es lo mismo montar una rueda en una una honda civic que en una super honda civic con dos faros, asi que si tengo un objeto de tipo honda civic y ejecuto el metodo montar faros quiero que use SU codigo y no el de honda civic dos faros y viceversa.
Para terminar solo un par de apuntes:
a) Se puede hacer POO con un lenguaje precedural. Solo que muchas de las cosas que tienes de “gratis” en POO te las tienes que currar. Como bien dices, la POO es una metodología (y/o paradigma) que le dicen, no la panacea.
b) Para programas pequeños , generalmente no vale la pena por el overhead que produce, pero si tienes que hacer algo medianamente genérico y/o grande la reutilización de código que te permite la POO es IMBATIBLE. Eso de que el mantenimiento es más complicado es mentira. El encapsulamiento permite aislar grandes partes de un programa que de otro modo pueden ser un infierno a la hora de arreglar un problema.
Al fin comienzo a entender qué es al POO. Y mira que tengo adaptado scripts en perl hechos con POO. Y funcionaban. No me explico cómo.
Como dice cruzki, confundes polimorfismo con sobrecarga. Tampoco te culpo, es un error común, el artículo de wikipedia en español por ejemplo cae en el mismo error mientras que la wikipedia inglesa sí que lo explica bien: http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming
Por otro lado, se trata de una explicación de POO en clave procedural y así normal que parezca engorroso. En POO no se trata de llamar a funciones sino de mandar mensajes a objetos que harán aquello que tengan que hacer como respuesta, en realidad POO está mucho más cercano a la semántica que utilizamos a diario ya que interactuamos con objetos de distintas formas y que hacen unas cosas u otras, normalmente no pensamos en un mundo de funciones sino en un mundo de objetos.
Cada uno es libre de elegir uno u otro paradigma pero lo cierto es que conozco poca gente que conociendo POO la prefiera al código procedural. De hecho, este debate hace tiempo que pasó de moda y bueno, todos los lenguajes que en su día eran procedurales han evolucionado para soportar POO.
Un ejemplo es el tan usado PHP, que en sus comienzos no soportaba mecanismos POO. Se implementó soporte en PHP4 pero muy deficiente y se juzgó lo suficientemente importante el tema del POO como para darle una vuelta entera y presentar un modelo de objetos nuevo en PHP5. Siguiendo con PHP5, pondré algunos ejemplos que ponen de relieve las ventajas de POO frente a PP:
PHP por su origen procedural no dispone de una clase String (dicen que quizá en PHP6) por lo que la forma de realizar un reemplazo (una) es esta: $cadena = str_replace(“A”,”O”, $cadena) Bien, pues eso es código procedural. Si el string fuera un objeto podríamos hacer algo así: $cadena->replace(“A”,”O”) . Esto en realidad es mucho más fácil de entender, le dices al objeto cadena que quieres sustituir A por O. PHP es un buen ejemplo de las desventajas de PP, basta ver su manual para darse cuenta que por ser originalmente un lenguaje únicamente procedural ha sido necesario el uso de nomenclaturas que obligan a consultar el manual constantemente. Y es que no hay que olvidar el problema de los espacios de nombres, esto se resuelve fácilmente en lenguajes POO mediante el uso de clases y namespaces mientras que en PP sólo se puede solucionar con nomenclatura, prefijos al fin y al cabo.
Otra desventaja de PP es la necesidad del operador referencia o de punteros (si se trata de lenguajes de más bajo nivel). En lenguajes POO no es necesario el uso de referencias ya que continuamente lo que se hace es mandar mensajes a objetos indirectamente trabajando con el manejador (handle) del objeto. Esto simplifica mucho la programación ya que las referencias son poco intuitivas, obligan a seguir el código a saltos como si gotos se trataran y no existen buenas nomenclaturas para distinguir cuando se espera una referencia y cuando no. Una vez más PHP es buen ejemplo de esto, que dispone de un operador referencia que mientras que hace años era indispensable para manejar estructuras de datos grandes, hoy en día sólo se utiliza para casos especiales ya que en general si usas POO ya estás trabajando todo el rato como si fuera por referencia.
Sin embargo, como conclusión, cada uno es libre de utilizar la metodología que prefiera, una vez más PHP es también un buen ejemplo de esto ya que quizá el soportar ambas metodologías sea una de las razones que le mantengan como el lenguaje más usado en web.
Por cierto, mencionas VB. Supongo que sabrás que hoy en día VB es un lenguaje POO como otros. No hay ni un sólo lenguaje que no haya evolucionado en ese sentido, curioso ¿verdad?. ¿Estará todo el mundo equivocado?.
Hola,
hasta ahora no quise entrar en esta discusión. Sabía que esta serie iba a dar mucho de qué hablar porque la red está llena de gente que sabe mucho de esto (y de otros que nos creemos que sabemos mucho, pero no).
Así que solo un apuntes aséptico:
Cruzki: dices que se puede hacer OO con un lenguaje que en principio no es orientado a objetos. Para mí, el ejemplo típico es Linux. Si has leído su código verás que utiliza un huevo de conceptos de la orientación a objetos: estructuras equivalentes a pseudoobjetos, con sus métodos y propiedades, pseudoherencia (estructuras que cogen parte de su comportamiento de otras), pseudoexcepciones (a base de GOTOs; sí sí, el prohibidísimo goto… pero bien usado),… y se nota que es un lío, artificial, y que buena parte podría haberse hecho mucho más clara con C++. Pero ahí está: orientación a objetos en C.
@cruzki: Ui, leches, eso pasa por hacer pseudocódigo que no puedes probar, jeje. Tienes razón. ¿Algún moderador que me diga si edito el artículo o lo dejo así? Respecto al polimorfismo, parece que tenía una idea equivocada del mismo (y la wiki española, como dice lector, no me ayudó mucho a cambiarla). ¿Cambio esto también para que el artículo quede correcto? Respecto a tus notas, a): sí se puede, en VB alguien hizo una estructura que emulaba POO y podías hacer tus programas siguiéndola. Creo recordar que lo único que no soportaba era polimorfismo. PERO, siempre será mejor que se soporte “de serie” y con todas las características. b): te puedo asegurar, porque me ha tocado hacerlo, que mantener un programa de menos de 5000 líneas con POO me costó bastante más que hacerlo con PP. Cada vez que el cliente pedía un cambio tenía que tocar 5 cosas (definir cosas en el padre, el hijo, el nieto, etc.), cuando en PP lo hubiera hecho con 1 sola. Pero también dependerá de lo bien diseñado que esté el programa en PP.
@Brigo: me alegro si el artículo te ha ayudado, esa es la intención, explicar de forma “informal” este pequeño universo de metodologías.
@lector: tus explicaciones han sido técnicamente perfectas, no puedo decirte que no a nada porque tienes razón en tus argumentos, sin embargo creo que al final te has metido en un terreno demasiado técnico, que era lo que quería evitar (referencias y punteros). Por cierto, no sé los demás, pero yo entiendo mucho mejor $cadena = str_replace(“A”,”O”, $cadena) que $cadena->replace(“A”,”O”). Piensa por un momento en el lenguaje natural habitual en el mundo cuando quieres transformar algo: algo = algo + una operación (por ejemplo i = i + 1). Vale que sea más cómodo escribir i++, pero tú ponle a una persona de la calle las dos operaciones y piensa cuál entenderá mejor. Yo es que no veo la facilidad de la POO por ningún lado. Todo es más enrevesado. Vale que una vez lo entiendas y te acostumbres tenga sus ventajas, pero de salida, y sin conocimientos profunos del asunto, para mí es más compejo. Ah, y no, VB no es un lenguaje POO (es VB.NET), VB (hasta su última versión 6) es y será siempre PP (de esto hubo grandes discusiones cuando Microsoft decidió abandonar VB y pasarse a VB.NET). Bueno, podemos decir que en .NET puedes escribir en varios lenguajes (C#, VB, etc.) y, obligatoriamente, es POO.
Finalmente un apunte. He tratado de que el tema se haga de la forma más abstracta y alejada de tecnicismos posible para entender las bases. No se pretende explicar en profundidad cada metodología, para eso imagino que hay miles de páginas centradas en cada mundo. Esto pretende ser solo una orientación de “por donde van los tiros”. No sé si lo he conseguido, pero es la intención.<
@Eagle: En mi opinión, lo mejor es editar el artículo y corregir los errores. Esta página tiene vocación de permanencia, según dice siempre Pedro, y creo que lo correcto es procurar que la información sea lo más correcta posible.
Por lo demás, excelente artículo!!
Saludos. Mac.
@Eagle
Lo de los punteros lo he querido mencionar porque una de las razones del éxito de POO es la abstracción respecto a eso. Hay gente que no quiere ver un puntero ni de cerca y en muchos lenguajes POO al tener recolección de basura lo consiguen. Esto tiene la contrapartida de que muchos programadores olvidan que debajo de su máquina virtual hay una máquina real con limitados recursos pero eso ya es una cuestión educativa.
“Por cierto, no sé los demás, pero yo entiendo mucho mejor $cadena = str_replace(“A”,”O”, $cadena) que $cadena->replace(“A”,”O”)”
Supongo que será cuestión de gustos. Bueno, y también cuestión de entender bien la sentencia OO que viene a decir “le digo al objeto cadena que reemplace la A por la O” frente al procedural de “le digo a la función reemplazar que en la cadena sustituya A por O y me devuelva la nueva cadena en el retorno que ya me encargo yo de machacar la cadena original”. ¿Y si quiero que la propia función se encargue de cambiar la cadena? Pues ya nos metemos en el tema de pasos por referencia frente a paso por valor, o retornos de referencias. Si no fuera por este tema quizá la PP sí que sería más asequible pero sólo por abstraerse de eso puede merecer la pena POO.
@Macluskey: ok, lo cambio en breve.
@lector: ojo, que no digo que la POO no merezca la pena. Lo merece y mucho, solo que a mí en particular me gusta que las cosas sean lo más simples y claras posibles, sin tener que “analizar minuciosamente” que se pretende hacer con cada acción. Entiendo que, para cosas sencillas, la PP tiene mucho más que decir que la POO. Para proyectos complejos, posiblemente sea mejor POO, más que nada porque seguramente no dependa de una sola persona.
Corregido el texto. @cruzki y @lector, ¿creeis que así está bien definido el polimorfismo?
@J
No he visto el código del kernel Linux, pero estaba pensando justamente en ese ejemplo porque más de una vez se ha dicho que “debería” pasarse a c++ y como réplica se explicaba que ya se estaba haciendo POO.
@Eagle
A mi me parece que ahora está bien.
Y en cuando a la pelea entre PP y POO la verdad: has lo que te sea más cómodo. Siempre que este todo decumentado y explicado va a dar igual el lenguaje que uses. Lo importante es que tengas claro lo que quieres hacer y como hacerlo (y conseguir explicárselo y que lo entiendan a tus compañeros de trabajo/usuarios). Ya has visto como Mac montaba sistemas con código spaguetti que funcionaban a las mil maravillas o como el kernel Linux está escrito en C (aunque es un poco tramposo). El usar POO o PP o XD o “ponga aquí la super chachi metodología” no va a resolverte el problema, te puede ayudar, pero el problema sigue siendo el mismo:
Tener claro lo que quieres hacer, como hacerlo y conseguir explicárselo (y que lo entiendan!) a tus compañeros de trabajo/usuarios.
@cruzki: Cuando hablas de que “Mac montaba sistemas con código spaguetti que funcionaban a las mil maravillas” igual te referías a mí… Pueees…. Esteeee….
Sí. Confieso. En los años setenta montábamos las aplicaciones con mogollón de GOTO’s. Y funcionaban como tiros (teniendo en cuenta las limitaciones de los sistemas de entonces, claro). Pero a la tercera modificación ya ni el propio autor era capaz de seguirlos.
Claro que en nuestro descargo podemos afirmar que por entonces no se conocía otra forma de programar, así que no te lo planteabas: lo hacías y ya. A partir de los ochenta, cuando conocimos las técnicas de Programación Estructurada (Warnier, Bertini y Jackson, por este orden cronológico), prohibimos el GOTO para siempre jamás. Y tan felices.
Pero… por mucho que nosotros no pongamos GOTO por parte alguna en nuestro fuente, nunca nunca hay que olvidar que, por dentro, el sistema se pasa la vida ejecutando instrucciones máquina GOTO (o branch, o jump, o como se llamen en cada sistema). Así que… ¡larga vida al goto!
Saludos!
Mac al final ha dado en el clavo. La POO y la PE son cuentos. El ordenador se jarta a CALL, JMP y CALL REG.
Los unicos articulos que decepcionan de todo el cedazo son estos. Los informaticos tirandose los trastos a la cabeza por un articulo dificil de entender para los profanos y lleno de errores e incongruencias.
El polimorfismo yo lo veo igual. La gracia del polimorfismo es que si dos clases comparten una interfaz comun puedes cambiar una por otra.
vehiculoparamontar=moto vehiculoparamontar.Montarpiezas() vehiculoparamontar=coche vehiculoparamontar.Montarpiezas()
funcionara le pases un coche o una moto porque como los dos heredan de vehiculo comparten la interfaz.
@yo mismo: nadie se tira los trastos a la cabeza. Que yo vea, estamos todos conversando y las correcciones que han hecho son correctas. De hecho esas aportaciones lo han hecho mejor aún.
Yo tampoco he visto a nadie tirar trastos; sí corregir posibles errores y exponer ideas diferentes, como debe ser, y salvo que se me haya escapado algún comentario, de manera civilizada (sobrenaturalmente civilizada, para Internet).
Creo que la guerra entre PP y POO no existe, es más, es una tonteria, POO no es un paradigma distinto a PP, de hecho, para hacer POO necesitas conocer muy bien la PP. Me he encontrado muchisimas veces con supuestos programadores de POO que no saben aplicar la potencia de POO porque no son capaces de programar corectamente sus procedimientos, y por lo tanto no hay donde aplicar ventajas. Una aplicacion PP bien hecha es el equivalente a una POO con un solo objeto, la aplicacion en si. De hecho, una aplicacion pequeña en POO se combierte en uno o dos objetos. POO envuelve PP y si no se conoce la segunda, no se pueden obtener ventajas de la primera.
Por otro lado, discutis de formas de trabajar, y si lo releis con un poco de distancia, la conclusion es que hay que trabajar bien, ya sea en PP o POO
Saludos a todos
@DragonV: es cierto, la conclusión a la que se llega, ya no solo en esto sino aplicado a cualquier trabajo, es que hay que trabajar bien. No hay más que ver un piso mal hecho y uno bien hecho para calificar al “profesional” que lo hizo…
Bueno ya entendi mejor eso de la POO, en verdad es dificil para alguien que toda su vida ha programado con PP. Tambien tengo algunos programas circulando por ahi, y todos los hice con el viejo metodo. Creo que ni el mas grande de mis programas se beneficiaria con la POO, ya son codigos ordenados y muy rapidos En fin, usen el metodo que mejor les convenga
Excelente explicación en rasgos generales, al final la decisión del uso de PP o POO depende netamente del problema a tratar. Me resultó interesante el asunto ya que desde hace algún tiempo llevo programando en C# (lenguaje “estrictamente” orientado a objetos), donde empleo los beneficios de la POO especialmente en la parte de controles, sin embargo la lógica empresarial la resolvemos empleando PP, evitando la creacion de objetos propiamente … generando así una especie de híbrido entre ambos … esta metodología fue criticada por algunos “eruditos” en el tema, sin embargo al hacer un analisis de rendimiento, coste, seguridad, mantenimiento y otros, superaba a los proyectos que solo empleaban PP o POO. El único inconveniente es que no podíamos adoptar una metodologia estandar de documentación (especificamente para el diseño). En base a su experiencia … creen que es aceptable, eficiente y eficaz trabajar de forma híbrida entre ambos paradigmas? y que tipo de documentación recomendarían para tal modelo (diagramas, descripciones, etc.)? (…entiendo que es un post antiguo, pero agradecería sus comentarios)
Lo unico sensatao que he escuchado es que no hay algo que hagas con POO que no puedas hacer con PP (no aqui, pero me suena coherente), hay cosas que me parece que solo tienen el enfoque de desarrollo y mezclan información que debe ser manejada desde la base de datos, no he encontrado un analisis real algo simple, por ejemplo el manejo del mantenimiento preventivo- correctivo de los equipos que aparezca por un lado el enfoque PP y por el otro el POO. Actualmente me dedico solo a la parte de Bases de datos, pero me quede con la curiosidad de poder tener los 2 mundos, si en PP no manejaron librerias y estandares de programacion obvi se les va a hacer algo supermega guau el enfoque que plantean, pero si hacian las cosas con un mejor nivel, no hay mucha diferencia, automatizar las tareas es el objetivo, hacer revoltijos indescifrables no hace un mejor producto.
Escribe un comentario