SlideShare una empresa de Scribd logo
1 de 61
GRUPO 4
CLEAN CODE BOOK
REVIEW
TABLE OF CONTENTS
Chapter 9
Chapter 11
Chapter 10
UNIT TESTS CLASSES
SYSTEMS
PRUEBAS UNITARIAS
Test que validan el comportamiento y
funcionamiento de partes de código
específicas y son aplicadas durante la
fase de Desarrollo de software.
CHAPTER 9
Pruebas Unitarias
1990-1997
Desconocimiento
sobre desarrollo
basado en pruebas.
Selección de
pequeños fragmentos
de código escrito para
probar su
funcionamiento
Uso de programas de
interacción y control
manual
Comprobar pruebas y
código
simultáneamente
Pruebas automatizadas
Leyes del TDD:
1. No crear código de producción hasta crear una prueba unitaria que
presente fallos.
2. No crear más de una prueba de unidad fallida.
3. Crear código de producción necesario para superar la prueba de fallo.
 Impulsadas por el desarrollo guiado por pruebas y el movimiento ágil.
 El TDD implica escribir el código de las pruebas previamente al código de producción.
Código en evolución encargado
de la eficiencia y funcionalidad
del código de producción.
Alto nivel de calidad e
importancia para asegurar
garantía del producto.
Aportan flexibilidad, facilitan el
mantenimiento y posibilidad de
reutilización.
Eliminan riesgos de errores de
difícil detección en código de
producción, posibilitan mejora
de planificación y arquitectura.
Pruebas limpias
¿Qué hace que las pruebas sean
limpias?
Claridad Simplicidad Densidad de
expresión
● Listado 9-1 SerializedPageResponderTest.java
public void testGetPageHieratchyAsXml() throws Exception
{
crawler.addPage(root, PathParser.parse("PageOne"));
crawler.addPage(root, PathParser.parse("PageOne.ChildOne"));
crawler.addPage(root, PathParser.parse("PageTwo"));
request.setResource("root");
request.addInput("type", "pages");
Responder responder = new SerializedPageResponder();
SimpleResponse response = (SimpleResponse) responder.makeResponse( new FitNesseContext(root),
request);
String xml = response.getContent();
assertEquals("text/xml", response.getContentType());
assertSubString("PageOne", xml); assertSubString("PageTwo", xml);
assertSubString("ChildOne", xml);
}
Ejemplos:
public void testGetPageHieratchyAsXmlDoesntContainSymbolicLinks() throws Exception
{
WikiPage pageOne = crawler.addPage(root, PathParser.parse("PageOne"));
crawler.addPage(root, PathParser.parse("PageOne.ChildOne"));
crawler.addPage(root, PathParser.parse("PageTwo"));
PageData data = pageOne.getData();
WikiPageProperties properties = data.getProperties();
WikiPageProperty symLinks = properties.set(SymbolicPage.PROPERTY_NAME);
symLinks.set("SymPage", "PageTwo");
pageOne.commit(data);
request.setResource("root");
request.addInput("type", "pages");
Responder responder = new SerializedPageResponder();
SimpleResponse response = (SimpleResponse) responder.makeResponse( new FitNesseContext(root),
request);
String xml = response.getContent();
assertEquals("text/xml", response.getContentType());
assertSubString("PageOne", xml); assertSubString("PageTwo", xml);
assertSubString("ChildOne", xml); assertNotSubString("SymPage", xml);
}
public void testGetDataAsHtml() throws Exception
{
crawler.addPage(root, PathParser.parse("TestPageOne"), "test page");
request.setResource("TestPageOne");
request.addInput("type", "data");
Responder responder = new SerializedPageResponder();
SimpleResponse response = (SimpleResponse) responder.makeResponse( new FitNesseContext(root), request);
String xml = response.getContent();
assertEquals("text/xml", response.getContentType());
assertSubString("test page", xml);
assertSubString("<Test", xml)
}
public void testGetPageHierarchyAsXml() throws Exception { makePages("PageOne",
"PageOne.ChildOne", "PageTwo");
submitRequest("root", "type:pages");
assertResponseIsXML();
assertResponseContains( "PageOne", "PageTwo", "ChildOne" );
}
public void testSymbolicLinksAreNotInXmlPageHierarchy() throws Exception
{
WikiPage page = makePage("PageOne");
makePages("PageOne.ChildOne", "PageTwo");
addLinkTo(page, "PageTwo", "SymPage");
submitRequest("root", "type:pages");
Listado 9-2 SerializedPageResponderTest.java (refactorizado)
assertResponseIsXML();
assertResponseContains( "PageOne", "PageTwo", "ChildOne" );
assertResponseDoesNotContain("SymPage");
}
public void testGetDataAsXml() throws Exception
{
makePageWithContent("TestPageOne", "test page");
submitRequest("TestPageOne", "type:data");
assertResponseIsXML();
assertResponseContains("test page", "<Test");
}
Diferencias entre códigos de prueba
9-1 SerializedPage
ResponderTest.java
Difícil de entender y
puede mejorarse
Existe código duplicado
que interfiere con
expresividad de prueba.
Ejecución, emisión,
recopilación y creación de
URL demasiado compleja.
9-2 SerializedPage
ResponderTest.java
(refactorizado)
Cumple la misma
función de forma clara y
descriptiva
Patrón BUILD-OPERATE-
CHECK en la estructura del
código
Utilizan tipos de datos y funciones
necesarias, mayor legibilidad y
comprensión para los lectores.
● En lugar de usar API para manipular el sistema, utilizar funciones y
utilidades que usan las API, para facilitar la lectura y escritura de las
pruebas.
● API: lenguaje de pruebas que los programadores usan parar crea
los test y facilitan el entendimiento del lector, evoluciona a través de
cambios continuos en el código.
● Código de la API de pruebas debe ser más sencillo, breve y
expresivo.
● Diferencia de estándares entre código de pruebas y producción en
términos de eficacia.
Lenguaje de prueba específico del dominio
Ejemplos:
● Listado 9-3 EnvironmentControllerTest.java (Prototipo de sistema de control
medioambiental)
● Esta prueba verifica que la alarma de baja temperatura, el calentador y el ventilador se
encienden cuando la temperatura sea demasiado fría.
@Test
public void turnOnLoTempAlarmAtThreashold() throws Exception
{
hw.setTemp(WAY_TOO_COLD);
controller.tic(); assertTrue(hw.heaterState());
assertTrue(hw.blowerState());
assertFalse(hw.coolerState());
assertFalse(hw.hiTempAlarm());
assertTrue(hw.loTempAlarm());
}
@Test
public void turnOnLoTempAlarmAtThreshold() throws Exception
{
wayTooCold();
assertEquals("HBchL", hw.getState());
}
● Función tic reemplazada por wayTooCold, en asserEqual se indica el estado activo e inactivo de los
elementos en el siguiente orden: {calentador, ventilador, enfriador, alarma de alta temperatura,
alarma de baja temperatura}.
● Conociendo el significado de las letras y el código podemos interpretar y comprender el resultado
con mayor facilidad que en la prueba pasada.
Listado 9-4 EnvironmentControllerTest.java (refactorizado)
● La función getState se desarrolla en el código 9.6 por lo que la codificación no es muy eficaz y en
lugar de esta función se pudo utilizar StringBuffer para cambiar las cadenas de estado.
@Test
public void turnOnCoolerAndBlowerIfTooHot() throws Exception
{
tooHot();
assertEquals("hBChl", hw.getState());
}
@Test
public void turnOnHeaterAndBlowerIfTooCold() throws Exception
{
tooCold();
assertEquals("HBchl", hw.getState());
}
Listado 9-5 EnvironmentControllerTest.java (selección más grande)
@Test
public void turnOnHiTempAlarmAtThreshold() throws Exception
{
wayTooHot();
assertEquals("hBCHl", hw.getState());
}
@Test
public void turnOnLoTempAlarmAtThreshold() throws Exception
{
wayTooCold();
assertEquals("HBchL", hw.getState());
}
public String getState()
{
String state = "";
state += heater ? "H" : "h";
state += blower ? "B" : "b";
state += cooler ? "C" : "c";
state += hiTempAlarm ? "H" : "h";
state += loTempAlarm ? "L" : "l";
return state;
}
● Sin embargo, se recomienda no utilizar los StringBuffer por ser poco atractivos en las pruebas,
evitarlos a todo lugar en código de producción y en proyectos de bajo presupuesto con pruebas de
tiempo real, por la limitación de recursos y memoria.
Listado 9-6 MockControlHardware.java
● “Todas las funciones de prueba de un test solo deben tener una instrucción
de afirmación para llegar a una conclusión de forma rápida y sencilla.”
● Listado 9-7 SerializedPageResponderTest.java (afirmación única)
public void testGetPageHierarchyAsXml() throws Exception
{
givenPages("PageOne", "PageOne.ChildOne", "PageTwo");
whenRequestIsIssued("root", "type:pages");
thenResponseShouldBeXML();
}
Una afirmación por prueba
public void testGetPageHierarchyHasRightTags() throws Exception
{
givenPages("PageOne", "PageOne.ChildOne", "PageTwo");
whenRequestIsIssued("root", "type:pages");
thenResponseShouldContain( "PageOne", "PageTwo", "ChildOne" );
}
● Funciones que se dividen en tres partes para tener una sola afirmación, para facilitar el
entendimiento, pero se duplica código.
● Para solucionar el problema podríamos crear una nueva clase con una prueba independiente o
nuevas funciones para llamarlas, pero es más complejo que dividir el código y asignar afirmaciones
múltiples, entonces, la regla de asignar una única afirmación se reemplaza por:
● El número de afirmaciones de una prueba debe ser mínimo.
● Probar un solo concepto en cada función de prueba. Evitar funciones de prueba largas que prueben
una miscelánea de cosas tras otra.
● Listado 9-8
/ ** * Pruebas varias para el método addMonths (). * /
public void testAddMonths()
{
SerialDate d1 = SerialDate.createInstance(31, 5, 2004);
SerialDate d2 = SerialDate.addMonths(1, d1);
assertEquals(30, d2.getDayOfMonth());
assertEquals(6, d2.getMonth());
assertEquals(2004, d2.getYYYY());
Un solo concepto por prueba
SerialDate d3 = SerialDate.addMonths(2, d1);
assertEquals(31, d3.getDayOfMonth());
assertEquals(7, d3.getMonth());
assertEquals(2004, d3.getYYYY());
SerialDate d4 = SerialDate.addMonths(1, SerialDate.addMonths(1, d1));
assertEquals(30, d4.getDayOfMonth());
assertEquals(7, d4.getMonth());
assertEquals(2004, d4.getYYYY());
}
Las tres funciones de prueba probablemente deberían ser así:
● Dado el último día de un mes con 31 días (como mayo):
1. Cuando agrega un mes, de modo que el último día de ese mes sea el 30
(como junio), entonces la fecha debe ser el 30 de ese mes, no 31.
2. Cuando agrega dos meses a esa fecha, de modo que el último mes tenga
31 días, entonces la fecha debería ser 31.
● Dado el último día de un mes con 30 días (como junio):
1. Cuando agrega un mes, de modo que el último día de ese mes tenga 31 días, entonces la fecha debe ser 30,
no 31.
Regla general
Cuando incrementa el mes, la fecha no puede ser mayor que el último día del mes.
Esto implica que incrementar el mes el 28 de febrero debería producir marzo 28.
Falta esa prueba y sería útil escribirla.
Entonces, no son las múltiples afirmaciones en cada sección del Listado 9-8 las que
causan el problema. Más bien, es el hecho de que se está probando más de un
concepto. Entonces probablemente la mejor opción sea en realidad minimizar el
número de afirmaciones por concepto y probar solo una concepto por función de
prueba.
Regla F.I.R.S.T
Rapidez Independecia Repetición
Validación
Automática
Puntualidad
● Las pruebas son tan importantes para la salud de un proyecto como el
código de producción.
● Se debe trabajar en las pruebas hasta que sean concisas y
suficientemente expresivas.
● Es necesario inventar API de prueba que actúen como lenguaje
específico del dominio, para ayuden en la creación de pruebas.
● Mantener una limpieza regular del código de las pruebas para evitar
que se corrompa el código de producción.
Conclusiones
CLASES
CHAPTER 10
Las clases deben ser de
tamaño reducido
Mantener resultados
consistentes
Encapsulación
Organización de clase
Cohesión
El principio de
responsabilidad única
SUBTEMAS
Organizar los cambios
Organización de clases
Según la convención estándar de Java, una clase:
• Comienza con una lista de variables.
• Primero, constantes estáticas públicas.
• Segundo, variables estáticas privadas.
• Tercero, variables de instancia privadas.
• Las funciones públicas deben seguir a la lista de variables.
Encapsulamiento
• Siuna regla del mismo paquete tiene que invocar una función o acceder a
una variable , hacemos que tenga ámbito protected o de paquete
Las clases deben ser de tamaño
reducido
• Con las funciones medimos el tamaño contando líneas físicas. Con las clases
usamos otra medida distinta: las responsabilidades.
Tamaño de la clase
Mal Bien
Pero…
• No solo hay que cuidar que no tenga muchos métodos, sino cuidar
especialmente que la clase no tenga muchas responsabilidades.
• Una clave para identificar las responsabilidades es asociar a las mismas con el
nombre de la clase.
• Cuanto mas ambiguo sea el nombre de una clase más probabilidades hay de
que tenga demasiadas responsabilidades.
• Otra clavees que a la hora de describir la clase no nos encontremos con
palabras como “y”, “o”, “si”, “pero”.
Principio de responsabilidad única
• Las clases solo deben tener una responsabilidad ypor ende, solo un motivo
para cambiar.
• Podemos extraer los tres métodos de SuperDashBoard relacionados con la
información de versiones en una clase independiente como Version. La clase
Version es una construcción que se puede reutilizar en otras aplicaciones.
Principio de responsabilidad única
• En conclusión: “Los sistemas deben estar formados por
muchas clases reducidas, no por algunas de gran tamaño.
Cada clase reducida encapsula una única responsabilidad,
tiene solo un motivo para cambiar ycolabora con algunas
otras para obtener los comportamientos deseados del
sistema”
Cohesión
• Las clases deben tener un número reducido de variables de instancia.
• Los métodos de una clase deben manipular una o varias de dichas variables.
• Cuantas más variables manipule un método, más cohesión tendrá con su
clase.
• Una clase en la que cada variable se usa en cada método tiene una cohesión
máxima.
• La idea es crear una dependencia lógica entre métodos y variables.
Cohesión = grado de utilización de las variables de instancia por parte de las
funciones. Queremos clases cohesionadas. Cuando se reduce el tamaño de
las funciones se aumenta el tamaño de variables de instancia (para no
pasarlas como parámetro a las subfunciones) y se pierde cohesión. En ese
caso lo mejor es dividir en subclases.
Ejemplo de cohesión
x
Mantener resultados consistentes en
clases de tamaño reducido
• La división de grandes funciones en otras más pequeña aumenta la
proliferación de clases.
• Sinecesito que dentro de una función 1 se llame a una función 2, en lugar de
mandarle a ésta las variables declaradas en la función 1, estas variables
hacerse de instancia o globales en la clase pero esto implica que se pierda
cohesión yaque acumularían más ymás variables globales que solo existen
para que otras funciones las compartan.
• Cuando esto sucede es conveniente crear otra clase.
● En un sistema limpio, organizamos nuestras clases para reducir el
riesgo de cambio, puesto que en la mayoría de sistemas el cambio es
continuo.
Listado 10-9
Organizándose para el cambio
public class Sql {
public Sql(String table, Column[] columns)
public String create()
public String insert(Object[] fields)
public String selectAll()
public String findByKey(String keyColumn, String keyValue)
public String select(Column column, String pattern)
public String select(Criteria criteria)
public String preparedInsert()
private String columnList(Column[] columns)
private String valuesList(Object[] fields, final Column[] columns)
private String selectWithCriteria(String criteria)
private String placeholderList(Column[] columns)
}
● Lo que podemos identificar en el listado 10-9 es que existe una clase con
varios métodos de los cuales se podrían definir varias responsabilidades,
lo cual en el SRP define que es difícil darles mantenimiento o extenderlo.
● La clase Sql del listado 10-9 podría cambiar cuando agreguemos un
nuevo tipo de declaración, además cambiaria cuando modifiquemos los
detalles de los tipos de declaración por lo que tendríamos 2
responsabilidades , con lo cual viola el SRP.
● SRP dicta que cada clase debe hacer solamente una cosa, ósea tener una
única responsabilidad.
● Si existiese el caso en el se supiera que el software no recibirá una
actualización en el futuro podríamos considerar al código del listado 10-9
como funcional.
Organizándose para el cambio
● Aplicando los principios de responsabilidad única (SRP) al código del
listado 10-9 nos quedaría de la siguiente manera:
Listado 10-10
Organizándose para el cambio
abstract public class Sql {
public Sql(String table, Column[] columns)
abstract public String generate();
}
public class CreateSql extends Sql {
public CreateSql(String table, Column[] columns)
@Override public String generate()
}
public class SelectSql extends Sql {
public SelectSql(String table, Column[] columns)
@Override public String generate()
}
public class InsertSql extends Sql {
public InsertSql(String table, Column[] columns, Object[] fields)
@Override public String generate()
private String valuesList(Object[] fields, final Column[] columns)
}
● Podemos observar que el código se ha vuelto mas simple y entendible,
además el riesgo de que al agregar una nueva funcional rompa otra
importante se va reduciendo.
● Adicional las clases del listado 10-10 admite otro principio clave de
diseño el cual es conocido como OCP (Principio Abierto-Cerrado) el cual
dicta que las clases deben estar abierta para extensiones en el código
pero cerradas para las posibles modificaciones del mismo.
● En el listado 10-10 cumple esto puesto que su código esta abierta para
permitir nuevas funcionalidades sin modificar las funcionalidades ya
existentes.
Organizándose para el cambio
● Dentro de nuestro sistemas existen clases que tienen detalles concretos
los cuales están en riesgo cuando se necesite modificar los mismo. Para
evitar los riesgos ante este tipo de situaciones lo que podemos aplicar
es el principio de inversión de dependencia (DIR).
● El DIR explica que nuestras clases no deben de depender de detalles
concretos sino que deberían de depender de abstracciones como las
interfaces, que lo que hace la interfaz es aislar los detalles concretos
para que el código se libre de depender de estos y que se desacople.
Aislamiento del cambio
Ejemplo de Aislamiento del
Cambio
En la imagen podemos observar dos clases; la clase botón y la clase lampara,
podemos observar que la clase botón depende directamente de lampara es
decir que si en la clase lámpara realizamos algún cambio el botón cambiara
también.
Otro aspecto es que el código no es reutilizable puesto que botón esta
simplemente enfocado a lámpara, es decir si en un futuro se quisiera
agregar una nueva clase televisión por ejemplo, la clase botón quedaría sin
utilidad para la clase televisión.
Ejemplo de Aislamiento del
Cambio
En la imagen podemos observar que se agrego una interfaz, con ello la
clase botón depende únicamente de abstracciones y esto conlleva a que
pueda ser reusado varias veces.
Adicional si se realiza cambios en la clase lampara la clase botón debería
recibir ningún cambio y la clase lámpara es quien debe adaptarse a la
interfaz definida, además se pueden acoplar varias clases, como
televisor, lavadora, etc.
Conclusiones
● Orden dentro de la clase: Contantes estáticas, variables estáticas, variables de
instancia y funciones. De todo ello, primero lo público y después lo privado.
● El tamaño debe ser reducido, debe tener una única responsabilidad, la que
indica su nombre. Nombres a evitar son Manager, Processor, Super ya que
denotan muchas responsabilidades.You can write about the topic here
● Single Responsibility Principle, una clase debe tener un único motivo para
cambiar.
● Open/Closed Principle = las clases deben estar abiertas a extensión y cerradas a
modificación. Los cambios mejor que se hagan extendiendo o introduciendo
nuevas clases, no modificando las existentes.
● La organización ante posibles cambios de nuestra aplicación es muy útil, puesto
que esto lo hace mas legible y fácil de modificar o aumentar ciertas
funcionalidades, de lo contrario se debería realizar nuevamente las clases que no
tengan una organización adecuada.
SISTEMAS
CHAPTER 11
● Considerar que la construcción es un proceso diferente al uso, el
proceso de inicio siempre es una preocupación que cualquier software
debe abordar. Para ello existe una técnica de diseño llamada la
separación de preocupaciones (SoC).
● SoC nos indica que que evitemos escribir funciones largas y complejas,
por ejemplo si notamos que la función comienza a aumentar de tamaño
posiblemente la función se este ocupando de demasiadas cosas a la
vez. Lo cual lo mas prudente seria refactorizarlo.
Separar la construcción de un sistema de
su uso
● Una forma de separar la construcción del uso, consiste en mover todos
los aspectos de la construcción al main, luego diseñar el resto del
sistema asumiendo que todos los objetos se han construido y
organizado de manera apropiada.
● El flujo de control es fácil de seguir. El main construye los objetos
necesarios para el sistema, luego los pasa a la aplicación, que
simplemente los usa. La aplicación no tiene conocimiento del proceso
del main o de construcción, simplemente espera que todo se haya
construido correctamente.
Separación de main
● Ciertas ocasiones necesitamos que la aplicación sea responsable de la
creación de objetos, por lo que es necesario el uso del patron de diseño
Abstract Factory.
Factories
● Una fabrica abstracta tiene métodos los cuales permite acceder a otras
fábricas independientes y sus familias para obtener la instancia de
algún objeto de dicha familia.
● En la fábrica abstracta se define métodos los cuales nos permitirán
tener una conexión con cada una de las familias independientes para
que sea más sencillo realizar un llamado a la familia que se necesite.
● Una fábrica independiente lo que se realiza es la implementación de la
fábrica abstracta con el objetivo de que podamos elegir a que objeto
deseamos acceder u obtener su instancia, una vez que obtenemos la
instancia de algún objeto también tenemos acceso a los métodos de
dicho objeto.
Factories
● DI nos permite inyectar comportamientos a componentes haciendo que
nuestras piezas de software sean independientes y se comuniquen
únicamente a través de una interface. DI extrae responsabilidades a un
componente para delegarlas en otro, estableciendo un mecanismo a
través del cual el nuevo componente puede ser cambiado en tiempo de
ejecución. Para lograr esta tarea DI se basa en un patrón más genérico
llamado Inversión de Control (Inversion of Control).
● DI tiene como finalidad solucionar un problema común que los
programadores encuentran en la construcción de aplicaciones. Este es,
mantener los componentes o capas de una aplicación lo más
desacopladas posible,
Inyección de dependencia
● Los sistemas de software son únicos en comparación con los sistemas
físicos. Sus arquitecturas pueden crecer incrementalmente, si
mantenemos la adecuada separación de preocupaciones.
● Las arquitecturas EJB no separan las preocupaciones de manera
adecuada, por lo tanto impide que el crecimiento orgánico. Esto vuelve
a EJB en una arquitectura bastante complicada y amplia. Crea
soluciones costosas y complejas.
Ampliar
En el desarrollo de cualquier aplicación, existen las llamadas
"preocupaciones transversales", que son actividades comunes de la mayoría
de las aplicaciones: inicio de sesión, seguridad, transacciones
PREOCUPACIONES TRANSVERSALES
Proxy: es un patrón de diseño estructural que proporciona un objeto que
actúa como sustituto de un objeto de servicio real utilizado por un cliente.
PROXY DE JAVA
AOP: una tecnología para programación orientada a aspectos, que realiza el
mantenimiento unificado de las funciones del programa a través de la
compilación previa y agentes dinámicos durante el tiempo de ejecución.
Spring AOP: El famoso framework para aplicaciones spring en su núcleo
tiene un framework para AOP. Este framework es implementado en java puro
con las anotaciones de java @Aspect o basado en esquema con un XML.
FRAMEWORKS DE JAVA PURO AOP
Es la extensión orientada a aspectos de java. Este esta disponible en Eclipse
Fundation. Es el lenguaje de POA más usado debido a que es particularmente
fácil de aprender y utilizar.
AspectJ Aspectos
 Probar la arquitectura del sistema.
 Optimizar la toma de decisiones.
 Utilizar los estándares con prudencia cuando añadan un valor
