¿Cuál es un proceso simple para diseñar un sistema OOP antes de codificarlo?


10

Cada vez que se me exigía construir un proyecto, siempre lo lograba, no de antemano ideando un plan o diseño, sino después de escribir primero una clase que era necesaria, desarrollar todo el proyecto, construir de abajo hacia arriba. Ahora sé que esta no es la forma correcta de crear software, pero no es fácil para mí entender lo que se llama Análisis y Diseño Orientado a Objetos. Puedo entender más fácilmente el diseño de procedimientos de arriba hacia abajo, ya que consiste simplemente en dividir las tareas en subtareas, cosas que tienen su contraparte en el código, funciones. Pero no puedo entender fácilmente el Análisis y el Diseño Orientado a Objetos, ya que no entiendo cómo uno puede saber qué clases necesitarán y cómo interactuarán, a menos que sepan cómo las codificarán.

Una vez que introducimos el concepto de clases y objetos en el proceso de diseño, ya no podemos diseñar de arriba hacia abajo, porque ya no estamos desglosando nuestros problemas en aquellas cosas que pueden implementarse como procedimientos. En cambio, de acuerdo con lo que he leído sobre el tema, debemos determinar qué clases son necesarias y crear varios artefactos en el Lenguaje de modelado unificado, que luego podemos usar cuando implementamos el software. Pero este tipo de proceso de diseño no lo entiendo. ¿Cómo se sabe qué clases necesitarán y cómo interactuarán, a menos que ya hayan concebido todo el sistema?

Este es mi problema. No entiendo cómo diseñar un sistema orientado a objetos, aunque sí entiendo los conceptos de programación orientada a objetos, y puedo usar esos conceptos en cualquier lenguaje de programación orientado a objetos que conozca. Por lo tanto, necesito que alguien me explique qué proceso simple puedo usar para diseñar sistemas orientados a objetos de una manera que tenga sentido para mí.


8
"Ahora sé que esta no es la forma correcta de crear software" , ¿quién te dijo esto? Parece que de alguna manera caes en la trampa popular de creer "el diseño es algo que haces antes de codificar, tal vez dibujando diagramas UML sofisticados". Para curarlo de este error, le recomiendo comenzar con "Code as Design" de Jack Reeves.
Doc Brown


@DocBrown. ¿No crees que el diseño mientras se codifica es lo que hace que nuestro trabajo sea tan artesanal? No me puedo imaginar otras ingenierías trabajando igual. Imagine a un arquitecto llenando ladrillos y mortero y diseñando el edificio / puente en el camino.
Laiv

55
@Laiv: la "codificación" es parte de lo que en otras disciplinas de ingeniería se llama diseño. En la construcción de viviendas, el paso desde el diseño hasta el producto final se realiza utilizando ladrillos de relleno y mortero. En la programación, el compilador realiza este paso al traducir el diseño (= programa) al producto final (= binario ejecutable). Y eso no es una nueva sabiduría. Los ensayos de Reeves tienen 25 años.
Doc Brown

@DocBrown, ¿el desarrollador * ya no está curado? El botón de suscripción está roto, por ejemplo.
radarbob

Respuestas:


20

De arriba hacia abajo, el estilo de cascada OOAD no garantiza que el código que escriba esté orientado a objetos en absoluto. He visto montañas de código estrictamente producido por OOAD que lo demuestra. Si OO te está confundiendo, no busques ayuda aquí. No lo encontrarás. OO NO requiere que diseñe de arriba hacia abajo.

Si te gusta codificar en una clase, que así sea. Déjame decirte una pista. Aplazar.

Es sorprendente lo fácil que es diseñar clases escribiendo código que las usa incluso cuando aún no existen. Olvídate del procedimiento. Olvídate de la estructura. Simplemente consiga un buen nivel constante de abstracción y manténgalo. No cedas a la tentación y mezcla detalles adicionales en ella. Cualquier cosa que lo saque de la abstracción actual puede hacerse en algún método que podría estar en algún otro objeto que de alguna manera sepa lo que necesita saber. No construyas nada que solo puedas pedir que te entreguemos.

Aprende a escribir así y verás que estás haciendo OO sin siquiera esforzarte mucho. Esto lo obliga a mirar sus objetos desde el punto de vista de cómo se usan (su interfaz) y qué objetos saben sobre qué otros objetos. ¿Adivina cuáles son los dos puntos principales de los diagramas UML?

Si puedes entrar en ese modo de pensar, entonces lo que queda es arquitectura. Todos todavía estamos descubriendo eso. Desde MVC hasta arquitectura limpia y diseño impulsado por dominio. Estudiarlos y jugar. Usa lo que funciona. Si encuentra algo 100% confiable, vuelva y avíseme. He estado haciendo esto durante décadas y todavía estoy buscando.


2
O te encuentras sin hacer OO y, sin embargo, todo "de alguna manera" funciona bien de todos modos ...
Derek Elkins dejó SE

2
"Es sorprendente lo fácil que es diseñar clases escribiendo código que las usa incluso cuando aún no existen" . A esto lo llamo diseño de arriba hacia abajo, pero parece que estoy equivocado. ¿Qué es el diseño de arriba hacia abajo y qué es lo que llamé así? ¿Está programando para una interfaz?
Piovezan

No es simplemente de arriba hacia abajo. También debe estar dispuesto a no construir cosas que solo puede pedir aceptando parámetros.
candied_orange

@Piovezan puedes hacer esto incluso cuando la interfaz aún no existe. Simplemente ignore su compilador por un momento. Más tarde, lo harás existir.
candied_orange

@CandiedOrange "También debes estar dispuesto a no construir cosas que solo puedes pedir aceptando parámetros". - No estoy seguro de entender, ¿podría aclarar / proporcionar un breve ejemplo (o un contraejemplo para el caso)?
Piovezan

4

Afirma que puede usar técnicas orientadas a objetos en su código, por lo que ya sabe cómo diseñar un sistema orientado a objetos , creo que su problema es más una cuestión de cuándo , no si puede o no. Parece cómodo con el diseño orientado a objetos de forma iterativa a corto plazo, en lugar de una planificación a largo plazo.

Cuando se desarrolla un proyecto por primera vez, puede ser muy difícil planificar y diseñar, entonces es cuando se favorece el desarrollo ágil sobre el desarrollo en cascada , ya que el gran alcance de un plan en cascada a menudo no capturará todas las complejidades de un proyecto de software.

Usted afirma que desarrollar sobre la marcha sin un "plan inicial" es:

"... no es la forma correcta de crear software ..."

Si su problema es que su plan inicial no está lo suficientemente detallado, tómese un poco más de tiempo para explicar sus primeros pensamientos. ¿Cuál es la primera parte del programa que planeas escribir? ¿Qué va a necesitar ? Quizás ni siquiera piense en qué objetos comenzar, sino piense en qué características y planifique desde allí.

Si su problema es que no confía en sus habilidades de documentación / diseño / UML , practique documentando un proyecto existente.

Personalmente, recomendaría no preocuparse de que sus diseños estén perfectamente orientados a objetos, la mayoría de los sistemas no están 100% orientados a objetos. El objetivo es crear una mejor comprensión y visualización del sistema, no una abstracción perfecta. La orientación a objetos no es la bala de plata, es solo otra herramienta en el cinturón.


También quería mencionar, aunque un poco fuera de tema para la respuesta ... ¡Tus planes no necesitan ser muy grandes! A veces, un plan es solo una cuestión de "Quiero ejecutarlo y hace algo". Eso es lo suficientemente bueno, si eso es realmente todo lo que va a hacer.
Erdrik Ironrose

2

OOAD es una utopía. Con eso no quiero decir que sea el mejor enfoque, quiero decir que nunca es realmente posible en mi humilde opinión. En mi experiencia, siempre cambia algo, ya sean requisitos o detalles, o incluso un conflicto de dependencia que te obliga a reemplazar una dependencia por completo. Ya sea porque aprendí de esta manera o porque es lo que me resulta más natural, mis ideas para el diseño surgen más fácilmente mientras escribo código. Si estoy a punto de codificar y no tengo una idea clara de cómo estructuraré el código, haré un punto para dedicar tiempo a comprender realmente el problema primero, aunque la mayoría de las veces, veo el necesidad para una clase y la lograré.

Mi consejo sería que lo mejor que puede hacer por usted mismo es el código usando fachadas , que proporciona una interfaz simple para entrada y salida, y espero que las entradas y salidas no cambien con frecuencia. Aunque incluso si lo hacen, sepan que no es un problema de diseño sino un problema de especificaciones (cambio de necesidad / operación / funcionalidad). Esto hará que su programa sea algo resistente a los problemas que resuenan dentro de su programa hacia aquellos que llaman a su programa o sección de código y viceversa.

En lo que respecta al diseño de un sistema orientado a objetos, debe decirse algo para tratar de hacer que todo esté orientado a objetos cuando no debería serlo. Ese es un error común entre los lenguajes de programación OOP como C # y Java es tratar de tratar todo como un objeto, lo que a menudo resulta en la creación de una sola instancia de una clase para realizar lo que de otro modo serían métodos estáticos que no cambian el estado en absoluto. Dicho esto, por supuesto, debe usar el diseño OOP cuando corresponda, aunque no sienta que lo está haciendo mal cuando se siente más natural escribir un método estático. No siempre es el instinto equivocado.

Debería considerar usar una clase cuando responda sí a cualquiera de las siguientes preguntas:

  • ¿Tengo un grupo de información que pertenece al mismo concepto (es decir, nombre, apellido, dirección)?
  • ¿Necesito realizar una operación que requiera varios datos (es decir calculatePrice(basePrice, quantity, tax))?
  • ¿Tengo un else si con bloques de código grandes que realizan operaciones ligeramente diferentes con la misma información o similar (es decir if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak())
  • ¿Tengo una clase existente que realiza más de una tarea específica y está creciendo demasiado?

Después de un tiempo, se convertirá en una segunda naturaleza para crear clases. No tenga miedo de usarlos si su código cae en uno de los casos anteriores. ¡Espero que eso ayude!


2

Creo que los puntos que hizo Doc Brown en los comentarios merecen mucha más visibilidad que un comentario, ya que tiene toda la razón:

" Ahora sé que esta no es la forma correcta de crear software ", ¿quién te dijo esto? Parece que de alguna manera caes en la trampa popular de creer "el diseño es algo que haces antes de codificar, tal vez dibujando diagramas UML sofisticados". Para curarlo de este error, le recomiendo comenzar con "Code as Design" de Jack Reeves. - Doc Brown 21 de junio a las 5:27

@Laiv: la "codificación" es parte de lo que en otras disciplinas de ingeniería se llama diseño. En la construcción de viviendas, el paso desde el diseño hasta el producto final se realiza utilizando ladrillos de relleno y mortero. En la programación, el compilador realiza este paso al traducir el diseño (= programa) al producto final (= binario ejecutable). Y eso no es una nueva sabiduría. Los ensayos de Reeves tienen 25 años. - Doc Brown 21 de junio a las 6:39

Este mismo sentimiento también se repite en otros lugares. Considere las charlas de Glenn Vanderburg sobre "Ingeniería de software real" y, en cierta medida, sus charlas sobre "Artesanía, ingeniería y esencia de la programación" e "Ingeniería de artesanía y software". Considere también las páginas / discusiones WhatIsSoftwareDesign y TheSourceCodeIsTheDesign en el wiki de C2.

El concepto de que el código es el diseño no es específico de ningún paradigma. Se puede aplicar igualmente a objetos orientados, funcionales, procesales, lógicos o cualquier otra cosa. La idea subyacente es la misma: el diseño es el código fuente en sí. El acto de construcción es el proceso mediante el cual un intérprete o compilador convierte el código fuente (el diseño) en algo útil.

En un sistema complejo, es probable que exista un diseño arquitectónico de nivel superior: identificación de subsistemas, componentes, módulos, servicios y asignación de requisitos antes de comenzar a escribir código. Puede usar UML como una forma de crear, documentar y ayudar en las discusiones sobre este diseño arquitectónico. Considere la idea de los modos UML que Martin Fowler discute , particularmente UML como un boceto y UML como notas . Considere también algunas ideas de Modelado ágil: modelado de arquitectura inicial , modelado de iteración y modelos apenas suficientes .

Todo esto significa que la forma correcta de crear software no es desarrollar todo el proyecto. Es pasar el tiempo suficiente para comprender los requisitos más críticos (en el momento actual), identificar dependencias técnicas y compensaciones entre los requisitos, y luego aprovechar el hecho de que el software es flexible. También reconozca que el costo de tomar su diseño y producir algo es increíblemente bajo (especialmente en comparación con tomar un diseño y producir algo en muchas otras disciplinas de ingeniería). Por lo tanto, repita sus actividades de diseño (codificación) y aproveche lo fácil y económico que es construir o modificar progresivamente lo que ha hecho.


1

OOAD se trata de identificar entidades y modelar objetos o conceptos de la vida real en un grado de abstracción. Lo percibirá como más fácil si, en lugar de escribir clases, escriba interfaces al principio, ya que realmente no tiene que implementarlas aún, pero el código se compila.

OOAD no excluye la posibilidad de pensar en el sistema como módulos grandes. Aún puedes hacer eso. Cada módulo existe para satisfacer un conjunto de historias de usuarios (casos de uso). Tales historias de usuario necesitan clases que colaboren para cumplirlas.

Una diferencia clave entre los enfoques procesales y OO es que, por lo general, el pensamiento procesal asigna los requisitos a las pantallas, mientras que OOD tiende a pensar en lo que sucede debajo del capó, dejando que el front-end sea realizado por otra persona o no.

Hay una técnica en Extreme Programming llamada CRC Cards . CRC significa "responsabilidades de clase-colaboradores".

Básicamente, identifica las clases evidentes y asigna una tarjeta a cada una. Digamos que la clase Invoicetiene su propia tarjeta.

Para cada clase de tenencia de cartas, usted escribe cuáles serían las responsabilidades de esa clase, por ejemplo, "calcula un gran total" .

También para cada clase de tarjeta, usted escribe qué otras clases tiene que pedir esa clase para cumplir con sus propias responsabilidades. Aquí puede descubrir que Invoicenecesita la colaboración InvoiceDetailo incluso descubrir que tal clase es necesaria en primer lugar.

Puede descubrir que algunas responsabilidades a las que creía pertenecer Invoce, realmente pertenecen a uno de sus colaboradores.

Después del ejercicio, cada tarjeta se convierte en una clase, cada responsabilidad se convierte en un método y cada relación de colaboración puede convertirse en una composición, una agregación o una simple llamada.

Ese ejercicio puede (y debe) realizarse en un grupo, donde incluso los empresarios participan.

Puede obtener más información sobre esta técnica en estos enlaces:

http://en.wikipedia.org/wiki/Class-responILITY-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

Ejemplos de tarjetas CRC:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí


0

El desafío principal para nosotros, como comunidad de profesionales del software; Más específicamente, los profesionales del diseño orientado a objetos, es el de materializar todos nuestros problemas / tareas en un software de programación. Ya se trate de tareas , representadas como funciones o sean actores de las tareas, representadas como interfaces / clases [dirigiéndose hacia OOAD]. A medida que evolucionamos nuestros hábitos de diseño de software, al obtener continuamente conocimiento sobre diversas metodologías / marcos. Nuestro punto de vista se refina cada vez más hacia una segregación clara de los objetos y qué objeto desempeñaría qué función.

En cuanto a dividir sus problemas en subproblemas con la presencia de objetos alrededor, aún puede hacerlo convenientemente, ya que USTED tiene el control total de qué objetos desea que estén presentes. También tiene la conveniencia de impartir naturaleza y propósito a sus objetos e interfaces. Todo lo que tiene que hacer es visualizar el enunciado del problema y pensar qué propósito / funcionalidad se puede impartir sobre qué objeto.

Trataré de explicar más adelante con la ayuda de un ejemplo de la gama de automóviles y resaltaré dos formas diferentes de visualizar el mismo modelo de objeto.

Tomemos un ejemplo del fabricante de automóviles que abarca varias categorías de automóviles: vehículos comerciales, automóviles de consumo (sedanes, hatchback, camionetas), etc.

Para que el fabricante tenga claramente una separación de categoría y propósito, existen múltiples formas con las que pueden crear sus clases.

Fabricante de vehículos OOAD

  1. Según la categoría (sector del mercado) del vehículo: vehículo pesado, vehículo de consumo [sedán, hatchback, camioneta, etc.]

  2. Según la capacidad del motor y la forma de conducir: 800-1500 CC,> 1500 CC, etc.

Siguiendo la mejor manera en que el fabricante puede impartir funciones individualmente a los objetos que pertenecen a cada una de estas clasificaciones, puede elegir un diseño de objeto subyacente apropiado y construir su modelo encima.


Empiezas bien, pero luego el último aspecto parece la falacia de que OOD se trata de clasificar las cosas en lugar de agrupar comportamientos similares.
Pete Kirkham
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.