Optimalizace diffu

Optimalizace diffu

Tento průvodce ukazuje, jak vyčistit surový diff — seznam DiffOperation hodnot (viz Diff jak jsou tyto vytvářeny) — do kanonické, minimální podoby pomocí post-processing průchodů v DiffOptimization pod-jmenném prostoru. Každý průchod implementuje IDiffOptimizationOperation a mění seznam diffů na místě, takže průchody lze řetězit v sekvenci a postupně zjednodušovat výsledek.


Smlouva o optimalizaci

IDiffOptimizationOperation definuje jedinou metodu, Execute(diffs), která normalizuje mutovatelný seznam hodnot DiffOperation na místě při zachování zdrojových a cílových textů, které diff reprezentuje. Každý optimalizátor v tomto pod-jmenném prostoru implementuje toto rozhraní, takže může být volán zaměnitelně nebo skládán do 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);

Sloučení sousedních operací

OperationsMerger sloučí diff do jeho kanonické minimální podoby: sloučí sousední sekvence stejného druhu operace a pro smíšený úsek delete/insert rozčlení jakýkoli společný prefix do předchozí rovnosti a jakýkoli společný suffix do následující rovnosti.

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

Odstraňování krátkých rovností

MergingOptimizer provádí sémantický úklidový průchod: odstraní rovnosti, které nejsou větší než úpravy je obklopující, zabalí tyto krátké společné sekvence zpět do sousedního delete/insert a poté znovu sloučí výsledek do kanonické podoby.

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

Posouvání úprav přes rovnosti

OperationsSlideMerger posune jedinou úpravu, která je na obou stranách obklopena rovnostmi, do strany, čímž eliminuje jednu z těchto rovností a dále kanonizuje diff.

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

Řízení pořadí delete/insert

Když je pro stejnou pozici vygenerován delete i insert, enum EditOperationsOrder určuje, který z nich optimalizér umístí jako první ve výsledné sekvenci operací: DeleteFirst nebo InsertFirst.

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

Tipy a osvědčené postupy

  • Spusťte OperationsMerger nejprve, aby se sloučily surové úpravy před aplikací sémantických průchodů — MergingOptimizer i OperationsSlideMerger předpokládají, že sousední operace stejného druhu již byly sloučeny.
  • Zvolte jednu hodnotu EditOperationsOrder a používejte ji důsledně ve všech optimalizérech v pipeline; míchání DeleteFirst a InsertFirst mezi průchody může zrušit pořadí, které stanovil předchozí průchod.
  • Všichni tři optimalizátory mění List<DiffOperation> přímo na místě — pokud potřebujete zachovat neoptimalizovaný diff pro porovnání, nejprve klonujte seznam.
  • Protože každý optimalizátor implementuje IDiffOptimizationOperation, můžete uchovávat pipeline jako IDiffOptimizationOperation[] a volat Execute na každém v cyklu místo toho, abyste pevně kódovali každý průchod podle jména.
  • Aplikujte OperationsSlideMerger po průchodech slučování — posouvání úpravy má smysl až poté, co jsou sousední bloky stejného typu již sloučeny.

Časté problémy

ProblémPříčinaOprava
Diff stále obsahuje malé fragmentované rovnostiByl spuštěn jen OperationsMerger; krátké rovnosti mezi úpravami nikdy nebyly složenyTaké spusťte MergingOptimizer po OperationsMerger
Pořadí mazání/vkládání se neočekávaně obrací mezi průchodyRůzné hodnoty EditOperationsOrder byly předány různým optimalizátorůmPoužijte stejnou hodnotu EditOperationsOrder pro každý optimalizátor v pipeline
Zdá se, že optimalizátor nemá žádný účinekSeznam diff byl již v kanonické podobě, nebo byl optimalizován kopií seznamu místo původní referencePotvrďte, že předáváte stejný odkaz List<DiffOperation>, který čte downstream kód

FAQ

Co znamená „kanonická forma“ pro diff?

To znamená, že sousední operace stejného typu byly sloučeny a jakýkoli společný prefix/suffix ve smíšených blocích mazání/vkládání byl přeneseno do sousední rovnosti, takže sekvence nemá žádnou nadbytečnou fragmentaci.

Musím použít všechny tři optimalizátory?

Ne. IDiffOptimizationOperation vám umožňuje použít jen ty průchody, které potřebujete, ale spuštění OperationsMerger před sémantickými průchody (MergingOptimizer, OperationsSlideMerger) dává nejkonzistentnější výsledky.

Jaký je rozdíl mezi OperationsMerger a MergingOptimizer?

OperationsMerger provádí strukturální slučování (běhy stejného druhu, společná předpona/přípona). MergingOptimizer jde dál a složí krátké rovnosti obklopené úpravami zpět do sousedního mazání/vložení před opětovným sloučením.

Mění EditOperationsOrder to, co diff představuje?

Ne. Pouze řídí pořadí generování mazání a vložení, které se vztahují ke stejnému místu — výsledná rekonstrukce textu není ovlivněna.


API Reference Shrnutí

Třída / MetodaPopis:
IDiffOptimizationOperationRozhraní pro post-processingový průchod, který normalizuje diff přímo na místě
IDiffOptimizationOperation.Execute(diffs)Spouští optimalizační průchod přes mutovatelný seznam hodnot DiffOperation
OperationsMergerSlučuje sousední operace stejného typu a faktorizuje společnou předponu/příponu do rovností
MergingOptimizerOdstraňuje krátké rovnosti obklopené úpravami, poté je znovu sloučí do kanonické formy
OperationsSlideMergerPosouvá úpravu obklopenou rovnostmi tak, aby se jedna z nich eliminovala
EditOperationsOrderVýčet, který řídí, zda je na sdílené pozici emitován DeleteFirst nebo InsertFirst

Viz také:

 Čeština