demostrable.
Recomendaciones
 COOL(COOrdination Language): trata los aspectos de sincronismo entre
hilos concurrentes. (Java)
 RIDL (Remote Interaction and Data transfers aspect Language)
 MALAJ (Multi Aspect LAnguage for Java)
 KALA: Modelos transaccionales avanzados
 DIE: Un lenguaje de aspectos de dominio específico para eventos de
IDE
 HYPERJ
 AspectG(ANTLR)
 AspectMatlab
Lenguajes de dominio específico
Referencias:
Martin, R. (2009). Clean Code. Pearson Education.
PREGUNTAS
https://forms.office.com/Pages/ResponsePage.aspx?id=aRS-
jZzHIU6dQ8pl2enEdaQanmCOBelNplUKCqFIgGxUMjU2SlpOSEM4SV
BGWlVOVDhNUTEwOTJSNS4u

Más contenido relacionado

Similar a Pruebas unitarias Clean Code Book (20)

Guia7 java
Guia7 javaGuia7 java
Guia7 java
 
preparedStatement
preparedStatementpreparedStatement
preparedStatement
 
Curso TDD Ruby on Rails #03: Tests unitarios
Curso TDD Ruby on Rails #03: Tests unitariosCurso TDD Ruby on Rails #03: Tests unitarios
Curso TDD Ruby on Rails #03: Tests unitarios
 
Mod2ud2 1
Mod2ud2 1Mod2ud2 1
Mod2ud2 1
 
Ingenieria de sw Junit
Ingenieria de sw JunitIngenieria de sw Junit
Ingenieria de sw Junit
 
Ayuda la clase statement
Ayuda la clase statementAyuda la clase statement
Ayuda la clase statement
 
ee
eeee
ee
 
Statement
StatementStatement
Statement
 
Qunit CookBook español
Qunit CookBook españolQunit CookBook español
Qunit CookBook español
 
Best Practices
Best PracticesBest Practices
Best Practices
 
Guia5 java
Guia5 javaGuia5 java
Guia5 java
 
Java básico
Java  básicoJava  básico
Java básico
 
Statement
Statement Statement
Statement
 
Prepared statement
Prepared statementPrepared statement
Prepared statement
 
Prepared statement
Prepared statementPrepared statement
Prepared statement
 
Statement
StatementStatement
Statement
 
Introducción a TDD y PHPUnit
Introducción a TDD y PHPUnitIntroducción a TDD y PHPUnit
Introducción a TDD y PHPUnit
 
¿Cómo mantener tu javascript?: Buenas prácticas
¿Cómo mantener tu javascript?: Buenas prácticas¿Cómo mantener tu javascript?: Buenas prácticas
¿Cómo mantener tu javascript?: Buenas prácticas
 
