Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

Clean Code

No description
by

claudia bernal

on 20 March 2014

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Clean Code

Clean Code
Comentarios
Formato
Introducción
¡Importante!
Manejo de errores
Todos necesitamos ser mejores programadores.
El código representa los detalles de los requerimientos.
Debe ser específico.
Crea herramientas a partir de requerimientos
Código limpio
Depende del punto de vista de las personas.
“Elegante y eficiente”, Bjarne Stroustrup.
“Simple y directo”, Grady Booch.
“Legible y entendible para cualquier otro desarrollador, con pruebas unitarias, mínimo de dependencias”, Big Dave Thomas.
“Pasa todas las pruebas, no tiene código duplicado, expresa todas las ideas de diseño y minimiza el número de entidades”, Ron Jeffries.
¿Qué es el código limpio?
Nombres significativos
Los nombres son todo en el software.

Nombres pronunciables.

Nombres descriptivos.

No es necesario el uso de prefijos.

Nombres significativos
Los lectores no deben traducir mentalmente.

Usar tu conocimiento para bien y escribe código que otros puedan entender.

Usar sustantivos para el nombre de clases y objetos.

Los métodos deben tener nombre de verbos.

No asignar nombres graciosos.
Nombres significativos
public List<int[]> getThem(){
List<int[]> list1 = new ArrayList<int[]>();
for(int[] x : theList){
if(x[0] == 4){
list1.add(x);
}
}
return list1;
}
public List<int[]> getFlaggedCells(){
List<int[]> flaggedCells = new ArrayList<int[]>();
for(int[] cell : gameBoard){
if(cell[STATUS_VALUE] == FLAGGED){
flaggedCells.add(cell);{
}
}
return flaggedCells;
}
public List<Cell> getFlaggedCells(){
List<Cell> flaggedCells = new ArrayList<Cell>();
for(Cell cell : gameBoard){
if(cell.isFlagged()){
flaggedCells.add(cell);
}
}
return flaggedCells;
}
Funciones
Deben ser pequeñas.

Indentación y bloques.

Cada función debe hacer solo una cosa.

Un nivel de abstracción por función.

Leer código de arriba hacia abajo
Funciones
Número ideal de parámetros es cero.

No pasar como parámetro una variable booleana.

Es mejor pasar como parámetros objetos.

Utilizar excepciones en lugar de códigos de error.

Regla de Dijkstra.
public static String testableHtml(PageData pageData, boolean includeSuiteSetup) throws Exception {
WikiPage wikiPage = pageData.getWikiPage();
StringBuffer buffer = new StringBuffer();
if (pageData.hasAttribute("Test")) {
if (includeSuiteSetup) {
WikiPage suiteSetup = PageCrawlerImpl.getInheritedPage(SuiteResponder.SUITE_SETUP_NAME, wikiPage);
if (suiteSetup != null) {
WikiPagePath pagePath = suiteSetup.getPageCrawler().getFullPath(suiteSetup);
String pagePathName = PathParser.render(pagePath);
buffer.append("!include -setup .").append(pagePathName).append("\n");
}
}
WikiPage setup = PageCrawlerImpl.getInheritedPage("SetUp", wikiPage);
if (setup != null) {
WikiPagePath setupPath = wikiPage.getPageCrawler().getFullPath(setup);
String setupPathName = PathParser.render(setupPath);
buffer.append("!include -setup .").append(setupPathName).
append("\n");
}
}
buffer.append(pageData.getContent());
if (pageData.hasAttribute("Test")) {
WikiPage teardown = PageCrawlerImpl.getInheritedPage("TearDown", wikiPage);
if (teardown != null) {
WikiPagePath tearDownPath = wikiPage.getPageCrawler().getFullPath(teardown);
String tearDownPathName = PathParser.render(tearDownPath);
buffer.append("\n").append("!include -teardown ."). append(tearDownPathName).append("\n");
}
if (includeSuiteSetup) {
WikiPage suiteTeardown = PageCrawlerImpl.getInheritedPage(SuiteResponder.SUITE_TEARDOWN_NAME, wikiPage);
if (suiteTeardown != null) {
WikiPagePath pagePath = suiteTeardown.getPageCrawler().getFullPath(suiteTeardown);
String pagePathName = PathParser.render(pagePath);
buffer.append("!include -teardown .").append(pagePathName).
append("\n");
}
}
}
pageData.setContent(buffer.toString());
return pageData.getHtml();
}
Funciones: Un mal ejemplo
Funciones – Ejemplo mejorado
public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception{
boolean isTestPage = pageData.hasAttribute("Test");
if (isTestPage) {
WikiPage testPage = pageData.getWikiPage();
StringBuffer newPageContent = new StringBuffer();
includeSetupPages(testPage, newPageContent, isSuite);
newPageContent.append(pageData.getContent());
includeTeardownPages(testPage, newPageContent, isSuite);
pageData.setContent(newPageContent.toString());
}
return pageData.getHtml();
}
public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception {
if (isTestPage(pageData)) {
includeSetupAndTeardownPages(pageData, isSuite);
}
return pageData.getHtml();
}
“No comentes mal código, vuelve a escribirlo”
Explica con código, no con comentarios.
// Verifica si el empleado es elegible por beneficios
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)){
// do something..
}
if (employee.isEligibleForFullBenefits()){
// do something...
}
Buenos comentarios
Licencias
// Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the GNU General Public License version 2 or later.
Comentarios informativos
// format matched kk:mm:ss EEE, MMM dd, yyyy
Pattern timeMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
Explicaciones de decisiones
//This is our best attempt to get a race condition by creating large number of threads.
for (int i = 0; i < 25000; i++) {
WidgetBuilderThread widgetBuilderThread = new WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
Thread thread = new Thread(widgetBuilderThread);
thread.start();
}
Aclaraciones
public void testCompareTo() throws Exception{
// do something...
assertTrue(a.compareTo(a) == 0);
// a == a
assertTrue(a.compareTo(b) != 0);
// a != b
assertTrue(ab.compareTo(ab) == 0);
// ab == ab
}
Avisos de consecuencias
// Don't run unless you
// have some time to kill.
public void _testWithReallyBigFile() {
writeLinesToFile(10000000);
response.setBody(testFile);
response.readyToSend(this);
String responseString = output.toString();
assertSubString("Content-Length: 1000000000", responseString);
assertTrue(bytesSent > 1000000000);
}

