✕ סגור 
צור קשר
תודה על ההתעניינות .

Thank you! Your submission has been received!

Oops! Something went wrong while submitting the form

תבניות עיצוב בעולם האוטומציה

תומר כהן
|
קלה
|
May 2, 2019
alt="facebook"alt="linkedin"להרשמה לניוזלטר

בתור מפתחי אוטומציה (ותוכנה בכלל), אנחנו נתקלים בלא מעט בעיות.

אנחנו לא זוכרים syntax מסוים, נזרק לנו exception שאנחנו רואים פעם ראשונה, או אפילו שגיאת קומפילציה שאנחנו לא מכירים.

מה אנחנו עושים כאשר דבר כזה קורה לנו? לרוב נפנה לד"ר גוגל. הרי כל דבר שקרה לנו כבר קרה למישהו אחר בעבר, ובכל בעיה בה נתקלנו, אנחנו כנראה לא הראשונים שנתקלנו בה. ואכן, ב-95% מהמקרים גוגל אכן פותר לנו את הבעיה.

אך מה קורה כאשר אנחנו נתקלים בבעיית Design בקוד שלנו?
אנחנו לא בטוחים כיצד לחבר את ה-classים, או שאנחנו יודעים שמה שעשינו "לא כל כך יפה", אבל אנחנו לא בטוחים כיצד לעשות זאת נכון.

לשם כך נוצרו ה- Design Patterns

Design Patterns הם הפתרונות לבעיות שלנו בכל הנוגע לעיצוב התוכנה - אלו מעין תבניות פתורות, וכל מה שנשאר למשתמש זה להתאים אותן למקרה שלו.

במילים אחרות, Design Patterns זה פשוט פתרון לבעיה בעיצוב הקוד.

היום נדבר על תבנית העיצוב שלא דיברנו עליה עוד בעבר, אבל אם אתם מתכנתים כבר תקופה, סביר להניח שכבר נתקלת ב Design Pattern הזה:

באמצעות template method pattern נוכל לבצע מספר מימושים שונים לאותו שלד של אלגוריתם.

במילים פשוטות, נוכל לספר את אותו הסיפור במספר דרכים שונות ועם התפתחויות שונות, וכל זאת כאשר יש לסיפור את אותו השם ואת אותם השמות לפרקיו.
לא לדאוג - בעוד רגע, הדברים יראו פשוטים בהרבה.

אז אמרנו ש-Design Pattern הוא פתרון לבעיה. אבל מהי הבעיה שלנו כאן?

נניח ובעבודתנו החדשה קיבלנו פרויקט - אנחנו צריכים לכתוב מכונה אוטומטית אשר מכינה תה. זה יהיה פשוט מאוד, הלא כן?
כל מה שנצטרך לעשות זה ליצור מחלקה, ובתוכה פעולה מרכזית להכנת תה, ואותה פעולה תקרא למספר פעולות קטנות.

הקוד יראה כך:

לצפיה בקוד לחצו כאן


סיימנו את הפרוייקט והבוס שלנו מרוצה מאוד! אבל, הגיעה דרישה נוספת מהלקוחות. הפעם הם רוצים שהמכונה תכין גם קפה.

אנחנו כבר יודעים איך להכין תה, אז להכין קפה בכלל לא יהווה בעיה עבורנו.

נעשה בדיוק את מה שעשינו קודם, רק שהפעם נשנה שתי פעולות קטנות:

לצפייה בקוד


ניתן לראות שכל מה שהשתנה בין הפעולה המכינה קפה לפעולה המכינה תה זה שני שלבים בתהליך האלגוריתם.

ועכשיו, יש לנו מחלקה שתכין לנו תה ומחלקה שתכין לנו קפה! כל מה שנשאר לעשות זה רק לקרוא לה מהתוכנית הראשית של מכונת השתייה החמה שלנו:


לצפייה בקוד

אז מהי בעצם הבעיה? יצרנו מכונה שעושה בדיוק את מה שרצה המנהל שלנו, וזה אפילו היה די פשוט!

קיימות שתי בעיות עיקריות בקוד שלנו:

האחת - הקוד שלנו לא עומד בעיקרון open/closed. למה? משום שבמידה והמכונה תצטרך להוסיף עוד סוגים של משקאות, ה- ifשלנו יכול להפוך לאינסופי, וזה דבר שפחות רצוי לעשות בתוכנית הראשית.
הבעיה השנייה היא שכפול קוד - אפשר לראות די בבירור שאנחנו משכפלים את הפעולות BoilWater ו- PourInCup.

איך נוכל לשפר את הקוד?

נתחיל מלהוציא את המשותף בקוד אל תוך מחלקת אב (HotDrinkMaker) אשר ממנה ירשו סוגי המשקאות השונים.

אם עד עכשיו דיאגרמת ה-UML  שלנו נראתה ככה:

נשנה אותה על מנת שתראה ככה:

אז מה עשינו?

יצרנו כאן מחלקת אב אבסטרקטית, אשר מממשת את הפעולות המשותפות לשתי המחלקות CoffeeMaker ו-TeaMaker, ירשנו מן המחלקה הזו והוספנו לכל מחלקת בת את הפעולות החסרות לה.
כך בעצם, מנענו את חלק גדול משכפול הקוד שראינו קודם.

מחלקת האב תראה כך:

לצפייה בקוד

אבל משהו עדיין חסר. אם ננסה להתרכז באילו עוד שלבים משותפים קיימים בין הכנת קפה ותה, נראה שגם שתי הפעולות הספציפיות למחלקה עושות פחות או יותר את את אותו הדבר רק בדרך שונה.
בעצם, יכולנו לקרוא לפעולות BrewCoffeeGrinds ו- SteepTeaBag באותו שם, Brew לדוגמה.
ולפעולות AddSugarAndMilk ו- AddLemon יכולנו לקרוא פשוט AddCondiments.

בעצם יצרנו עוד שיתוף בין המחלקות שלנו וכל זאת מבלי לפגוע בקריאות הקוד.
ועכשיו, באורח פלא, לא נצטרך להשאיר את הפעולה PrepareRecipe אבסטרקטית!

מכיוון שמעתה כל הפעולות יהיו קיימות במחלקת האב, המחלקה PrapareRecipe תהיה ממומשת.
וכעת הדברים הופכים להיות פשוטים בהרבה.

דיאגרמת ה-UML תראה כך:

והמחלקה HotDrinkMaker תראה כך:

לצפייה בקוד


אם זה עדיין לא ברור, השתמשנו עכשיו ב-Template method pattern!

כמו שאמרנו קודם, באמצעותTemplate Method, אנחנו מספרים את אותו הסיפור בדרכים שונות.

ואותו הדבר קרה כאן: סיפרנו "סיפור" של הכנת משקה חם, פעם בעבור קפה ופעם בעבור תה. באמצעות פעולה אחת אשר מתארת את הכנת שתי המשקאות באותה צורה, חסכנו שכפול קוד והפכנו את התוכנה שלנו לקריאה יותר ופשוטה יותר לתחזוקה!

אבל איך כל זה מתקשר לאוטומציה?


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

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

סיכום


היום דיברנו על Template method pattern. מטרת ה-Design Pattern הנ"ל היא למנוע שכפול קוד וליצור קריאות וקלות תחזוקה באזורים בהם מצאנו שהקוד שלנו יכול להפוך ל-template, ושחלקו יכול לעבור כאבסטרקטי למחלקת האב.

מאת: תומר כהן, מומחה טכנולוגיות אוטומציה

בתור מפתחי אוטומציה (ותוכנה בכלל), אנחנו נתקלים בלא מעט בעיות.

אנחנו לא זוכרים syntax מסוים, נזרק לנו exception שאנחנו רואים פעם ראשונה, או אפילו שגיאת קומפילציה שאנחנו לא מכירים.

מה אנחנו עושים כאשר דבר כזה קורה לנו? לרוב נפנה לד"ר גוגל. הרי כל דבר שקרה לנו כבר קרה למישהו אחר בעבר, ובכל בעיה בה נתקלנו, אנחנו כנראה לא הראשונים שנתקלנו בה. ואכן, ב-95% מהמקרים גוגל אכן פותר לנו את הבעיה.

אך מה קורה כאשר אנחנו נתקלים בבעיית Design בקוד שלנו?
אנחנו לא בטוחים כיצד לחבר את ה-classים, או שאנחנו יודעים שמה שעשינו "לא כל כך יפה", אבל אנחנו לא בטוחים כיצד לעשות זאת נכון.

לשם כך נוצרו ה- Design Patterns

Design Patterns הם הפתרונות לבעיות שלנו בכל הנוגע לעיצוב התוכנה - אלו מעין תבניות פתורות, וכל מה שנשאר למשתמש זה להתאים אותן למקרה שלו.

במילים אחרות, Design Patterns זה פשוט פתרון לבעיה בעיצוב הקוד.

היום נדבר על תבנית העיצוב שלא דיברנו עליה עוד בעבר, אבל אם אתם מתכנתים כבר תקופה, סביר להניח שכבר נתקלת ב Design Pattern הזה:

באמצעות template method pattern נוכל לבצע מספר מימושים שונים לאותו שלד של אלגוריתם.

במילים פשוטות, נוכל לספר את אותו הסיפור במספר דרכים שונות ועם התפתחויות שונות, וכל זאת כאשר יש לסיפור את אותו השם ואת אותם השמות לפרקיו.
לא לדאוג - בעוד רגע, הדברים יראו פשוטים בהרבה.

אז אמרנו ש-Design Pattern הוא פתרון לבעיה. אבל מהי הבעיה שלנו כאן?

