Pregunta

Estoy leyendo mucho sobre 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 pasa del mal al buen diseño? He dividido la interfaz (xaml) y el código subyacente de la clase principal de businesslogic. Esa última clase está creciendo a lo grande. He intentado dividirlo en clases más pequeñas, pero ahora estoy atrapado. ¿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 llaman a partir de eventos manejados en el código subyacente. ¿Alguna idea de a dónde ir desde aquí?

Información adicional:

Ya llevamos unos 6 meses en este proyecto. He trabajado con idiomas orientados a objetos durante años (primero c ++, java y ahora c #), pero nunca en un proyecto grande como este. Creo que hemos hecho algunos giros equivocados al principio 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 separo todas las clases, ¿cómo las vuelvo a unir? ¿Tal vez sea aún mejor continuar de esta manera hasta la primera versión y las partes reconstruidas después de eso, para una segunda versión?

¿Fue útil?

Solución

  

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 metodos   para realizar estos cálculos que   se llaman desde eventos manejados en el   código detrás. Alguna idea de a dónde ir   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, ¿tal vez podrían vivir dentro de los tipos?

En términos de realizar operaciones similares pero diferentes en diferentes tipos, considere usar el patrón de estado ( vea esto como un reemplazo para las declaraciones de cambio) que le permite tratar a las entidades de manera uniforme.

Una gran cantidad de OOP se trata de descartar un enfoque de microgestión de arriba hacia abajo y considerar un enfoque de autosuficiencia de abajo hacia arriba. Vale la pena recordar que ninguno de los enfoques es "correcto" aisladamente. Crear un código que se pueda mantener consiste en encontrar un equilibrio razonable que requiera mucho pensamiento y que generalmente se desarrolle a través de la experiencia.

Otros consejos

Practica y lee. Repetir :)

Algunos libros recomendados:

  • Código limpio de Robert C Martin
  • Patrones de diseño GoF
  • Refactorización por Martin Fowler

Personalmente también me gustaron los patrones de diseño de Head First, pero el estilo puede no ser para todos. Hay un libro similar llamado C # 3.0 Design Patterns (ver ora.com). Tiene casi las mismas cosas, pero de una manera más tradicional.

Recomiendo encarecidamente recoger Código completo . Es un gran libro que ofrece toneladas de buenos consejos sobre preguntas como la suya.

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 solo una cosa. Cuando empiezas a pensar así, puedes identificar rápidamente el código que no pertenece. Si algo no pertenece, factorízalo en una nueva clase y úsalo de tu clase original.

Editar: Lleve ese pensamiento al método " nivel también: haga que sus métodos sean responsables de una cosa y solo de una cosa. Ayuda a dividir los métodos grandes (> 50 líneas) muy rápidamente en trozos de código reutilizables.

Cambia tu 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és haciendo algo mal.

Gran lugar para comenzar: lea el Pensamiento de objetos de David West & # 8217; s

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

Cuanto mejor obtengo en OO, más parezco reducir el tamaño del objeto. No es que vaya por un tamaño de objeto pequeño ni nada, pero parece estar sucediendo.

Manteniéndolos pequeños, responsabilidad única, fáciles de usar y comprender, todo crítico. Cada objeto debe estar lo más cerca posible a prueba de balas, verifique sus parámetros y nunca permita que su objeto pase a un estado no válido. Defina todos los estados válidos claramente en la documentación.

Cada vez que cree una clase, cree una prueba para esa clase. No solo prueba tu código, sino que te obliga a consumir tu propio diseño. Piensa siempre en tu clase desde esa "Vista exterior". Asegúrese de no pedirle demasiado a la persona que usa su clase y todo lo que le pida debe documentarse en la interfaz. A menudo, solo agrego un archivo principal rápido a una clase si no hay un marco de prueba disponible; coloca un ejemplo de cómo usar su código allí mismo en el mismo archivo.

En la codificación, casi todo mi tiempo lo paso tratando de averiguar qué hizo otra persona. Si pudiera publicar código usando API conocidas o bien documentadas, mi trabajo sería trivial y los horarios serían significativamente más cortos.

Design-first puede ser difícil. Considere la habilidad de codificación como similar a la habilidad deportiva. La mayoría de nosotros jugamos 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. Acepte esto y planifique el cambio: las iteraciones son su amigo. (Por cierto, la mayoría de nosotros PIENSAMOS que estamos a nivel estatal fácilmente. No lo estamos).

Además de la recomendación de Brian de Código limpio de Robert C Martin , es posible que desee leer sobre "El tío Bob" Principios SÓLIDOS de diseño orientado a objetos .

Puede escucharlo hablar sobre los Principios SOLID en Hanselminutes Podcast 145 y clean código en .NET Rocks! Mostrar # 388 . ¡También hay más con él en .NET Rocks! Muestra # 410 , pero de lo que habla no está realmente relacionado con tu pregunta, solo lo incluí en caso de que hayas disfrutado los dos primeros.

De los tres podcasts, preferí los minutos de Hansel.

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

Patrones de diseño 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 aplicaciones. Por ejemplo, Vista pasiva

Michael Feathers " Trabajando efectivamente con código heredado " se supone que ser muy bueno, pero confieso que no lo he leído yo mismo.

Lo mismo ocurre con " Refactorización a patrones. "

Descubrí que trabajar en una 'tarea' compleja sin ayuda y luego ver cómo alguien más lo hizo fue una gran experiencia de aprendizaje para mí.

Una tarea en particular fue crear un programa tipo banco donde teníamos que rastrear las transacciones y poder calcular los intereses ganados y cosas así. Realmente fue mi primer programa OOP y realmente excelente debido a su complejidad. Se vuelve demasiado confuso (para un principiante) hacerlo en un estilo lineal sin cometer errores.

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 de si te ayudará mucho.

Básicamente, mi enfoque es tener la menor cantidad 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 trabaja en ella al mismo tiempo, puede ser que no sea necesario para almacenarlo.

Segundo, ¿qué haces con él? Si va a iterar a través de ciertas formas simplificadas, puede considerarlo como 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 un conjunto de instrucciones de código de bytes, con un intérprete, y codificar su información en ese conjunto de instrucciones.

Tercero, ¿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ódigo es fácil de escribir porque solo trata parte de la información de entrada, la parte que cambia lentamente.

Gran parte de la estructura de datos que veo en estos días existe para admitir la interfaz de usuario. Claramente, esto no es la celebración de objetos que le interesan al usuario, e idealmente tampoco debería tener que preocuparse. Así que construí un DSL para UI que oculta todo ese truco.

Manténgase alejado de los eventos y notificaciones si es posible, porque suceden en momentos y, por lo tanto, representan cambios incrementales en el estado. Tendrá que estar muy preocupado por la posibilidad de que se caigan, dupliquen o ordenen incorrectamente. A menudo se usan con la teoría de que un estilo de sondeo simple sería "menos eficiente". cuando de hecho sucede lo contrario.

Entonces, cuando veo que las personas se involucran en la tecnología de las clases, etc., generalmente es porque están haciendo una gran cantidad de estructura de datos.

Solo mi cebo de voto negativo ...

Recomiendo Feather's Working Effectively with Legacy Code , disponible y disponible en Safari , sobre Refactorización . Está lleno de capítulos útiles y empáticos como No tengo mucho tiempo y tengo que cambiarlo y Mi aplicación no tiene estructura.

Perspectivas a tener en cuenta:

  1. Automatizar las pruebas de calidad del diseño: busque herramientas que proporcionen métricas sobre la calidad del diseño, como una verificación cruzada de sus decisiones de diseño.
  2. Code Testability: ¿alguna de sus refactorizaciones ayuda u obstaculiza el desarrollo basado en pruebas, escribiendo pruebas unitarias o escribiendo pruebas funcionales? ¿Qué tan difícil será probar grandes piezas de la arquitectura una vez integradas?
  3. Justificación: cómo defiende estas decisiones, tanto desde un CYA cínico hasta la gestión y, lo que es más importante, para que su equipo crea en el rediseño. ¿Puede explicar de manera fácil y coherente por qué se realizó un cambio y esa explicación será fácil de encontrar dentro de 6 meses?

Preferencias personales en diseño, especialmente refactorización:

  1. Clases para conceptos : en caso de duda, si hay un concepto claro, debe incluirse en una clase en lugar de implicarse como un comportamiento en uno o métodos.
  2. Muchas cosas de comunicación con responsabilidades son más fáciles de pensar y auditar. Cuando tenga dudas sobre cómo un diseño se asigna al mundo real, regrese a la antigua Responsability-Driven- Enfoque de diseño para escribir las responsabilidades de cada clase. Si le resulta difícil, sus conceptos de lo que hace cada clase pueden estar confusos o están haciendo demasiado.
  3. No tengas miedo de que las cosas sean grandes si son regulares. A veces, por ejemplo: muchos controladores de eventos en GUI, legítimamente tendrá clases con muchos más métodos o propiedades que las métricas recomendadas.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top