2009-01-13 18 views
5

Estoy leyendo mucho sobre las buenas y malas prácticas en el diseño de OOP. Es bueno saber que tu diseño es malo o bueno. ¿Pero cómo se obtiene del diseño malo al bueno? He dividido la interfaz (xaml) y el código detrás de la clase businesslogic principal. Esa última clase está creciendo a lo grande. Intenté dividirlo en clases más pequeñas, pero ahora estoy estancado. ¿Alguna idea sobre cómo dividir clases grandes? La clase principal tiene 1 lista de datos de diferentes tipos. Estoy haciendo cálculos sobre el total, pero también sobre los tipos individuales. Tengo métodos para realizar estos cálculos que se invocan desde eventos manejados en el código subyacente. ¿Alguna idea de dónde ir desde aquí?¿Cómo pasar de malo a buen diseño OOP?

Información adicional:

Ya estamos cerca de 6 meses en este proyecto. He trabajado con lenguajes orientados a objetos durante años (primero C++, java y ahora C#), pero nunca en un proyecto grande como este. Creo que al principio hemos dado algunos giros equivocados y creo que debemos corregirlos. No puedo especificar ningún detalle sobre este proyecto en este momento. Voy a pedir uno o dos libros sobre diseño. Si separé todas las clases, ¿cómo las vuelvo a unir? ¿Tal vez sea mejor continuar de esta manera hasta la primera versión y reconstruir partes después de eso, para una segunda versión?

Respuesta

2

La clase principal tiene 1 lista de datos de diferentes tipos. Estoy haciendo cálculos en el total, pero también en los tipos individuales. Tengo los métodos para realizar estos cálculos que se llaman desde eventos manejados en el código detrás. ¿Alguna idea de dónde ir desde aquí?

Si hay muchos cálculos basados ​​en el contenido de la lista, ¿ha considerado mover las operaciones a una clase de lista personalizada? Lo mismo ocurre con las operaciones en los tipos específicos, ¿quizás podrían vivir dentro de los tipos?

En términos de realizar operaciones similares pero diferentes en diferentes tipos, considere usar el state pattern (vea esto como un reemplazo para declaraciones de interruptor) que le permite tratar las entidades de manera uniforme.

Una gran cantidad de OOP se trata de tirar un enfoque de "arriba hacia abajo"/microgestión y teniendo en cuenta un enfoque de "abajo hacia arriba"/autosuficiencia. Vale la pena recordar que ninguno de los enfoques es "correcto" de forma aislada. Crear un código que se pueda mantener se trata de encontrar un equilibrio sensato que requiera mucha reflexión y, por lo general, se desarrolla a través de la experiencia.

+0

Me gusta la idea de mover la lista a una clase de lista. Tengo que mirar en el patrón de estado. – Sorskoot

10

Practica y lee. Repetir :)

Algunos libros recomendados:

  • código limpio por Robert C. Martin
  • GoF Design Patterns
  • Refactoring por Martin Fowler

Personalmente también les gustó Head First Design Patterns , pero el estilo puede no ser para todos. Hay un libro similar llamado C# 3.0 Design Patterns (vea ora.com). Tiene muchas de las mismas cosas, pero de una manera más tradicional.

+0

Un + adicional para la refactorización. Si no hace nada más, memorice el capítulo 3 - huele mal el código - y comprenda las razones detrás de ellos. El solo hecho de entender los principios detrás de estos "olores" ayudará a su código OO más que cualquier otro capítulo que haya leído. –

+0

Estoy de acuerdo, saber cómo identificar los olores de códigos es muy valioso. –

4

Recomiendo encarecidamente recoger Code Complete. Es un gran libro que ofrece toneladas de buenos consejos sobre preguntas como la tuya.

Para darle una respuesta rápida a su pregunta sobre cómo dividir clases grandes, esta es una buena regla general: haga que su clase sea responsable de una cosa, y una sola cosa. Cuando empiezas a pensar así, puedes identificar rápidamente el código que no pertenece. Si algo no le pertenece, factorícelo en una nueva clase y úselo de su clase original.

Editar: Lleva ese pensamiento al nivel de "método" también, haz que tus métodos sean responsables de una cosa, y una sola cosa. Ayuda a descomponer los métodos grandes (> 50 líneas) muy rápidamente en trozos de código reutilizables.

+0

La división de responsabilidades es lo que quiero, pero tengo tantos métodos que dependen de cada uno. Métodos pequeños, con la excepción de unos pocos +/- 50 liners las 10 líneas o menos. – Sorskoot

