Diff-optimalisatie

Diff-optimalisatie

Deze gids laat zien hoe je een ruwe diff — een lijst van DiffOperation waarden (zie Diff voor hoe die zijn opgebouwd) — om te zetten naar een canonieke, minimale vorm met behulp van de post-processing passes in de DiffOptimization sub-namespace. Elke pass implementeert IDiffOptimizationOperation en wijzigt de diff-lijst in-place, zodat passes in volgorde kunnen worden gekoppeld om het resultaat geleidelijk te vereenvoudigen.


Het optimalisatiecontract

IDiffOptimizationOperation definieert één methode, Execute(diffs), die een mutabele lijst van DiffOperation waarden in-place normaliseert, terwijl de bron- en doeltteksten die de diff representeert behouden blijven. Elke optimizer in deze sub-namespace implementeert deze interface, zodat ze onderling uitwisselbaar kunnen worden aangeroepen of in een pipeline kunnen worden samengesteld.

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);

Aangrenzende bewerkingen samenvoegen

OperationsMerger voegt een diff samen tot zijn canonieke minimale vorm: het combineert aangrenzende runs van hetzelfde type bewerking, en bij een gemengde delete/insert-run verplaatst het eventuele gemeenschappelijke voorvoegsel naar de voorafgaande gelijkheid en eventuele gemeenschappelijke achtervoegsel naar de daaropvolgende gelijkheid.

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

Korte gelijkheden elimineren

MergingOptimizer voert een semantische opschoonbeurt uit: het verwijdert gelijkheden die niet groter zijn dan de bewerkingen eromheen, vouwt die korte gemeenschappelijke reeksen terug in de aangrenzende delete/insert, en voegt vervolgens het resultaat opnieuw samen tot de canonieke vorm.

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

Bewerking over gelijkheden schuiven

OperationsSlideMerger verplaatst een enkele bewerking die aan beide kanten door gelijkheden wordt omgeven, zijwaarts, waardoor een van die gelijkheden verdwijnt en de diff verder wordt gecanoniseerd.

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

De volgorde van delete/insert regelen

Wanneer er een delete en een insert worden uitgegeven voor dezelfde positie, bepaalt de EditOperationsOrder enum welke ervan een optimizer als eerste plaatst in de resulterende operatiesequentie: DeleteFirst of InsertFirst.

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

Tips en best practices

  • Voer OperationsMerger eerst uit om ruwe bewerkingen te coalesceren voordat de semantische passes worden toegepast — MergingOptimizer en OperationsSlideMerger gaan er beide van uit dat aangrenzende bewerkingen van hetzelfde type al zijn samengevoegd.
  • Kies één EditOperationsOrder-waarde en gebruik deze consequent in elke optimizer van een pipeline; het combineren van DeleteFirst en InsertFirst tussen passes kan de door een vorige pass ingestelde volgorde ongedaan maken.
  • Alle drie optimalisatoren muteren de List<DiffOperation> ter plaatse — kloon de lijst eerst als je de niet-geoptimaliseerde diff voor vergelijking moet behouden.
  • Aangezien elke optimizer IDiffOptimizationOperation implementeert, kun je een pijplijn opslaan als IDiffOptimizationOperation[] en Execute op elk element aanroepen in een lus in plaats van elke stap handmatig bij naam te coderen.
  • Voer OperationsSlideMerger uit na de merge-passes — het verschuiven van een bewerking is alleen zinvol wanneer naast elkaar liggende reeksen van dezelfde soort al zijn samengevoegd.

Veelvoorkomende problemen

ProbleemOorzaakOplossing
Diff bevat nog steeds kleine gefragmenteerde gelijkhedenAlleen OperationsMerger werd uitgevoerd; korte gelijkheden tussen bewerkingen werden nooit gevouwenVoer ook MergingOptimizer uit na OperationsMerger
Delete/insert-volgorde keert onverwacht om tussen passesVerschillende EditOperationsOrder-waarden werden doorgegeven aan verschillende optimalizersGebruik dezelfde EditOperationsOrder-waarde voor elke optimizer in de pipeline
Optimizer lijkt geen effect te hebbenDe diff-lijst was al in canonieke vorm, of er werd een kopie van de lijst geoptimaliseerd in plaats van de oorspronkelijke referentieBevestig dat je dezelfde List<DiffOperation> referentie doorgeeft die downstream code leest

FAQ

Wat betekent “canonieke vorm” voor een diff?

Het betekent dat aangrenzende bewerkingen van dezelfde soort zijn samengevoegd en dat eventuele gemeenschappelijke voor- of achtervoegsels in gemengde verwijder-/invoegreeksen zijn opgenomen in de naburige gelijkheid, zodat de reeks geen overbodige fragmentatie meer bevat.

Moet ik alle drie optimalisatoren gebruiken?

Nee. IDiffOptimizationOperation laat je alleen de passes toepassen die je nodig hebt, maar het uitvoeren van OperationsMerger vóór de semantische passes (MergingOptimizer, OperationsSlideMerger) geeft de meest consistente resultaten.

Wat is het verschil tussen OperationsMerger en MergingOptimizer?

OperationsMerger voert structurele coalescentie uit (reeksen van hetzelfde type, gemeenschappelijke voor- of achtervoegsels). MergingOptimizer gaat een stap verder en vouwt korte gelijkheden die door bewerkingen worden omsloten terug in de aangrenzende delete/insert voordat opnieuw wordt samengevoegd.

Verandert EditOperationsOrder wat de diff vertegenwoordigt?

Nee. Het regelt alleen de volgorde van uitgifte van een delete en een insert die op dezelfde positie van toepassing zijn — de resulterende tekstreconstructie blijft onaangedaan.


API Reference Samenvatting

Klasse / MethodeBeschrijving
IDiffOptimizationOperationInterface voor een post-processing stap die een diff ter plaatse normaliseert
IDiffOptimizationOperation.Execute(diffs)Voert de optimalisatie-stap uit over een mutabele lijst van DiffOperation waarden
OperationsMergerVoegt aangrenzende operaties van hetzelfde type samen en factoriseert gemeenschappelijke voor- en achtervoegsels tot gelijkheden
MergingOptimizerElimineert korte gelijkheden die door bewerkingen worden omgeven, en voegt ze vervolgens opnieuw samen tot een canonieke vorm
OperationsSlideMergerVerplaatst een bewerking die door gelijkheden wordt omgeven om er één te elimineren
EditOperationsOrderEnum die bepaalt of DeleteFirst of InsertFirst wordt uitgegeven op een gedeelde positie

Zie ook

 Nederlands