Clean Code Raybert Paredes
Nov 29, 2014
Clean Code Raybert Paredes
http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/solid-development-principles-in-motivational-pictures.aspx
http://www.albertelli.com/photoarchive/Random_2003/lawn_jenga0002.jpeg
Que pasa cuando nos toca modificar código?
http://blog.rwbenwick.com/wp-content/uploads/2009/12/Reason-For-Leaving-iStock_000008369823Medium.jpg
Da miedo…
http://www.albertelli.com/photoarchive/Random_2003/lawn_jenga0002.jpeg
http://browse.deviantart.com/?qh=§ion=&q=avengers#/d41k54l
Quien nos podrá ayudar?
Pues….
Tampoco…. http://www.pharmatek.com/developers/developers.htm
http://www.catosplace.net/blogs/personal/wp-content/uploads/2011/04/developers.jpg
Nosotros
Pero como??
http://4.bp.blogspot.com/-wLWxI2BZTEo/TbP44yGHHXI/AAAAAAAACMA/ck1BVzrucHo/s1600/bg_doubt.jpg
Etc…
Aprendiendo un poco de…
En donde???
Y otros mas…
Veremos un poco de…
Escrito por: Tío Bob
Craftsmanship
Bueno, manos a la ubre!!
Perdón, a la obra…. ;)
Entonces, ¿Por qué debería interesarme
escribir mejor mi código?
http://www.websoftwareqa.com/wp-content/uploads/2010/07/Computer-Code.jpg
http://www.osnews.com/story/19266/WTFs_m
Pasamos mas tiempo leyendo código
http://3.bp.blogspot.com/_gP9GcIrRlbg/TDw7pXAfmeI/AAAAAAAAB-8/EDZjyqptYFE/s400/frustrated-computer-scream-entrepenuer.jpg
Y a veces nos damos cuenta que fuimos nosotros mismos los que escribimos ese DESASTRE!!!!
http://photos.pcpro.co.uk/blogs/wp-content/uploads/2010/10/frustrated.jpg
Clean Code
Leer código debería ser como leer una novela… Grady Booch
Costo de Poseer código no mantenible
El Arte de escribir código entendible
“Escribir código que entienda la computadora es una técnica, escribir código que entienda un ser
humano es un Arte”
¡¡Actitud!!
The Boy scout Rule
Nombres Significativos
int d; // Tiempo transcurrido en días int tiempoTranscurridoEnDias; int diasTranscurridosDesdeCreacion;
Preferir Nombres claros a cometarios
public List<int[]> obtener() { List<int[]> lista1 = new ArrayList<int[]>(); for (int[] x : laLista) if (x[0] == 4) lista1.add(x); return lista1; }
Usar nombres que revelen su intención
Usar nombres que revelen su intención
1. ¿Qué tipos de cosas se almacenan en laLista? 2. ¿Cual es el significado del item “CERO”? 3. ¿Cuál es el significado del valor 4? 4. ¿Para que se utiliza la lista que retorna ese método?
public List<Celda> obtenerCeldasConBanderas() { List<Celda> celdasConBanderas = new ArrayList<Cell>(); foreach (Celda celda in tableroJuego) if (celda.estaConBandera()) celdasConBanderas.add(celda); return celdasConBanderas; }
Usar nombres que revelen su intención
int a = l; if ( O == l ) a = O1; else l = 01;
Evitar la desinformación
Use nombres pronunciables
class DtaRcrd102 { private date credmahms; private date moddmahms; private string pszqint = "102"; };
class Cliente { private date fechaCreacion; private date fechaModificacion; private string clienteId = "102"; }
Funciones
Funciones pequeñas Deberían ser entre 20 y 30 líneas por función
Hacer una sola cosa Single Responsibility Principle
Un solo nivel de abstracción por función
ingresarOperacionRescate(Operacion operacion); calcularIGV(Operacion operacion);
//impuestoACobrar = operacion.Monto * impuesto.IGV contabilizarOperacion(Operacion operacion);
Leer de Arriba hacia abajo
Como un periódico
Switch Evitarlo, rompe la regla de solamente una cosa
Argumentos Uno es bueno, Cero es mejor
EscribirArchivoEnDisco(archivo)
Flag Es preferible usar polimorfismo, o crear nuevas funciones
Mostrar(true) mostrarEnDesarrollo() mostrarEnPruebas()
Comentarios
“Un código bien escrito no debería requerir comentarios”
“No comentes un mal código, REESCRÍBELO”
private string REGEXP_FORMATO_FECHA =
"[LMJVSD][a-z]{2}\\,\\s[0-9]{2}\\s[EFMAJSOND][a-z]{2}\\s"+ "[0-9]{4}\\s[0-9]{2}\\:[0-9]{2}\\:[0-9]{2}\\sGMT";
private Cliente cliente; private Operacion operacion; private FileStream archivoGrabar; private date fechaLocal; // Ejemplo: "Lun, 02 Apr 2003 22:18:49 GMT"
Explíca todo en código // Verifica si el empleado es candidato a // obtener beneficios sociales if ((empleado.tipoEmpleado = EMPLEADO_PLANILLAS) && (empleado.edad > 65)) ó if (empleado.esCandidatoBeneficiosSociales())
Buenos Comentarios Legal: // Derechos reservados por Seriva Inc. 2012 // Lanzado bajo GNU General Public License version 2.
Informativos: // format matched kk:mm:ss EEE, MMM dd, yyyy Pattern patronTiempo = Pattern.compile( "\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
Explicación de una intención: // Este es nuestro mejor intento de obtener una // condición de un gran numero de hilos.
Buenos Comentarios Clarificación: assertTrue(a.compareTo(a) == 0); // a == a assertTrue(a.compareTo(b) != 0); // a != b
Advertencias de consecuencias: // No correr este test a menos que // tengas bastante tiempo (Demora).
TODO: // TODO: Tarea a realizar
Ampliar información // Indica más información relevante
Malos comentarios Redundancia: // Declaro una variable “x” del tipo entero int x;
Comentario erróneo: Puede introducir errores Comentarios mandatorios: Tienden a que el se utilice de manera inadecuada Comentarios tipo Diario: Existen repositorios de código fuente para hacer esta tarea
Malos comentarios Ruido: /* Constructor por defecto */ protected AnnualDateRule()
Marcadores de posición: /****************************** Al cerrar una llave: } // if, Si las funciones son cortas no es necesario Código comentado: // if (prueba == true) { }
Formato
“El código es escrito por desarrolladores no por personas excedidas en alcohol”
Formato vertical
Código como Periódico
package fitnesse.wikitext.widgets; import java.util.regex.*; public class BoldWidget extends ParentWidget { public static final String REGEXP = "'''.+?'''"; private static final Pattern pattern = Pattern.compile("'''(.+?)'''", Pattern.MULTILINE + Pattern.DOTALL); public BoldWidget(ParentWidget parent, String text) throws Exception { super(parent); Matcher match = pattern.matcher(text); match.find(); addChildWidgets(match.group(1));} public String render() throws Exception { StringBuffer html = new StringBuffer("<b>"); html.append(childHtml()).append("</b>"); return html.toString();
Densidad Vertical Comentarios innecesarios suman líneas verticales Distancia vertical Conceptos ligados deben ir verticalmente cerca Declaración de variables ¿Al inicio?, ¿Al final? Variables de instancia Siempre en un mismo lugar Funciones dependientes Deben estar cerca
Formato vertical
Densidad horizontal: Google,cuyo.sistema,Android funciona.en los,teléfonos; totalChars+=lineSize; lineWidthHistogram.addLine(lineSize,lineCount); return b*b - 4*a*c;
Alineación horizontal: private Socket socket; private OutputStream output;
private Socket socket; Identacion public CommentWidget(string text){ super(text); }
Reglas de Equipo
Estructuras de Datos
Abstracción
public interface Vehiculo { double obtenerCapacidadEnGalones(); double ontenerGalonesDeGasolina(); }
public interface Vehiculo { double obtenerPorcentajeDeCombustibleRestante(); }
Abstracción
public class Punto { public double x; public double y; }
public interface Punto { double obtenerX(); double obtenerY(); void establecerCoordenada(double x, double y); double obtenerR(); double obtenerTheta(); void establecerPolar(double r, double theta); }
Estructura de Datos / Objetos Código procedural, (usando estructura de datos) hace fácil adicionar nuevas funciones sin cambiar las estructuras de datos existentes. La orientación a objetos, por otro lado, hace fácil adicionar nuevas clases sin tener que cambiar funciones. El código procedural hace difícil adicionar nuevas estructuras de datos porque todas las funciones deben cambiar. La orientación a objetos hace difícil agregar nuevas funciones porque todas las clases deben cambiar. OO: El comportamiento esta en las clases hijas Estructurado: El comportamiento esta en la clase padre
La ley de Demeter
• Cada unidad debe tener un limitado conocimiento sobre otras unidades y solo conocer aquellas unidades estrechamente relacionadas a la unidad actual.
• Cada unidad debe hablar solo a sus amigos y no hablar con extraños.
• Solo hablar con sus amigos inmediatos.
Manejo de excepciones
Usar exepciones en vez de codigos de error
public class DispositivoCOntrolador{ ... public void enviarApagado() { DeviceHandle handle = getHandle(DEV1); // verifica el estado de device if (handle != DeviceHandle.INVALID) { // guarda el estadp retrieveDeviceRecord(handle); // si no esta suspendido if (record.getStatus() != DEVICE_SUSPENDED) {
Usar exepciones en vez de codigos de error
public class DeviceController { ... public void sendShutDown() { try { tryToShutDown(); } catch (DeviceShutDownError e) { logger.log(e); } } ...
¡No retornar NULL!
public void registrarProducto(Producto producto) { if (producto != null) { RegistroProducto registro = tienda.obtemerRegistroProducto(); if (registro != null) {
¡No enviar NULL!
Limites
Usando código de terceros
• Método 1
• Método 2
Uso
• Función
• Método
Interface • FDDFGRR
• Function133
API
Usando código de que no existe
¿¿¿¿???
¿API?
Interface
Software
Learning Test
Pruebas Unitarias
Primera Regla: Solo puede escribir el código de producción solamente si se ha escrito su respectivo código de prueba. Segunda Regla: Solo puede escribir el código de prueba mínimo necesario que haga que el código de producción falle. Tercera Regla: Solo puede escribir el código de producción necesario para hacer que éste pase su código de prueba.
• Fast (Rápido) • Independent (Independiente) • Repeteable (Repetible) • Self validating (Autovalidación) • Timely (Oportuno)
Clases
Las clases deben ser pequeñas
Las clases deben tener solamente una responsabilidad (SRP)
“Solo una razon para cambiar”
Acoplamiento y Cohesión
Sistemas
Construir es diferente a Usar
¿Arquitectura sobredimensionada?
Emerger
De acuerdo con Kent Beck un diseño es "simple“ si sigue las siguientes reglas: • Ejecutar todas las pruebas • No contener duplicación • Expresar la intensión del ptrogemador • Minimizar el numero de clases y
métodos
• REFACTORIZAR!!!
Concurrencia
Copias de solo lectura
Si no es necesario bloquear, no lo hagas