¿Cómo saber qué hay que hacer en el diseño orientado a objetos?

12

Primero un descargo de responsabilidad: realmente no sé si esta pregunta se ajusta a este sitio web, pero sigo encontrando que es una pregunta relevante no solo para mí sino para otras personas que son principiantes. Si la pregunta puede ser mejorada para que encaje aquí, por favor señale los comentarios int. Si no encaja, avíseme también y, si es posible, hágame saber dónde se puede discutir esto porque no encontré ningún buen foro para esto.

Aprendí a programar en 2009 cuando estudié PHP. Más adelante en 2012, me mudé a C # y .NET. De todos modos, la codificación no es el problema, escribir algoritmos no es mi problema. Mi problema real es saber qué debe codificarse para cumplir un requisito y dónde debe codificarse.

La mayoría de los cursos disponibles en la web abordan el cómo : cómo escribir código en un idioma determinado, cómo usar algunos conjuntos de API, etc. Ese no es mi punto aquí.

En estos años, he leído mucho sobre un montón de cosas: análisis y diseño orientado a objetos, patrones de diseño, diseño dirigido por dominios, etc. Entiendo, por ejemplo, los principios SÓLIDOS, algunas de las ideas principales de DDD, como la necesidad de involucrar a expertos en dominios, el desarrollo de un lenguaje ubicuo, etc. Me atrevería a decir que tengo una base teórica al menos razonable.

Pero cuando se trata de practicar siento que soy un desastre. Hace algún tiempo necesitaba continuar el desarrollo de un sistema financiero que ya estaba siendo desarrollado por otra persona. Es ese tipo de "sistema antiguo" desarrollado con C # y WinForms. Fue la primera vez que elegí un proyecto con una complejidad de dominio real, con muchas reglas comerciales, etc.

Confieso que cuando recibo los requisitos la mayoría de las veces pienso "¿cómo puede hacerse esto?" - No tengo idea de cómo comenzar a trabajar en los requisitos para averiguar qué se debe hacer. Creo que mis principales confusiones son lo que debo codificar, qué clases, interfaces y dónde va cada pieza de lógica, en qué clase debe estar cada cosa. El problema es que no sé por dónde empezar.

La mayoría de las veces, con mucho pensamiento termino con algunas ideas, pero nunca sé cómo juzgar si mi idea es correcta o no.

Quiero decir que no creo que esto sea una falta de teoría, ya que dije que leí sobre un montón de cosas sobre arquitectura de software y orientación a objetos que me recomendaron, pero no ayudó mucho a identificar lo que se debe hacer en la práctica. .

Entonces, ¿cómo puedo aprender a hacer realmente diseño orientado a objetos? Lo que quiero aprender es: los requisitos dados saben cómo comenzar a trabajar en ellos en un proceso que conduce a descubrir qué hay que hacer y dónde pertenece cada parte del código. ¿Cómo puedo aprender a juzgar si mi idea es correcta o no?

Creo que explicar esto completamente como respuesta aquí no sería posible. Sin embargo, lo que estoy buscando, que puede estar de acuerdo con el estilo del sitio, son respuestas que solo dan una visión general y señalan algunas referencias (libros, cursos en línea, etc.) que pueden usarse para expandir las ideas y realmente aprender estas cosas.

usuario1620696
fuente
1. ¿Ya comprende todos los conceptos fundamentales de C #, incluidas cosas como la diferencia entre la sobrecarga de operadores y la anulación de operadores, qué es una clase abstracta y en qué se diferencia de una interfaz, encapsulación, polimorfismo, etc.? Saber estas cosas primero es esencial para comprender completamente OO en C #. Consulte c-sharpcorner.com/technologies/oop-ood .
Robert Harvey
2
2. Las aplicaciones más antiguas escritas en Winforms tienden a convertirse en grandes bolas de lodo a menos que estén diseñadas correctamente. La separación de las preocupaciones se vuelve primordial. Ver winformsmvp.codeplex.com
Robert Harvey
1
Realmente no hay un proceso. El diseño se trata principalmente de saber cómo organizar, lo que viene con la experiencia. Los principios SÓLIDOS son un buen comienzo, pero no son suficientes, y las personas tienden a perderse en SÓLIDOS y olvidan por qué existen los principios.
Robert Harvey
1
Comience poco. Los requisitos son problemas. Un problema puede ser tan grande como "Queremos desarrollar el próximo sitio de Stackexchange" o tan pequeño como "queremos que nuestro próximo Stackexchange tenga un inicio de sesión". Convierta un gran problema en muchos, pero menos inteligentes. En general, date la oportunidad de hacer las cosas "mal" primero y mejorar con el tiempo.
Laiv
1
Simultáneamente quiero votar y votar esto ...
svidgen

Respuestas:

21

Entonces, ¿cómo puedo aprender a hacer realmente diseño orientado a objetos? Lo que quiero aprender es: los requisitos dados saben cómo comenzar a trabajar en ellos en un proceso que conduce a averiguar qué se debe hacer y dónde pertenece cada parte del código. ¿Cómo puedo aprender a juzgar si mi idea es correcta o no?

Bueno, antes que nada, deja de pensar en el diseño orientado a objetos como correcto. Es como pensar que el inglés es correcto.

El paradigma orientado a objetos no es correcto. Tiene ciertas ventajas y desventajas. Es un ideal. No es nuestro único. Es mejor que nada, pero ciertamente no lo es todo.

Llevo décadas codificando. He estudiado estas cosas durante casi tanto tiempo como sus ideas han existido. Todavía estoy aprendiendo lo que significa. Los expertos todavía están aprendiendo lo que significa. Todo nuestro campo tiene menos de 100 años.

Entonces, cuando tomas un montón de requisitos y obtienes un código que los satisface y sientes que el código que escribiste es un desastre trágico, no estás solo. El código de trabajo es simplemente el primer paso para un gran código. Código que no solo funciona sino que otros pueden leer y comprender fácilmente. Código que se puede adaptar rápidamente cuando cambian los requisitos. Código que te hace querer sentarte y decir "Wow, eso es tan simple".

El problema es que no nos pagan para hacer todo eso. Hacemos todo eso porque somos profesionales. Tenemos que hacer todo eso cuando el jefe no está buscando porque siempre hay una fecha límite. Pero queremos volver en 5 años y decirles a los novatos: "Oh, sí, escribí eso. Todavía funciona, ¿eh? Genial".

¿Cómo se llega allí? Práctica. No aceptes NINGUNA idea de diseño sobre la fe. ¿Alguien no callará sobre cómo el diseño impulsado por eventos simplificará este diseño? ¿No estás seguro si tienen razón? Construye tu propio proyecto de juguete en casa que use el patrón de observador. Meterse con eso. Trate de encontrar cosas con las que NO ayuda.

Leer. Pregunta. Prueba. Repetir.

Cuando llegues al punto de que has estado haciendo eso el 80% de tu vida, estarás tan confundido como yo.

Confieso que cuando recibo los requisitos la mayoría de las veces pienso "¿cómo puede hacerse esto?" - No tengo idea de cómo comenzar a trabajar en los requisitos para averiguar qué se debe hacer. Creo que mis principales confusiones son lo que debo codificar, qué clases, interfaces y dónde va cada pieza de lógica, en qué clase debe estar cada cosa. El problema es que no sé por dónde empezar.

Yo solía sentir lo mismo. Entonces descubrí la alegría de refactorizar. Esté dispuesto a adaptar los diseños a medida que codifica. Tratar de resolver todo en papel con anticipación es la forma más difícil de hacerlo. Escriba código que pueda probarse que está equivocado, demuestre que está equivocado y corríjalo.

naranja confitada
fuente
2
Esta es una respuesta genial. He estado programando durante 15 años, y agregaré que todo el campo de la Ingeniería de Software (mi profesión) es "difuso": es una mezcla de arte y función, y dependiendo del desarrollador es más uno que otro. Se me ocurre una idea para una arquitectura en papel, pero no puedo resolver los detalles del diseño de OO hasta que me meta en la tierra, pierda el tiempo y encuentre lo que funciona y lo que no.
jropella
¡Gracias por la respuesta! Entonces, su punto es: una vez que tenemos al menos una solución para implementar un requisito, y funciona, lo implementamos, y luego, cuando vemos cómo se relaciona con el otro código y otros requisitos, ¿lo refactorizamos para mejorarlo? Pero todavía hay situaciones en las que obtengo algunos requisitos y no tengo idea de cómo comenzar. En esos casos, ¿tiene algún consejo sobre cómo comenzar? A veces creo que lo mejor sería discutir los requisitos y las posibles implementaciones, pero trabajo solo. ¿Hay algún foro donde este tipo de discusión sea bienvenida?
user1620696
2
Bueno, primero, deja de trabajar solo. Incluso tener un novato despistado que te frena para explicarte las cosas es mejor que eso. Segundo, aprenda a dividir un requisito en partes. Sigue haciendo eso hasta que tengas algo manejable sobre lo que puedas obtener tracción. Escriba el código de prueba de concepto en un entorno completamente diferente si es necesario. Simplemente haga algo que exprese su comprensión de lo que se necesita. Luego prueba esa expresión. Usted puede encontrar que hizo malas suposiciones. Eso es bueno. Estar dispuesto a cambiarlos.
candied_orange
1

El desarrollo de software se reduce a la entrega de software en funcionamiento, a tiempo, dentro del presupuesto y cumpliendo con todos sus criterios de aceptación. Suponiendo que haya logrado hacer eso, la calidad percibida del código o su estructura es una preocupación secundaria.

El problema, por supuesto, es que escribir un nuevo código greenfield nuevo tiende a ser mucho más barato y más fácil que mantener el código heredado, por lo que, en lugar de estar demasiado obsesionado con la calidad o la arquitectura del código, recuerde que su verdadero problema es la mantenibilidad.

Por lo general, el código se considera mantenible cuando los costos, el tiempo y los riesgos asociados con el cambio de ese código son proporcionalmente bajos como para que la reparación de errores o la implementación de cambios en los requisitos siga siendo rentable, y que al implementar esos cambios no se perpetúa una "espiral de la muerte "de codificación-entropía.

Por el contrario, el código se considera no mantenible cuando no puede cambiar o refactorizar con confianza sin un riesgo grave de romper algo o gastar tiempo / dinero excesivo para garantizar que no se rompa nada, es decir, cuando el tiempo, el costo y el riesgo involucrados en trabajar con ese código son desproporcionadamente alto en comparación con los beneficios de realizar cambios (es decir, su empleador o cliente no está perdiendo dinero al agregar nuevas funciones, corregir errores, etc.)

Recuerde que incluso el desorden de espagueti más diabólico puede ser potencialmente mantenible si tiene suficientes provisiones alrededor del desorden para protegerse contra cambios importantes (aunque tales casos son raros). El problema con un desorden de spaghetti es que protegerlo contra cambios importantes tiende a ser bastante costoso e ineficiente, especialmente si lo está haciendo retrospectivamente.

Quizás la forma más confiable de asegurarse de que haya escrito un código que se pueda mantener es escribir (cuando sea razonablemente posible) un conjunto adecuado de pruebas automatizadas al mismo tiempo (al mismo tiempo que aprovecha al máximo cualquier otra herramienta de análisis estático que pueda estar disponible).

No es necesario que siga una metodología de desarrollo estricta como TDD / BDD para terminar con suficientes pruebas automatizadas que le permitan refactorizar; solo necesita lo suficiente para proteger el código contra cambios accidentales en el futuro.

Si su código está cubierto por pruebas automatizadas, puede relajarse sobre su diseño y estructura sabiendo que está cubierto por esas pruebas; puedes refactorizar agresivamente en una fecha posterior, o incluso tirarlo y comenzar de nuevo.

Esto plantea la cuestión de cómo escribir código fácilmente comprobable; este es típicamente el argumento principal para seguir los principios SÓLIDOS; de hecho, el sello distintivo del código que se adhiere a los principios SOLID es que es fácil y rentable / tiempo escribir pruebas unitarias.

Por supuesto, a veces tampoco tienes tiempo para escribir pruebas unitarias; sin embargo, si ha escrito todo su código teniendo en cuenta la pregunta "¿Cómo escribo pruebas automáticas para esto?" (incluso si realmente no implementó esas pruebas), probablemente también haya logrado encontrar un diseño que sea razonablemente mantenible.

Ben Cottrell
fuente
1
nunca tenemos tiempo para escribir pruebas automatizadas, pero siempre tenemos tiempo para ejecutar pruebas manuales una y otra vez ...
Nick Keighley
Del mismo modo, nunca tenemos tiempo para escribir el código "correctamente" y "limpiamente" la primera vez, pero parece que tenemos un tiempo infinito para seguir retrocediendo y corregirlo, una y otra vez debido a la mentalidad equivocada pero tan prevalente presentada en esta publicación.
Dunk
@Dunk No creo que sea realista esperar que el código nunca deba cambiar o ser revisado. Las prácticas de pruebas unitarias y las directrices SOLID se refieren a prácticas alentadoras que dan como resultado un código que es fácil y barato de cambiar cuando sucede lo inevitable; por ejemplo, alguien encuentra un error oscuro realmente extraño que el desarrollador no consideró en ese momento, o el cliente ve el solución y cambia los requisitos, o incluso el código original contenía errores porque los desarrolladores son solo humanos; o tal vez el desarrollador no entendió los requisitos, o descubrió limitaciones técnicas previamente desconocidas ...
Ben Cottrell
1
@BenCottrell - Estoy totalmente de acuerdo. El código siempre tendrá que ser revisado. Sin embargo, debido a eso, lleva a las personas a apuntar a tomarse el tiempo para hacer un "diseño inicial" y escribir algo "código limpio" como algún tipo de falla. Usan el mantra "a tiempo" y "dentro del presupuesto" para justificar un código / diseño deficiente. Puede utilizar todas las "prácticas" que desee, pero no va a comprarle un "código fácil y barato de cambiar" sin tener un buen diseño y un "código limpio" para empezar. Un buen diseño y un "código limpio" tendrán el subproducto de lograr realmente el objetivo a tiempo y dentro del presupuesto.
Dunk
@Dunk Parece que estás diciendo que muchos desarrolladores simplemente no se preocupan por la calidad del código, lo cual no creo que sea el caso. En realidad, creo que hay dos problemas mayores: en primer lugar, si bien los desarrolladores pueden ser los que proporcionan una estimación del presupuesto y la fecha límite, las estimaciones pueden resultar fácilmente incorrectas. En segundo lugar, las partes interesadas del proyecto obtienen la última palabra sobre tiempo / costo, lo que significa que los riesgos, los presupuestos y las fechas límite anulan las preocupaciones técnicas. Dada la posibilidad de elegir entre "definitivamente tarde / sobre presupuesto" o "código potencialmente malo", encuentro que las partes interesadas con frecuencia eligen este último.
Ben Cottrell