+0

¿Puedes agrupar esos pequeños métodos en varias categorías? –

+0

Sí. Intenté ubicarlos en clases propias, pero como todos comparten y trabajan en la misma lista, es difícil separarlos. Incluso nombré los métodos para las categorías allí, así que sé para qué están mirando sus nombres. – Sorskoot

2

Refactoring por Martin Fowler es un excelente libro sobre cómo cambiar el diseño de su software sin romperlo.

Design Patterns funciona de manera similar a los algoritmos pero le indica cómo combinar objetos para realizar varias tareas útiles.

Finalmente, Martin Fowler tiene una variedad de patrones de diseño útiles para las aplicaciones. Por ejemplo Passive View

1

me encontré con que trabajar en un complejo de 'asignación' sin ayuda y luego ver cómo alguien más lo hizo fue una gran experiencia de aprendizaje para mí.

Una asignación en particular fue la creación de un programa tipo banco donde tuvimos que rastrear las transacciones y poder calcular el interés ganado y cosas por el estilo. Realmente fue mi primer programa de OOP y realmente genial por su complejidad. Se vuelve demasiado confuso (para un principiante) para hacerlo en un estilo lineal sin cometer errores.

3

Cambie la forma de pensar sobre los objetos. Cada objeto debe tener una responsabilidad muy específica. Si tiene una clase llamada algo genérico, como "MainBusinessLogic", probablemente esté haciendo algo mal.

gran lugar para empezar: objeto de Lee David West Pensando.

+0

La redacción de "responsabilidad" es un poco ambigua. –

+0

El nombramiento de esa clase es una de las cosas que creo que hice bien.Es un sustantivo que explica de qué se trata, como Counter (en una tienda). – Sorskoot

+0

De todos los libros enumerados, Object Thinking es el más desafiante, puede tomar años dar sentido al mundo real ... – goofballLogic

3

Esto es solo una adición a algunas buenas sugerencias de libros aquí.

Cuanto mejor me pongo en OO, más parece reducir el tamaño del objeto. No es como si fuera para un objeto pequeño o algo por el estilo, pero parece estar sucediendo.

Manteniéndolas pequeñas, una sola responsabilidad, fáciles de usar y comprender, todas críticas. Cada objeto debe ser lo más cercano posible a las balas, verifique sus parámetros y nunca permita que su objeto se vuelva inválido. Definir claramente todos los estados válidos en la documentación.

Cada vez que crea una clase, cree una prueba para esa clase. No solo prueba tu código, sino que te obliga a consumir tu propio diseño. Siempre piense en su clase desde esa "Vista exterior". Asegúrate de que no estás pidiendo demasiado a la persona que usa tu clase y todo lo que le pidas debe documentarse en la interfaz. A menudo simplemente lanzo una entrada principal rápida a una clase si no hay un marco de prueba disponible; pone un ejemplo de cómo usar el código allí mismo en el mismo archivo.

En la codificación, casi todo mi tiempo lo paso tratando de descubrir qué hizo otra persona. Si fuera capaz de poner código usando API conocidas o bien documentadas, mi trabajo sería trivial y las programaciones serían significativamente más cortas.

El primer diseño puede ser difícil. Considere la capacidad de codificación como similar a la habilidad deportiva. La mayoría de nosotros juega en nuestras entradas, algunos juegan en equipos deportivos locales. Hacer un buen diseño inicial en un proyecto complicado es tarea de un jugador de la liga nacional, son uno en un millón. Acepta esto y planifica el cambio; las iteraciones son tu amigo. (Por cierto, la mayoría de nosotros PIENSA que estamos en el nivel estatal fácilmente. No lo somos).

+0

Perdón por nitpick pero ¿no te refieres a clases o tipos y no a objetos? –

+0

Sí, tengo un trastorno que me hace sustituir términos relacionados en conversaciones a veces. (Hmm, me pregunto si existe tal cosa. Si lo hay, de todos modos, lo tengo, y si no, debería llevar el nombre) –

3

Además de la recomendación de Brian de Código de limpieza de Robert C Martin, es posible que desee leer en "Uncle Bob's" SOLID Principles of Object Oriented Design.

Puede oírlo hablar sobre los Principios SÓLIDOS en Hanselminutes Podcast 145 y limpiar el código en .NET Rocks! Show #388. También hay más con él en .NET Rocks! Show #410, pero de lo que él habla no está realmente relacionado con su pregunta, simplemente lo incluí en caso de que disfrutara de los dos primeros.

