תכנון פונקציית Undo

תכנון פונקציית Undo

או קיי חברים, יש לי מערכת עם סרגל כלים עמוס פעולות. אני רוצה לאפשר לעשות UNDO. איך מממשים דבר כזה? נגיד שהמשתמש מחק לקוח. הלקוח כבר נמחק מהDB, כל הקשרים שלו, החשבונות שלו, הכרטיסיות שלו נמחקו. הטרנזקציה כבר עברה Commit ועכשיו אני צריך להחזיר הכל. האם הדרך הנכונה זה לשמור הכל בצד (כמו הסל מיחזור), ואז ליצור הכל מחדש? יש דרך מתוכמת יותר? מה לגבי Undo של שינויים אחרים?
 

ddalus

New member
הפתרון העקרוני

אליבא ד'GOF (מה שנקרא "חבורת הארבעה", כותבי הספר "Design Patterns"). הבעיה של היסטריית פקודות שמאפשרת UNDO ניתנת לפתרון בעזרת התבנית "Command". פרטים נוספים ניתן למצוא בספר עצמו, או בסיכומים שלו ברשת (או אפילו בפורום זה?). רק הערה: פעולת המחיקה שאתה מתאר כוללת מספר גישות נפרדות ל-DB. כדאי לוודא שכל הפרוצודורה היא transactional באופן אינהרנטי, כלומר שאם חלק מהפרוצדורה נכשל, אז במקום המשך commit יש roll-back - אבל זה כבר לא רלוונטי כל-כך לשאלה.
 

ייוניי

New member
כוון כללי

כשאני מתכנן UNDO אני רואה לנגד עיני ממשק פשוט:
public interface UndoableAction { void undo(); void redo(); string getActionName(); }​
שאותו תיישם כל פעולה שניתן לעשות לה undo. היישום אמנם איננו טריויאלי אבל גם לא מאוד מורכב (תלוי במהן הפעולות שהמערכת מאפשרת). לאחר מכן מיישמים מחסניות ל undo ו redo וזהו! עכשיו, לגבי טרנזאקציות מול DB אני יכול לתת לך רעיון לא ממש מקורי של עבודה עם רשומות הסטוריות. כלומר, שמחיקת לקוח לא תגרום למחיקה של רשומות ב DB (שבעולם המידע של ימינו זה בכלל דבר לא מומלץ) אלא בסימון דגל של "מחוק" (או "הסטורי" אם להיות פוליטיקלי קורקט). אחרי שתוסיף פעולה של "שחזור לקוח הסטורי" תוכל ליישם את UndoableAction כך שפעולת ה undo תשחזר את הלקוח ופעולת ה redo תמחק אותו שוב וכו'... כמובן שתמיד יהיו פעולות מסויימות שאינן undoable (כמו למשל Commit ב DB כמו שהזכרת) וכל מה שחשוב במקרה כזה זה להודיע למשתמש שיזהר. אגב, יצא לי גם לראות אפליקציות שמשתמשות ב rollback וב save points (לפחות ב oracle) על מנת לבצע Undo בתוך טרנזאקציה במהלך סימולציות על ה DB (כמובן שבמקרה הזה אין תמיכה ב redo).
 
למעלה