Samuel bailon sanchez
Samuel bailon sanchezSamuel bailon sanchez
Samuel bailon sanchez
 
Samuel bailon sanchez
Samuel bailon sanchezSamuel bailon sanchez
Samuel bailon sanchez
 

Último

MANUAL DE NORMAS SANITARIAS PERUANAS ACTUALIZADO 2024.pdf
MANUAL DE NORMAS SANITARIAS PERUANAS ACTUALIZADO 2024.pdfMANUAL DE NORMAS SANITARIAS PERUANAS ACTUALIZADO 2024.pdf
MANUAL DE NORMAS SANITARIAS PERUANAS ACTUALIZADO 2024.pdfciteagrohuallaga07
 
SESION 2- 2 ATOMO Y ESTRUCTURA ATÓMICA.pdf
SESION 2- 2 ATOMO Y ESTRUCTURA ATÓMICA.pdfSESION 2- 2 ATOMO Y ESTRUCTURA ATÓMICA.pdf
SESION 2- 2 ATOMO Y ESTRUCTURA ATÓMICA.pdfEsvinAlvares
 
PRIMER Y SEGUNDO TEOREMA DE CASTIGLIANO.pdf
PRIMER Y SEGUNDO TEOREMA DE CASTIGLIANO.pdfPRIMER Y SEGUNDO TEOREMA DE CASTIGLIANO.pdf
PRIMER Y SEGUNDO TEOREMA DE CASTIGLIANO.pdfAuraGabriela2
 
Guía para la identificación de materiales peligrosos
Guía para la identificación de materiales peligrososGuía para la identificación de materiales peligrosos
Guía para la identificación de materiales peligrososAdrianVarela22
 
La Evolución Industrial en el Ecuador.pdf
La Evolución Industrial en el Ecuador.pdfLa Evolución Industrial en el Ecuador.pdf
La Evolución Industrial en el Ecuador.pdfAnthony Gualpa
 
Capacitación Anexo 6 D.s. 023 seguridad y salud ocupacional
Capacitación Anexo 6 D.s. 023 seguridad y salud ocupacionalCapacitación Anexo 6 D.s. 023 seguridad y salud ocupacional
Capacitación Anexo 6 D.s. 023 seguridad y salud ocupacionalamador030809
 
Sanidad en alpacas, enfermedades infecciosas y parasitarias
Sanidad en alpacas, enfermedades infecciosas y parasitariasSanidad en alpacas, enfermedades infecciosas y parasitarias
Sanidad en alpacas, enfermedades infecciosas y parasitariasJilvertHuisaCenteno
 
PRESENTACIÓN ANALISIS ESTRUCTURAL II.pptx
PRESENTACIÓN ANALISIS ESTRUCTURAL II.pptxPRESENTACIÓN ANALISIS ESTRUCTURAL II.pptx
PRESENTACIÓN ANALISIS ESTRUCTURAL II.pptxStibeCr
 
ENSAYO DE PENETRACIÓN ESTÁTICA CTP ULTRADEFINITIVO.pptx
ENSAYO DE PENETRACIÓN ESTÁTICA CTP ULTRADEFINITIVO.pptxENSAYO DE PENETRACIÓN ESTÁTICA CTP ULTRADEFINITIVO.pptx
ENSAYO DE PENETRACIÓN ESTÁTICA CTP ULTRADEFINITIVO.pptxjosetuanama2
 
04-circuitos-comparadores de amplificadores operacionales.pptx
04-circuitos-comparadores de amplificadores operacionales.pptx04-circuitos-comparadores de amplificadores operacionales.pptx
04-circuitos-comparadores de amplificadores operacionales.pptxHenryApaza12
 
Análisis de Varianza- Anova y pruebas de estadística
Análisis de Varianza- Anova y pruebas de estadísticaAnálisis de Varianza- Anova y pruebas de estadística
Análisis de Varianza- Anova y pruebas de estadísticaJoellyAlejandraRodrg
 
FOLIACIONES Y LINEACIONES GEOLOGÍA ESTRUCTURAL
FOLIACIONES Y LINEACIONES GEOLOGÍA ESTRUCTURALFOLIACIONES Y LINEACIONES GEOLOGÍA ESTRUCTURAL
FOLIACIONES Y LINEACIONES GEOLOGÍA ESTRUCTURALRiveraPemintelAlejan
 
electricidad básica, ejemplos prácticos y ejercicios
electricidad básica, ejemplos prácticos y ejercicioselectricidad básica, ejemplos prácticos y ejercicios
electricidad básica, ejemplos prácticos y ejerciciosEfrain Yungan
 
INSTRUCTIVO_NNNNNNNNNNNNNNSART2 iess.pdf
INSTRUCTIVO_NNNNNNNNNNNNNNSART2 iess.pdfINSTRUCTIVO_NNNNNNNNNNNNNNSART2 iess.pdf
INSTRUCTIVO_NNNNNNNNNNNNNNSART2 iess.pdfautomatechcv
 
PRESENTACION Y PROGRAMAS PRE-REQUISITOS DEL SISTEMA HACCP BPM Y PHS 2023.pptx
PRESENTACION Y PROGRAMAS PRE-REQUISITOS DEL SISTEMA HACCP BPM Y PHS 2023.pptxPRESENTACION Y PROGRAMAS PRE-REQUISITOS DEL SISTEMA HACCP BPM Y PHS 2023.pptx
PRESENTACION Y PROGRAMAS PRE-REQUISITOS DEL SISTEMA HACCP BPM Y PHS 2023.pptxciteagrohuallaga07
 
