it-swarm-es.com

Ventajas de la programación orientada a objetos.

Nota : esta pregunta es un extracto editado de un publicación de blog que escribí hace unos meses. Después de colocar un enlace al blog en un comentario en Programmers.SE alguien solicitó que publique una pregunta aquí para que puedan responderla. Esta publicación es la más popular, ya que las personas parecen escribir "No obtengo programación orientada a objetos" en Google ¡mucho. 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?

35
Joel J. Adamson

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 lo más posible para reducir los efectos indeseables entre ellas, se hacen muchas suposiciones sobre la condición de los componentes que se encuentran 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; así, las operaciones a realizar 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 que se espera realizar, pero deja los detalles de los pasos a la máquina específica del componente para que la maneje.

En cuanto a las ventajas de la orientación a objetos sobre el software no orientado a objetos:

  • comportamiento específico del componente - haciendo que los detalles sobre cómo manejar un componente en particular, la responsabilidad de la máquina más pequeña específica del componente garantiza que cada vez que se maneje ese componente, su máquina lo hará de manera apropiada;
  • expresiones polimórficas - debido a que las máquinas específicas del componente realizan operaciones adaptadas a su componente particular, el mismo mensaje enviado a diferentes máquinas puede actuar de manera diferente;
  • abstracción de tipo - a menudo tiene sentido que varios tipos diferentes de componentes utilicen el mismo vocabulario para las operaciones que realizan sus máquinas;
  • separación de preocupaciones - dejar detalles específicos del componente en sus máquinas significa que la máquina de proceso solo necesita manejar las preocupaciones más generales y más grandes de su proceso y los datos necesarios para administrarlo; Además, es menos probable que se vea afectado por cambios en otros componentes;
  • adaptabilidad - los componentes que se centran en su área de especialidad se pueden adaptar al uso imprevisto simplemente cambiando los componentes que usa, o poniéndolos a disposición de otra máquina de proceso;
  • reutilización de código - los componentes con un enfoque limitado y una mayor adaptabilidad pueden aprovechar su costo de desarrollo si se utilizan con más frecuencia.
7
Huperniketes

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 usar 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 (no objeto de procedimiento estándar orientado al programa), 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 va al usuario u otras ubicaciones diferentes.

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, se hace 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 un cosa que nunca deberías hacer , si puedes evitarlo. Solo ten cuidado de entender tu objeto base, o podrías terminar con canguros asesinos .

Para mí, estos son los principios fundamentales de la programación orientada a objetos: gestión de complejidad, centralización de 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,

¿Puede explicar qué contiene un "programa orientado a objetos" (aparte de estas definiciones elegantes que ha esbozado) que es fundamentalmente diferente de un programa imperativo? ¿Cómo "haces rodar la pelota"?

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, llama a Application.Initialize, luego una llamada a Application.CreateForm para cada formulario que desee cargar en la memoria desde el principio, y luego Application.Run, que muestra el formulario principal en la pantalla e inicia el ciclo de entrada/evento que forma el núcleo de cualquier programa informático interactivo.

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 OOP clases en la universidad.

46
Mason Wheeler

Creo que OOP es básicamente solo un nombre dado a algo que puede haber estado tentado de hacer en el camino, como yo lo estaba.

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 forma, 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.

6
Mike Dunlavey

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 tratar de mostrar cómo Java OO es similar al Común Sistema de objetos LISP, 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. Para considerar un punto en sí mismo, tiene sentido juntar todos los datos en algo así como una 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 la definición Circle, y si queremos agregar un Quartercircle 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 diferentes como subclases de una clase llamada Shape, podemos hacer que nuestro código manipule Shapes, y es el trabajo de los subobjetos de formas 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 código antiguo que puede aprovechar directamente el código nuevo. 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 mantenemos las subclases Shape. 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 en 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.

5
David Thornley

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 Java definición 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 mayor 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 cientos de líneas. En particular, OO idiomas sin buenas influencias funcionales tienden para 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 la baja potencia del subyacente idioma .

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 ha ganado el concurso de popularidad. Porque es el mismo mecanismo que Java personas se aplican a los pequeños problemas de 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 atascado en C++, o bien (como yo, trabajando diariamente en C #) use OO pero simplemente no se entusiasme tanto por eso).

3
Jesse Millikan

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. ;-)

1
Steven A. Lowe

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,

  • La persona es un objeto. Una persona tiene algunas propiedades, como la edad y el género. Una persona puede hacer cosas: comer, dormir, conducir un automóvil.
  • El automóvil también es un objeto (aunque de diferente tipo). También tiene propiedades como marca, modelo y año. Un automóvil puede hacer cosas: moverse.

Pero un automóvil no puede moverse solo, necesita una persona para conducirlo: interacción entre objetos.

1
ysolik

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 como simplemente "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: OO la programación 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 comunicándose entre sí a través de punteros de función.

0
Bryan Oakley

La forma en que lo entendí por primera vez es:

Antes de la programación orientada a objetos, tenías 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 " ¿Qué información de bruja debo tratar? ". Esto facilita la abstracción.

0
DavRob60

Escribí una publicación de blog hace un tiempo que podría ser útil: Procedimiento vs. OOP Explicado .

0
VirtuosiMedia