נניח ובעבודתנו החדשה קיבלנו פרויקט - אנחנו צריכים לכתוב מכונה אוטומטית אשר מכינה תה. זה יהיה פשוט מאוד, הלא כן?
כל מה שנצטרך לעשות זה ליצור מחלקה, ובתוכה פעולה מרכזית להכנת תה, ואותה פעולה תקרא למספר פעולות קטנות.

הקוד יראה כך:

לצפיה בקוד לחצו כאן


סיימנו את הפרוייקט והבוס שלנו מרוצה מאוד! אבל, הגיעה דרישה נוספת מהלקוחות. הפעם הם רוצים שהמכונה תכין גם קפה.

אנחנו כבר יודעים איך להכין תה, אז להכין קפה בכלל לא יהווה בעיה עבורנו.

נעשה בדיוק את מה שעשינו קודם, רק שהפעם נשנה שתי פעולות קטנות:

לצפייה בקוד


ניתן לראות שכל מה שהשתנה בין הפעולה המכינה קפה לפעולה המכינה תה זה שני שלבים בתהליך האלגוריתם.

ועכשיו, יש לנו מחלקה שתכין לנו תה ומחלקה שתכין לנו קפה! כל מה שנשאר לעשות זה רק לקרוא לה מהתוכנית הראשית של מכונת השתייה החמה שלנו:


לצפייה בקוד

אז מהי בעצם הבעיה? יצרנו מכונה שעושה בדיוק את מה שרצה המנהל שלנו, וזה אפילו היה די פשוט!

קיימות שתי בעיות עיקריות בקוד שלנו:

האחת - הקוד שלנו לא עומד בעיקרון open/closed. למה? משום שבמידה והמכונה תצטרך להוסיף עוד סוגים של משקאות, ה- ifשלנו יכול להפוך לאינסופי, וזה דבר שפחות רצוי לעשות בתוכנית הראשית.
הבעיה השנייה היא שכפול קוד - אפשר לראות די בבירור שאנחנו משכפלים את הפעולות BoilWater ו- PourInCup.

איך נוכל לשפר את הקוד?

נתחיל מלהוציא את המשותף בקוד אל תוך מחלקת אב (HotDrinkMaker) אשר ממנה ירשו סוגי המשקאות השונים.

אם עד עכשיו דיאגרמת ה-UML  שלנו נראתה ככה:

נשנה אותה על מנת שתראה ככה:

אז מה עשינו?

יצרנו כאן מחלקת אב אבסטרקטית, אשר מממשת את הפעולות המשותפות לשתי המחלקות CoffeeMaker ו-TeaMaker, ירשנו מן המחלקה הזו והוספנו לכל מחלקת בת את הפעולות החסרות לה.
כך בעצם, מנענו את חלק גדול משכפול הקוד שראינו קודם.

מחלקת האב תראה כך:

לצפייה בקוד

אבל משהו עדיין חסר. אם ננסה להתרכז באילו עוד שלבים משותפים קיימים בין הכנת קפה ותה, נראה שגם שתי הפעולות הספציפיות למחלקה עושות פחות או יותר את את אותו הדבר רק בדרך שונה.
בעצם, יכולנו לקרוא לפעולות BrewCoffeeGrinds ו- SteepTeaBag באותו שם, Brew לדוגמה.
ולפעולות AddSugarAndMilk ו- AddLemon יכולנו לקרוא פשוט AddCondiments.

בעצם יצרנו עוד שיתוף בין המחלקות שלנו וכל זאת מבלי לפגוע בקריאות הקוד.
ועכשיו, באורח פלא, לא נצטרך להשאיר את הפעולה PrepareRecipe אבסטרקטית!

מכיוון שמעתה כל הפעולות יהיו קיימות במחלקת האב, המחלקה PrapareRecipe תהיה ממומשת.
וכעת הדברים הופכים להיות פשוטים בהרבה.

דיאגרמת ה-UML תראה כך:

והמחלקה HotDrinkMaker תראה כך:

לצפייה בקוד


אם זה עדיין לא ברור, השתמשנו עכשיו ב-Template method pattern!

כמו שאמרנו קודם, באמצעותTemplate Method, אנחנו מספרים את אותו הסיפור בדרכים שונות.

ואותו הדבר קרה כאן: סיפרנו "סיפור" של הכנת משקה חם, פעם בעבור קפה ופעם בעבור תה. באמצעות פעולה אחת אשר מתארת את הכנת שתי המשקאות באותה צורה, חסכנו שכפול קוד והפכנו את התוכנה שלנו לקריאה יותר ופשוטה יותר לתחזוקה!

אבל איך כל זה מתקשר לאוטומציה?


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

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

סיכום


היום דיברנו על Template method pattern. מטרת ה-Design Pattern הנ"ל היא למנוע שכפול קוד וליצור קריאות וקלות תחזוקה באזורים בהם מצאנו שהקוד שלנו יכול להפוך ל-template, ושחלקו יכול לעבור כאבסטרקטי למחלקת האב.

מאת: תומר כהן, מומחה טכנולוגיות אוטומציה

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
תומר כהן
בואו נעבוד ביחד
צרו קשר