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...
}