Transporte y Manipulación de Explosivos - SUCAMEC
Transporte y Manipulación de Explosivos - SUCAMECTransporte y Manipulación de Explosivos - SUCAMEC
Transporte y Manipulación de Explosivos - SUCAMECamador030809
 
209530529 Licuacion-de-Suelos-en-Arequipa.pdf
209530529 Licuacion-de-Suelos-en-Arequipa.pdf209530529 Licuacion-de-Suelos-en-Arequipa.pdf
209530529 Licuacion-de-Suelos-en-Arequipa.pdfnurix_15
 
R. Contraloria 432-2023-CG obras x AD.pdf
R. Contraloria 432-2023-CG obras x AD.pdfR. Contraloria 432-2023-CG obras x AD.pdf
R. Contraloria 432-2023-CG obras x AD.pdfrudy cabezas
 
EXPOSICION UNIDAD 3 MANTENIMIENTOO .pptx
EXPOSICION UNIDAD 3 MANTENIMIENTOO .pptxEXPOSICION UNIDAD 3 MANTENIMIENTOO .pptx
EXPOSICION UNIDAD 3 MANTENIMIENTOO .pptxKeylaArlethTorresOrt
 
La mineralogia y minerales, clasificacion
La mineralogia y minerales, clasificacionLa mineralogia y minerales, clasificacion
La mineralogia y minerales, clasificacionnewspotify528
 

Último (20)

MANUAL DE NORMAS SANITARIAS PERUANAS ACTUALIZADO 2024.pdf
MANUAL DE NORMAS SANITARIAS PERUANAS ACTUALIZADO 2024.pdfMANUAL DE NORMAS SANITARIAS PERUANAS ACTUALIZADO 2024.pdf
MANUAL DE NORMAS SANITARIAS PERUANAS ACTUALIZADO 2024.pdf
 
SESION 2- 2 ATOMO Y ESTRUCTURA ATÓMICA.pdf
SESION 2- 2 ATOMO Y ESTRUCTURA ATÓMICA.pdfSESION 2- 2 ATOMO Y ESTRUCTURA ATÓMICA.pdf
SESION 2- 2 ATOMO Y ESTRUCTURA ATÓMICA.pdf
 
PRIMER Y SEGUNDO TEOREMA DE CASTIGLIANO.pdf
PRIMER Y SEGUNDO TEOREMA DE CASTIGLIANO.pdfPRIMER Y SEGUNDO TEOREMA DE CASTIGLIANO.pdf
PRIMER Y SEGUNDO TEOREMA DE CASTIGLIANO.pdf
 
Guía para la identificación de materiales peligrosos
Guía para la identificación de materiales peligrososGuía para la identificación de materiales peligrosos
Guía para la identificación de materiales peligrosos
 
La Evolución Industrial en el Ecuador.pdf
La Evolución Industrial en el Ecuador.pdfLa Evolución Industrial en el Ecuador.pdf
La Evolución Industrial en el Ecuador.pdf
 
Capacitación Anexo 6 D.s. 023 seguridad y salud ocupacional
Capacitación Anexo 6 D.s. 023 seguridad y salud ocupacionalCapacitación Anexo 6 D.s. 023 seguridad y salud ocupacional
Capacitación Anexo 6 D.s. 023 seguridad y salud ocupacional
 
Sanidad en alpacas, enfermedades infecciosas y parasitarias
Sanidad en alpacas, enfermedades infecciosas y parasitariasSanidad en alpacas, enfermedades infecciosas y parasitarias
Sanidad en alpacas, enfermedades infecciosas y parasitarias
 
PRESENTACIÓN ANALISIS ESTRUCTURAL II.pptx
PRESENTACIÓN ANALISIS ESTRUCTURAL II.pptxPRESENTACIÓN ANALISIS ESTRUCTURAL II.pptx
PRESENTACIÓN ANALISIS ESTRUCTURAL II.pptx
 
ENSAYO DE PENETRACIÓN ESTÁTICA CTP ULTRADEFINITIVO.pptx
ENSAYO DE PENETRACIÓN ESTÁTICA CTP ULTRADEFINITIVO.pptxENSAYO DE PENETRACIÓN ESTÁTICA CTP ULTRADEFINITIVO.pptx
ENSAYO DE PENETRACIÓN ESTÁTICA CTP ULTRADEFINITIVO.pptx
 
04-circuitos-comparadores de amplificadores operacionales.pptx
04-circuitos-comparadores de amplificadores operacionales.pptx04-circuitos-comparadores de amplificadores operacionales.pptx
04-circuitos-comparadores de amplificadores operacionales.pptx
 
Análisis de Varianza- Anova y pruebas de estadística
Análisis de Varianza- Anova y pruebas de estadísticaAnálisis de Varianza- Anova y pruebas de estadística
Análisis de Varianza- Anova y pruebas de estadística
 
FOLIACIONES Y LINEACIONES GEOLOGÍA ESTRUCTURAL
FOLIACIONES Y LINEACIONES GEOLOGÍA ESTRUCTURALFOLIACIONES Y LINEACIONES GEOLOGÍA ESTRUCTURAL
FOLIACIONES Y LINEACIONES GEOLOGÍA ESTRUCTURAL
 
electricidad básica, ejemplos prácticos y ejercicios
electricidad básica, ejemplos prácticos y ejercicioselectricidad básica, ejemplos prácticos y ejercicios
electricidad básica, ejemplos prácticos y ejercicios
 
INSTRUCTIVO_NNNNNNNNNNNNNNSART2 iess.pdf
INSTRUCTIVO_NNNNNNNNNNNNNNSART2 iess.pdfINSTRUCTIVO_NNNNNNNNNNNNNNSART2 iess.pdf
INSTRUCTIVO_NNNNNNNNNNNNNNSART2 iess.pdf
 
PRESENTACION Y PROGRAMAS PRE-REQUISITOS DEL SISTEMA HACCP BPM Y PHS 2023.pptx
PRESENTACION Y PROGRAMAS PRE-REQUISITOS DEL SISTEMA HACCP BPM Y PHS 2023.pptxPRESENTACION Y PROGRAMAS PRE-REQUISITOS DEL SISTEMA HACCP BPM Y PHS 2023.pptx
PRESENTACION Y PROGRAMAS PRE-REQUISITOS DEL SISTEMA HACCP BPM Y PHS 2023.pptx
 
Transporte y Manipulación de Explosivos - SUCAMEC
Transporte y Manipulación de Explosivos - SUCAMECTransporte y Manipulación de Explosivos - SUCAMEC
Transporte y Manipulación de Explosivos - SUCAMEC
 
209530529 Licuacion-de-Suelos-en-Arequipa.pdf
209530529 Licuacion-de-Suelos-en-Arequipa.pdf209530529 Licuacion-de-Suelos-en-Arequipa.pdf
209530529 Licuacion-de-Suelos-en-Arequipa.pdf
 
R. Contraloria 432-2023-CG obras x AD.pdf
R. Contraloria 432-2023-CG obras x AD.pdfR. Contraloria 432-2023-CG obras x AD.pdf
R. Contraloria 432-2023-CG obras x AD.pdf
 
EXPOSICION UNIDAD 3 MANTENIMIENTOO .pptx
EXPOSICION UNIDAD 3 MANTENIMIENTOO .pptxEXPOSICION UNIDAD 3 MANTENIMIENTOO .pptx
EXPOSICION UNIDAD 3 MANTENIMIENTOO .pptx
 
La mineralogia y minerales, clasificacion
La mineralogia y minerales, clasificacionLa mineralogia y minerales, clasificacion
La mineralogia y minerales, clasificacion
 

Pruebas unitarias Clean Code Book

  • 1. GRUPO 4 CLEAN CODE BOOK REVIEW
  • 2. TABLE OF CONTENTS Chapter 9 Chapter 11 Chapter 10 UNIT TESTS CLASSES SYSTEMS
  • 3. PRUEBAS UNITARIAS Test que validan el comportamiento y funcionamiento de partes de código específicas y son aplicadas durante la fase de Desarrollo de software. CHAPTER 9
  • 4. Pruebas Unitarias 1990-1997 Desconocimiento sobre desarrollo basado en pruebas. Selección de pequeños fragmentos de código escrito para probar su funcionamiento Uso de programas de interacción y control manual Comprobar pruebas y código simultáneamente
  • 5. Pruebas automatizadas Leyes del TDD: 1. No crear código de producción hasta crear una prueba unitaria que presente fallos. 2. No crear más de una prueba de unidad fallida. 3. Crear código de producción necesario para superar la prueba de fallo.  Impulsadas por el desarrollo guiado por pruebas y el movimiento ágil.  El TDD implica escribir el código de las pruebas previamente al código de producción.
  • 6. Código en evolución encargado de la eficiencia y funcionalidad del código de producción. Alto nivel de calidad e importancia para asegurar garantía del producto. Aportan flexibilidad, facilitan el mantenimiento y posibilidad de reutilización. Eliminan riesgos de errores de difícil detección en código de producción, posibilitan mejora de planificación y arquitectura. Pruebas limpias
  • 7. ¿Qué hace que las pruebas sean limpias? Claridad Simplicidad Densidad de expresión
  • 8. ● Listado 9-1 SerializedPageResponderTest.java public void testGetPageHieratchyAsXml() throws Exception { crawler.addPage(root, PathParser.parse("PageOne")); crawler.addPage(root, PathParser.parse("PageOne.ChildOne")); crawler.addPage(root, PathParser.parse("PageTwo")); request.setResource("root"); request.addInput("type", "pages"); Responder responder = new SerializedPageResponder(); SimpleResponse response = (SimpleResponse) responder.makeResponse( new FitNesseContext(root), request); String xml = response.getContent(); assertEquals("text/xml", response.getContentType()); assertSubString("PageOne", xml); assertSubString("PageTwo", xml); assertSubString("ChildOne", xml); } Ejemplos:
  • 9. public void testGetPageHieratchyAsXmlDoesntContainSymbolicLinks() throws Exception { WikiPage pageOne = crawler.addPage(root, PathParser.parse("PageOne")); crawler.addPage(root, PathParser.parse("PageOne.ChildOne")); crawler.addPage(root, PathParser.parse("PageTwo")); PageData data = pageOne.getData(); WikiPageProperties properties = data.getProperties(); WikiPageProperty symLinks = properties.set(SymbolicPage.PROPERTY_NAME); symLinks.set("SymPage", "PageTwo"); pageOne.commit(data); request.setResource("root"); request.addInput("type", "pages"); Responder responder = new SerializedPageResponder(); SimpleResponse response = (SimpleResponse) responder.makeResponse( new FitNesseContext(root), request); String xml = response.getContent();
  • 10. assertEquals("text/xml", response.getContentType()); assertSubString("PageOne", xml); assertSubString("PageTwo", xml); assertSubString("ChildOne", xml); assertNotSubString("SymPage", xml); } public void testGetDataAsHtml() throws Exception { crawler.addPage(root, PathParser.parse("TestPageOne"), "test page"); request.setResource("TestPageOne"); request.addInput("type", "data"); Responder responder = new SerializedPageResponder(); SimpleResponse response = (SimpleResponse) responder.makeResponse( new FitNesseContext(root), request); String xml = response.getContent(); assertEquals("text/xml", response.getContentType()); assertSubString("test page", xml); assertSubString("<Test", xml) }
  • 11. public void testGetPageHierarchyAsXml() throws Exception { makePages("PageOne", "PageOne.ChildOne", "PageTwo"); submitRequest("root", "type:pages"); assertResponseIsXML(); assertResponseContains( "PageOne", "PageTwo", "ChildOne" ); } public void testSymbolicLinksAreNotInXmlPageHierarchy() throws Exception { WikiPage page = makePage("PageOne"); makePages("PageOne.ChildOne", "PageTwo"); addLinkTo(page, "PageTwo", "SymPage"); submitRequest("root", "type:pages"); Listado 9-2 SerializedPageResponderTest.java (refactorizado)
  • 12. assertResponseIsXML(); assertResponseContains( "PageOne", "PageTwo", "ChildOne" ); assertResponseDoesNotContain("SymPage"); } public void testGetDataAsXml() throws Exception { makePageWithContent("TestPageOne", "test page"); submitRequest("TestPageOne", "type:data"); assertResponseIsXML(); assertResponseContains("test page", "<Test"); }
  • 13. Diferencias entre códigos de prueba 9-1 SerializedPage ResponderTest.java Difícil de entender y puede mejorarse Existe código duplicado que interfiere con expresividad de prueba. Ejecución, emisión, recopilación y creación de URL demasiado compleja. 9-2 SerializedPage ResponderTest.java (refactorizado) Cumple la misma función de forma clara y descriptiva Patrón BUILD-OPERATE- CHECK en la estructura del código Utilizan tipos de datos y funciones necesarias, mayor legibilidad y comprensión para los lectores.
  • 14. ● En lugar de usar API para manipular el sistema, utilizar funciones y utilidades que usan las API, para facilitar la lectura y escritura de las pruebas. ● API: lenguaje de pruebas que los programadores usan parar crea los test y facilitan el entendimiento del lector, evoluciona a través de cambios continuos en el código. ● Código de la API de pruebas debe ser más sencillo, breve y expresivo. ● Diferencia de estándares entre código de pruebas y producción en términos de eficacia. Lenguaje de prueba específico del dominio
  • 15. Ejemplos: ● Listado 9-3 EnvironmentControllerTest.java (Prototipo de sistema de control medioambiental) ● Esta prueba verifica que la alarma de baja temperatura, el calentador y el ventilador se encienden cuando la temperatura sea demasiado fría. @Test public void turnOnLoTempAlarmAtThreashold() throws Exception { hw.setTemp(WAY_TOO_COLD); controller.tic(); assertTrue(hw.heaterState()); assertTrue(hw.blowerState()); assertFalse(hw.coolerState()); assertFalse(hw.hiTempAlarm()); assertTrue(hw.loTempAlarm()); }
  • 16. @Test public void turnOnLoTempAlarmAtThreshold() throws Exception { wayTooCold(); assertEquals("HBchL", hw.getState()); } ● Función tic reemplazada por wayTooCold, en asserEqual se indica el estado activo e inactivo de los elementos en el siguiente orden: {calentador, ventilador, enfriador, alarma de alta temperatura, alarma de baja temperatura}. ● Conociendo el significado de las letras y el código podemos interpretar y comprender el resultado con mayor facilidad que en la prueba pasada. Listado 9-4 EnvironmentControllerTest.java (refactorizado)
  • 17. ● La función getState se desarrolla en el código 9.6 por lo que la codificación no es muy eficaz y en lugar de esta función se pudo utilizar StringBuffer para cambiar las cadenas de estado. @Test public void turnOnCoolerAndBlowerIfTooHot() throws Exception { tooHot(); assertEquals("hBChl", hw.getState()); } @Test public void turnOnHeaterAndBlowerIfTooCold() throws Exception { tooCold(); assertEquals("HBchl", hw.getState()); } Listado 9-5 EnvironmentControllerTest.java (selección más grande)
  • 18. @Test public void turnOnHiTempAlarmAtThreshold() throws Exception { wayTooHot(); assertEquals("hBCHl", hw.getState()); } @Test public void turnOnLoTempAlarmAtThreshold() throws Exception { wayTooCold(); assertEquals("HBchL", hw.getState()); }
  • 19. public String getState() { String state = ""; state += heater ? "H" : "h"; state += blower ? "B" : "b"; state += cooler ? "C" : "c"; state += hiTempAlarm ? "H" : "h"; state += loTempAlarm ? "L" : "l"; return state; } ● Sin embargo, se recomienda no utilizar los StringBuffer por ser poco atractivos en las pruebas, evitarlos a todo lugar en código de producción y en proyectos de bajo presupuesto con pruebas de tiempo real, por la limitación de recursos y memoria. Listado 9-6 MockControlHardware.java
  • 20. ● “Todas las funciones de prueba de un test solo deben tener una instrucción de afirmación para llegar a una conclusión de forma rápida y sencilla.” ● Listado 9-7 SerializedPageResponderTest.java (afirmación única) public void testGetPageHierarchyAsXml() throws Exception { givenPages("PageOne", "PageOne.ChildOne", "PageTwo"); whenRequestIsIssued("root", "type:pages"); thenResponseShouldBeXML(); } Una afirmación por prueba
  • 21. public void testGetPageHierarchyHasRightTags() throws Exception { givenPages("PageOne", "PageOne.ChildOne", "PageTwo"); whenRequestIsIssued("root", "type:pages"); thenResponseShouldContain( "PageOne", "PageTwo", "ChildOne" ); } ● Funciones que se dividen en tres partes para tener una sola afirmación, para facilitar el entendimiento, pero se duplica código. ● Para solucionar el problema podríamos crear una nueva clase con una prueba independiente o nuevas funciones para llamarlas, pero es más complejo que dividir el código y asignar afirmaciones múltiples, entonces, la regla de asignar una única afirmación se reemplaza por: ● El número de afirmaciones de una prueba debe ser mínimo.
  • 22. ● Probar un solo concepto en cada función de prueba. Evitar funciones de prueba largas que prueben una miscelánea de cosas tras otra. ● Listado 9-8 / ** * Pruebas varias para el método addMonths (). * / public void testAddMonths() { SerialDate d1 = SerialDate.createInstance(31, 5, 2004); SerialDate d2 = SerialDate.addMonths(1, d1); assertEquals(30, d2.getDayOfMonth()); assertEquals(6, d2.getMonth()); assertEquals(2004, d2.getYYYY()); Un solo concepto por prueba
  • 23. SerialDate d3 = SerialDate.addMonths(2, d1); assertEquals(31, d3.getDayOfMonth()); assertEquals(7, d3.getMonth()); assertEquals(2004, d3.getYYYY()); SerialDate d4 = SerialDate.addMonths(1, SerialDate.addMonths(1, d1)); assertEquals(30, d4.getDayOfMonth()); assertEquals(7, d4.getMonth()); assertEquals(2004, d4.getYYYY()); } Las tres funciones de prueba probablemente deberían ser así: ● Dado el último día de un mes con 31 días (como mayo): 1. Cuando agrega un mes, de modo que el último día de ese mes sea el 30 (como junio), entonces la fecha debe ser el 30 de ese mes, no 31. 2. Cuando agrega dos meses a esa fecha, de modo que el último mes tenga 31 días, entonces la fecha debería ser 31. ● Dado el último día de un mes con 30 días (como junio): 1. Cuando agrega un mes, de modo que el último día de ese mes tenga 31 días, entonces la fecha debe ser 30, no 31.
  • 24. Regla general Cuando incrementa el mes, la fecha no puede ser mayor que el último día del mes. Esto implica que incrementar el mes el 28 de febrero debería producir marzo 28. Falta esa prueba y sería útil escribirla. Entonces, no son las múltiples afirmaciones en cada sección del Listado 9-8 las que causan el problema. Más bien, es el hecho de que se está probando más de un concepto. Entonces probablemente la mejor opción sea en realidad minimizar el número de afirmaciones por concepto y probar solo una concepto por función de prueba. Regla F.I.R.S.T Rapidez Independecia Repetición Validación Automática Puntualidad
  • 25. ● Las pruebas son tan importantes para la salud de un proyecto como el código de producción. ● Se debe trabajar en las pruebas hasta que sean concisas y suficientemente expresivas. ● Es necesario inventar API de prueba que actúen como lenguaje específico del dominio, para ayuden en la creación de pruebas. ● Mantener una limpieza regular del código de las pruebas para evitar que se corrompa el código de producción. Conclusiones
  • 27. Las clases deben ser de tamaño reducido Mantener resultados consistentes Encapsulación Organización de clase Cohesión El principio de responsabilidad única SUBTEMAS Organizar los cambios
  • 28. Organización de clases Según la convención estándar de Java, una clase: • Comienza con una lista de variables. • Primero, constantes estáticas públicas. • Segundo, variables estáticas privadas. • Tercero, variables de instancia privadas. • Las funciones públicas deben seguir a la lista de variables.
  • 29. Encapsulamiento • Siuna regla del mismo paquete tiene que invocar una función o acceder a una variable , hacemos que tenga ámbito protected o de paquete
  • 30. Las clases deben ser de tamaño reducido • Con las funciones medimos el tamaño contando líneas físicas. Con las clases usamos otra medida distinta: las responsabilidades.
  • 31. Tamaño de la clase Mal Bien
  • 32. Pero… • No solo hay que cuidar que no tenga muchos métodos, sino cuidar especialmente que la clase no tenga muchas responsabilidades. • Una clave para identificar las responsabilidades es asociar a las mismas con el nombre de la clase. • Cuanto mas ambiguo sea el nombre de una clase más probabilidades hay de que tenga demasiadas responsabilidades. • Otra clavees que a la hora de describir la clase no nos encontremos con palabras como “y”, “o”, “si”, “pero”.
  • 33. Principio de responsabilidad única • Las clases solo deben tener una responsabilidad ypor ende, solo un motivo para cambiar. • Podemos extraer los tres métodos de SuperDashBoard relacionados con la información de versiones en una clase independiente como Version. La clase Version es una construcción que se puede reutilizar en otras aplicaciones.
  • 34. Principio de responsabilidad única • En conclusión: “Los sistemas deben estar formados por muchas clases reducidas, no por algunas de gran tamaño. Cada clase reducida encapsula una única responsabilidad, tiene solo un motivo para cambiar ycolabora con algunas otras para obtener los comportamientos deseados del sistema”
  • 35. Cohesión • Las clases deben tener un número reducido de variables de instancia. • Los métodos de una clase deben manipular una o varias de dichas variables. • Cuantas más variables manipule un método, más cohesión tendrá con su clase. • Una clase en la que cada variable se usa en cada método tiene una cohesión máxima. • La idea es crear una dependencia lógica entre métodos y variables.
  • 36. Cohesión = grado de utilización de las variables de instancia por parte de las funciones. Queremos clases cohesionadas. Cuando se reduce el tamaño de las funciones se aumenta el tamaño de variables de instancia (para no pasarlas como parámetro a las subfunciones) y se pierde cohesión. En ese caso lo mejor es dividir en subclases.
  • 38. Mantener resultados consistentes en clases de tamaño reducido • La división de grandes funciones en otras más pequeña aumenta la proliferación de clases. • Sinecesito que dentro de una función 1 se llame a una función 2, en lugar de mandarle a ésta las variables declaradas en la función 1, estas variables hacerse de instancia o globales en la clase pero esto implica que se pierda cohesión yaque acumularían más ymás variables globales que solo existen para que otras funciones las compartan. • Cuando esto sucede es conveniente crear otra clase.
  • 39. ● En un sistema limpio, organizamos nuestras clases para reducir el riesgo de cambio, puesto que en la mayoría de sistemas el cambio es continuo. Listado 10-9 Organizándose para el cambio public class Sql { public Sql(String table, Column[] columns) public String create() public String insert(Object[] fields) public String selectAll() public String findByKey(String keyColumn, String keyValue) public String select(Column column, String pattern) public String select(Criteria criteria) public String preparedInsert() private String columnList(Column[] columns) private String valuesList(Object[] fields, final Column[] columns) private String selectWithCriteria(String criteria) private String placeholderList(Column[] columns) }
  • 40. ● Lo que podemos identificar en el listado 10-9 es que existe una clase con varios métodos de los cuales se podrían definir varias responsabilidades, lo cual en el SRP define que es difícil darles mantenimiento o extenderlo. ● La clase Sql del listado 10-9 podría cambiar cuando agreguemos un nuevo tipo de declaración, además cambiaria cuando modifiquemos los detalles de los tipos de declaración por lo que tendríamos 2 responsabilidades , con lo cual viola el SRP. ● SRP dicta que cada clase debe hacer solamente una cosa, ósea tener una única responsabilidad. ● Si existiese el caso en el se supiera que el software no recibirá una actualización en el futuro podríamos considerar al código del listado 10-9 como funcional. Organizándose para el cambio
  • 41. ● Aplicando los principios de responsabilidad única (SRP) al código del listado 10-9 nos quedaría de la siguiente manera: Listado 10-10 Organizándose para el cambio abstract public class Sql { public Sql(String table, Column[] columns) abstract public String generate(); } public class CreateSql extends Sql { public CreateSql(String table, Column[] columns) @Override public String generate() } public class SelectSql extends Sql { public SelectSql(String table, Column[] columns) @Override public String generate() } public class InsertSql extends Sql { public InsertSql(String table, Column[] columns, Object[] fields) @Override public String generate() private String valuesList(Object[] fields, final Column[] columns) }
  • 42. ● Podemos observar que el código se ha vuelto mas simple y entendible, además el riesgo de que al agregar una nueva funcional rompa otra importante se va reduciendo. ● Adicional las clases del listado 10-10 admite otro principio clave de diseño el cual es conocido como OCP (Principio Abierto-Cerrado) el cual dicta que las clases deben estar abierta para extensiones en el código pero cerradas para las posibles modificaciones del mismo. ● En el listado 10-10 cumple esto puesto que su código esta abierta para permitir nuevas funcionalidades sin modificar las funcionalidades ya existentes. Organizándose para el cambio
  • 43. ● Dentro de nuestro sistemas existen clases que tienen detalles concretos los cuales están en riesgo cuando se necesite modificar los mismo. Para evitar los riesgos ante este tipo de situaciones lo que podemos aplicar es el principio de inversión de dependencia (DIR). ● El DIR explica que nuestras clases no deben de depender de detalles concretos sino que deberían de depender de abstracciones como las interfaces, que lo que hace la interfaz es aislar los detalles concretos para que el código se libre de depender de estos y que se desacople. Aislamiento del cambio
  • 44. Ejemplo de Aislamiento del Cambio En la imagen podemos observar dos clases; la clase botón y la clase lampara, podemos observar que la clase botón depende directamente de lampara es decir que si en la clase lámpara realizamos algún cambio el botón cambiara también. Otro aspecto es que el código no es reutilizable puesto que botón esta simplemente enfocado a lámpara, es decir si en un futuro se quisiera agregar una nueva clase televisión por ejemplo, la clase botón quedaría sin utilidad para la clase televisión.
  • 45. Ejemplo de Aislamiento del Cambio En la imagen podemos observar que se agrego una interfaz, con ello la clase botón depende únicamente de abstracciones y esto conlleva a que pueda ser reusado varias veces. Adicional si se realiza cambios en la clase lampara la clase botón debería recibir ningún cambio y la clase lámpara es quien debe adaptarse a la interfaz definida, además se pueden acoplar varias clases, como televisor, lavadora, etc.
  • 46. Conclusiones ● Orden dentro de la clase: Contantes estáticas, variables estáticas, variables de instancia y funciones. De todo ello, primero lo público y después lo privado. ● El tamaño debe ser reducido, debe tener una única responsabilidad, la que indica su nombre. Nombres a evitar son Manager, Processor, Super ya que denotan muchas responsabilidades.You can write about the topic here ● Single Responsibility Principle, una clase debe tener un único motivo para cambiar. ● Open/Closed Principle = las clases deben estar abiertas a extensión y cerradas a modificación. Los cambios mejor que se hagan extendiendo o introduciendo nuevas clases, no modificando las existentes. ● La organización ante posibles cambios de nuestra aplicación es muy útil, puesto que esto lo hace mas legible y fácil de modificar o aumentar ciertas funcionalidades, de lo contrario se debería realizar nuevamente las clases que no tengan una organización adecuada.
  • 48. ● Considerar que la construcción es un proceso diferente al uso, el proceso de inicio siempre es una preocupación que cualquier software debe abordar. Para ello existe una técnica de diseño llamada la separación de preocupaciones (SoC). ● SoC nos indica que que evitemos escribir funciones largas y complejas, por ejemplo si notamos que la función comienza a aumentar de tamaño posiblemente la función se este ocupando de demasiadas cosas a la vez. Lo cual lo mas prudente seria refactorizarlo. Separar la construcción de un sistema de su uso
  • 49. ● Una forma de separar la construcción del uso, consiste en mover todos los aspectos de la construcción al main, luego diseñar el resto del sistema asumiendo que todos los objetos se han construido y organizado de manera apropiada. ● El flujo de control es fácil de seguir. El main construye los objetos necesarios para el sistema, luego los pasa a la aplicación, que simplemente los usa. La aplicación no tiene conocimiento del proceso del main o de construcción, simplemente espera que todo se haya construido correctamente. Separación de main
  • 50. ● Ciertas ocasiones necesitamos que la aplicación sea responsable de la creación de objetos, por lo que es necesario el uso del patron de diseño Abstract Factory. Factories
  • 51. ● Una fabrica abstracta tiene métodos los cuales permite acceder a otras fábricas independientes y sus familias para obtener la instancia de algún objeto de dicha familia. ● En la fábrica abstracta se define métodos los cuales nos permitirán tener una conexión con cada una de las familias independientes para que sea más sencillo realizar un llamado a la familia que se necesite. ● Una fábrica independiente lo que se realiza es la implementación de la fábrica abstracta con el objetivo de que podamos elegir a que objeto deseamos acceder u obtener su instancia, una vez que obtenemos la instancia de algún objeto también tenemos acceso a los métodos de dicho objeto. Factories
  • 52. ● DI nos permite inyectar comportamientos a componentes haciendo que nuestras piezas de software sean independientes y se comuniquen únicamente a través de una interface. DI extrae responsabilidades a un componente para delegarlas en otro, estableciendo un mecanismo a través del cual el nuevo componente puede ser cambiado en tiempo de ejecución. Para lograr esta tarea DI se basa en un patrón más genérico llamado Inversión de Control (Inversion of Control). ● DI tiene como finalidad solucionar un problema común que los programadores encuentran en la construcción de aplicaciones. Este es, mantener los componentes o capas de una aplicación lo más desacopladas posible, Inyección de dependencia
  • 53. ● Los sistemas de software son únicos en comparación con los sistemas físicos. Sus arquitecturas pueden crecer incrementalmente, si mantenemos la adecuada separación de preocupaciones. ● Las arquitecturas EJB no separan las preocupaciones de manera adecuada, por lo tanto impide que el crecimiento orgánico. Esto vuelve a EJB en una arquitectura bastante complicada y amplia. Crea soluciones costosas y complejas. Ampliar
  • 54. En el desarrollo de cualquier aplicación, existen las llamadas "preocupaciones transversales", que son actividades comunes de la mayoría de las aplicaciones: inicio de sesión, seguridad, transacciones PREOCUPACIONES TRANSVERSALES
  • 55. Proxy: es un patrón de diseño estructural que proporciona un objeto que actúa como sustituto de un objeto de servicio real utilizado por un cliente. PROXY DE JAVA
  • 56. AOP: una tecnología para programación orientada a aspectos, que realiza el mantenimiento unificado de las funciones del programa a través de la compilación previa y agentes dinámicos durante el tiempo de ejecución. Spring AOP: El famoso framework para aplicaciones spring en su núcleo tiene un framework para AOP. Este framework es implementado en java puro con las anotaciones de java @Aspect o basado en esquema con un XML. FRAMEWORKS DE JAVA PURO AOP
  • 57. Es la extensión orientada a aspectos de java. Este esta disponible en Eclipse Fundation. Es el lenguaje de POA más usado debido a que es particularmente fácil de aprender y utilizar. AspectJ Aspectos
  • 58.  Probar la arquitectura del sistema.  Optimizar la toma de decisiones.  Utilizar los estándares con prudencia cuando añadan un valor demostrable. Recomendaciones
  • 59.  COOL(COOrdination Language): trata los aspectos de sincronismo entre hilos concurrentes. (Java)  RIDL (Remote Interaction and Data transfers aspect Language)  MALAJ (Multi Aspect LAnguage for Java)  KALA: Modelos transaccionales avanzados  DIE: Un lenguaje de aspectos de dominio específico para eventos de IDE  HYPERJ  AspectG(ANTLR)  AspectMatlab Lenguajes de dominio específico
  • 60. Referencias: Martin, R. (2009). Clean Code. Pearson Education.