Otimização de Diff

Otimização de Diff

Este guia mostra como limpar um diff bruto — uma lista de DiffOperation valores (veja Diff para como eles são construídos) — em uma forma canônica e mínima usando as passagens de pós-processamento no DiffOptimization sub-namespace. Cada passagem implementa IDiffOptimizationOperation e altera a lista de diff no local, permitindo que as passagens sejam encadeadas em sequência para simplificar progressivamente o resultado.


O contrato de otimização

IDiffOptimizationOperation define um único método, Execute(diffs), que normaliza uma lista mutável de valores DiffOperation in-place enquanto preserva os textos de origem e destino que o diff representa. Cada otimizador neste sub-namespace implementa essa interface, de forma que podem ser invocados de maneira intercambiável ou compostos em um pipeline.

List<DiffOperation> diffs = new List<DiffOperation>
{
    new DiffOperation(Operation.Equal, "The quick "),
    new DiffOperation(Operation.Delete, "brown "),
    new DiffOperation(Operation.Insert, "red "),
    new DiffOperation(Operation.Equal, "fox")
};

IDiffOptimizationOperation optimizer = new OperationsMerger(EditOperationsOrder.DeleteFirst);
optimizer.Execute(diffs);

Mesclando operações adjacentes

OperationsMerger mescla um diff em sua forma canônica mínima: ele combina sequências adjacentes do mesmo tipo de operação, e para uma sequência mista de exclusão/inserção ele extrai qualquer prefixo comum para a igualdade anterior e qualquer sufixo comum para a igualdade subsequente.

var merger = new OperationsMerger(EditOperationsOrder.DeleteFirst);
merger.Execute(diffs);

Eliminando igualdades curtas

MergingOptimizer executa uma passagem de limpeza semântica: elimina igualdades que não são maiores que as edições ao seu redor, dobrando essas curtas sequências comuns de volta nas exclusões/inserções adjacentes e, em seguida, remescla o resultado na forma canônica.

var semanticOptimizer = new MergingOptimizer(EditOperationsOrder.InsertFirst);
semanticOptimizer.Execute(diffs);

Deslizando edições ao longo de igualdades

OperationsSlideMerger desloca lateralmente uma única edição que está cercada por igualdades em ambos os lados, removendo uma dessas igualdades e aprimorando ainda mais a forma canônica da diferença.

IDiffOptimizationOperation slideMerger = new OperationsSlideMerger();
slideMerger.Execute(diffs);

Controlando a ordem de delete/insert

Quando uma exclusão e uma inserção são emitidas para a mesma posição, o enum EditOperationsOrder define qual delas o otimizador coloca primeiro na sequência de operações resultante: DeleteFirst ou InsertFirst.

var order = EditOperationsOrder.DeleteFirst;
var optimizer = new MergingOptimizer(order);
optimizer.Execute(diffs);

Dicas e boas práticas

  • Execute OperationsMerger primeiro para agrupar edições brutas antes de aplicar as passagens semânticas — MergingOptimizer e OperationsSlideMerger pressupõem que operações semelhantes próximas já foram combinadas.
  • Escolha um valor de EditOperationsOrder e utilize-o de forma consistente em todos os otimizadores de um pipeline; misturar DeleteFirst e InsertFirst entre as passagens pode desfazer a ordem estabelecida por uma passagem anterior.
  • Todos os três otimizadores alteram o List<DiffOperation> no local — clone a lista primeiro se precisar manter o diff não otimizado para comparação.
  • Como cada otimizador implementa IDiffOptimizationOperation, você pode manter um pipeline como IDiffOptimizationOperation[] e chamar Execute em cada um dentro de um loop, em vez de codificar manualmente cada passagem pelo nome.
  • Aplique OperationsSlideMerger após as passagens de mesclagem — deslizar uma edição só é útil depois que blocos adjacentes do mesmo tipo já foram coalescidos.

Problemas comuns

ProblemaCausaCorreção
A diferença ainda contém pequenas igualdades fragmentadasSó OperationsMerger foi executado; pequenas igualdades entre edições nunca foram compactadasExecute também MergingOptimizer após OperationsMerger
A ordem de exclusão/inserção inverte inesperadamente entre as passagensValores diferentes de EditOperationsOrder foram passados para otimizadores diferentesUse o mesmo valor de EditOperationsOrder para cada otimizador no pipeline
O otimizador parece não ter efeitoA lista de diferenças já estava em forma canônica, ou uma cópia da lista foi otimizada em vez da referência originalConfirme que está passando a mesma referência List<DiffOperation> que o código downstream lê

FAQ

O que significa “forma canônica” para um diff?

Significa que operações consecutivas do mesmo tipo foram coalescidas e qualquer prefixo/sufixo comum em sequências misturadas de exclusão/inserção foi incorporado à igualdade vizinha, de modo que a sequência não possui fragmentação redundante.

Preciso usar os três otimizadores?

Não. IDiffOptimizationOperation permite que você aplique apenas as passagens necessárias, mas executar OperationsMerger antes das passagens semânticas (MergingOptimizer, OperationsSlideMerger) produz os resultados mais consistentes.

Qual é a diferença entre OperationsMerger e MergingOptimizer?

OperationsMerger realiza a coalescência estrutural (sequências de mesmo tipo, prefixo/sufixo comum). MergingOptimizer aprofunda o processo e incorpora pequenas igualdades cercadas por alterações ao bloco de exclusão/inserção vizinho antes de fazer a nova fusão.

O EditOperationsOrder altera o que o diff representa?

Não. Ele apenas controla a ordem de emissão de uma exclusão e de uma inserção que se aplicam ao mesmo ponto — a reconstrução final do texto permanece inalterada.


API Reference Resumo

Classe / MétodoDescrição
IDiffOptimizationOperationInterface para uma passagem de pós-processamento que normaliza um diff no local
IDiffOptimizationOperation.Execute(diffs)Executa a passagem de otimização sobre uma lista mutável de valores DiffOperation
OperationsMergerAgrupa operações vizinhas da mesma categoria e transforma prefixos/sufixos comuns em igualdades
MergingOptimizerElimina equalidades curtas cercadas por edições, então refunde em forma canônica
OperationsSlideMergerDesloca uma edição cercada por equalidades para eliminar uma delas
EditOperationsOrderEnum que controla se DeleteFirst ou InsertFirst é emitido em uma posição compartilhada

Ver também

 Português