יום שבת, 12 במאי 2007

מבט אישי על תכנות תיאורי (DP)

לאחר שקיבלנו רקע על חלק מהיכולות ואופן השימוש ב-Descriptive Programming, אני יכול לדבר על הנושא מזוית אישית יותר. עם השנים פיתחתי הרגלי כתיבת קוד שונים ומשונים, בין השאר בנוגע ל-DP. הרגלים הם שרירותיים מעצם טיבם, ויתכן שיש דרכים יעילות או טובות יותר להשתמש ב-DP, אבל אם אני כבר כאן, למה שלא אחלוק חלק מהם:

אני לא סומך על Regular Expressions ב-DP.
כאשר מכניסים תכונות זיהוי לאובייקט Description סטאטי, אפשר להגדיר את הערכים הצפויים בעזרת תבניות Regular Expression, באופן הבא:


Dim oDesc
Set oDesc = Description.Create

oDesc("property1").Value = "RegExPattern"
oDesc("property1").RegularExpression = True



אני אישית מעדיף לא לסמוך על RegEx במקרה הזה, היות ולפעמים הקריטריונים לזיהוי מורכבים מאוד, דורשים מגע בתכונות Run-Time, וכו'. במקום לסנן את האובייקטים כבר באמצעות תכונות הזיהוי שלהם, אני מעדיף לקבל את כל האובייקטים העונים למכנה משותף מאוד נמוך (לדוגמה – סוג האובייקט – Combobox/CheckBox וכו'); לפעמים אעדיף אפילו לקבל את כלל האובייקטים בחלון / אפליקציה.

לאחר שקיבלתי אוסף גדול עם כל האובייקטים, אני יכול לרוץ עליו סדרתית, ולמצוא את האובייקטים הדרושים לי בקלות, גם אם הקריטריונים לסינון הם מאוד מורכבים. לדוגמה, נניח ונרצה למצוא Checkbox בעל Tooltip מסויים:



Dim oDesc, oChildren
Dim i
Set oDesc = Description.Create

oDesc("micclass").Value = "VbCheckbox"
Set oChildren = VbWindow("Main").ChildObjects(oDesc)

For I = 0 to oChildren.Count -1
If oChildren(i).GetROProperty("ToolTipText") = "WantedToolTip" Then
oChildren(i).Set "ON"
End If
Next



העובדה שאני יכול לכתוב את קוד הזיהוי בעצמי (כלומר, את התנאים ב-IF) נותנת חופש וגמישות מוחלטים, ולרוב מאפשרת לכתוב קוד קריא בהרבה (אפשר לאחד הרבה פקודות oChildren ע"י קבלת כל האובייקטים, וטיפול במקרים השונים באמצעות Select Case)

אני יוצר אוספים של אובייקטים גם ללא ChildObjects
כפי שאתם מבינים, אני משתמש ב-ChildObjects בחלקים נרחבים מהקוד שלי, וכפועל יוצא, הרבה מהפונקציות שלי מקבלות אוספים של אובייקטים - ולא את האובייקטים עצמם. המשמעות היא שאם אני מעוניין לעבוד עם אובייקטים באופן "רגיל" (כלומר, ספציפית עם האובייקט), עומדות בפני שתי אפשרויות : לכתוב קוד כפול שמטפל גם באובייקטים בודדים וגם באוספים, או להפוך אובייקטים בודדים לאוסף המכיל פריט אחד. היות וקוד כפול הוא התגלמות זרע השטן בעולם הדיגיטאלי, אני משתמש באפשרות השניה. להלן דוגמה ליצירת אוסף באופן מלאכותי, ולצירוף אובייקט קיים :


Dim oObjectCollection
Set oObjectCollection = CreateObject("Scripting.Dictionary")

oObjectCollection.Add 0, VbWindow("Main")



משמעות השורה האחרונה, היא הוספת האובייקט VbWindow("Main"), וקביעת המזהה שלו כ-0 (הדרך בה יהיה ניתן "לשלוף" אותו). מזהים יכולים להיות גם מחרוזות, אולם על מנת לשמור על תאימות לאוספי האובייקטים הנוצרים באמצעות ChildObjects אני משתמשים במזהה מספרי (מתחיל מ-0). הגישה לאובייקט מתבצעת באופן דומה ל-DP רגיל (באמצעות המזהה) :


oObjectCollection(0).Click



לאובייקט Scripting.Dictionary ישנן תכונות מועילות רבות, וכדאי להשתמש בו באופן כללי, מעבר למסגרת המצומצמת של DP. למידע נוסף מומלץ לפנות לעזרה של ה-QTP, תחת הערך Dictionary Object.

אני מעדיף שימוש בלעדי ב-DP על פני שילוב פקודות שמשנות את מאגר האובייקטים
יש תוכניתנים שמעדפים להקליט אובייקטים באופן המסורתי, ולשנות את התכונות שלהם במידת הצורך באמצעות פקודת SetTOProperty (הפקודה מאפשרת לשנות תכונות של אובייקטים שהוקלטו לזמן הריצה הנוכחית - נרחיב עליה בהזדמנות אחרת). לדעתי פיזור ההגדרות בין מאגר האובייקטים לפקודות שמשנות אותו, גורם לבלבול, הופך את הקוד לפחות קריא, ומקשה על הבנת בעיות בזמן Debug.

אני תמיד משתמש בתכונת Index
הוספת תכונת הזיהוי Index להצהרות DP מגנה מפני מקרים בהם יש יותר מאובייקט אחד המתאים לתיאור שפרטנו. אני מעדיף להגן על עצמי מפני מצבים כאלו, במחיר אי-ידיעה האם היו אובייקטים כפולים במהלך הריצה. ב-QTP-8.2, תכונת Index הייתה עובדת רק כאשר יש יותר מאובייקט אחד שמתאים לתיאור, אבל בגרסאות 9 ומעלה הבעיה נפתרה, ופתחה את הדלת לשימוש חופשי בתכונה.


VBWindow("title:=Example", "index:=0").VBCheckBox("visible:=true", _
"index:=0").Set "ON"

אין תגובות: