161 leituras

Refactoring 029 - Como substituir NULL com coleção

por Maximiliano Contieri6m2025/06/02
Read on Terminal Reader

Muito longo; Para ler

Substitua atributos opcionais anuláveis por coleções vazias para eliminar verificações nulas e alavancar o polimorfismo.
featured image - Refactoring 029 - Como substituir NULL com coleção
Maximiliano Contieri HackerNoon profile picture

Transformar atributos opcionais em coleções vazias para código mais limpo, mais seguro e polimórfico, eliminando o erro de bilhões de dólares

TL;DR: Substitua atributos opcionais anuláveis por coleções vazias para eliminar verificações nulas e alavancar o polimorfismo.

TL;DR: Substitua atributos opcionais anuláveis por coleções vazias para eliminar verificações nulas e alavancar o polimorfismo.

Problemas resolvidos

  • Exceções de referência nulas
  • Lógica condicional excessiva e IFs
  • Erros fracos de manuseio
  • Atributos opcionais
  • Código de validação complexo
  • Polimorfismo

Passos

  1. Identificar atributos opcionais que possam ser coleções
  2. Substituir objetos exclusivos por coleções vazias
  3. Remover todas as verificações nulas relacionadas a esses atributos opcionais
  4. Métodos de atualização para trabalhar com coleções em vez de objetos individuais

Código de amostra

Antes do

public class ShoppingCart {
    private List<Item> items = new ArrayList<>();
    private Coupon coupon = null;
    
    public void addItem(Item item) {
        this.items.add(item);
    }
    
    public void redeemCoupon(Coupon coupon) {
        this.coupon = coupon;
    }
    
    public double total() {
        double total = 0;
        
        for (Item item : this.items) {
            total += item.getPrice();
        }
        
        // This a polluted IF and null check
        if (this.coupon != null) {
            total -= this.coupon.getDiscount();
        }
        
        return total;
    }
    
    public boolean hasUnsavedChanges() {
        // Explicit null check
        return !this.items.isEmpty() || this.coupon != null;
    }
    
    public boolean hasCoupon() {        
        return this.coupon != null;
    }
}
public class ShoppingCart {
    private final List<Item> items = new ArrayList<>();
  
    // This version uses Optionals
    // Not all programming languages support this feature
    private Optional<Coupon> coupon = Optional.empty();

    public void addItem(Item item) {
        items.add(item);
    }

    public void redeemCoupon(Coupon coupon) {
        // You need to understand how optionals work
        this.coupon = Optional.ofNullable(coupon);
    }
    
    public boolean hasUnsavedChanges() {
        return !items.isEmpty() || !coupon.isPresent();
    }

    public boolean hasCoupon() {
        return coupon.isPresent();
    }
}

Depois disso 🙂

public class ShoppingCart {
  private List<Item> items = new ArrayList<>();
    
  // 1. Identify nullable optional attributes
  // that could be collections
  // 2. Replace single nullable objects with empty collections
  private List<Coupon> coupons = new ArrayList<>();
    
  public void addItem(Item item) {
      this.items.add(item);
  }
    
  // Step 4: Work with collection
  // instead of single nullable object
  public void redeemCoupon(Coupon coupon) {
      this.coupons.add(coupon);
  }
    
  // Step 4: Simplified logic without null checks
  public double total() {
    double total = 0;
      
    for (Item item : this.items) {
        total += item.getPrice();
    }
      
    // 3. Remove all null checks 
    // related to these optional attributes        
    for (Coupon coupon : this.coupons) {
        total -= coupon.getDiscount();
    }
      
    return total;
  }
    
  // Consistent behavior with empty collections
  public boolean hasUnsavedChanges() {
    // 4. Update methods to work with collections
    // instead of single objects 
    return !this.items.isEmpty() || !this.coupons.isEmpty();
  }
    
  // 3. Remove all null checks 
  // related to these optional attributes
  // Collection-based check instead of null check
  public boolean hasCoupon() {
    return !this.coupons.isEmpty();
  }
}

Tipo

  • [x] Semiautomático

Segurança ️

Este refactoring é geralmente seguro quando você controla todos os pontos de acesso aos atributos da coleção.


Você precisa certificar-se de que nenhum código externo espera valores nulos e lidar com as APIs internas.


O refactoring mantém o mesmo comportamento externo enquanto simplifica a lógica interna.


Você deve verificar se todos os construtores e métodos de fábrica iniciam as coleções corretamente.

Por que o código é melhor?

O código refactorizado eliminaExceções de ponto zeroReduzindo a complexidade condicional.


Coleções vazias e coleções não vazias se comportam polimórficamente, permitindo que você as trate uniformemente.


O código torna-se mais previsível porque as coleções sempre existem (pelo menos vazias) e respondem às mesmas operações.


Implementações de métodos tornam-se mais curtas e mais focadas na lógica de negócios em vez de manipulação nula.


A abordagem está alinhada com o princípio de tornar os estados ilegais não representáveis em seu modelo de domínio, levando a um código mais robusto e mantido.


Coleções vazias e coleções não vaziaspolymorphic.

Como melhorar a qualidade de vida? ️

No mundo real, contêineres existem mesmo quando estão vazios.


Ao representar coleções opcionais como coleções vazias em vez de nulas, você cria um modelo de realidade mais preciso.


O zero não existe no mundo real, e sempre quebra oBijeção.


Isso mantém a correspondência one-to-one entre conceitos do mundo real e seu modelo computacional, criando uma boaMapa.


Quando você devolve uma coleção em vez de nulls, você também reduzConexão.

Limitações ️

Este refactoring pode não ser adequado quando null tem um significado semântico diferente de "vazio".Algumas APIs legadas podem esperar valores null, exigindo camadas de adaptação.


Você precisa garantir que todos os caminhos de código iniciem coleções consistentemente para evitar estados nulos e vazios misturados.

Refactor com AI

Prompt sugerido: 1. Identificar atributos opcionais revogáveis que poderiam ser coleções 2. Substituir objetos individuais revogáveis por coleções vazias 3. Remover todos os controles nulos relacionados a esses atributos opcionais 4. Atualizar métodos para trabalhar com coleções em vez de objetos individuais 5. Teste que coleções vazias e não-vazias se comportam de forma consistente

Prompt sugerido: 1. Identificar atributos opcionais revogáveis que poderiam ser coleções 2. Substituir objetos individuais revogáveis por coleções vazias 3. Remover todos os controles nulos relacionados a esses atributos opcionais 4. Atualizar métodos para trabalhar com coleções em vez de objetos individuais 5. Teste que coleções vazias e não-vazias se comportam de forma consistente

Without Proper Instructions

With Specific Instructions

ChatGPT

ChatGPT

Claude

Claude

Perplexity

Perplexity

Copilot

Copilot

Gemini

Gemini

DeepSeek

DeepSeek

Meta AI

Meta AI

Grok

Grok

Qwen

Qwen

ChatGPT

ChatGPT

Claude

Claude

Perplexidade

Perplexidade

Filho Piloto

Filho Piloto

Gêmeos

Gêmeos

DeepSeek

DeepSeek

A meta é

A meta é

Grão

Grão

Quênia

Quênia

Dias ️

  • zero

Nível

  • [x] Intermediário

Veja também

Crédito

Imagem porE o K.ÉPixabay


Este artigo faz parte da série Refactoring.


Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks