275 lecturas

Refactoring 027 - Cómo eliminar Getters

por Maximiliano Contieri7m2025/04/20
Read on Terminal Reader

Demasiado Largo; Para Leer

Eliminar o reemplazar los getters con métodos ricos en comportamiento que realicen operaciones en lugar de exponer el estado interno.
featured image - Refactoring 027 - Cómo eliminar Getters
Maximiliano Contieri HackerNoon profile picture

Desactivar el comportamiento de objeto más allá del acceso a los datos

y

TL;DR: Eliminar o reemplazar los getters con métodos ricos en comportamiento que realizan operaciones en lugar de exponer el estado interno.

y

TL;DR: Eliminar o reemplazar los getters con métodos ricos en comportamiento que realizan operaciones en lugar de exponer el estado interno.

Problemas solucionados

    y
  • Objetos anémicos
  • y
  • Conjunto excesivo
  • y
  • La encapsulación perdida
  • y
  • Mutaciones esenciales
  • y
  • La ley de la violación de Demeter
  • y
  • Fuga de información
  • y
  • Expuestos internos
  • y
  • La obsesión primitiva
  • y

Código relacionado Olor

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiv

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiii

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiv

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxix

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiv

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiii

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd

https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxv

Pasos

    y
  1. Identificar los getters que exponen el estado de objeto interno
  2. y
  3. Encuentra todos los usos de la codebase
  4. y
  5. Comportamiento de movimiento que utiliza el getter en el objeto mismo
  6. y
  7. Crear métodos de revelación de intenciones que realicen operaciones (suprimir el prefijo Get)
  8. y
  9. Actualiza tu código para utilizar los nuevos métodos
  10. y

Código de muestreo

Antes de

public class Invoice {
    private List<LineItem> items;
    private Customer customer;
    private LocalDate dueDate;
    
    public Invoice(Customer customer, LocalDate dueDate) {
        this.customer = customer;
        this.dueDate = dueDate;
        this.items = new ArrayList<>();
    }
    
    public void addItem(LineItem item) {
        // This is the right way 
        // to manipulate the internal consistency
        // adding assertions and access control if necessary
        items.add(item);
    }
    
    public List<LineItem> getItems() {
        // You are exposing your internal implementation
        // In some languages, you also open a backdoor to
        // manipulate your own collection unless you return
        // a copy
        return items;
    }
    
    public Customer getCustomer() {
        // You expose your accidental implementation
        return customer;
    }
    
    public LocalDate getDueDate() {
        // You expose your accidental implementation
        return dueDate;
    }
}
 
Invoice invoice = new Invoice(customer, dueDate);
// Calculate the total violating encapsulation principle
double total = 0;
for (LineItem item : invoice.getItems()) {
    total += item.getPrice() * item.getQuantity();
}

// Check if the invoice is overdue
boolean isOverdue = LocalDate.now().isAfter(invoice.getDueDate());

// Print the customer information
System.out.println("Customer: " + invoice.getCustomer().getName());

Después de 🙂

public class Invoice {
    private List<LineItem> items;
    private Customer customer;
    private LocalDate dueDate;
    
    public Invoice(Customer customer, LocalDate dueDate) {
        this.customer = customer;
        this.dueDate = dueDate;
        this.items = new ArrayList<>();
    }
    
    public void addItem(LineItem item) {
        items.add(item);
    }
    
    // Step 3: Move behavior that uses the getter into the object
    public double calculateTotal() {
        // Step 4: Create intention-revealing methods
        double total = 0;
        for (LineItem item : items) {
            total += item.price() * item.quantity();
        }
        return total;
    }
    
    public boolean isOverdue(date) {
        // Step 4: Create intention-revealing methods
        // Notice you inject the time control source
        // Removing the getter and breaking the coupling
        return date.isAfter(dueDate);
    }
    
    public String customerInformation() {
        // Step 4: Create intention-revealing methods
        // You no longer print with side effects 
        // And coupling to a global console
        return "Customer: " + customer.name();        
    }
    
    // For collections, return an unmodifiable view if needed
    // Only expose internal collaborators if the name 
    // is an actual behavior
    public List<LineItem> items() {
        return Collections.unmodifiableList(items);
    }
    
    // Only if required by frameworks 
    // or telling the customer is an actual responsibility
    // The caller should not assume the Invoice is actually
    // holding it
    public String customerName() {
        return customer.name();
    }
    
    // You might not need to return the dueDate
    // Challenge yourself if you essentially need to expose it
    // public LocalDate dueDate() {
    //     return dueDate;
    // }
}

// Client code (Step 5: Update client code)
Invoice invoice = new Invoice(customer, dueDate);
double total = invoice.calculateTotal();
boolean isOverdue = invoice.isOverdue(date);
System.out.println(invoice.customerInformation());

Tipo

    y
  • [x] Semi-automático
  • y

Seguridad ️

Este refactoring es generalmente seguro, pero requiere una ejecución cuidadosa.


Usted debe asegurarse de que todos los usos del getter son identificados y reemplazados por los nuevos métodos de comportamiento.


El mayor riesgo ocurre cuando los getters devuelven objetos o colecciones mutables, ya que el código del cliente podría haber modificado estos objetos.


Debe comprobar que el comportamiento no ha cambiado a través de pruebas completas antes y después de la refactorización.


Para las colecciones, devuelva copias o vistas no modificables para mantener la seguridad durante la transición. Para los marcos que requieren acceso de propiedad, es posible que necesite conservar accesorios simples sin el prefijo "get" junto a sus métodos ricos en comportamiento.


Como de costumbre, debe agregar cobertura comportamental (no estructural) a su código antes de realizar el refactoring.

¿Por qué el código es mejor?

El código refactorizado es mejor porque se adhiere a laNo te preguntesPrincipio, haciendo que sus objetos sean inteligentes en lugar de sólo contenedores de datos anémicos.


La solución centraliza la lógica relacionada con los datos del objeto dentro del objeto mismo, reduciendo la duplicación. oculta los detalles de implementación, permitiendo cambiar la representación interna sin afectar al código del cliente


Este enfoque reduceConexiónLos clientes no necesitan conocer la estructura interna del objeto.


También evita las violaciones de la Ley de Demeter al eliminar las cadenas de getters.


Desde elLa esencia no se mueve, la solución permite una mejor validación y ejecución de reglas de negocio dentro del objeto.

¿Cómo mejorar la bijeción? ️

La eliminación de gérmenes mejora laBijeciónentre el código y la realidad haciendo que los objetos se comporten más como sus homólogos del mundo real.


En el mundo real, los objetos no exponen su estado interno para que otros manipulen; realizan operaciones basadas en solicitudes.


Por ejemplo, usted no pide a una cuenta bancaria su saldo y luego calcula si una retirada es posible usted mismo. En su lugar, le pregunta a la cuenta, "¿Puedo retirar $ 100?"


Crea una representación más fiel de los conceptos de dominio modelando sus objetos para realizar operaciones en lugar de exponer los datos.

Esto fortalece la correspondencia uno a uno entre el mundo real y su modelo computable, haciendo que su código sea más intuitivo y alineado con la forma en que la gente piensa sobre el dominio del problema.


Este enfoque sigue laMapaprincipio garantizando que los objetos computacionales reflejan las entidades del mundo real en estructura y comportamiento.

Limitaciones ☀️

Frameworks y bibliotecas a menudo esperan métodos de serialización/deserialización.


Las bases de código heredadas pueden tener un uso generalizado de getter que es difícil de refactor todo de una vez.


Las pruebas de unidad pueden ser más desafiantes a medida que el estado interno es menos accesible. Recuerde, nunca debe probar métodos privados.

Refactor con AI

y

Prompt sugerido: 1. Identificar los getters que exponen el estado de objeto interno 2. Encontrar todos los usos de getter en la base de código 3. Mover el comportamiento que utiliza el getter en el objeto mismo 4. Crear métodos de revelación de intención que realicen operaciones (eliminar el prefixo de get) 5. Actualizar su código para usar los nuevos métodos

y

Prompt sugerido: 1. Identificar los getters que exponen el estado de objeto interno 2. Encontrar todos los usos de getter en la base de código 3. Mover el comportamiento que utiliza el getter en el objeto mismo 4. Crear métodos de revelación de intención que realicen operaciones (eliminar el prefixo de get) 5. Actualizar su código para usar los nuevos métodos

ySin instrucciones correctas con instrucciones específicas ChatGPT ChatGPT Claude Claude Perplexity Perplexity Copilot Copilot Gemini DeepSeek DeepSeek Meta AI Meta AI Grok Grok Qwen Qwen
Sin instrucciones correctas con instrucciones específicas ChatGPT ChatGPT Claude Claude Perplexity Perplexity Copilot Copilot Gemini DeepSeek DeepSeek Meta AI Meta AI Grok Grok Qwen QwenSin instrucciones adecuadas con instrucciones específicasSin instrucciones adecuadas

Sin instrucciones adecuadas

y

Con instrucciones específicas

Con instrucciones específicas

ChatGPT ChatGPTy

ChatGPT

ChatGPT

y

ChatGPT

ChatGPT

yClaudeyClaudeyClaude

Claude

Claude

Claude

Perplexidad PerplexidadPerplejidad

Perplejidad

Perplejidad

Perplejidad

piloto copilotopiloto

piloto

piloto

piloto

Gemini GeminiGemini

Gemini

Gemini

Gemini

Siguiente DeepSeeky

profundidad

profundidad

y

profundidad

profundidad

yEl objetivo esyEl objetivo esyEl objetivo es

El objetivo es

El objetivo es

El objetivo es

El gordoGrúas

Grúas

Grúas

Grúas

El Qwen QwenQuien

Quien

Quien

Quien

Tags ️

    y
  • Encapsulación
  • y

Nivel

    y
  • [x] El Intermedio
  • y

Reacciones relacionadas

Es decir,

Créditos

Imagen porKrisesPixabay


Este artículo forma parte de la serie Refactoring.


Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks