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
OperationsMergereerst uit om ruwe bewerkingen te coalesceren voordat de semantische passes worden toegepast —MergingOptimizerenOperationsSlideMergergaan 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 vanDeleteFirstenInsertFirsttussen 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
IDiffOptimizationOperationimplementeert, kun je een pijplijn opslaan alsIDiffOptimizationOperation[]enExecuteop elk element aanroepen in een lus in plaats van elke stap handmatig bij naam te coderen. - Voer
OperationsSlideMergeruit 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
| Probleem | Oorzaak | Oplossing |
|---|---|---|
| Diff bevat nog steeds kleine gefragmenteerde gelijkheden | Alleen OperationsMerger werd uitgevoerd; korte gelijkheden tussen bewerkingen werden nooit gevouwen | Voer ook MergingOptimizer uit na OperationsMerger |
| Delete/insert-volgorde keert onverwacht om tussen passes | Verschillende EditOperationsOrder-waarden werden doorgegeven aan verschillende optimalizers | Gebruik dezelfde EditOperationsOrder-waarde voor elke optimizer in de pipeline |
| Optimizer lijkt geen effect te hebben | De diff-lijst was al in canonieke vorm, of er werd een kopie van de lijst geoptimaliseerd in plaats van de oorspronkelijke referentie | Bevestig 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 / Methode | Beschrijving |
|---|---|
IDiffOptimizationOperation | Interface 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 |
OperationsMerger | Voegt aangrenzende operaties van hetzelfde type samen en factoriseert gemeenschappelijke voor- en achtervoegsels tot gelijkheden |
MergingOptimizer | Elimineert korte gelijkheden die door bewerkingen worden omgeven, en voegt ze vervolgens opnieuw samen tot een canonieke vorm |
OperationsSlideMerger | Verplaatst een bewerking die door gelijkheden wordt omgeven om er één te elimineren |
EditOperationsOrder | Enum die bepaalt of DeleteFirst of InsertFirst wordt uitgegeven op een gedeelde positie |