De los tres podcasts preferí los Hanselminutes.

+0

Me encantan esos dos shows. Estoy escuchando .net Rocks # 410 en este momento :) – Sorskoot

0

Solo puedo decir lo que funciona para mí, y realmente no he encontrado a nadie que trabaje de la misma manera, así que no estoy seguro si eso te ayudará mucho.

Básicamente, mi enfoque es tener el menor número de clases posible, pero no menos.

Primero, la única vez que necesita guardar información es si la recibe en el momento A y la necesita en un momento posterior B. Si la obtiene y la trabaja al mismo tiempo, puede ser que no haya necesito almacenarlo

En segundo lugar, ¿qué haces con él? Si vas a iterar a través de él de ciertas maneras simplificadas, puedes pensar que es un conjunto de instrucciones y el programa que opera en él como un intérprete de un conjunto de instrucciones. En ese caso, es posible que desee diseñar realmente un conjunto de instrucciones de código de bytes, con un intérprete, y codificar su información en ese conjunto de instrucciones.

En tercer lugar, ¿con qué frecuencia cambia la información? Si parte de la información cambia con muy poca frecuencia, es posible que pueda usar una evaluación parcial (es decir, generación de código). Es decir, toma la información que cambia con poca frecuencia y la usa para generar un programa ad-hoc que hace lo que su programa general haría con esa información, pero mucho más rápido. El generador de códigos es fácil de escribir porque solo trata con parte de la información de entrada, la parte que cambia lentamente.

Gran parte de la estructura de datos que veo actualmente existe para soportar la IU. Esto claramente no contiene objetos que le interesen al usuario, e idealmente tampoco debería tener que importarle. Así que construí un DSL para UI que oculta todo lo que hay.

Aléjate de los eventos y las notificaciones, si puedes, porque ocurren en momentos puntuales y, por lo tanto, representan cambios incrementales en el estado. Tendrás que estar muy preocupado por si se los deja caer, duplicar o desordenar. A menudo se usan bajo la teoría de que un estilo de votación simple sería "menos eficiente" cuando de hecho sucede a menudo lo contrario.

Así que cuando veo que la gente se involucra en la tecnología de las clases y demás, generalmente se debe a que están creando una estructura de datos demasiado grande.

Just my downvote-cebo ...

0

recomiendo de pluma trabajo efectivo con el código heredado, disponibles y se pueden buscar en Safari, sobre Refactoring. Está lleno de capítulos útiles y comprensivos como No tengo mucho tiempo y tengo que cambiarlo y Mi aplicación no tiene estructura.

Perspectivas a considerar:

  1. La automatización de las pruebas de calidad de diseño - buscar herramientas que proporcionan las métricas de calidad del diseño, como un control cruzado a sus decisiones de diseño.
  2. Code Testability: ¿alguna de sus refactorizaciones ayuda u obstaculiza el desarrollo basado en pruebas, pruebas de unidad de escritura o pruebas funcionales de escritura? ¿Qué tan difícil será probar grandes piezas de la arquitectura una vez integrada?
  3. Justificación: cómo defiende estas decisiones, tanto de un CYA cínico a la gestión y, lo que es más importante, para que su equipo crea en el rediseño. ¿Puede explicar fácil y consistentemente por qué se realizó un cambio y será fácil encontrar esa explicación dentro de 6 meses?

preferencias personales en el diseño, especialmente de refactorización:

  1. Clases para los conceptos - en caso de duda, si hay un solo concepto claro, que debe ser envuelto en una clase en lugar de implícita como una comportamiento en uno o métodos.
  2. Muchas de las pequeñas cosas que se comunican con las responsabilidades son más fáciles de pensar y auditar. Cuando tenga dudas acerca de cómo un diseño se asigna al mundo real, regrese al viejo enfoque Responsibility-Driven-Design de anotar las responsabilidades de cada clase. Si le resulta difícil, sus conceptos de lo que hace cada clase pueden ser confusos o están haciendo demasiado.
  3. No tengas miedo por las cosas que son grandes si son regulares. A veces, por ejemplo: muchos manejadores de eventos en GUI, legítimamente tendrá clases con muchos más métodos o propiedades de las recomendadas por las métricas.
0

Intente escribir un código más comprobable, esto solo me obligó a investigar e implementar mejores prácticas de OOP/conceptos de diseño.

Cuestiones relacionadas