Botón para abrir el Menú Botón para cerrar el Menú
Logo da empresa Alura
Iniciar Sesión Nuestros Planes
Formaciones Conoce a Luri
  • Programación _
  • Front End _
  • Data Science _
  • DevOps _
  • Innovación y Gestión _
Artículos de Tecnología

Simplificando el código con la refactorización en Java

Simplificando el código con la refactorización en Java
Alex Felipe
Alex Felipe
14 de Diciembre

Compartir

img1

Es muy común en nuestro día a día, como desarrolladores, trabajar con códigos escritos por otros desarrolladores, ya sea para comprender una regla de negocio o para la evolución del programa en general.

Para entender mejor esta situación, consideremos una aplicación Java para un inventario de productos. En esta aplicación, tenemos el siguiente código:

public class ProductoDAO {

public List<Producto> lista() {
    // Implementación cualquiera que devuelve una lista de productos
}

public void productosResumido() {
    List<Producto> prs = lista();
    for (Producto p : prs) {
        String dse = p.getDescripcion().trim();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < dse.length(); i++) {
            if (i > 15) {
                sb.append("...");
                break;
            }
            sb.append(dse.charAt(i));
        }

        String da = sb.toString();
        String vf = p.getValor().toString().replace(".", ",");
        String df = p.getId() + " - " + da + " - $ " + vf;
        System.out.println(df);
    }
}

}
public class Producto {
    private Integer id;
    private String descripcion;
    private Double valor;

// Constructores, getters, setters y métodos
}

Al ejecutar el método productosResumido(), obtenemos el siguiente resultado:

1 
- Refresco de ... - R$ 5,0 2 
- Doritos ... - R$ 3,5 3 
- Pan de forma Pre... - R$ 4,5 4 
- Leche Larga Vida... - R$ 2,75 5 
- Jugo Tang 30g - R$ 4,0

Observando el resultado, obtenemos un resumen de los productos guardados en el inventario. Sin embargo, al analizar rápidamente la implementación del método produtosResumido(), no resulta tan evidente que este resultado se presentaría de manera tan clara. A primera vista, no...

Entendiendo la refactorización de código

En otras palabras, observa que hemos llegado a una situación en la que tiene todo el sentido detenerse y pensar en maneras de mejorar nuestro código actual, ¿cierto?

Este proceso de mejora del código se conoce técnicamente como code refactoring, o en español, refactorización de código.

Esta técnica, en términos generales, consiste en diversas prácticas que buscan mejorar el código en los siguientes aspectos:

  • Simplicidad: minimizar la cantidad de código.
  • Legibilidad: mejorar la lectura del código para los humanos.
  • Rendimiento: aumentar la velocidad de ejecución.

A primera vista, podrías estar pensando:

""¡La refactorización es genial, pero si hago esto, estaré modificando el comportamiento de mi aplicación!"

La primera impresión que tenemos durante este tipo de proceso es imaginar que nuestra aplicación será modificada y presentará comportamientos diferentes.

Esto es algo muy común, pero la idea de la refactorización es aplicar técnicas que modifican únicamente el aspecto visual del código, es decir, ¡el comportamiento inicial sigue siendo el mismo!

¡Parece demasiado bueno para ser verdad, verdad? Por lo tanto, apliquemos algunas técnicas de refactorización en el código que vimos inicialmente ¡y veremos cómo ocurre la magia!

Renombrando variables

La primera técnica que aplicaremos será la renombración de variables. A simple vista, puede parecer algo trivial, pero echemos un vistazo a un fragmento de nuestro código:

Aquí tienes el código traducido al español:

List<Producto> productos = lista(); 
for (Producto producto : productos) { 
    String descripcionFormatada = producto.getDescripcion().trim(); 
    // restante del código
}

¿Para ti, prs, p, dse tienen algún significado? Para mí y para cualquier persona que vea este código por primera vez, no tienen significado alguno a primera vista. Entonces, ¿qué tal si hacemos la siguiente modificación?

List<Producto> productos = lista(); 
for (Producto producto : productos) { 
    String descripcionSinEspacios = producto.getDescripcion().trim(); 
    // resto del código
}

Ahora es evidente que estamos trabajando con una lista de productos, y que para cada producto de la lista productos estamos obteniendo una descripcionSinEspacios.

¡Nota que incluso leer el código es más fácil! En otras palabras, durante el proceso de refactorización, renombrar variables facilita la lectura del código. Por lo tanto, cuanto más significativo sea el nombre de la variable, más fácil será leerlo. Ajustemos los demás puntos:

public void productosResumidos() { 
    List<Producto> productos = lista(); 
    for (Producto producto : productos) { 
        String descripcionSinEspacios = producto.getDescripcion().trim(); 
        StringBuilder sb = new StringBuilder(); 
        for (int i = 0; i < descripcionSinEspacios.length(); i++) { 
            if (i > 15) { 
                sb.append("..."); 
                break; 
            } 
            sb.append(descripcionSinEspacios.charAt(i)); 
        } 
        String descripcionAjustada = sb.toString(); 
        String valorFormateado = producto.getValor().toString().replace(".", ","); 
        String descripcionFinal = producto.getId() + " - " + descripcionAjustada + " - R$ " + valorFormateado; 
        System.out.println(descripcionFinal); 
    } 
}

Observa que la variable sb, que se refiere a la instancia de la clase StringBuilder, se mantiene. Dado que es una instancia de una clase conocida por la mayoría de los desarrolladores y no tiene un nombre tan corto, no hay problema en dejarla como sb.

En otras palabras, para casos en los que estamos creando una instancia de una clase con un nombre largo, podemos usar una abreviación. En el caso de StringBuilder, incluso podríamos haber usado builder, ya que tendría un significado suficiente.

Recuerda: Durante el proceso de renombrar las variables, lo más importante es que al momento de leer el código, la lectura sea fácil y objetiva. Es decir, incluso para alguien que no esté tan familiarizado con la implementación, debería ser comprensible simplemente leyendo el código.

Extracción de método Aunque nuestro código ha mejorado significativamente en términos de legibilidad —es decir, con nombres más claros para nosotros los humanos—, sigue siendo algo complejo. Si observamos con atención, tenemos una gran cantidad de líneas dentro de un solo método.

Teniendo en cuenta esta situación, ¿qué podemos hacer para resolver este detalle? Para este tipo de escenario, podemos aplicar la técnica conocida como extracción de método. Ahora probablemente estés pensando:

"Genial, pero ¿cómo funciona esta técnica?"

Extracción de método y renombrado de variables: traducido al español


Básicamente, al leer el código, analizamos y verificamos qué hace un conjunto de código. Por ejemplo, este fragmento:

String descripcionSinEspacios = producto.getDescripcion().trim();
StringBuilder sb = new StringBuilder(); 
for (int i = 0; i < descripcionSinEspacios.length(); i++) { 
    if (i > 15) { 
        sb.append("..."); 
        break;
    } 
    sb.append(descripcionSinEspacios.charAt(i));
} 
String descripcionAjustada = sb.toString();

Si lo observamos con atención, ¡todo este código tiene como objetivo ajustar la descripción de un producto! Entonces, ¿qué tal si transformamos todo este bloque en un método como este?

private String ajustarDescripcion(Producto producto) { 
    String descripcionSinEspacios = producto.getDescripcion().trim();
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < descripcionSinEspacios.length(); i++) {
        if (i > 15) { 
            sb.append("..."); 
            break; 
        } 
        sb.append(descripcionSinEspacios.charAt(i)); 
    } 
    return sb.toString(); 
}

Ahora basta con realizar la siguiente llamada dentro de nuestro código anterior:

public void productosResumidos() { 
    List<Producto> productos = lista(); 
    for (Producto producto : productos) {
        String descripcionAjustada = ajustarDescripcion(producto); 
        String valorFormateado = producto.getValor().toString().replace(".", ",");
        String descripcionFinal = producto.getId() + " - " + descripcionAjustada + " - $ " + valorFormateado; 
        System.out.println(descripcionFinal);
    }
}

¡Mira cómo se redujo el método! Leerlo se vuelve mucho más fácil de esta manera. Podemos aplicar lo mismo a otros puntos del código, como este:

String valorFormateado = producto.getValor().toString().replace(".", ",");

Básicamente, este fragmento formatea el valor de acuerdo con la moneda. En este caso, nada nos impide extraer otro método:

private String formatearMoneda(Producto producto) { 
    return producto.getValor().toString().replace(".", ","); 
}

Además, podemos aplicar el mismo concepto al siguiente fragmento de código:

String descripcionFinal = producto.getId() + " - " + descripcionAjustada + " - $ " + valorFormateado;

Y extraerlo de esta forma:

private String resumirDescripcion(Producto producto, String descripcionAjustada, String valorFormateado) {
    return producto.getId() + " - " + descripcionAjustada + " - $ " + valorFormateado;
}

Ahora nuestro método inicial queda así:

public void productosResumidos() { 
    List<Producto> productos = lista(); 
    for (Producto producto : productos) { 
        String descripcionAjustada = ajustarDescripcion(producto); 
        String valorFormateado = formatearMoneda(producto); 
        String descripcionFinal = resumirDescripcion(producto, descripcionAjustada, valorFormateado); 
        System.out.println(descripcionFinal);
    }
}

¡Mucho más fácil de leer, cierto?

Incluso podemos simplificar más, en lugar de enviar tres parámetros para crear la descripción final, podemos enviar solo el objeto Producto y llamar a los demás métodos dentro de resumirDescripcion():

public void productosResumidos() { 
    List<Producto> productos = lista(); 
    for (Producto producto : productos) { 
        String descripcionFinal = resumirDescripcion(producto); 
        System.out.println(descripcionFinal); 
    }
}

private String resumirDescripcion(Producto producto) { 
    String descripcionAjustada = ajustarDescripcion(producto); 
    String valorFormateado = formatearMoneda(producto); 
    return producto.getId() + " - " + descripcionAjustada + " - $ " + valorFormateado; 
}

private String formatearMoneda(Producto producto) { 
    return producto.getValor().toString().replace(".", ","); 
}

private String ajustarDescripcion(Producto producto) { 
    String descripcionSinEspacios = producto.getDescripcion().trim();
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < descripcionSinEspacios.length(); i++) { 
        if (i > 15) { 
            sb.append("..."); 
            break; 
        } 
        sb.append(descripcionSinEspacios.charAt(i));
    }
    return sb.toString(); 
}

Ahora el método productosResumidos() es mucho más fácil de entender. Sabemos rápidamente que recorre cada producto, genera una descripcionFinal y la imprime.

Conclusión: Aunque el código parecía complejo al principio, simplemente aplicando algunas técnicas de refactorización como extracción de método y renombrado de variables logramos mejorar mucho la legibilidad y comprensión del código.

¿Te gustaría aprender más técnicas de refactorización? Entonces consulta nuestro curso de Refactorización en la práctica con Java, donde abordamos estas técnicas y otras que marcan una gran diferencia en la mejora del código.

Navegación

  • Planes
  • Instructores
  • Blog
  • Política de privacidad
  • Términos de uso
  • Sobre nosotros
  • Preguntas frecuentes

¡CONTÁCTANOS!

  • ¡Quiero entrar en contacto!

Blog

  • Programación
  • Data Science
  • Front End
  • Innovación y Gestión
  • DevOps

AOVS Sistemas de Informática S.A CNPJ 05.555.382/0001-33

SÍGUENOS EN NUESTRAS REDES SOCIALES

YouTube Facebook Instagram Linkedin Whatsapp Spotify

NOVEDADES Y LANZAMIENTOS

Aliados

  • Programa de aceleração Scale-Up Endeavor
  • En Alura somos unas de las Scale-Ups seleccionadas por Endeavor, programa de aceleración de las empresas que más crecen en el país.
  • Growth Academy 2021 do Google For Startups
  • Fuimos unas de las 7 startups seleccionadas por Google For Startups en participar del programa Growth Academy en 2021
Alura

Powered by

Caelum

AOVS Sistemas de Informática S.A CNPJ 05.555.382/0001-33

SÍGUENOS EN NUESTRAS REDES SOCIALES

YouTube Facebook Instagram Linkedin Whatsapp Spotify

Cursos

Cursos de Programación
Lógica de Programación | Java
Cursos de Front End
HTML y CSS | JavaScript | React
Cursos de Data Science
Data Science | Machine Learning | Excel | Base de Datos | Data Visualization | Estadística
Cursos de DevOps
Docker | Linux
Cursos de Innovación y Gestión
Transformación Ágil | Marketing Analytics

Alura

  • Educação em Tecnologia

    • logo fiap FIAP
    • logo casa do codigo Casa do Código
    • logo pm3 PM3 - Cursos de Produto
  • Mais Alura

    • logo alura start START BY Alura
    • logo alura lingua Alura Língua
    • logo alura para empresas Alura Para Empresas
    • logo alura latam Alura LATAM
  • Comunidade

    • logo tech guide Tech Guide
    • logo 7 days of code 7 days of code
    • logo Hipsters ponto Jobs Hipsters ponto Jobs
  • Podcasts

    • logo Hipster Network Hipster Network
    • logo Hipsters ponto Tech Hipsters ponto Tech
    • logo Dev sem fronteiras Dev sem Fronteiras
    • logo Like a Boss Like a Boss
    • logo IA Sob Controle IA Sob Controle
    • logo Mesa de Produto Mesa de Produto
    • logo Decode Decode
    • logo FIAPCast FIAPCast