Grado amarillo

Índice

Principios

Principio de segregación de interfaces (ISP)

¿Por qué? Las descripciones de servicios que son independientes de un cumplimiento específico son independientes.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
El principio de segregación de interfaces (ISP) es otro SÓLIDO Principio. Segregación significa Separación. Este principio establece que un cliente no debe depender de detalles de un servicio que no necesita. Cuanto menos contenga su interfaz, menor será el acoplamiento entre los dos componentes. Imaginemos que tenemos que planificar un conector para conectar un monitor a un ordenador. Decidimos simplemente hacer que todas las señales que se producen en un ordenador estén disponibles a través de un conector. Puede que tenga unos cientos de clavijas, pero es extremadamente flexible. Por desgracia, esto también maximiza el acoplamiento. En el ejemplo del conector, es obvio que una conexión de monitor sólo debe contener las señales necesarias para mostrar una imagen en el monitor. Lo mismo ocurre con las interfaces de software. También deben ser lo más pequeñas posible para evitar acoplamientos innecesarios. Y al igual que el conector del monitor, la interfaz debe tener un alto nivel de cohesión: Sólo debe contener cosas que realmente estén estrechamente relacionadas. Para aplicar el principio de segregación de interfaces, las dos refactorizaciones Interfaz de extracción y Extraer Superclase disponible.

Fuentes

Fuente Autor Breve descripción
ObjectMentor Robert C. Martin Artículo sobre el Principio de Segregación de Interfaces de 1996, publicado en el Cuaderno de Ingeniería para Informe C

Principio de inversión de la dependencia (DIP)

¿Por qué? Para realizar pruebas precisas es necesario aislar las clases. El aislamiento se produce cuando las clases ya no dependen de las implementaciones, ni en tiempo de ejecución ni en tiempo de traducción. Por tanto, las dependencias concretas deben decidirse lo más tarde posible. Preferiblemente en tiempo de ejecución.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
El principio de inversión de la dependencia (DIP) es una SÓLIDO principio. Dice lo siguiente:
  • Las clases de alto nivel no deben depender de las clases de bajo nivel, pero ambas deben depender de las interfaces.
  • Las interfaces no deben depender de los detalles, sino los detalles de las interfaces.
Si una clase de alto nivel utiliza directamente una clase de bajo nivel, existe un fuerte acoplamiento entre ambas. A más tardar cuando se intente probar la clase de alto nivel de forma aislada, se encontrarán dificultades. Por esta razón, la clase de alto nivel debe depender de una interfaz, que a su vez es implementada por la clase de bajo nivel. Esto significa que la clase de bajo nivel en la prueba unitaria puede ser implementada por un Maqueta ser reemplazado. En principio, existen tres opciones para resolver la dependencia invertida y abstracta con un objeto concreto en tiempo de ejecución:
  • utilizando parámetros constructores "a mano"
  • Uso de un contenedor de inversión de control (contenedor IoC) como Castle Windsor
  • Búsqueda de dependencias
En el grado amarillo inicialmente sólo inyectamos las dependencias a través de los parámetros de los constructores. Inicialmente, esta es la solución más sencilla y funciona bastante bien con un puñado de clases. Más adelante en el grado verde utilizamos un contenedor IoC y la búsqueda de dependencias.

Fuentes

Fuente Autor Breve descripción
objetor Robert C. Martin Artículo sobre el Principio de Inversión de Dependencia de 1996, publicado en el Cuaderno de Ingeniería para Informe C

Principio de sustitución de Liskov (LSP)

¿Por qué? Quien trata con herederos no quiere llevarse sorpresas cuando conoce a los testadores.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
El principio de sustitución de Liskov (LSP) es una SÓLIDO principio. Establece que los subtipos deben comportarse de la misma manera que su tipo base. A primera vista suena banal. El ejemplo de las excepciones deja claro qué problemas surgen si se viola el principio: Si el tipo base no lanza una excepción al ejecutar un método, todos los subtipos deben cumplir esta regla. Si, a pesar de ello, el método de un subtipo lanza una excepción, esto causaría problemas a los usuarios que esperan un objeto del tipo base porque no están preparados para ello. Si el tipo base no lanza una excepción en este punto, el usuario no está preparado para tener que manejar excepciones. En términos más generales, el principio también puede expresarse de forma que un subtipo sólo pueda ampliar la funcionalidad de un tipo base, pero no restringirla. Si un método del tipo base está definido en un determinado rango de valores, el subtipo puede adoptar o ampliar este rango de valores, pero no puede restringirlo en ningún caso. El Principio de Sustitución de Liskov también recomienda pensar muy detenidamente en la herencia. En la inmensa mayoría de los casos, la composición es preferible a la herencia (Prefiera la composición a la herencia). Con la herencia, siempre hay que pensar en el comportamiento, no sólo en la estructura. En lugar de heredar comoes-un y considerar únicamente la estructura (de datos), sería mejor hablar de una se comporta-como relación y tener en cuenta el comportamiento de la clase.