JavaDocs en funciones públicas.
Malos comentarios
Mumbling
public void loadProperties() {
try {
String propertiesPath = propertiesLocation + "/" + PROPERTIES_FILE;
FileInputStream propertiesStream = new FileInputStream(propertiesPath);
loadedProperties.load(propertiesStream);
} catch(IOException e){
// No properties files means all defaults are loaded
}
}
Redundantes
Engañosos
// Utility method that returns when this.closed is true. Throws an exception if the timeout is reached.
public synchronized void waitForClose(final long timeoutMillis) throws Exception {
if(!closed) {
wait(timeoutMillis);
}
if(!closed) {
throw new Exception("MockResponseSender could not be closed");
}
}
Obligados
/**
*
* @param title The title of the CD
* @param author The author of the CD
* @param tracks The number of tracks on the CD
* @param durationInMinutes The duration of the CD in minutes
*/
public void addCD(String title, String author, int tracks, int durationInMinutes) {
CD cd = new CD();
cd.title = title;
cd.author = author;
cd.tracks = tracks;
cd.duration = duration;
cdList.add(cd);
}
Control de modificaciones
* Changes (from 11-Oct-2001)
* --------------------------
* 11-Oct-2001 : Re-organised the class and moved it to new package com.jrefinery.date (DG);
* 05-Nov-2001 : Added a getDescription() method, and eliminated NotableDate class (DG);
* 12-Nov-2001 : IBD requires setDescription() method, now that NotableDate class is gone (DG); Changed getPreviousDayOfWeek(),
* getFollowingDayOfWeek() and getNearestDayOfWeek() to correct bugs (DG);
* 05-Dec-2001 : Fixed bug in SpreadsheetDate class (DG);
* 29-May-2002 : Moved the month constants into a separate interface (MonthConstants) (DG);
* 27-Aug-2002 : Fixed bug in addMonths() method, thanks to N???levka Petr (DG);
* 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
* 13-Mar-2003 : Implemented Serializable (DG);
* 29-May-2003 : Fixed bug in addMonths method (DG);
* 04-Sep-2003 : Implemented Comparable. Updated the isInRange javadocs (DG);
* 05-Jan-2005 : Fixed bug in addYears() method (1096282) (DG);

