Prática com o Padrão Builder no Rainbow: Evitando Vazamentos de Memória e Afogos de Desempenho

O Rainbow é uma biblioteca especializada em formatação de saída do console para desenvolvedores Swift. Ele utiliza o padrão Builder para permitir a construção de texto formatado de forma elegante e encadeada. Este artigo explora como aplicar o padrão Builder no Rainbow, focando em evitar vazamentos de memória e afogos de desempenho.

Compreendendo o Padrão Builder no Rainbow

O Rainbow implementa dois principais tipos de Builder: CondicionalEstilizadorBuilder e ConstrutorTextoEstilizado. Estes servem para construir estilos condicionais e strings de alto desempenho, respectivamente. ### ConstrutorTextoEstilizado: Construtor de Strings de Alto Desempenho

Introduzido na versão 4.2.0 do Rainbow, o ConstrutorTextoEstilizado é baseado em um tipo de valor, retornando uma nova instância a cada chamada de método, evitando problemas de gerenciamento de memória associados a tipos de referência. ``` public struct ConstrutorTextoEstilizado { public init(_ texto: String) { ... } private init(texto: String, cor: TipoCor?, fundo: TipoFundoCor?, estilos: [Estilo]) { ... }

public func aplicandoCor(_ cor: TipoCor) -> ConstrutorTextoEstilizado {
    return ConstrutorTextoEstilizado(texto: texto, cor: cor, fundo: fundo, estilos: estilos)
}

// Mais métodos de construção...

}


### CondicionalEstilizadorBuilder: Construtor de Estilos Condicionais

O `CondicionalEstilizadorBuilder` oferece a capacidade de construir estilos baseados em condições, utilizando um design orientado a classes para gerenciar a lógica interna dos estilos condicionais. ```
public class CondicionalEstilizadorBuilder {
    public init(texto: String) { ... }
    init(builder: CondicionalEstilizadorBuilder, condicao: Bool) { ... }
    
    public func cor(_ cor: CorNomeada) -> CondicionalEstilizadorBuilder { ... }
    public func fundo(_ cor: FundoCorNomeada) -> CondicionalEstilizadorBuilder { ... }
    public func estilo(_ estilo: Estilo) -> CondicionalEstilizadorBuilder { ... }
    
    // Mais métodos de construção...
}

Práticas Chave para Evitar Vazamentos de Memória

1. Preferir Builders Baseados em Tipos de Valor

O ConstrutorTextoEstilizado, sendo um tipo de valor, elimina o risco de vazamento de memória. Tipos de valor são copiados ao serem passados ou atribuídos, evitando ciclos de referência. ``` // Uso seguro let textoEstilizado = ConstrutorTextoEstilizado("Olá Rainbow") .vermelho .negrito .construir()


### 2. Lidar Cautelosamente com Builders Baseados em Tipos de Referência

Ao usar o `CondicionalEstilizadorBuilder`, é crucial evitar referências fortes a `self` dentro de fechamentos, especialmente em operações assíncronas. ```
// Risco potencial
let construtor = CondicionalEstilizadorBuilder(texto: "Olá")
algumaOperacaoAssincrona {
    // Se aqui houver uma referência forte a self, pode ocorrer um ciclo de referência
    construtor.cor(.vermelho).estilo(.negrito)
}

// Prática segura
let construtor = CondicionalEstilizadorBuilder(texto: "Olá")
algumaOperacaoAssincrona { [fraco self] in
    guarda let self = self else { return }
    construtor.cor(self.corErro).estilo(.negrito)
}

3. Liberar Instâncias de Builder a Tempo

Embora o ARC do Swift gerencie a memória automaticamente, é recomendável definir instâncias de Builder que persistem por tempo longo como nulas após seu uso, ajudando o sistema a recuperar a memória mais rapidamente. ``` var construtor: CondicionalEstilizadorBuilder? = CondicionalEstilizadorBuilder(texto: "Operação longa") // Usar construtor... construtor = nil // Liberar explicitamente após o uso


Dicas Úteis para Otimizar o Desempenho do Padrão Builder
--------------------------------------------------------

### 1. Utilizar Design Imutável para Reduzir Custos de Cópia

A estrutura do `ConstrutorTextoEstilizado` aproveita as características dos tipos de valor do Swift, usando design imutável para minimizar cópias desnecesssárias. Apenas as propriedades alteradas são atualizadas, enquanto as não alteradas são compartilhadas. ```
// Chamadas encadeadas eficientes
let construtorBase = ConstrutorTextoEstilizado("Texto base").negrito
let textoVermelho = construtorBase.vermelho // Apenas a cor é copiada
let textoVerde = construtorBase.verde // Apenas a cor é copiada

2. Aplicar Estilos em Lotes para Reduzir Instâncias Intermediárias

Ao aplicar múltiplos estilos, tente usar métodos em lotes para reduzir a criação de instâncias intermediárias, melhorando o desempenho. ``` // Melhor desempenho let textoEstilizado = ConstrutorTextoEstilizado("Olá") .aplicandoEstilos([.negrito, .sublinhado]) .aplicandoCor(.azul) .construir()

// Em comparação, cria mais instâncias intermediárias let textoEstilizado = ConstrutorTextoEstilizado("Olá") .negrito .sublinhado .azul .construir()


### 3. Reutilizar Instâncias de Builder

Para requisitos de construção de estilo repetitivos, considere reutilizar instâncias de Builder, evitando custos de criação e destruição frequentes de objetos. ```
// Reutilização de instâncias de Builder
let construtorBase = ConstrutorTextoEstilizado("").negrito.azul

let mensagem1 = construtorBase.aplicandoTexto("Mensagem 1").construir()
let mensagem2 = construtorBase.aplicandoTexto("Mensagem 2").construir()
let mensagem3 = construtorBase.aplicandoTexto("Mensagem 3").construir()

Caso de Uso Prático: Construindo um Sistema de Log de Alto Desempenho

Abaixo está um exemplo de como utilizar o padrão Builder do Rainbow para construir um sistema de log de alto desempanho, equilibrando legibilidade do código e desempenho em tempo de execução: ``` classe Registrador { private let construtorPadrao: ConstrutorTextoEstilizado

init() {
    // Pré-configurar estilos padrão
    construtorPadrao = ConstrutorTextoEstilizado("")
        .aplicandoEstilo(.escuro)
        .aplicandoCor(.pretoClaro)
}

func registrarInfo(_ mensagem: String) {
    let log = construtorPadrao
        .aplicandoTexto("[INFO] \(mensagem)")
        .aplicandoCor(.azul)
        .construir()
    print(log)
}

func registrarErro(_ mensagem: String) {
    let log = construtorPadrao
        .aplicandoTexto("[ERRO] \(mensagem)")
        .aplicandoCor(.vermelho)
        .aplicandoEstilo(.negrito)
        .construir()
    print(log)
}

// Outros métodos de registro...

}

Tags: swift rainbow design-patterns builder-pattern memory-management

Publicado em 10-8 09:45