Fuentes

Fuente Autor Breve descripción
objetor Robert C. Martin Artículo sobre el Principio de Sustitución de Liskov de 1996, publicado en el Cuaderno de Ingeniería de Informe C

Principio del menor asombro

¿Por qué? Si un componente se comporta inesperadamente de forma distinta a la esperada, su uso se complica innecesariamente y es propenso a errores.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
El desarrollo de software es, en gran medida, un proceso creativo. En este proceso, es importante sumergirse en el flujo. Una vez alcanzado este estado, el código sale a borbotones. Cualquier alteración del flujo provoca interrupciones y, en última instancia, que se produzca poco código en el tiempo disponible o que la calidad del código no sea óptima. Después de cada interrupción, el desarrollador tiene que volver a acelerar y retomar el flujo. Las sorpresas son interrupciones. Provocan interrupciones y errores. He aquí un ejemplo: Si la asignación de teclas en el entorno de desarrollo es tal que una combinación de teclas habitual, como Ctrl-C, tiene un significado completamente distinto, esto supone un obstáculo para el desarrollador. Un desarrollador se enfadará cada vez que utilice la combinación de teclas "equivocada". Esto dificulta el trabajo creativo. El software debe implementarse con pocas sorpresas. Si un método de consulta llamado ObtenerValor() no sólo proporciona un valor, sino que también cambia el estado del sistema, el desarrollador evitará este método en el mejor de los casos, ya que espera sorpresas desagradables. En el peor de los casos, no se dará cuenta a tiempo de este extraño comportamiento. (Los métodos de consulta que cambian el estado infringen la norma Separación de consultas de comandos ). El desarrollo basado en pruebas promueve interfaces con pocas sorpresas, ya que la interfaz se diseña e implementa desde la perspectiva de su uso.

Principio de ocultación de información

¿Por qué? Al ocultar los detalles en una interfaz, se reducen las dependencias.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
Al diseñar una interfaz, debe preguntarse qué detalles deben ser visibles externamente. Por interfaz no sólo entendemos interfaces en el sentido orientado a objetos, sino también interfaces implícitas. Toda clase tiene inevitablemente una interfaz implícita: contiene todos los detalles visibles desde el exterior. Cuantos más detalles sean visibles desde el exterior, mayor será el acoplamiento entre la clase y sus usuarios. Una vez que los usuarios de una clase utilizan un detalle, resulta más difícil cambiarlo. Esto es contrario a la capacidad de cambio del software.

Prácticas

Pruebas unitarias automatizadas

¿Por qué? Sólo las pruebas automatizadas se ejecutan realmente de forma coherente. Cuanto más preciso sea el código de prueba, mejor.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
En el grado naranja hemos introducido las pruebas de integración, ahora es el momento de las pruebas unitarias. A diferencia de las pruebas de integración, las pruebas unitarias implican probar una única unidad funcional (principalmente clases, pero también métodos o componentes) de forma aislada. Para ello, es necesario poder liberar esta unidad funcional de sus dependencias. Si hay que añadir pruebas unitarias a posteriori para el código existente, suele ser necesario refactorizarlo. Las pruebas de integración nos dan la certeza de que no estamos introduciendo ningún error. Las pruebas automatizadas ofrecen dos ventajas:
  • Ahorras tiempo
  • Quitan el miedo
Cuanto más cambia una base de código, más tiempo se puede ahorrar. Porque cuando cambia el código, hay que probar lo nuevo y lo viejo (pruebas de regresión) una y otra vez. La automatización simplemente ahorra tiempo. Y cuanto más complejo es el código, mayor es la reducción de la ansiedad. Porque si hay que cambiar un código complejo -para añadirle funcionalidades, optimizarlo o simplemente corregirlo- existe un alto riesgo de introducir errores involuntariamente. Sin embargo, las pruebas automatizadas en pequeños pasos los descubren, así que no hay por qué temer "empeorar las cosas". Véase también Herramientas.

Maquetas

¿Por qué? No hay pruebas fácilmente controlables sin maniquíes.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
Por regla general, los componentes utilizan otros componentes. Si desea probar un componente de forma aislada, estas dependencias deben separarse. Ahora sólo nos interesa la funcionalidad del componente que se va a probar (Sistema bajo prueba (SUT)). Y nos interesa saber cómo interactúa el componente con los demás. Al aislar, utilizamos las llamadas maquetas. Se utilizan en lugar de los componentes reales. De este modo, el sistema bajo prueba interactúa con maquetas fácilmente controlables en lugar de componentes reales durante las pruebas. La bibliografía conoce otros términos para designar las maquetas, como Stub, Maniquí o Falsoque a veces se utilizan como sinónimo de maqueta, pero que pueden utilizarse para Diferentes modos de funcionamiento de pie. Antes de utilizar un marco simulado como Rhino Mocks primero debe implementar una maqueta "a mano". Esto ayuda a comprender el mecanismo. Véase también Herramientas.

Análisis de la cobertura del código

¿Por qué? Confíe sólo en las pruebas que sabe que realmente cubren el área de prueba.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
Si es posible, las pruebas unitarias deben cubrir todos los caminos a través de nuestro código. Sólo así podremos estar seguros de que el código funciona correctamente. Para saber qué áreas del código aún no están cubiertas por las pruebas, utilizamos la función Análisis de la cobertura del código. Esto se utiliza para descubrir áreas en el código que aún no se ejecutan durante las pruebas automatizadas. En realidad, las pruebas unitarias deberían cubrir 100% del código que se va a probar. Aunque esto no significa automáticamente que haya suficientes pruebas, una cobertura del código inferior a 100% indica que aún quedan partes del código sobre las que no se puede afirmar que sean correctas. Por tanto, siempre hay que aspirar a una cobertura de código de 100%. En la práctica, sin embargo, resulta que la cobertura de código 100% no siempre puede alcanzarse con una cantidad de esfuerzo inmediatamente justificable. Como en cualquier otra parte de la vida, el esfuerzo para el último 2,3,4 por ciento puede aumentar de forma desproporcionada. Por lo tanto, tras analizar detenidamente la situación de la cobertura, puede ser aceptable conformarse con menos de 100%. Por debajo de 90%, sin embargo, la cobertura es tan irregular que puede considerarse poco profesional. Por eso, si se empieza con pruebas automáticas, siempre hay que medir al mismo tiempo la cobertura del código. De lo contrario, no se puede hacer ninguna afirmación sobre la calidad de las pruebas. Existen dos métricas sencillas para medir la cobertura del código, conocidas como métricas C0 y C1. El ratio C0 mide la cobertura de sentencias, mientras que el ratio C1 mide la cobertura de decisiones o cobertura de ramas.
C0 = (número de instrucciones probadas / número de instrucciones totales) * 100%
C1 = (número de decisiones o ramas probadas / número de decisiones o ramas totales) * 100%
C1 es el indicador más fuerte, ya que 100% de solapamiento de decisión o solapamiento de bifurcación implica 100% de solapamiento de instrucción. Lo contrario no es cierto. La prueba de cobertura de sentencias y la prueba de cobertura de bifurcaciones funcionan sobre la base de un gráfico de flujo de control, véase http://de.wikipedia.org/wiki/Kontrollflussgraphmientras que la prueba de cobertura de decisiones se basa directamente en el código fuente. La prueba de cobertura de sentencias y la prueba de cobertura de ramas están muy bien descritas en http://de.wikipedia.org/wiki/Kontrollflussorientierte_Testverfahren descrito. Véase también Herramientas.

Participación en actos profesionales

¿Por qué? Aprendemos mejor de los demás y en comunidad.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
Para no quedarse "cocido en su propio jugo", es importante debatir e intercambiar experiencias regularmente con otros desarrolladores de software. Para pensar con originalidad, el intercambio debe tener lugar con desarrolladores ajenos a tu propio equipo, a la rutina diaria. Los grupos de usuarios que se pueden encontrar en todas las regiones de Alemania son muy adecuados para ello. Los grupos de usuarios regionales se centran en el intercambio de experiencias. Esto es importante. Sin embargo, cuanto más tiempo pase dentro del mismo grupo, cuanto mejor conozcas a las personas con las que hablas, más convergerán las opiniones dentro de un grupo de usuarios. Por eso es importante seguir pensando con originalidad. Las conferencias interregionales de desarrolladores ofrecen nuevos temas de reflexión y debates con desarrolladores completamente distintos. Por tanto, un CCD debe estar atento a tres niveles para el intercambio de ideas e inspiración: su propio equipo de desarrollo, el grupo regional de usuarios y la conferencia suprarregional. Cada nivel tiene su propio ritmo: diario, mensual, anual. Izquierda:

Refactorizaciones complejas

¿Por qué? No es posible escribir código directamente en la forma definitiva.
Cambiabilidad   
Corrección   
Eficacia de la producción   
Mejora continua   
Desarrollador único
Ya en el grado rojo se han introducido refactorizaciones sencillas. Pero Cambie el nombre de y Método de extracción no bastan para mejorar el código: a menudo es necesario realizar intervenciones importantes. La división en refactorizaciones simples y complejas tiene sentido porque las refactorizaciones complejas sólo pueden llevarse a cabo de forma eficiente y sin riesgos con las pruebas automatizadas existentes. Sin pruebas, no se sabría si el código sigue siendo correcto tras la refactorización. Véase también refactorización-legacy-code.net y bajo Herramientas. Continúa con el grado verde
es_ESEspañol