No usar comentarios cuando se puede utilizar un método o una variable.
ArrayList moduleDependees = smodule.getDependSubsystems();
String ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.contains(ourSubSystem))
// does the module from the global list <mod> depend on the
// subsystem we are part of?
if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem()))
Marcadores de posición
// Actions //////////////////////////////////
Para denotar cierres de bloques
while ((line = in.readLine()) != null) {
lineCount++;
charCount += line.length();
String words[] = line.split("\\W");
wordCount += words.length;
}
//while

Codigo que ya no se usará
InputStreamResponse response = new InputStreamResponse();
response.setBody(formatter.getResultStream(), formatter.getByteCount());
// InputStream resultsStream = formatter.getResultStream();
// StreamReader reader = new StreamReader(resultsStream);
// response.setContent(reader.read(formatter.getByteCount()));
Comentarios HTML


JavaDocs en funciones no públicas
Información innecesaria
Sirve para comunicar mejor lo que queremos representar.

Vertical.

¿Qué tan grande debe ser el código en un archivo?

Espacio entre funciones.

Densidad.

Distancia.

Orden.
Horizontal

¿Qué tan grande debe ser el código en un archivo?

Densidad y espacio.

Alineación.

Indentación.
Impresiona con el formato
de tu código.
Objetos y estructuras de datos
Abstracción de datos.

Objetos exponen comportamiento y ocultan datos.

Estructuras de datos exponen datos y no tienen comportamiento significativo.

Flexibilidad para agregar comportamiento.
El manejo de errores es importante, pero si oscurece la lógica, está mal.
Usar excepciones en lugar de códigos de error.

Escribir bloques Try-Catch-Finally.

Proporciona información con las excepciones.

Definir el flujo normal.

No regresar objetos nulos.

No pasar objetos nulos.
Pruebas unitarias
TDD – Desarrollo guiado por pruebas.

No poner el código en producción si aún no existen pruebas unitarias.

No escribir más pruebas unitarias, si las que existen ya provocan fallos.

No escribir más código si el existente ya pasa las pruebas.

Mantener las pruebas limpias.

Legibilidad, legibilidad y ... legibilidad.
Fast – Rápida.

Independent – Independiente.

Repeatable – Repetible.

Self-Validating – Validación automática.

Timely - Oportuno.
F.I.R.S.T
Clases
Organización de las clases
Lista de variables.
Constantes estáticas y públicas.
Variables estáticas y privadas.
Variables privadas.
Rara vez hay una razón de tener una variable pública.
Funciones públicas.
Funciones privadas justo después de la función pública que la llama.

Las clases deben ser pequeñas.

Principio de responsabilidad única.

Alta cohesión.
Sistemas

Inyección de dependencias.

Separar la construcción del uso.
Escalabilidad.
Kent dice que, el diseño es “simple” si se siguen las reglas:

Se pasan todas las pruebas.

No contiene duplicados.

Expresa la idea del programador.

Minimiza el número de métodos y clases.
try{
// do something...
}catch(Exception e){
// do nothing...
}
try{
// do something...
}catch(SQLException sqlException){
throws new SQLException("Mensaje especializado", sqlException);
throws new MyDAOException("Mensaje especializado", sqlException);
}catch(Exception exception){
// do something...
}finally{
// do something...
}
boolean noEsUnico = !this.validaUnicidad();
if(noEsUnico == false){
//do something...
}
boolean esUnico = this.validaUnicidad();
if(!esUnico){
//do something...
}
¿Dudas?
public static final String CONSTANTE = "Constante";
public static final String CONSTANTE_LARGA = "Constante Larga";
public final contante = "constante";
public final static CONSTANTELARGA = "constante Larga";
if(validacion)
if(validacion2)
System.out.println("hola");
System.out.println("adios");
if(validacion){
if(validacion2){
System.out.println("hola");
}
}
System.out.println("adios");
if(persona.getEdad() == 35){
// do something...
}
if(persona.getEdad() == EDAD_MAXIMA){
//do something
}
Full transcript