Nota : esta pregunta es un extracto editado de una publicación de blog que escribí hace unos meses. Después de colocar un enlace al blog en un comentario sobre Programadores, alguien solicitó que publique una pregunta aquí para poder responderla. Este anuncio es mi más popular, ya que la gente parece que escribir "No entiendo la programación orientada a objetos" en Google un montón . No dude en responder aquí, o en un comentario en Wordpress.
¿Qué es la programación orientada a objetos? Nadie me ha dado una respuesta satisfactoria. Siento que no obtendrás una buena definición de alguien que dice "objeto" y "orientado a objetos" con la nariz en el aire. Tampoco obtendrá una buena definición de alguien que no haya hecho nada más que programación orientada a objetos. Nadie que entienda tanto la programación procesal como la orientada a objetos me ha dado una idea coherente de lo que realmente hace un programa orientado a objetos.
¿Alguien puede darme sus ideas sobre las ventajas de la programación orientada a objetos?
fuente
Respuestas:
Piense en el software como una máquina o línea de ensamblaje que existe dentro de la computadora. Algunas materias primas y componentes se alimentan a la máquina, y sigue un conjunto de procedimientos para procesarlos en algún producto final. Los procedimientos se configuran para realizar una operación específica en alguna materia prima o componente a un conjunto específico de parámetros (por ejemplo, tiempo, temperatura, distancia, etc.) en un orden particular. Si los detalles de la operación a realizar fueran incorrectos, o si los sensores de la máquina no estuvieran correctamente calibrados, o si alguna materia prima o componente no estuviera dentro de los estándares de calidad esperados, podría cambiar el resultado de la operación y el producto no resultaría como se esperaba.
Dicha máquina es muy rígida en su funcionamiento e insumos aceptables. Las máquinas no cuestionan la inteligencia de los diseñadores ni su entorno operativo actual. Continuará siguiendo los procedimientos mientras se le indique. Incluso si un cambio en las materias primas o componentes pudiera tener un efecto dramático en lo que sucedió en operaciones posteriores, la máquina aún realizaría sus procedimientos. El proceso necesitaría ser revisado para ver qué cambios a los procedimientos fueron necesarios para compensar y producir el resultado deseado. Un cambio en el diseño o la configuración del producto también puede requerir un cambio significativo en las operaciones realizadas o en su pedido. Aunque los encargados de la producción aprendieron rápidamente la importancia de aislar las operaciones tanto como sea posible para reducir los efectos indeseables entre ellas, se hacen muchas suposiciones de la condición en que los componentes están en proceso de procesamiento; supuestos que podrían no detectarse hasta que el producto final esté en manos del usuario en un entorno operativo diferente.
Así es la programación procesal.
Lo que proporciona la orientación a objetos es una forma de eliminar los supuestos de la condición de los componentes; por lo tanto, las operaciones que se realizarán en ese componente y cómo integrarlo en el producto final. En otras palabras, OOP es como tomar los detalles del proceso para tratar con algún componente en particular y dárselo a una máquina más pequeña. La máquina más grande responsable del proceso le dice a la máquina específica del componente qué operación espera realizar, pero deja los detalles de los pasos para que la máquina específica del componente se encargue.
En cuanto a las ventajas de la orientación a objetos sobre el software no orientado a objetos:
fuente
Desde su blog, parece que está familiarizado con la programación imperativa y funcional, y que está familiarizado con los conceptos básicos involucrados en la programación orientada a objetos, pero nunca ha tenido realmente "clic" sobre qué lo hace útil Trataré de explicar en términos de ese conocimiento, y espero que sea útil para usted.
En esencia, OOP es una forma de utilizar el paradigma imperativo para gestionar mejor los altos grados de complejidad mediante la creación de estructuras de datos "inteligentes" que modelan el dominio del problema. En un programa (estándar de procedimiento no orientado a objetos), tiene dos cosas básicas: variables y código que sabe qué hacer con ellas. El código toma información del usuario y de otras fuentes, la almacena en variables, opera en ella y produce datos de salida que van al usuario u otras ubicaciones.
La programación orientada a objetos es una forma de simplificar su programa tomando ese patrón básico y repitiéndolo en una escala más pequeña. Al igual que un programa es una gran colección de datos con código que sabe qué hacer con él, cada objeto es un pequeño dato vinculado al código que sabe qué hacer con él.
Al dividir el dominio del problema en partes más pequeñas y asegurarse de que la mayor cantidad de datos posible esté directamente relacionada con el código que sabe qué hacer con él, hace que sea mucho más fácil razonar sobre el proceso en su conjunto y también sobre el sub- problemas que componen el proceso.
Al agrupar los datos en clases de objetos, puede centralizar el código relacionado con esos datos, haciendo que el código relevante sea más fácil de encontrar y de depurar. Y al encapsular los datos detrás de los especificadores de acceso y solo acceder a ellos a través de métodos (o propiedades, si su idioma los admite), reduce en gran medida el potencial de corrupción de datos o la violación de invariantes.
Y al usar la herencia y el polimorfismo, puede reutilizar clases preexistentes, personalizándolas para satisfacer sus necesidades específicas, sin tener que modificar los originales o reescribir todo desde cero. (Lo cual es algo que nunca debe hacer , si puede evitarlo). Solo tenga cuidado de comprender su objeto base, o podría terminar con canguros asesinos .
Para mí, estos son los principios fundamentales de la programación orientada a objetos: gestión de la complejidad, centralización del código y modelado mejorado del dominio de problemas mediante la creación de clases de objetos, herencia y polimorfismo, y una mayor seguridad sin sacrificar el poder o el control mediante el uso de encapsulación y propiedades. Espero que esto te ayude a entender por qué tantos programadores lo encuentran útil.
EDITAR: en respuesta a la pregunta de Joel en los comentarios,
Un pequeño descargo de responsabilidad aquí. Mi modelo de "un programa orientado a objetos" es básicamente el modelo Delphi, que es muy similar al modelo C # /. NET ya que fueron creados por ex miembros del equipo de Delphi. Lo que digo aquí puede no aplicarse, o no aplicarse tanto, en otros idiomas OO.
Un programa orientado a objetos es aquel en el que toda la lógica está estructurada en torno a objetos. Por supuesto, esto tiene que ser arrancado en alguna parte. Su programa típico de Delphi contiene un código de inicialización que crea un objeto singleton llamado
Application
. Al comienzo del programa, llamaApplication.Initialize
, luego llama aApplication.CreateForm
cada formulario que desea cargar en la memoria desde el principio, y luegoApplication.Run,
muestra el formulario principal en la pantalla e inicia el ciclo de entrada / evento que forma el núcleo de cualquier Programas informáticos interactivos.La aplicación y sus formularios sondean los eventos entrantes del sistema operativo y los traducen en llamadas a métodos en su objeto. Una cosa que es muy común es el uso de controladores de eventos, o "delegados" en .NET-speak. Un objeto tiene un método que dice "haz X e Y, pero también verifica si este controlador de eventos en particular está asignado y llámalo si es así". Un controlador de eventos es un puntero de método, un cierre muy simple que contiene una referencia al método y una referencia a la instancia del objeto, que se utiliza para extender el comportamiento de los objetos. Por ejemplo, si tengo un objeto de botón en mi formulario, personalizo su comportamiento adjuntando un controlador de eventos OnClick, lo que hace que algún otro objeto ejecute un método cuando se hace clic en el botón.
Por lo tanto, en un programa orientado a objetos, la mayor parte del trabajo se realiza definiendo objetos con ciertas responsabilidades y vinculándolos, ya sea a través de punteros de método o mediante un objeto que llama directamente a un método definido en la interfaz pública de otro objeto. (Y ahora volvemos a la encapsulación). Esta es una idea de la que no tenía idea antes de tomar clases de OOP en la universidad.
fuente
Creo que OOP es básicamente un nombre dado a algo que tal vez te sentiste tentado a hacer en el camino, como yo lo hice.
Hace mucho tiempo, cuando era un programador de bebés, incluso en Fortran, había algo así como un puntero a una subrutina. Es realmente útil poder pasar un puntero a una subrutina como argumento a otra subrutina.
Entonces, lo siguiente que sería realmente útil sería almacenar un puntero a una subrutina dentro de un registro de una estructura de datos. De esa manera, podría decir que el registro "sabe" cómo hacer operaciones en sí mismo.
No estoy seguro de si alguna vez construyeron eso en Fortran, pero es fácil de hacer en C y sus descendientes.
Entonces, debajo, es una idea simple y útil que podría haber tenido la tentación de hacerlo usted mismo, y es más fácil de hacer en idiomas más recientes, incluso si algunas personas lo convirtieron en un carro gigante lleno de palabras de moda aterradoras.
fuente
Hay varios tipos de sistemas OO, y es difícil obtener una definición en la que todos estén de acuerdo. En lugar de intentar mostrar cómo el OO de Java es similar al Common Lisp Object System, comenzaré con algo más convencional, paso a paso.
Suponga que tiene muchos objetos existentes como datos dispersos. Los puntos, por ejemplo, pueden ser elementos en una matriz X, Y y Z. Con el fin de tener en cuenta un punto en sí, tiene sentido para tirar todos los datos juntos en algo así como un C
struct
.Ahora, para cualquier objeto de datos, tenemos todos los datos juntos. Sin embargo, en un programa de procedimiento, el código está disperso. Supongamos que estamos tratando con formas geométricas. Hay una gran función para dibujar formas, y necesita conocer todas las formas. Hay una gran función para encontrar el área y otra para el perímetro. El código para un círculo está disperso a través de múltiples funciones, y para agregar otro tipo de forma necesitamos saber qué funciones cambiar. En un sistema orientado a objetos, reunimos las funciones en el mismo tipo de cosas (
class
) que los datos. Por lo tanto, si queremos ver todo el código del círculo, está allí en laCircle
definición, y si queremos agregar unoQuartercircle
simplemente escribimos su clase y tenemos el código.Un beneficio adicional de esto es que podemos mantener invariantes de clase, cosas que son ciertas acerca de cada miembro de la clase. Al restringir el código fuera de la clase para que no se meta directamente con los miembros de datos de la clase, tenemos todo el código que puede cambiar los datos de la clase en un solo lugar, y podemos confirmar que no hace nada mal (como tener un triángulo con una pata) más largo que los otros dos combinados). Esto significa que podemos contar con algunas propiedades de cada miembro de la clase, y no tenemos que verificar si un objeto está sano cada vez que lo usamos.
El principal beneficio viene con la herencia y el polimorfismo. Al definir todas estas formas diversas como subclases de una clase llamada
Shape
, podemos hacer que nuestro código manipuleShape
s, y es el trabajo de los subobjetos de forma hacer lo que las manipulaciones exijan. Esto significa que no necesitamos tocar el antiguo código probado cuando agregamos nuevas formas o refinamos el comportamiento de las más antiguas. Tenemos automáticamente un código antiguo que puede aprovechar directamente el nuevo código. En lugar de hacer que el código de control sea consciente de todas las diferentes formas posibles, y tener que mantener funciones que sean conscientes de todas las diferentes formas posibles, simplemente nos ocupamos de las formas y sus propiedades, mientras mantenemosShape
subclases. Esto simplifica el código de control.Tenemos varias ventajas aquí. Como tenemos invariantes de clase, podemos razonar sobre objetos de datos más grandes de la misma manera que razonamos sobre tipos incorporados, lo que significa que a menudo podemos dividir conceptos complejos en otros más simples. Dado que el código del círculo está contenido en gran parte
Circle
, hemos aumentado la localidad. Como no hay conceptos de un círculo disperso a través de varias funciones diferentes en diferentes lugares, obtenemos menos acoplamiento entre las rutinas y no tenemos que preocuparnos por mantenerlas sincronizadas. Como las clases son, en efecto, tipos, podemos aprovechar el sistema de tipos existente para detectar el uso incompatible de nuestras clases.fuente
OO tiene muchas definiciones diferentes, sí. Estoy seguro de que puede encontrar muchos de estos por su cuenta. Personalmente, me gusta Rees Re: OO como una forma de darles sentido. Supongo que ya lo has leído desde que citas a Paul Graham. (Se lo recomiendo a cualquier persona interesada en OO). Voy a adoptar más o menos la definición de Java aquí {1,2,3,7,8,9}.
La cuestión de la utilidad de OO, especialmente la forma en que lo abordo, merece una respuesta mucho más amplia con unos pocos miles de líneas de código (en parte para no ser solo un montón de afirmaciones). Sin embargo, aquí hay un resumen de ese documento hipotético.
No creo que OO sea terriblemente útil a pequeña escala, digamos, unos pocos cientos de líneas. En particular, los lenguajes OO sin buenas influencias funcionales tienden a hacer que sea realmente doloroso hacer cosas simples con cualquier tipo de colección o cualquier cosa que necesite muchos tipos de datos. Aquí es donde entran en juego la mayoría de los patrones de diseño; son curitas en el bajo poder del lenguaje subyacente .
Alrededor de mil líneas, comienza a ser más difícil hacer un seguimiento de todas las operaciones y estructuras de datos y cómo se relacionan. Es útil, en este punto, tener una forma de organizar explícitamente las estructuras y operaciones de datos, dibujar los límites del módulo y definir responsabilidades, y tener una manera conveniente de comprender esas definiciones mientras intentas programar contra ellas.
Java-ish OO es una solución intermedia para estos problemas que han ganado el concurso de popularidad. Debido a que es el mismo mecanismo que las personas de Java aplican a los problemas a pequeña escala creados por un lenguaje poco potente, tiende a comenzar a parecerse más a una solución mágica para todo que a una forma de mantenerse organizado. Las personas familiarizadas con la programación funcional tienden a preferir otras soluciones, como CLOS o las clases de tipos de Haskell, o la metaprogramación de plantillas cuando están atrapados en C ++, o bien (como yo, trabajando a diario en C #) usan OO pero simplemente no se entusiasman tanto. .
fuente
OOP intenta modelar conceptos del mundo real en términos de objetos e interacciones entre ellos. Como humanos, tendemos a procesar el mundo en términos de objetos. El mundo está lleno de objetos que tienen ciertas propiedades y pueden hacer cosas como interactuar con otros objetos. OOP permite modelar el mundo en términos similares. Por ejemplo,
Pero un automóvil no puede moverse solo, necesita una persona para conducirlo: interacción entre objetos.
fuente
OOP = estructuras de datos + paso de mensajes + herencia, todas las cuales son evoluciones lógicas en modelos de programación.
OOP puede ser entendido (por los programadores) en aproximadamente 90 segundos (ver mi perfil para un enlace). Los conceptos son muy simples.
Cómo aplicarlo es otra cuestión. El hecho de que sepa cómo golpear un martillo no significa que sepa cómo diseñar y construir una casa. ;-)
fuente
Escribí una publicación de blog hace un tiempo que podría ser útil: Explicación de procedimientos frente a OOP .
fuente
La forma en que lo entendí por primera vez es:
Antes de la programación orientada a objetos, tenía una programación estructurada . Todo se centra en el proceso. La primera pregunta que debes hacerte es " ¿Qué quiero hacer con la información? ".
Con la programación orientada a objetos, se centra en los datos. La primera pregunta que debes hacerte es "¿Con qué información de brujas tengo que lidiar? ". Esto facilita la abstracción.
fuente
Dado que comprende las estructuras, y comprende los punteros de función, y comprende las estructuras con punteros de función, desde su perspectiva, definiría la programación orientada a objetos simplemente como "programación, con un uso intensivo de estructuras que tienen punteros de función". Todavía está programando en el sentido tradicional: son todos datos y códigos que actúan sobre los datos. La diferencia es simplemente cómo se define toda esa información y cómo se enfoca en definirla.
Quizás una simplificación excesiva es que la programación tradicional es "código, con algunas estructuras de datos", y la programación orientada a objetos es "estructuras de datos, con algún código". Ambos todavía tienen estructuras de datos, y ambos todavía tienen código. La programación orientada a objetos, entonces, no es más que el acto de definir tipos de datos por adelantado, y hacer cumplir los contratos de cómo se comunican a través de conjuntos de funciones.
Como ha observado, existe una gran clase de aplicaciones para las cuales esta no es una excelente manera de implementar una solución. Parece que vives en un mundo compuesto principalmente por tales aplicaciones. En su publicación de blog, menciona mirar implementaciones del problema "99 botellas de cerveza" (su "escaparate de programación favorito"). 99 botellas de cerveza son ciertamente parte de esa categoría. Tratar de comprender la programación orientada a objetos mirando las implementaciones de 99 botellas de cerveza es un poco como tratar de entender la arquitectura de gran altura mirando una casa en el árbol. Incluso una casa en el árbol muy bien construida solo puede enseñarte mucho.
TL; DR: la programación OO es como la programación tradicional, excepto que enfoca más su esfuerzo en definir las estructuras de datos por adelantado, y tiene esas estructuras de datos que se comunican entre sí a través de punteros de función.
fuente
Creo que la página de Wikipedia es un buen lugar para obtener los fundamentos:
http://en.wikipedia.org/wiki/Object-oriented_programming
Básicamente, la idea es que la programación de procedimientos, que es lo que OOP estaba tratando de mejorar, se centró en los procesos que se están modelando. OOP cambia a un modelo donde el foco está en las "cosas" que está modelando, y los procesos y datos de esas cosas están contenidos dentro de esas cosas.
Entonces, como ejemplo, digamos que estaba diseñando una aplicación para rastrear una lista de tareas. En la programación de procedimientos, sus entidades de nivel superior en el modelo serían los procesos que ocurren, como crear una tarea, eliminar una tarea, cambiar la información de la tarea, etc. En un modelo OOP, en su lugar, se centraría en crear una Tarea, y Piense de qué datos y procesos debe ser responsable esa Tarea. Y luego concéntrese en con qué otros objetos debe interactuar la Tarea, como posiblemente una Nota o algo si desea mantener notas sobre Tareas.
Espero que eso ayude. Simplemente siga leyendo y mirando el código y de repente "hará clic". Esa fue mi experiencia.
fuente