design - interior - architecture projects
Mejores prácticas: diseño antes de la codificación (11)
Al realizar proyectos importantes como el desarrollo de juegos, tiendo a tratar de estructurar cuidadosamente mi código y crear funciones y clases ficticias no funcionales desde el principio. Desde el archivo de código principal, dividí todo en clases dentro de otros módulos y submódulos, si es necesario. Por ejemplo; Mi página de códigos principal consistiría en nada más que incluye y llama a los inicializadores de clase para mis módulos principales. Aquí hay un ejemplo de init.py para un juego que estoy haciendo en Python en este momento;
de la importación commonheaders *
if arguements.debug:
debug.init()
try:
graphics.init()
sound.init()
physics.init()
input.init()
loop.start("scene1")
except Exception, e:
print "Error!"
print e
Es muy sencillo y fácil de entender, pero lo que más me gusta es que ofrece una separación muy definida entre los diversos aspectos principales del código. Si me siento frustrado con algo en la clase de gráficos, puedo ir a trabajar en la clase de sonido u otra cosa para hacer otras cosas y mantener los gráficos fuera de mi mente por un tiempo hasta que pasen las nubes. En todas las llamadas de clase init () hay argumentaciones opcionales, como widht / height para gráficos, pero normalmente las dejo fuera de allí y las establezco en el archivo commonheaders.py oa través de los modificadores de línea de comandos.
Intento que ninguno de mis módulos supere las 100 líneas antes de pensar en lo que puedo recortar y colocar en su propio módulo. Hace todo mucho más limpio y es mucho más fácil encontrar lo que estás buscando cuando se divide así. He trabajado con varios proyectos de código abierto antes y he visto módulos individuales en las decenas de miles de líneas anteriores ... había tanto código redundante que fácilmente podría haberse descargado a las funciones de ayuda. Uso comentarios cuando sea necesario, pero trato de mantener mi código estructurado de tal manera que ni siquiera necesite leer los comentarios.
Me gusta mucho tener el marco no funcional construido desde el comienzo, ya que hace que sea muy fácil ver lo que aún debe hacerse y lo que se puede mejorar en términos de estructura. Es mejor que apresurarse a escribir miles de líneas de códigos solo para descubrir que había una manera más elegante y funcional de hacerlo que requeriría una reestructuración total del código.
Tengo curiosidad ¿Cómo piensan ustedes? (Me refiero a una forma de pensar) sobre la arquitectura de diseño de sus bibliotecas, sistemas, marcos, etc. antes de comenzar a codificarla.
Recientemente me di cuenta de que sentía dolor por lo que había hecho, y prácticamente cada vez que quiero comenzar todo desde cero ...
Hago diseños antes, pintando algunos esquemas en el papel e imagino cómo funcionará, pero ¿quizás lo hago de forma incorrecta?
Por ejemplo, ¿cómo decide qué Interfaces necesitará o cómo se conectará todo de la mejor manera?
(Tuve un problema hace un día, mi amigo me preguntó en una biblioteca qué hice hace algún tiempo, y en lugar de darle solo un archivo, tuve que darle de 3 a 4 archivos, y eso es porque están conectado de alguna manera ... pero no en la correcta, creo :) así que fue un error de diseño ...)
Aunque no es una respuesta completa a su pregunta, a veces encuentro que la manera más fácil de ponerme en marcha para un proyecto, por así decirlo, es encontrar una pequeña pieza de funcionalidad aislada para comenzar y trabajar en eso, mientras que también pienso en el panorama general.
De esta forma, no te obsesionas demasiado con cada detalle y eres productivo y te das un respiro para ver lo que necesitas hacer con claridad.
Como digo, no una respuesta.
El problema es que cuando comienzas un nuevo proyecto, tiende a ser nuevo (¿no es obvio ahora?). Y, en general, uno no entiende nuevas cosas al azar, a menos que sea un consultor muy especializado haciendo exactamente lo mismo una y otra vez, lo que suena extraño ...
Porque eres inevitablemente nuevo en el sistema que creaste, tu diseño y tu código no van a ser perfectos la primera vez, así que reiteras el diseño y refactorización del código, hasta que esté listo.
Normalmente dedico de 2 a 4 horas para hacer el diseño de mi aplicación y luego la anoto en un cuaderno.
Luego empiezo a codificar, y cada vez que algo se complica (porque algo no está en el lugar correcto) me refactorizo. Mueva una clase a otro paquete, o extraiga el método, etc. Cuando el "diseño" se siente bien, puedo continuar.
De esta manera evito la "parálisis del análisis" que solía ocurrirme bastante. Muchas veces, cuando diseñé por adelantado, terminé sin usar algunos artefactos.
Por lo tanto, tomé este enfoque más "ágil".
Dibuje el diseño muy rápidamente y "refine" (refactorizando) en la ejecución.
Por supuesto, esto es posible para aplicaciones pequeñas (de 2 a 4 semanas)
Le sugiero que lea este artículo: ¿El diseño ha muerto de Martin Fowler? Es un poco largo pero vale la pena leerlo.
EDITAR
Enlace adicional (ligeramente offtopic) Cómo diseñar una buena API y por qué es importante por Joshua Bloch. Habla sobre la relevancia del diseño cuando tienes una audiencia para tu API. Resumen, comience lo más privado posible y el crecimiento a partir de ahí.
Por lo general, hago un análisis suficiente del dominio del problema en papel / pizarra para comprender lo suficiente el dominio del problema para comenzar a escribir el código. Raramente dibujo diagramas de implementación o clase en papel. Una técnica clave que he encontrado para lograr un mejor diseño es no apegar demasiado al código que escribe. Si no me gusta, lo borro, cambio de nombre, me muevo y lo mezclo hasta que expresa una solución lo suficientemente buena para lo que intento resolver. ¿Suena fácil? ¡De ningún modo! Pero con buenas herramientas de "codificación", escribir el código no es el mayor esfuerzo. Escribir algunos, refactorizar, eliminar, escribir de nuevo ...
El buen diseño casi nunca comienza bien. Evoluciona a bueno Aceptar esto hace que sea más fácil trabajar en pequeños pasos sin frustrar por qué el diseño no es "perfecto". Para que este proceso funcione, debes poseer buenas habilidades de diseño. El punto es que incluso los excelentes diseñadores no lo hacen bien la primera vez.
Muchas veces, pensé que entendía el dominio del problema cuando comencé, pero no lo hice. Luego vuelvo a la pizarra, hablo con alguien o leo en el dominio del problema si me doy cuenta de que no lo entiendo lo suficiente. Luego vuelvo al código.
Es un proceso muy iterativo.
Una pregunta interesante que debe hacerse cuando se trata de cómo piensan los programadores es cómo desarrollaron su forma de pensar. Personalmente, mi forma de pensar ha evolucionado a lo largo de los años, pero algunos eventos han tenido una profunda influencia en la forma en que desarrollo el software. El más importante de ellos ha sido diseñar software con personas que son diseñadores expertos. Nada me ha influenciado más que pasar iteraciones con grandes diseñadores. Otro evento que tiene, y aún afecta, la forma en que creo que se remonta y mira el software que escribí hace un tiempo.
Prefiero un diseño de abajo hacia arriba. Si no existe un marco de aplicación, tiendo a ensamblarlo o compilarlo primero. Un buen marco de aplicación es portátil y no depende de las aplicaciones, abordando en gran medida problemas transversales. Normalmente contendrá cosas tales como registro, manejo de excepciones, ayudantes de validación, métodos de extensión, etc.
A partir de ahí, me gusta ir con un enfoque en gran parte DDD (Diseño impulsado por el dominio). Entrevistar a los usuarios comerciales, si es necesario, para construir el modelo de dominio. Una vez que el modelo de dominio y el posterior DAL (Data Access Layer) se han solucionado, me desplazo a la capa de lógica de negocios (BLL).
Personalmente trato de mantenerme lo más alejado posible de la implementación de front-end, ya que definitivamente no es un punto fuerte mío. Definitivamente, una de las razones por las que me encantan las pruebas unitarias es porque puedo centrarme en la funcionalidad central y ser capaz de probar esa funcionalidad sin saltar a decisiones de interfaz prematuras.
Pregunta abierta. Habrá casi tantas respuestas como carteles. 1) eche un vistazo a muchos libros de ingeniería de software. Algunos discuten con un buen diseño, el resto es muy fácil. Eso es una mentira recta 2) Vea cuán intrusivos son los diversos marcos, más vale que los use de la manera prevista, de lo contrario, mejor implemente las cosas nuevamente para sus necesidades 3) El diseño necesitaría un cambio constante como cualquier escritura. Ves las oraciones pero sientes que no encajan del todo. Entonces lo reescribes. Por lo tanto, cada diseño debe tener en cuenta que las cosas son diferentes, ya que parecen haber escrito el diseño.
Saludos Friedrich
Principalmente empiezo con una caja de cartas y escribo los conceptos del dominio que quiero modelar. A veces uso un mapa mental para eso.
Eche un vistazo a las partes interesadas y lo que quieren lograr. Es importante comenzar allí, porque le permite priorizar correctamente (es decir, no en la parte técnica más interesante, sino en la parte con mayor valor comercial)
El pensamiento sobre el diseño se escribe principalmente en pruebas. Escrito antes del código para implementarlo. Comience con las metas finales de las partes interesadas, trabaje desde allí hacia atrás hasta el comienzo (Inversión temporal). Eso asegura que te concentres en qué y menos en cómo. La interacción entre objetos es más importante para obtener los atributos correctos que los atributos del objeto.
La otra parte está principalmente en la pizarra. Una cámara digital compacta es un equipo estándar en estos días.
Hacer un marco antes de tener tres implementaciones que lo necesitan es una mala práctica. Si es necesario, prepárese para cambios significativos en la interfaz (y la implementación).
Ver:
Sigo una versión muy suelta de Rational Unified Process.
Primero, empiece con un documento de visión que indique claramente lo que está tratando de hacer, para quién lo está haciendo y quizás algunos detalles clave sobre los métodos / algoritmos propuestos. No necesita ser elegante e incluso podría ser un trazador de líneas para un sistema simple "Un sistema para predecir los números ganadores de la lotería, para uso personal únicamente, basado en las últimas investigaciones de la escuela Hogwarts". Para un sistema más complejo, podría Ser alrededor de cinco páginas, pero no más. Este no es el diseño sino más bien una lista de deseos.
Luego, haga algunos casos / historias de uso. Estas deberían ser descripciones de texto en lenguaje natural simple de todas las interacciones con el mundo externo. El minimalismo es la clave aquí; el propósito de los casos de uso es identificar todas las funcionalidades requeridas y solo la funcionalidad requerida. También encuentro que aquí es donde ocurre la mayor parte de la creatividad.
Un caso de uso podría comenzar de la siguiente manera:
User presses the "magic" button. System displays next weeks winning number. User writes down number. User buys lottery ticket. Lottery draws winning number. User claims money lottery pays up.
Después de mucho trabajo, termina como:
User presses "magic" button System selects next weeks numbers. System logs on to lottery system. System enters winning numbers. Lottery selects winning numbers. Lottery transfers winnings to users account. User spends money.
Una vez que haya realizado sus casos de uso, puede activar su entorno de desarrollo y las diversas clases e interacciones se pondrán en su lugar.
Tiene que ser un equilibrio.
Si tratas de diseñar todo por adelantado con muchas fotos en una pizarra, entonces es probable que te pierdas algunos detalles cuando se trata de codificarlo.
Si comienza a piratear en una pequeña parte del sistema, probablemente perderá de vista la "gran imagen" y terminará con un diseño pobre.
Al mirar las bibliotecas, quiere que sean reutilizables tanto como sea posible. Por lo tanto, para el diseño inicial, piense en los casos más generales que pueda de entre los usos previstos de su biblioteca que ya conozca ; no se preocupe demasiado en esta etapa sobre usos hipotéticos futuros que bien podrían nunca suceder. Codifique ese diseño con pruebas unitarias y refactorice a medida que aprende más y encuentra problemas con el diseño.
Trate de poner tan poco conocimiento específico sobre los usuarios de la biblioteca en la biblioteca misma. Entonces, con suerte, terminará con algo reutilizable y no querrá comenzar de cero la próxima vez.
Para un enfoque orientado a objetos, me parece que en general es una buena idea alejarse un poco de la interfaz de usuario y centrarse en qué entidades (objetos) existirán en el sistema y qué propiedades y acciones son apropiadas.
Dibujar en una pizarra blanca o en una hoja grande de papel, usar diferentes colores para identificar varias características también es una buena idea. Las notas post-it también son una buena forma de visualizar su modelo.
Incluso si paso mucho tiempo pensando en un diseño con mucho cuidado, SIEMPRE termino cambiándolo a medida que avanzo. Por lo tanto, es bueno tener en cuenta que su diseño cambiará a medida que tome una decisión sobre cómo documentar su diseño.