Este artículo proviene de un motor de traducción automática.
Patrones en la práctica
Entrega incremental mediante diseño continuo
Jeremy Miller
Contenido
Distribución incremental de características
Diseño continuo
El último momento responsable
Reversibility
YAGNI y Thing más sencillo que posiblemente podría trabajar
¿Cuánto modelado antes codificación?
Novedades de antemano
En anteriores patrones en columnas de la práctica, ha centrado principalmente en patrones de"técnicos", pero en este artículo, trataré el lado más suave de "práctica" de diseño de software. El objetivo final de los proyectos de software es ofrecer valor para el cliente y mi experiencia es que el diseño de software es un factor importante en cómo correctamente un equipo puede entregar ese valor. A través de diseño, en diseño, o simplemente plana fuera incorrecto diseño impide un proyecto. Un buen diseño permite que un equipo que más éxito en sus esfuerzos.
Mi experiencia es también que los diseños mejores son un producto de diseño continuo (también conocido como diseño emergent o evolutivo) en lugar del resultado de un esfuerzo que intenta obtener todo el diseño por adelantado derecho. En diseño continuo, podría empezar con un modicum del diseño inicial, pero retrasar confirmar instrucciones técnicas lo posible. Este enfoque permite intentar aplicar las lecciones aprendidas del proyecto para mejorar continuamente el diseño, en lugar de convertirse en bloqueado en un diseño erróneo desarrollado demasiado pronto en el proyecto.
Además, creo firmemente que la mejor forma para crear el valor empresarial es a través de entrega incremental de trabajar características en lugar de centrarse primero en la creación de infraestructura. En este artículo, explicaré cómo incremental entrega del trabajo habilita características mejor proporcionar valor empresarial y cómo mediante diseño continuo puede habilitar la entrega incremental a ser más eficaz y ayudarle a crear diseños de software mejor un equipo de proyecto.
Predicción frente a diseño reactivo
En primer lugar, ¿qué es el diseño de software? Para muchas personas, software diseño significa "crear una especificación de diseño antes de codificación inicia" o "Fase de diseño y elaboración". Me gustaría paso fuera de procesos formales y documentación intermedia y definir el diseño de software más general como "el acto de determinar cómo debe estructurar el código". Que se decía, podemos ahora pensar de diseño de software sucede en dos modos diferentes: predicción o reactiva (o reflectante si lo prefiere).
Diseño predictivo es el trabajo de diseño que realice antes de codificación. Diseño predictivo es crear modelos UML o CRC, realizar sesiones de diseño con el equipo de desarrollo al principio de iteración y escribir especificaciones de diseño. Reactivo el diseño es los ajustes que basado en comentarios durante o después de codificación. La refactorización es diseño reactiva. Cada equipo y incluso personas dentro de un equipo tienen preferencias diferentes utilizando el diseño predictivo o reactivo. Diseño continuo simplemente pone más importancia en diseño reactivo que los procesos de desarrollo de software tradicionales.
Distribución incremental de características
En 2002, mi empresa, a continuación, se experimentar con recién minted Microsoft .NET Framework y tenía inicia un proyecto de prueba mediante ASP.NET 1.0. I, junto con muchos otros, concienzudamente inspeccionando el proyecto con la esperanza de éxito para que se puede iniciar utilizando este nuevo marco interesante en proyectos de nuestros propios. Seis meses más tarde se ha cancelado el proyecto. El equipo había sido ciertamente ocupado y por todas las cuentas que ha escrito una gran cantidad de código, pero ninguno de los que el código era adecuado para la producción.
La experiencia de ese equipo del proyecto genera algunas lecciones importantes. El equipo primero escribí una especificación de diseño que se parece bastante completa y conformed los estándares de nuestra organización. Con este documento en mano, el equipo inicia el proyecto intentaba generar la capa de acceso de datos completa, a continuación, la capa de lógica empresarial y finalmente la interfaz de usuario. Cuando inicia el código de las pantallas de interfaz de usuario, los desarrolladores realizadas rápidamente que el código de acceso de datos existente no era exactamente lo necesitaban para generar la interfaz de usuario, incluso aunque ese código se ajustaban a los documentos de diseño. En ese momento, la administración de TI y los socios comerciales no vea cualquier valor que se entregan en el proyecto y produjo en la cocina en favor de otras iniciativas.
Irónicamente, me la empresa principal era y uno ejemplos iniciales del mundo de un fabricante eficiente o just-in-time. La mayoría de nuestros competidores utilizadas producción, en la que grandes cantidades de elementos se ordenan las líneas de fábrica según la demanda prevista durante algún período de tiempo de "inserta". Problemas de fabricación de inserción son que perder dinero cualquier momento que pedir más partes que se puede utilizar; tendrá que pagar adicional para almacenar las cotizaciones de excedentes partes antes de que esté listo para utilizarlos; y son vulnerables a escasez de parte en la fábrica cualquier momento las previsiones son incorrectos, y las previsiones son poco precisas.
En contraste, mi empresa, a continuación, utiliza fabricación de "extracción". Los sistemas de fábrica programación los pedidos de cliente necesarias para generar en el siguiente par de horas, varias veces al día determina las cantidades de partes que necesarios para completar los pedidos y, a continuación, ordenar para su entrega inmediata exactamente el número y tipo de elementos necesarios. Las ventajas de fabricación de extracción son que por comprar sólo lo necesario, desperdicia mucho menos dinero en partes que no se puede utilizar; fábricas tienen mucho menos cotizaciones de parte en mano a enfrentarse con, realizar algo más eficaz de fabricación; puede adaptarse a circunstancias nuevas rápidamente y fuerza cuando que no enlazado por previsiones realizadas meses; y las previsiones y son más precisas cuando realiza a través de corto plazo en lugar de un término más estimaciones del mercado.
¿Cómo se aplica la extracción frente al problema de inserción al desarrollo de software? El proyecto describe anteriormente utilizado inserción diseño intenta primero determinar todas las necesidades infrastructural del sistema e intentar crear la infraestructura de acceso de datos antes de escribir otros tipos de código. El equipo desperdicia mucho esfuerzo a diseñar, documentar y crear código que nunca se utilizó en producción.
En su lugar, ¿qué ocurre si el equipo tenía liquidado para escribir rápidamente una especificación de alto nivel con detalles mínima, realizado para desarrollar la prioridad más alta de la característica de calidad de producción preparadas, a continuación, la característica de prioridad más alta siguiente y así sucesivamente. En este escenario, se crearía el equipo sólo código de infraestructura, como código de acceso de datos, que se extraen los requisitos de la característica particular.
Piense en esto. ¿Qué es un mejor resultado para un proyecto al final de su escala de tiempo programada?
- 1 Sólo 50 por ciento de las características propuestas son completa, pero las características más importantes de la propuesta de proyecto inicial están preparadas para distribuir a producción.
- 2 La mayor parte de la infraestructura de codificación está completo, pero no características son totalmente utilizables y nada puede implementarse en producción.
En ambos casos el equipo sólo es aproximadamente medio realizada y ningún resultado es realmente un éxito en comparación con el plan inicial y la programación. ¿Pero qué "failure" sería bastante explicar a su jefe? Sé que mi jefe lo nuestro equipo de ventas sería preferible definitivamente el primer resultado basado en entrega incremental.
Las principales ventajas de entrega incremental son los siguientes:
- Trabajando en el negocio de orden de prioridad. Generar incrementalmente por característica le ofrece la mejor oportunidad para completar las características más importantes para la empresa. Después de todo, ¿por qué debería dedicar cualquier tiempo absoluto diseñar, generar y probar una característica de "fantástico tener" antes de las características de "debe tener"?
- Mitigación del riesgo. Francamente, el mayor riesgo en la mayoría de los proyectos no técnico. El mayor riesgo es que no proporcionar valor de negocio o entregar el sistema incorrecto. Además, la realidad sea dura es que los requisitos y análisis de proyecto le ha proporcionado es probable sólo como que sea incorrecto como su diseño o código. Demostrando las características de trabajo a los socios comerciales pronto en el proyecto, puede obtener valiosos comentarios sobre los requisitos del proyecto. Para mi equipo demostraciones anticipadas al nuestro equipo de administrador y ventas de producto han sido un valor incalculable para ajustar el uso de nuestra aplicación.
- Pronta entrega. Características completadas se pueden poner en producción antes el resto del sistema para iniciar la ganancia algunos retorno de valor.
- Entrega flexible. Créalo o no, los socios comerciales y de su jefe de producto cambian en ocasiones sus prioridades. En lugar de gnashing los dientes en injustice de todo, puede trabajar de manera que asume que se cambiarán las prioridades. Asociando código de infraestructura a las características de reproducción, reducir la probabilidad de esfuerzo desaprovechado debido al cambio de prioridades.
Ahora, para el inconveniente de entrega incremental: es difícil hacer. En el ejemplo de fabricación eficiente extracción fabricación funcionaba sólo porque cadena de suministro de la compañía era ultraefficient y era capaz de fábricas de stock con partes casi a petición. El mismo es cierto para la entrega incremental. Debe poder rápidamente los elementos de las nuevas características de diseño y mantener la calidad de la estructura de código lo suficientemente alta para que no realice generar características futuras más difíciles. Lo que no tiene tiempo para realizar es dedicar semanas o incluso meses en un momento trabajando preocupaciones arquitectónicas estrictamente, pero siguen existen los problemas de arquitectura. Tiene que cambiar el modo Diseñar sistemas de software para ajustar el modelo de entrega incremental. Aquí es donde entra el diseño continuo en la imagen.
Diseño continuo
Defensores de desarrollo tradicional a menudo creen que proyectos están mayor éxito cuando el diseño puede ser completamente especificado por adelantado para reducir esfuerzos inútiles en codificación y rehacer. El auge de programación de Agile y lean ha pide tradicionales nociones del tiempo de diseño de software introduciendo un proceso de diseño continuo que sucede durante el ciclo de vida del proyecto. Diseño continuo intencionadamente retrasa compromisos a diseños determinados, extiende más trabajo de diseño durante el ciclo de vida del proyecto y anima a un equipo para desarrollar un diseño como el proyecto que se desarrolla aplicando lecciones aprendidas en el código.
Considérelo de esta forma. Simplemente no desarrollar el diseño detallado de una característica hasta que tenga tiempo para generar dicha característica. Se podría diseñar de ahora, pero ese trabajo de diseño no proporciona ningún ventajas hasta mucho más adelante, y en el momento mi equipo obtiene a esa característica, es probable que saber mucho más acerca de nuestra arquitectura y el sistema y poder idear un mejor diseño que podría tener al principio del proyecto.
Antes que cualquier otra, me gustaría decir que diseño continuo no implica ningún trabajo de diseño que tiene lugar por adelantado. Me gustaEsta oferta de Robert C. (Tío Bob) Martin: " El objetivo es crear un diseño inicial pequeño, pero capaz, a continuación, mantener y evolucionar ese diseño con la vida del sistema ."
Antes de escribir fuera diseño continuo como arriesgado y propensa a errores, vamos a explicar cómo realizar diseño continuo correctamente (en otras palabras, voy a intentar convencer a que no loco).
La importancia de comentarios
Muchos proyectos son realmente sencillos, entiende bien-requisitos y estrictamente utilizan tecnologías conocidas. Diseño inicial podría funcionar bastante bien con estos proyectos, pero mi experiencia es la contraria. Casi todos los proyectos que ha trabajado en ha tenido cierto grado de novedad, en la tecnología utilizada, las técnicas de desarrollo utilizadas, o en los requisitos. En esos casos, creo que la mejor para tener éxito consiste en adoptar una actitud de humility y dudoso. Nunca se debe suponer que lo está haciendo y pensando funciona hasta que tenga algún tipo de comentarios que comprueba el código o diseño.
Diseño continua implica la evolución de la estructura del código, lo que es aún más importante al utilizar este enfoque para crear comentarios rápido ciclos para detectar errores de compilación causados por cambios en el código. Examinemos el modelo de programación Extreme (XP) de desarrollo como un ejemplo. XP llama a para un enfoque altamente iterativo de desarrollo que permanece controvertido. Controvertidos casi como es el hecho de que XP especifica una serie de recomendaciones que son algo más difícil que acepten para muchos desarrolladores y tiendas. Específicamente, prácticas XP en gran medida están diseñadas para compensar la tasa rápida de iteración proporcionando comentarios rápida y completa ciclos.
- Propiedad mediante programación de par colectiva. Encanta o odia, par programación requiere que al menos dos pares de ojos revisen cada línea de código de producción. Programación de par proporciona comentarios de un diseño o código revisión simple segundos después de escribe el código
- Pruebas de desarrollo (BDD) y aceptación de desarrollo controlado por pruebas (TDD), controlado por comportamiento. Todas estas actividades creación comentarios muy rápido. TDD y BDD ayudan unidad fuera defectos en el código cuando se escribe inicialmente, pero sólo como importante, el nivel alto de cobertura de prueba unitaria hace los cambios de diseño posteriores y adiciones en el código mucho más seguro al detectar errores de regresión de forma minuciosa.
- Integración continua. Cuando se combina con un alto grado de cobertura de prueba automatizada y herramientas de análisis de código estático posiblemente, integración continua puede encontrar rápidamente problemas en la base de código que cada vez código está protegido.
- Retrospecciones. Esto requiere que el equipo de desarrollo detener y explique cómo el diseño de software es ayudar a o perjudicar el esfuerzo de desarrollo. He visto numerosas mejoras de diseño de la iteración y suelte las retrospecciones.
La calidad y la cantidad de sus mecanismos de comentarios afectará enormemente modo de diseño. Por ejemplo, cobertura de prueba automatizada alta con unidad bien escrita prueba hace mucho más sencillo y más eficaz de refactorización. Refactorización con baja o sin cobertura de prueba automatizada es probablemente demasiado arriesgada. Las pruebas unitarias mal escrito pueden ser casi tan inútil como tener no comprueba caso.
Reversibility del código se ha mejorado considerablemente mediante mecanismos de comentarios sólido.
El último momento responsable
¿Si no es de antemano, cuando puede hacer las decisiones de diseño? Una de las más importantes lecciones que aprenderá a través de diseño continuo es cognizant de las decisiones sobre el diseño y para decidir conscientemente cuando esas decisiones. Programación eficiente enseña a nosotros para tomar decisiones en el "último responsable de momento." Según a María Poppendieck (en su libro Lean Software Development), siguiendo este principio significa "retrasar el compromiso … hasta que el momento en que no realice una decisión elimina alternativa importante."
El punto es tomar decisiones más tarde posible porque es cuando tiene más información con el que tomar la decisión. Piense en volver al proyecto error que he descrito al principio de este artículo. Ese equipo desarrollado y asignadas a un diseño detallado para el código de acceso a datos demasiado pronto. Si los desarrolladores tenían permiten la interfaz de usuario y lógica empresarial necesita unidad de la forma de código de acceso a datos ya que crean al usuario las características de la interfaz, podría haber impedido que bastante un poco de esfuerzos inútiles. (Esto es un ejemplo de "Diseño controlado por el cliente", donde crear el consumidor de una API primero para definir la forma y firma de la propia API.)
Una de las ideas clave aquí es que debe considerar con antelación y proponer continuamente los cambios de diseño, pero no debería asignar forma definitiva una dirección de diseño hasta que tenga a. No queremos actuar en función de diseño especulativo. Confirmar un diseño anticipado impide la posibilidad de utilizar una alternativa más sencilla o mejor que puede presentar más adelante en el proyecto. Para citar un colega anterior, Mike dos de fame NUnit 2, "reflexión sí con antelación, anticipada no."
Reversibility
Martin Fowler dice, "Si puede cambiar fácilmente sus decisiones, esto significa que es menos importante obtenerlas derecha, lo que hace la vida mucho más sencillo." Estrechamente relacionadas al último momento responsable es el concepto de reversibility, que describiré como la capacidad o la incapacidad para cambiar una decisión. Está cognizant del reversibility inherente de sus decisiones es esencial para siguiendo el principio del último momento. La primera decisión mi equipo realizado para un proyecto reciente era si va a desarrollar con Ruby on Rails o permanecer con una arquitectura de .NET. Elegir una plataforma y lenguaje de programación no son una decisión fácilmente reversible y sabíamos que necesitábamos decidirlo pronto. En otros proyectos, he tenido que coordinar con grupos externos que necesitan para definir y programar sus meses de tiempo de antelación. En los casos, mi equipo absolutamente había que tomar decisiones con antelación para comprometerse con equipos externos.
Una decisión clásica que implica reversibility es si la generación de almacenamiento en caché en una aplicación. Piense en casos donde no sabe por seguro si realmente necesita caché algún dato. Si estás miedo de que la caché será imposible reajustar más adelante, invariablemente tendrá que generar que almacenamiento en caché al principio, aunque puede ser una pérdida de tiempo. Por otro lado, ¿qué ocurre si se ha estructurado el código para aislar el acceso a este datos de tal manera que fácilmente se podría reajustar almacenamiento en caché en el código existente con poco riesgo? En el segundo caso responsable puede renunciar a la compatibilidad con almacenamiento en caché el momento y ofrecer la funcionalidad más rápido.
Reversibility guías también mi equipo en qué tecnologías y técnicas utilizamos. Dado que se utiliza un proceso de entrega incremental (Kanban con prácticas de ingeniería Extreme Programming), hemos favorecer definitivamente tecnologías y prácticas que promover reversibility superior. Nuestro sistema probablemente tendrá que admiten varios motores de base de datos en algún momento en el futuro. Con ese fin, utilizamos un marco de asignación relacional de objetos para desacoplar en gran medida nuestro nivel intermedio el motor de base de datos real. Sólo como importante, tenemos un bastante amplio conjunto de pruebas automatizadas que ejercicio nuestro acceso de la base de datos. Cuando llega el tiempo para intercambiar los motores de base de datos, podemos utilizar dichas pruebas para estar seguro de que nuestro sistema funciona con el nuevo motor de base de datos, o al menos señalar exactamente donde estamos incompatibles.
YAGNI y Thing más sencillo que posiblemente podría trabajar
Para realizar el diseño continuo, tenemos que facilitar el cambiar de nuestro código, pero realmente queremos evitar gran cantidad de modificaciones en nuestro código como se está realizando cambios en él. Para hacerlo entrega incremental, desea centrarse en crear sólo las características que se está encargados con la creación de ahora, pero no queremos que la característica siguiente imposible o difíciles de desarrollar haciendo clic en el diseño sea incompatible con las necesidades futuras.
Programación extrema introdujo dos sayings para el argot de desarrollo que aquí son relevantes: "no se gonna necesita" (YAGNI, pronunciado "yawg nee") y "La más sencilla lo que posiblemente podría trabajar."
En primer lugar, YAGNI prohíbe agregar cualquier código en el sistema ahora no será utilizado por características actuales. " Parálisis del análisis"en el desarrollo de software es un problema muy real y YAGNI corta a través de este problema obligando a centrarse en sólo el problema inmediato. Trabajar con la complejidad es difícil, pero YAGNI ayuda a reducir el ámbito del diseño del sistema que debe considerar en cualquier momento.
Por supuesto, puede sonar miedo YAGNI y quizá incluso irresponsable ya muy bien podría ser necesario el nivel de complejidad omite la primera vez. Siguiente YAGNI no significa que eliminar las posibilidades futuras. Uno de las mejores formas de garantizar consiste en emplear "lo más sencillo que posiblemente podría trabajar."
Me gusta definición de Alan Shalloway de más sencilla lo que posiblemente podría trabajar se muestra en la lista siguiente. (La regla de una vez-y-sólo de vez hace referencia a la eliminación de duplicación desde el código; es otra forma de describir el principio "no repetir manualmente"). Debe elegir la solución más sencilla que todavía se ajusta a estas reglas:
- Ejecuta todas las pruebas.
- Sigue la regla de una vez-y-sólo de vez.
- Tiene alta cohesión.
- Tiene el acoplamiento flexible.
Estas calidades estructurales de código facilitan la modificar posteriormente de código.
El punto de estos sayings complementarias es que cada pieza de complejidad tiene que ganar a su derecha para existe. Piense en todas las cosas que pueden ocurrir cuando se elige una solución más compleja a través de una sencilla:
- Claramente se garantiza la complejidad adicional.
- La complejidad adicional no es necesaria y representa esfuerzos inútiles a través de un enfoque más sencillo.
- La complejidad adicional dificulta el desarrollo más.
- La complejidad adicional resulta para ser incorrecto flat-out y tiene cambiado o reemplazarse.
El resultado de agregar complejidad incluyen un resultado positivo y tres resultados negativos. En cambio, hasta que se demuestre lo contrario, puede ser una solución sencilla adecuada. Más importante, enfoque sencillo probablemente le resultará mucho más fácil para generar y utilizar con otras partes del código, y si tiene que se va a cambiar, bueno, resulta más fácil cambiar código simple que código complejo. El peor es que debe tirar el sencillo código e iniciar a través, sino que vez que esté probable que tenga una mucho mejor comprensión del problema de todos modos.
A veces una solución más compleja se deben activar definitivamente a estar justificado y la elección correcta, pero más a menudo de no, mediante un enfoque más sencillo es mejor al final. Constantemente siguientes YAGNI y "lo más sencillo" cuando está en duda simplemente sigue las probabilidades.
¿Cuánto modelado antes codificación?
Pongamos los requisitos de documentación aparte por el momento. Ésta es una pregunta clásica en el desarrollo de software: "¿cuánto diseño y modelado debe hacer antes de comenzar a código?" No hay ninguna respuesta definitiva porque cada situación es distinta. El punto clave aquí es que cuando no está seguro de cómo continuar, esto significa que se encuentra en un modo de aprendizaje. Si realizar algunos modelado o codificación exploratorias primero estrictamente depende qué enfoque le ayuda a aprender más rápidamente el problema en cuestión y, por supuesto, se debe repetir esta cita clásico de Bertrand Meyer: "No fallo burbujas".
- Si está trabajando con una tecnología desconocida o modelo de diseño, creo que modelado no es casi tan útil como obtener desfasadas con algún código exploratorias las manos.
- Si una idea de diseño es mucho más fácil visualizar en un modelo que en código, por todo es dibujar algunos modelos.
- Si no tienes sabe dónde empezar en el código, no sólo fijamente en la ventana IDE con la esperanza de inspiración. Sacar un lápiz y papel y anote las tareas lógicas y responsabilidades de la tarea que está trabajando.
- Cambie a la segunda llegue a un punto de devoluciones de beneficios con modelos de codificación. (Recuerde que no bloquee burbujas!) Alinear mejor los cuadros del diagrama no ayuda a escribir código mejor!
- Si saltar directamente en la codificación y empezar a tienen dificultades, detener y volver a modelos.
- Recuerde que puede cambiar entre la codificación y definición de modelos. Muchas veces cuando se enfrenta con un problema difícil de codificación, lo mejor es seleccionar las tareas más sencillas, código de aislamiento y utilice el formulario de dicho código para ayudarle a determinar el aspecto que debe tener el resto del código.
Otra cosa a tener en cuenta es que algunas formas de modelado son más ligeras que otros. Si UML no ayuda con un problema, cambie a tarjetas CRC o diagramas de relación de entidad incluso.
Novedades de antemano
En este artículo no tenía ningún tipo de código, pero creo establecimiento inflexible de tipos que estos conceptos se aplican a casi todas las decisiones de diseño. En una columna futura, hablaré sobre algunos conceptos específicos y estrategias para desarrollar diseños que le permiten utilizar los principios de diseño continuo. También describiré con más detalle cómo encaja la refactorización en diseño continuo.
Envíe sus preguntas y comentarios ammpatt@Microsoft.com.
Jeremy Miller , MVP de Microsoft para C#, también es autor de laherramienta de código de código abiertopara la inserción de dependencia con .NET y el próximamenteStoryTellerherramienta para pruebas en .NET de aceptación automática. Visite su blog "El desarrollador del árbol de la sombra"parte del sitio CodeBetter.