אופטימיזציית Diff
אופטימיזציית Diff
מדריך זה מציג כיצד לנקות diff גולמי — רשימה של DiffOperation ערכים (ראה Diff כיצד הם נבנים) — לצורה קנונית, מינימלית באמצעות מעברי העיבוד שלאחר מכן ב- DiffOptimization תת-מרחב השם. כל מעבר מיישם IDiffOptimizationOperation ומשנה את רשימת ה-diff במקום, כך שהמעברים יכולים להיות מקושרים ברצף כדי לפשט את התוצאה באופן הדרגתי.
חוזה האופטימיזציה
IDiffOptimizationOperation מגדיר שיטה יחידה, Execute(diffs), שמנרמלת רשימה ניתנת לשינוי של ערכי DiffOperation במקום תוך שמירה על טקסטי המקור והיעד שה-diff מייצג. כל אופטימייזר בתת-מרחב השמות הזה מממש את הממשק הזה, ולכן ניתן לקרוא להם באופן החלף או להרכיב אותם בצינור.
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);מיזוג פעולות סמוכות
OperationsMerger ממזג diff לצורתו הקנונית המינימלית: הוא מאחד רצפים סמוכים של אותו סוג פעולה, ובמקרה של רצף משולב של מחיקה/הוספה הוא מפצל כל קידומת משותפת אל השוויון הקודם וכל סיומת משותפת אל השוויון הבא.
var merger = new OperationsMerger(EditOperationsOrder.DeleteFirst);
merger.Execute(diffs);הסרת שוויונים קצרים
MergingOptimizer מבצע מעבר ניקוי סמנטי: הוא מסיר שוויונות שאינם גדולים מהעריכות שמסביבם, מקפל את הרצפים הקצרים המשותפים חזרה לתוך המחיקה/ההוספה הסמוכה, ולאחר מכן ממזג מחדש את התוצאה לצורה קנונית.
var semanticOptimizer = new MergingOptimizer(EditOperationsOrder.InsertFirst);
semanticOptimizer.Execute(diffs);הזזת עריכות על פני שוויונות
OperationsSlideMerger מזיז עריכה יחידה שמוקפת משני הצדדים על ידי שוויונות, לצד, ומסיר אחד מהשוויונות הללו, ובכך מקנון נוסף של ההבדל.
IDiffOptimizationOperation slideMerger = new OperationsSlideMerger();
slideMerger.Execute(diffs);בקרת סדר מחיקה/הוספה
כאשר מחיקה והוספה נוצרות לאותו מיקום, המונה EditOperationsOrder שולט באיזה אחת האופטימייזר מציב ראשונה ברצף הפעולות המתקבל: DeleteFirst או InsertFirst.
var order = EditOperationsOrder.DeleteFirst;
var optimizer = new MergingOptimizer(order);
optimizer.Execute(diffs);טיפים ושיטות מומלצות
- הפעל את
OperationsMergerתחילה כדי לאחד עריכות גולמיות לפני יישום המעברים הסמנטיים —MergingOptimizerו-OperationsSlideMergerמניחים ששתי פעולות סמוכות מאותו סוג כבר משולבות. - בחר ערך
EditOperationsOrderאחד והשתמש בו בעקביות בכל אופטימייזר בצינור; ערבוב שלDeleteFirstו-InsertFirstבין מעברים יכול לבטל את סדר הפעולות שהמעבר הקודם קבע. - כל שלושת האופטימייזרים משנים את
List<DiffOperation>במקום — שכפל את הרשימה תחילה אם אתה צריך לשמור על ההבדל הבלתי-אופטימלי לצורך השוואה. - מאחר שכל אופטימייזר מממש את
IDiffOptimizationOperation, אתה יכול להחזיק צינור עבודה כ-IDiffOptimizationOperation[]ולקרוא ל-Executeעל כל אחד בלולאה במקום לקודד במפורש כל שלב בשם. - החל את
OperationsSlideMergerאחרי שלבי המיזוג — החלקת עריכה שימושית רק לאחר שרצפים סמוכים מאותו סוג כבר מוזגים.
בעיות נפוצות
| בעיה | גורם | תיקון |
|---|---|---|
| ה-Diff עדיין מכיל שוויונים קטנים מקוטעים | רק OperationsMerger הורץ; שוויונים קצרים בין העריכות מעולם לא קופלו | הפעל גם את MergingOptimizer אחרי OperationsMerger |
| סדר המחיקה/ההוספה מתהפך באופן בלתי צפוי בין ריצות | ערכי EditOperationsOrder שונים נשלחו לאופטימייזרים שונים | השתמש באותו ערך של EditOperationsOrder עבור כל אופטימייזר בצינור |
| נראה שהאופטימייזר אינו משפיע | רשימת ה-diff הייתה כבר בצורה קנונית, או שהעתק של הרשימה באופטימיזציה במקום ההפנייה המקורית | אשר שאתה מעביר את אותה הפנייה List<DiffOperation> שהקוד התחתון קורא |
FAQ
מה משמעות “צורה קנונית” עבור diff?
זה אומר שהפעולות הסמוכות מאותו סוג מוזגו וכי כל קידומת/סיומת משותפת בריצות משולבות של מחיקה/הוספה קופצה לתוך השוויון השכני, כך שהרצף אינו מכיל פיצול מיותר.
האם עליי להשתמש בכל שלושת האופטימייזרים?
לא. IDiffOptimizationOperation מאפשר לך להפעיל רק את ההעברות שאתה צריך, אך הרצת OperationsMerger לפני ההעברות הסמנטיות (MergingOptimizer, OperationsSlideMerger) נותנת את התוצאות העקביות ביותר.
מה ההבדל בין OperationsMerger ל-MergingOptimizer?
OperationsMerger מבצע קואלציית מבנה (רצפים מאותו סוג, קידומת/סיומת משותפת). MergingOptimizer הולך צעד נוסף וקורא שוויונים קצרים שמוקפים בעריכות חזרה לתוך המחיקה/ההוספה הסמוכה לפני מיזוג מחדש.
האם EditOperationsOrder משנה את מה שה-diff מייצג?
לא. הוא רק שולט בסדר ההפצה של מחיקה והוספה החלים על אותה מיקום — שיחזור הטקסט המתקבל אינו מושפע.
API Reference סיכום
| מחלקה / מתודה | תיאור |
|---|---|
IDiffOptimizationOperation | ממשק עבור שלב עיבוד לאחרון שמנרמל diff במקום |
IDiffOptimizationOperation.Execute(diffs) | מריץ את שלב האופטימיזציה על רשימה ניתנת לשינוי של ערכי DiffOperation values |
OperationsMerger | מאחד פעולות סמוכות מאותו סוג ומפרק קידומת/סיומת משותפת לשוויונים |
MergingOptimizer | מבטל שוויונים קצרים המוקפים בעריכות, ואז ממזג מחדש לצורה קנונית |
OperationsSlideMerger | הזזת עריכה המוקפת בשוויונים כדי לבטל אחת מהן |
EditOperationsOrder | Enum ששולט האם DeleteFirst או InsertFirst נשלחים במיקום משותף |