Date post: | 02-Jul-2015 |
Category: |
Technology |
Upload: | software-guru |
View: | 295 times |
Download: | 1 times |
www.sgcampus.com.mx @sgcampus
www.sgcampus.com.mx
@sgcampus
TDD y Clean Code
Por Jorge Jiménez y Fernando Arana
www.sgcampus.com.mx @sgcampus
BAD CODE
¿Quién se identifica con esto?
xkcd.com
www.sgcampus.com.mx @sgcampus
BAD CODE
O peor… ¿A quién le ha pasado?
www.sgcampus.com.mx @sgcampus
BAD CODE
Y entonces…
www.sgcampus.com.mx @sgcampus
¿Existe alguna solución?
¿Extensos estándares? ¿Documentación?
¿Poner extremo cuidado?¿Análisis estático de código?
¿Inspecciones?¿Pedir la bendición para el código productivo?
www.sgcampus.com.mx @sgcampus
Test Drive Development
www.sgcampus.com.mx @sgcampus
Test Drive Development
“No soy un gran programador. Sólo
soy un buen programador con
grandes hábitos”
―Kent Beck
Inventor de TDD
www.sgcampus.com.mx @sgcampus
Test Drive Development
TDD es una técnica de desarrollo que nació con
XP (eXtreme Programming)
Se hace diseño y codificación guiado por las
pruebas unitarias
Con TDD podemos lograr que el diseño “emerja”
del código
www.sgcampus.com.mx @sgcampus
Test Drive Development
Pero antes…
1. Has una lista de las posibles pruebas que se
harán al requerimiento
2. Comienza con las pruebas más sencillas
3. Aquellas que rodean el requerimiento
4. DETÉN el impulso de programar todas las
reglas de negocio en una sola vez
www.sgcampus.com.mx @sgcampus
Test Drive Development
Consta de 3 pasos:
1. Escribes una prueba que falla
2. Escribes el MÍNIMO código productivo que
hace que la prueba pase
3. Haces Refactor usando Clean Code
www.sgcampus.com.mx @sgcampus
Clean Code
“Sabes que estás trabajando con Código Limpio
cuando cada rutina que lees resulta ser
exactamente lo que esperabas de ella”
-Ward Cunningan
“Sabes que ves un Código Limpio cuando:
• Corren todas las pruebas
• No tiene código duplicado
• Expresa todas las ideas que tiene el sistema
• Minimiza el número de entidades como clases,
métodos, y funciones”
-Ron Jeffries
Fuente: libro “Clean Code” por Bob Martin
www.sgcampus.com.mx @sgcampus
Clean Code
www.sgcampus.com.mx @sgcampus
Clean Code
Mapa Mental por
Gustavo García en
base a los videos de
cleancoders.com
www.sgcampus.com.mx @sgcampus
Clean Code
Nombres:
Los nombres deben reflejar su intención
Deben poder pronunciarse
Usar nombres de acuerdo a las reglas de negocio
Evitar encodings (prefijos, tipos de datos)
Algunas reglas de nombrado:
Clases = Sustantivos
Variables = Nombres
Métodos = Verbos
Booleanos = “is” o “has”
www.sgcampus.com.mx @sgcampus
Clean Code
Nombres
VS
Fuente: libro “Clean Code” por Bob Martin
www.sgcampus.com.mx @sgcampus
Clean Code
Funciones:
Deben de ser pequeñas
Y más pequeñas aún: 4 a 6 líneas
Una función larga puede tener algunas clases
escondidas
No pasar más de 2 argumentos
Extraer hasta no poder extraer más, así
aseguramos un nivel de abstracción
“FUNCTIONS SHOULD DO ONE THING. THEY
SHOULD DO IT WELL. THEY SHOULD DO IT ONLY”
Fuente: libro “Clean Code” por Bob Martin
www.sgcampus.com.mx @sgcampus
Clean Code
Formato:
Comentarios: El mejor comentario es el que no se
escribe
Tamaño de archivos: entre más pequeños, mejor
Formato Vertical: uniformidad en interlineado,
sangría, ciclos, etc.
Step Down Rule: Organizar métodos del más
abstracto al más específico.
El código debe entenderse en secuencia de arriba
hacia abajo
Fuente: libro “Clean Code” por Bob Martin
www.sgcampus.com.mx @sgcampus
Clean Code
Fuente: libro “Clean Code” por Bob Martin
www.sgcampus.com.mx @sgcampus
¿Qué es una Kata?
Una Kata es una manera de poner en práctica y
aprender de manera segura
En una Kata, el aprendizaje es más importante
que el resultado (es decir, no importa si el
programa “no jala” o se queda incompleto)
Por eso, las Katas se tienen que hacer más de
una vez
www.sgcampus.com.mx @sgcampus
Kata Factores Primos
Escribe un clase llamada “PrimeFactors” que tiene
un método estático: generate
El método generate toma un argumento entero y
regresa una lista de enteros “List<Integer>” Esta
lista contiene los factores primos en secuencia
numérica.
+ generate(n : int)
Prime Factors
www.sgcampus.com.mx @sgcampus
Productivo
Junit
@Testpublic void dadoUno_regresaVacio() throws Exception {
FactoresPrimos factorador = new FactoresPrimos();List<Integer> factores = factorador.buscarFactoresPrimos(1);assertEquals(0, factores.size());
}
public class FactoresPrimos {
public List<Integer>buscarFactoresPrimos(int i) {return null;
}
}
www.sgcampus.com.mx @sgcampus
Junit
@Testpublic void dadoUno_regresaVacio() throws Exception {
FactoresPrimos factorador = new FactoresPrimos();List<Integer> factores = factorador.buscarFactoresPrimos(1);assertEquals(0, factores.size());
}
Productivo
public class FactoresPrimos {
public List<Integer>buscarFactoresPrimos(int i) {return new ArrayList<Integer>();
}
}
www.sgcampus.com.mx @sgcampus
Junit
private FactoresPrimos factorador;
@Testpublic void setUp() throws Exception {
this.factorador = new FactoresPrimos();}
@Testpublic void dadoUno_regresaVacio() throws Exception {
List<Integer> factores = factorador.buscarFactoresPrimos(1);assertEquals(0, factores.size());
}
www.sgcampus.com.mx @sgcampus
Productivo
Junit
@Testpublic void dadoDos_regresaListaConSoloDos() throws Exception {
List<Integer> factores = factorador.buscarFactoresPrimos(2);assertEquals(1, factores.size());assertEquals(2, factores.get(0).intValue());
}
public List<Integer> buscarFactoresPrimos(int numero) {ArrayList<Integer> listaDeFactores = new ArrayList<Integer>();if (numero > 1) {
listaDeFactores.add(2);}return listaDeFactores;
}
www.sgcampus.com.mx @sgcampus
Productivo
Junit
@Testpublic void dadoTres_regresaListaConSoloTres() throws Exception {
List<Integer> factores = factorador.buscarFactoresPrimos(3);
assertEquals(1, factores.size());assertEquals(3, factores.get(0).intValue());
}
public List<Integer> buscarFactoresPrimos(int numero) {ArrayList<Integer> listaDeFactores = new ArrayList<Integer>();if (numero % 2 == 0) {
listaDeFactores.add(2);} else if (numero % 3 == 0) {
listaDeFactores.add(3);}return listaDeFactores;
}
www.sgcampus.com.mx @sgcampus
Junit
private void assertFactoresPrimos(int numeroAEvaluar) {List<Integer> factores =
factorador.buscarFactoresPrimos(numeroAEvaluar);assertEquals(1, factores.size());assertEquals(numeroAEvaluar, factores.get(0).intValue());
}
@Testpublic void dadoDos_regresaListaConSoloDos() throws Exception {
assertFactoresPrimos(2);}
@Testpublic void dadoTres_regresaListaConSoloTres() throws Exception {
assertFactoresPrimos(3);}
www.sgcampus.com.mx @sgcampus
public List<Integer> buscarFactoresPrimos(int numero) {ArrayList<Integer> listaDeFactores = new ArrayList<Integer>();for (int primo = 2; primo <= numero; primo++) {
añadirPrimo(listaDeFactores, primo, numero);}return listaDeFactores;
}
private void añadirPrimo(ArrayList<Integer> listaDeFactores, int primo, int numero) {if (numero % primo == 0) {
listaDeFactores.add(primo);}
}
Productivo
www.sgcampus.com.mx @sgcampus
Productivo
Junit@Testpublic void dadoCuatro_regresaDosYDos() throws Exception {
List<Integer> factores = factorador.buscarFactoresPrimos(4);assertEquals(2, factores.size());assertEquals(2, factores.get(0).intValue());assertEquals(2, factores.get(1).intValue());
}
public List<Integer> buscarFactoresPrimos(int numero) {int aEvaluar = numero;final ArrayList<Integer> listaDeFactores = new ArrayList<Integer>();for (int primo = 2; primo <= aEvaluar;) {
if (numero % primo == 0) {listaDeFactores.add(primo);aEvaluar = aEvaluar / primo;
} else {primo++;
}}return listaDeFactores;
}
}
www.sgcampus.com.mx @sgcampus
public class FactoresPrimos {
private static final int PRIMER_FACTOR_PRIMO = 2;
public List<Integer> buscarFactoresPrimos(final int numero) {siguientesFatoresPrimos(listaDeFactores, PRIMER_FACTOR_PRIMO, numero);return listaDeFactores;
}
private void siguientesFatoresPrimos(final ArrayList<Integer> listaDeFactores, final int primo, final int numero) {
if (primo <= numero) {evaluaFactorPrimo(listaDeFactores, primo, numero);
}}
private void evaluaFactorPrimo(final ArrayList<Integer> listaDeFactores, final int primo, final int numero) {
if (numero % primo == 0) {listaDeFactores.add(primo);siguientesFatoresPrimos(listaDeFactores, primo, numero /
primo);} else {
siguientesFatoresPrimos(listaDeFactores, primo + 1, numero);}
}}
Productivo
www.sgcampus.com.mx @sgcampus
Productivopublic class FactoresPrimos {
private static final int PRIMER_FACTOR_PRIMO = 2;
public List<Integer> buscarFactoresPrimos(final int numero) {siguientesFatoresPrimos(listaDeFactores, PRIMER_FACTOR_PRIMO, numero);return listaDeFactores;
}
private void siguientesFatoresPrimos(final ArrayList<Integer> listaDeFactores, final int primo, final int numero) {
if (primo <= numero) {evaluaFactorPrimo(listaDeFactores, primo, numero);
}}
private void evaluaFactorPrimo(final ArrayList<Integer> listaDeFactores, final int primo, final intnumero) {
if (numero % primo == 0) {listaDeFactores.add(primo);siguientesFatoresPrimos(listaDeFactores, primo, numero / primo);
} else {siguientesFatoresPrimos(listaDeFactores, primo + 1, numero);
}}
}
www.sgcampus.com.mx @sgcampus
Junit
private void assertFactoresPrimos(final int numeroAEvaluar, final int... valores) {final List<Integer> factores = factorador.buscarFactoresPrimos(numeroAEvaluar);assertEquals(valores.length, factores.size());for (int i = 0; i < valores.length; i++) {
assertEquals(valores[i], factores.get(i).intValue());}
}
@Testpublic void dadoUno_regresaVacio() throws Exception {
assertFactoresPrimos(1);}
@Testpublic void dadoDos_regresaListaConSoloDos() throws Exception {
assertFactoresPrimos(2, 2);}
@Testpublic void dadoTres_regresaListaConSoloTres() throws Exception {
assertFactoresPrimos(3, 3);}
@Testpublic void dadoCuatro_regresaDosYDos() throws Exception {
assertFactoresPrimos(4, 2, 2);}
www.sgcampus.com.mx @sgcampus
Productivo
Junit
@Testpublic void dadoCinco_regresaCinco() throws Exception {
assertFactoresPrimos(5, 5);}
Pasa
www.sgcampus.com.mx @sgcampus
Junit
@Testpublic void dadoUno_regresaVacio() throws Exception {
assertFactoresPrimos(1);}@Testpublic void dadoDos_regresaListaConSoloDos() throws Exception {
assertFactoresPrimos(2, 2);}@Testpublic void dadoTres_regresaListaConSoloTres() throws Exception {
assertFactoresPrimos(3, 3);}@Testpublic void dadoCuatro_regresaDosYDos() throws Exception {
assertFactoresPrimos(4, 2, 2);}@Testpublic void dadoCinco_regresaCinco() throws Exception {
assertFactoresPrimos(5, 5);}
public void dadoNumero_regresaSusFacotresPrimos() throws Exception {assertNumeroGeneraFactoresPrimos(1);assertNumeroGeneraFactoresPrimos(2, 2);assertNumeroGeneraFactoresPrimos(3, 3);assertNumeroGeneraFactoresPrimos(4, 2, 2);assertNumeroGeneraFactoresPrimos(5, 5);
}
private void assertFactoresPrimos(final int numeroAEvaluar, final int... valores) private void assertNumeroGeneraFactoresPrimos(final int numeroAEvaluar, final int... valores)
www.sgcampus.com.mx @sgcampus
Productivo
Junit
Pasan
assertNumeroGeneraFactoresPrimos(6, 2, 3);
assertNumeroGeneraFactoresPrimos(7, 7);assertNumeroGeneraFactoresPrimos(8, 2, 2, 2);assertNumeroGeneraFactoresPrimos(11, 11);assertNumeroGeneraFactoresPrimos(2 * 3 * 5 * 7 * 11 * 13 * 17, 2, 3, 5, 7, 11, 13, 17);
www.sgcampus.com.mx @sgcampus
Conclusiones
Fuente: libro “Clean Code” por Bob Martin
Utilizando TDD y Clean Code tendremos los siguientes beneficios:
Seguridad al modificar código (red de protección de pruebas unitarias)
Código mantenible para poder arreglar bugs o implementar nuevos features
Mejor trabajo en equipo (¡por fin nos entendemos!)
Clientes satisfechos
Estimaciones más certeras
Enfocarnos en cosas más interesantes: nuevos frameworks, Clean Architecture, Patrones, Sistemas resistentes a fallos, Escalabilidad…
www.sgcampus.com.mx @sgcampus
Clean Code
“Deja el código mejor de cómo lo encontraste”
www.sgcampus.com.mx @sgcampus
Bibliografía
Fuente: libro “Clean Code” por Bob Martin
Clean code: A Handbook of Agile Software Craftsmanship
(Robert C. Martin)
Test Driven Development: By Example (Kent Beck)
Refactoring: Improving the Design of Existing Code (Martin
Fowler)
Working Effectively with Legacy Code (Michael Feathers)
The Clean Coder: A Code of Conduct for Professional
Programmers (Robert C. Martin)
The Coding Dojo Handbook (Emily Bache)
CleanCoders.com