סיכום תכנות מערכות מתקדם PDF - תכנות, ניהול גרסאות

Summary

המסמך מסכם נושאים מהקורס "תכנות מערכות מתקדם", ומכיל מידע מקיף על נושאים כמו ניהול גרסאות עם Git, תהליכים ותהליכונים, פיתוח ממשקי משתמש, מסדי נתונים שונים וטכניקות פיתוח מתקדמות. המסמך כולל גם מבוא ל-API חיצוני, ובנוסף, ניתוח וסקירה של תבניות עיצוב חשובות.

Full Transcript

‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫תכנות מערכות מתקדם‬ :‫תוכן עניינים‬ Git - 1 ‫הרצאה‬...

‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫תכנות מערכות מתקדם‬ :‫תוכן עניינים‬ Git - 1 ‫הרצאה‬ Software engineering & Jira - 2 ‫הרצאה‬ Writing better code & Docker - 3 ‫הרצאה‬ Networks and sockets - 4 ‫הרצאה‬ Multi-Processing & Multi-Threading – 5 ‫הרצאה‬ Web server - 6 ‫הרצאה‬ MVC - 7 ‫הרצאה‬ MongoDB - 8 ‫הרצאה‬ UI development - 9 ‫הרצאה‬ Android - 10 ‫הרצאה‬ 11 ‫הרצאה‬ Data access o Branching Strategies o CI/CD o 12 ‫הרצאה‬ Compilation o GC o Design Patterns - 13 ‫הרצאה‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪( Git‬הרצאה ‪)1‬‬ ‫‪.1‬מהי מערכת לניהול גרסאות?‬ ‫מערכת לניהול גרסאות מאפשרת מעקב אחר שינויים בקוד לאורך זמן‪ ,‬שיחזור גרסאות קודמות ועבודה‬ ‫משותפת עם צוותים‪.‬קיימות שתי גישות מרכזיות‪:‬‬ ‫מרכזית – )‪ (Client-Server‬כל הגרסאות נשמרות בשרת מרכזי (‪ SVN‬לדוגמה)‪.‬‬ ‫ ‬ ‫מבוזרת – )‪ (Distributed‬כל משתתף מחזיק עותק מלא של ההיסטוריה (‪ Git‬לדוגמה)‪.‬‬ ‫ ‬ ‫‪.2‬מבוא ל‪ – Git‬עקרונות בסיסיים‪:‬‬ ‫‪ Git‬היא מערכת ניהול גרסאות מבוזרת‪ ,‬כלומר‪ ,‬כל עותק של המאגר )‪ (repository‬כולל את כל‬ ‫ההיסטוריה של הפרויקט‪.‬היא מאפשרת‪:‬‬ ‫‪.1‬עבודה מקומית עם אפשרות לסנכרון עם מאגר מרוחק‪.‬‬ ‫‪.2‬פיצול עבודה באמצעות "סניפים" (‪)Branches‬‬ ‫‪.3‬שיתוף פעולה עם צוותים על אותו פרויקט‪.‬‬ ‫‪.3‬עבודה עם ‪:repository‬‬ ‫‪ – git init‬יצירת מאגר חדש‪.‬‬ ‫ ‬ ‫]‪ – git clone [URL‬שכפול מאגר קיים (העתקה למחשב)‪.‬‬ ‫ ‬ ‫]‪ – git add [file‬הוספת קבצים לאזור ההמתנה (‪.)Staging‬‬ ‫ ‬ ‫”‪ – git commit -m “message‬שמירת שינויים עם תיאור‪.‬‬ ‫ ‬ ‫‪ – git push‬שליחת השינויים למאגר מרוחק‪.‬‬ ‫ ‬ ‫‪ – git pull‬משיכת שינויים ממאגר מרוחק‪.‬‬ ‫ ‬ ‫‪.4‬עבודה עם ‪:Branches‬‬ ‫עבודה עם ‪ branches‬מאפשרת לנו עבודה במקביל על פיצ'רים חדשים ללא השפעה על הקוד הראשי‪.‬‬ ‫ישן מספר פקודות חשובות לעבודה עם ‪:branches‬‬ ‫]‪ – git branch [branch name‬יצירת ‪ branch‬חדש‪.‬‬ ‫ ‬ ‫]‪ – git checkout [branch name‬מעבר ל‪.branch-‬‬ ‫ ‬ ‫‪.5‬איחוד (‪:)merge‬‬ ‫כאשר אנו עובדים על ‪ branch‬נפרד‪ ,‬ומסיימים את פיתוח הפיצ'ר‪ ,‬נרצה לאחד את הקוד שלנו עם הקוד‬ ‫הראשי בעזרת הפקודה ‪.merge‬כאשר אנו ניגשים לבצע איחוד‪ ,‬ישנם מספר תרחישים איתם נצטרך‬ ‫להתמודד‪:‬‬ ‫‪ – Fast-Forward Merge‬תיאור פעולת האיחוד במקרה בו הקוד ב‪ main‬לא השתנה מאז שפתחנו‬ ‫ ‬ ‫את ה‪ branch‬הייעודי שלנו (‪ main‬נשאר זהה‪ feature ,‬השתנה)‪.‬במקרה זה‪ ,‬ביצוע ‪" merge‬יקדם‬ ‫את ה‪ "Pointer‬של ניהול הגרסאות‪ ,‬ו‪ main‬יקבל את העדכונים שלנו מתוך ה‪.feature‬‬ ‫‪ – Three-Way Merge‬כאשר גם ‪ main‬וגם ‪ feature‬מכילים שינויים מהגרסה הראשית בעת פתיחת‬ ‫ ‬ ‫ה‪.branch‬במצב זה‪ ,‬ביצוע ‪ merge‬ייצור ‪ merge commit‬חדש שמכיל את איחוד השינויים משני‬ ‫ה‪.branches‬‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪.6‬קונפליקטים‪:‬‬ ‫קונפליקטים נוצרים כאשר ‪ Git‬לא יכול לבצע את פעולה ה‪ merge‬באופן אוטומטי‪.‬מצב זה עלול להיגרם‬ ‫ממספר סיבות‪:‬‬ ‫שני ה‪ branches‬המעורבים ב‪ merge‬ערכו את אותו קטע קוד (אותה המתודה עודכנה גם ב‪main‬‬ ‫ ‬ ‫וגם ב‪.)feature‬‬ ‫עבור שני ‪ branches‬המעורבים ב‪ ,merge‬מתודה‪/‬קובץ מסוים נמחק ב‪ branch‬אחד ועודכן ב‪branch‬‬ ‫ ‬ ‫השני‪.‬‬ ‫כאשר יש לנו קונפליקט‪ ,‬אנו נדרשים לפתור אותו ידנית בכך שנחליט איזה אחד מהשינויים הוא העדכני‬ ‫והנכון (נבחר האם להמשיך עם אחד העדכונים או אם ליצור איחוד של שניהם)‪.‬‬ ‫את הקונפליקטים נוכל לפתור בצורה ידנית (נעדכן את הקוד של אחד ה‪ )branches‬או בעזרת ‪merge‬‬ ‫‪( editor‬כלים מובנים אשר מזהים את התבנית של ‪ git‬לקונפליקטים ומאפשרים לנו בלחיצת כפתור‬ ‫לבחור איזה מהמימושים הוא הנכון)‪.‬‬ ‫‪.7‬ביצוע ‪ merge‬בעזרת ‪:pull request‬‬ ‫כאשר אנו עובדים בצוות‪ ,‬לרוב נרצה שאחד או יותר מחברי הצוות האחרים יבצעו בקרה לקוד שלנו לפני‬ ‫שאנו מבצעים ‪ merge‬ל‪ branch‬הראשי‪ ,‬ולכן נשתמש ב‪.pull request‬‬ ‫בעזרת ‪ ,pull request‬אנו מצהירים כי סיימנו לעבוד על הקוד ו"מבקשים אישור" לבצע ‪ merge‬לתוך‬ ‫ ‬ ‫‪ branch‬אחר (יכול להיות ל‪ main‬אך יכול גם להיות לכל ‪ branch‬אחר)‪.‬לאחר מכן‪ ,‬נתייג את מי‬ ‫שנרצה שיעבור על הקוד‪ ,‬והוא יסתכל על השינויים שצפויים להיכנס לתוך ה‪ branch‬הראשי‪.‬‬ ‫במידה וחבר הצוות שבחן את הקוד מאשר את השינויים‪ ,‬ואין אף קונפליקט בין ה‪ ,branches‬לחיצה‬ ‫ ‬ ‫על ‪ merge pull request‬תבצע את האיחוד ותשלים את הפעולה‪.‬‬ ‫במידה ויש בעיות בקוד ‪ /‬בוחן הקוד זיהה שינוי שמשפיע על קטע קוד אחר ‪ /‬קיימים קונפליקטים‪ ,‬יוכל‬ ‫ ‬ ‫הבוחן להחליט האם לתקן בעצמו (בעיקר בעת פתרון קונפליקטים)‪ ,‬או שהוא מחזיר את ה‪branch‬‬ ‫לעבודה אצל המפתח המקורי‪.‬‬ ‫* כאשר יש קונפליקטים‪ ,‬לא תתאפשר לחיצה על ‪.merge pull request‬כלומר‪ git ,‬לא מאפשר לנו לבצע‬ ‫‪ merge‬כאשר יש קונפליקטים גם בעזרת ‪.pull request‬‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪( Software‬הרצאה ‪)2‬‬ ‫‪engineering & Jira‬‬ ‫‪.1‬הנדסת תוכנה‪:‬‬ ‫הנדסת תוכנה היא גישה שיטתית לפיתוח תוכנה‪ ,‬המבוססת על עקרונות הנדסיים‪.‬היא מבטיחה‬ ‫שהתוכנה תהיה אמינה‪ ,‬מתוחזקת ויעילה‪ ,‬ומסייעת בשיפור איכות הקוד‪ ,‬עמידה בזמנים ובתקציבים‬ ‫ובניהול שינויים בדרישות לאורך הפרויקט‪.‬‬ ‫‪.2‬תהליכי פיתוח תוכנה – השלבים המרכזיים‪:‬‬ ‫ניתוח דרישות – הבנת צרכי הלקוח והגדרת הבעיה‪.‬‬ ‫ ‬ ‫תכנון (‪ – )design‬עיצוב הארכיטקטורה של המערכת‪.‬‬ ‫ ‬ ‫מימוש (‪ – )Implementation‬כתיבת הקוד בפועל‪.‬‬ ‫ ‬ ‫בדיקות (‪ – )Testing‬בדיקות תקינות ואיכות‪.‬‬ ‫ ‬ ‫פריסה (‪ – )Deployment‬העלאת המערכת לשימוש הלקוח‪.‬‬ ‫ ‬ ‫תחזוקה ושיפורים – פתרון תקלות ועדכונים‪.‬‬ ‫ ‬ ‫‪.3‬מתודולוגיות פיתוח תוכנה‪:‬‬ ‫לאורך השנים‪ ,‬פותחו מספר מתודולוגיות פיתוח תוכנה שמטרתן לארגן את ניהול הפרויקט על כל שלביו‪,‬‬ ‫ולסייע למנהלי הפרויקט לעמוד בדרישות הפרויקט תוך עמידה בזמנים ובתקציב‪ ,‬גם בעת עדכון דרישות‬ ‫לאורך הפרויקט‪.‬השיטות המרכזיות הן‪:‬‬ ‫מודל המפל (‪ – )Waterfall‬תהליך לינארי‪ ,‬כל שלב חייב להסתיים לפני המעבר לשלב הבא‪.‬‬ ‫ ‬ ‫מודל ה‪ – )V-model( V-‬מבוסס על ‪ ,Waterfall‬אך עם דגש על בדיקות בכל שלב‪.‬‬ ‫ ‬ ‫מודל האיטרציות (‪ – )Iterative & Incremental Model‬פיתוח אבטיפוס מהיר‪ ,‬ולאחריו פיתוח‬ ‫ ‬ ‫גרסאות בשלבים קטנים‪ ,‬המלווים בבדיקות מקיפות בכל שלב‪ ,‬והצגה ללקוחות כהכנה לגרסה הבאה‪.‬‬ ‫פיתוח אג'ילי (‪ )Agile‬ו‪ – Scrum-‬עבודה במקטעים קצרים (ספרינטים)‪ ,‬תוך התאמות לפי משוב‬ ‫ ‬ ‫שוטף‪.‬‬ ‫‪.4‬ניהול פרויקטים באמצעות ‪:Jira‬‬ ‫‪ Jira‬היא מערכת ניהול פרויקטים מבוססת ענן‪ ,‬המשמשת בעיקר לניהול פיתוח תוכנה ומתאימה למודלים‬ ‫כמו ‪ Scrum‬ו‪.Kanban-‬תהליך העבודה עם ‪ Jira‬מלווה את הפרויקט בעזרת התכונות הבאות‪:‬‬ ‫יצירת פרויקטים – נבחר את סוג הפרויקט שלנו (‪.)Scrum/Kanban‬‬ ‫ ‬ ‫ניהול ‪ – backlog‬מיפוי כלל המשימות שלנו ותיעודן כ‪.Issues-‬סוגי ‪:Issues‬‬ ‫ ‬ ‫‪ – User story‬מתאר דרישה כתהליך שיבצע הלקוח‪.‬‬ ‫‪o‬‬ ‫‪ – Task‬משימת פיתוח (מימוש מתודה‪ ,‬מימוש תמיכה במחלקה חדשה‪.)...‬‬ ‫‪o‬‬ ‫‪ – Bug‬משימת תיקון תקלה‪.‬‬ ‫‪o‬‬ ‫חלוקת ה‪ Issues-‬ל‪ – Epics-‬חלוקה של המשימות לתחומים שונים בפרויקט (תשתית‪ )Data ,UI ,‬או‬ ‫ ‬ ‫למשימות גדולות המכילות תתי משימות קטנות יותר‪.‬‬ ‫ניהול ‪ – Sprints‬חלוקת ה‪ Issues-‬למחזורי עבודה קצרים (במתודולוגיית ‪.)Scrum‬‬ ‫ ‬ ‫מעקב אחר סטטוס משימות – מעבר בין ‪.TODO → In Progress → Code Review → Done‬‬ ‫ ‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪( Docker‬הרצאה ‪)3‬‬ ‫‪& writing better code‬‬ ‫‪:Clean code.1‬‬ ‫כתיבת "קוד נקי" משמעה כתיבת קוד שקל להבין‪ ,‬לתחזק ולהרחיב‪.‬הקוד צריך לענות על העקרונות‪:‬‬ ‫שמות רלוונטיים וברורים לפונקציות ומשתנים‪.‬‬ ‫ ‬ ‫חלוקת הקוד לפונקציות קטנות‪.‬‬ ‫ ‬ ‫הימנעות מקוד משוכפל‪.‬‬ ‫ ‬ ‫שימוש נכון בתבניות עיצוב (‪.)design patterns‬‬ ‫ ‬ ‫‪:Code smells.2‬‬ ‫בעיות נפוצות בכתיבת קוד ההופכות אותו ל"קוד מסריח"‪:‬‬ ‫‪ – God object‬מחלקה אחת שעושה יותר מדי דברים‪.‬‬ ‫ ‬ ‫‪ – Long method‬פונקציות ארוכות מדי שקשה לקרוא ולתחזק‪.‬‬ ‫ ‬ ‫‪ – Tight coupling‬תלות חזקה בין מחלקות‪ ,‬מקשה על שינוי קוד‪.‬‬ ‫ ‬ ‫‪ – Magic numbers‬מספרים חסרי משמעות בתוך הקוד‪ ,‬עדיף להגדירם כקבועים (‪.)const‬‬ ‫ ‬ ‫‪ – SOLID.3‬חמישה עקרונות לפיתוח נכון‪:‬‬ ‫‪ – Single Responsibility Principle‬לכל מחלקה אחריות אחת בלבד‪.‬‬ ‫ ‬ ‫‪ – Open/Closed Principle‬קוד צריך להיות פתוח להרחבה אך סגור לשינויים‪.‬‬ ‫ ‬ ‫‪ – Liskov Substitution Principle‬מחלקות נגזרות צריכות להחליף את הבסיסית ללא בעיות‪.‬‬ ‫ ‬ ‫‪ – Interface Segregation Principle‬עדיף לחלק ממשקים גדולים לכמה קטנים וממוקדים‪.‬‬ ‫ ‬ ‫‪ – Dependency Inversion Principle‬יש לתלות בממשקים מופשטים‪ ,‬לא במימושים קונקרטיים‪.‬‬ ‫ ‬ ‫‪:Refactoring.4‬‬ ‫תהליך לשיפור קוד ללא שינוי התנהגות שלו‪.‬נבצע פעולות כמו פירוק פונקציות גדולות‪ ,‬פיצול קוד‬ ‫משוכפל לפונקציות נפרדות ושימוש בתבניות עיצוב בכדי לשפר את הקוד‪ ,‬ללא שינוי בפונקציונליות‪.‬‬ ‫‪ – Docker.5‬פיתוח מבוסס קונטיינרים‪:‬‬ ‫‪ Docker‬היא פלטפורמה שמאפשרת יצירת קונטיינרים (‪ – )Containers‬סביבות עבודה קלות משקל‬ ‫ומבודדות להפעלת יישומים‪.‬השימוש ב‪ Docker-‬פותר בעיות רבות‪ ,‬למשל‪:‬‬ ‫תלויות בין גרסאות ‪ -‬כל סביבת עבודה מבודדת ולא תלויה בגרסת מערכת ההפעלה‪.‬‬ ‫ ‬ ‫העברת קוד בין סביבות שונות ‪ -‬ניתן להריץ את אותה תוכנה על ‪ Mac, Windows‬ולינוקס‪.‬‬ ‫ ‬ ‫ניהול חבילות ותלויות ‪ -‬מאפשר להגדיר גרסאות ותלויות בצורה מבוקרת‪.‬‬ ‫ ‬ ‫ההבדל בין ‪ Docker‬למכונה וירטואלית (‪ VM – )VM‬כוללת מערכת הפעלה מלאה ומשאבים מוקצים‬ ‫מראש‪.‬הדוקר משתמש במערכת ההפעלה של השרת המארח ומבודד את היישום‪ ,‬ולכן חסכוני יותר‪.‬‬ ‫‪.6‬שירותים נוספים של ‪:Docker‬‬ ‫‪ – DockerHub‬מכיל תמונות מוכנות מראש של כלים שימושיים (‪ redis, mysql, nginx‬ועוד)‪.‬‬ ‫ ‬ ‫‪ – Docker Compose‬מאפשר להריץ מספר קונטיינרים יחד עם הגדרת תלויות‪.‬‬ ‫ ‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪( Networks‬הרצאה ‪)4‬‬ ‫‪& Sockets‬‬ ‫‪.1‬מודלי תקשורת‪:‬‬ ‫מודל תקשורת הוא מבנה תאורטי שמתאר כיצד נתונים מועברים ממחשב אחד לאחר ברשת‪.‬‬ ‫נעסוק בשני מודלים (‪ )TCP/IP ,OSI‬המייצגים גישות שונות לארגון וניהול תקשורת ברשת‪.‬‬ ‫מודל ‪:OSI‬‬ ‫ ‬ ‫מודל המחלק את התקשורת בין מחשבים ל‪ 7-‬שכבות‪ ,‬כאשר כל שכבה מבצעת משימה ספציפית‪.‬‬ ‫דוגמאות‬ ‫תיאור‬ ‫שכבה‬ ‫כבל רשת‪Wi-Fi ,‬‬ ‫העברת ביטים דרך כבל או אלחוטי‬ ‫‪( Physical‬פיזית)‬ ‫‪Ethernet, MAC address‬‬ ‫קביעת חוקים להעברת מסגרות (‪ )frames‬בין התקנים‬ ‫‪( Data link‬קישור נתונים)‬ ‫)‪IP, ICMP (ping‬‬ ‫ניתוב (‪ )Routing‬כתובות ‪ IP‬ומסלולים‬ ‫‪( Network‬רשת)‬ ‫‪TCP, UDP‬‬ ‫שליטה על זרימת הנתונים‪ ,‬תיקון שגיאות‬ ‫‪( Transport‬תחבורה)‬ ‫‪NetBIOS, RPC‬‬ ‫ניהול חיבור בין מחשבים (התחלה‪/‬סיום תקשורת)‬ ‫‪( Session‬שיחה)‬ ‫‪SSL/TLS, JPEG, MP3‬‬ ‫קידוד והצפנה‪ ,‬דחיסת נתונים‬ ‫‪( Presentation‬ייצוג נתונים)‬ ‫‪HTTP, FTP, DNS‬‬ ‫הפרוטוקולים בהם משתמשים תוכנות הקצה‬ ‫‪( Application‬יישום)‬ ‫מודל ‪:TCP/IP‬‬ ‫ ‬ ‫מודל ‪ TCP/IP‬הוא המודל המעשי שנמצא בשימוש באינטרנט‪.‬הוא פחות תאורטי ממודל ‪ OSI‬ומבוסס‬ ‫על ארבע שכבות‪.‬‬ ‫מקבילה במודל ‪OSI‬‬ ‫תיאור‬ ‫שכבה‬ ‫שכבות ‪( 1+2‬פיזית וקישור נתונים)‬ ‫חיבור פיזי ופרוטוקולי גישה לרשת‬ ‫‪( Network access‬גישה לרשת)‬ ‫שכבת הרשת (‪)Network‬‬ ‫ניתוב וחיבור בין רשתות‬ ‫‪( Internet‬אינטרנט)‬ ‫שכבת התחבורה (‪)Transport‬‬ ‫ניהול תקשורת בין התקנים‬ ‫‪( Transport‬תחבורה)‬ ‫שכבות ‪)Session, Presentation, Application( 5-7‬‬ ‫שירותים עבור המשתמש‬ ‫‪( Application‬יישום)‬ ‫נבצע השוואה מהירה בין שני המודלים‪:‬‬ ‫ ‬ ‫מודל ‪TCP/IP‬‬ ‫מודל ‪OSI‬‬ ‫קריטריון‬ ‫מודל מעשי המבוסס על פרוטוקולי האינטרנט‬ ‫מודל תאורטי שנועד להסביר תקשורת‬ ‫מטרת הפיתוח‬ ‫‪4‬‬ ‫‪7‬‬ ‫מספר השכבות‬ ‫שילוב של כמה שכבות ביישום מעשי‬ ‫כל שכבה מופרדת בבירור‬ ‫הפרדה בין שכבות‬ ‫משמש בפועל בתקשורת אינטרנט‬ ‫משמש ללימוד והבנה‬ ‫שימוש בפועל‬ ‫שכבה אחת לכל השירותים‬ ‫מחולקת ל‪ 3-‬שכבות נפרדות‬ ‫שכבת היישום‬ ‫מבוסס בעיקר על ‪ TCP‬ועל ‪UDP‬‬ ‫ניהול מפורט של חיבורי נתונים‬ ‫ניהול חיבורים‬ ‫‪.2‬כתובות ‪ IP‬ופורטים‪:‬‬ ‫כתובת ‪ IP‬היא מספר ייחודי שמזהה מחשב ברשת‪:‬‬ ‫‪ – IPv4‬פורמט של ארבע קבוצות מספרים (למשל‪.)192.168.1.1 ,‬‬ ‫ ‬ ‫‪ – IPv6‬פורמט מתקדם יותר שתומך במספר גדול יותר של קבוצות‪.‬‬ ‫ ‬ ‫לכל תוכנה מאזינה יש מספר פורט (‪ )port‬ייחודי (למשל‪)SSH-22 ,HTTPS-443 ,HTTP-80 ,‬‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪.3‬פרוטוקולים להעברת מידע (‪ TCP‬ו‪:)UDP-‬‬ ‫תקשורת בין מחשבים מאפשרת העברת נתונים בין מערכות שונות‪.‬הרשתות מחברות בין מחשבים‬ ‫באופן פיזי או אלחוטי‪ ,‬והנתונים עוברים ביניהם לפי פרוטוקולים מוגדרים‪.‬קיימים שני פרוטוקולים‬ ‫מרכזיים‪:‬‬ ‫)‪:TCP (Transmission Control Protocol‬‬ ‫ ‬ ‫מחייב יצירת חיבור בין שני צדדים‪.‬‬ ‫‪o‬‬ ‫מבטיח שכל הנתונים יגיעו בשלמותם ובסדר הנכון‪.‬‬ ‫‪o‬‬ ‫משמש בפרוטוקולים כמו ‪.SSH ,FTP ,HTTP‬‬ ‫‪o‬‬ ‫)‪:UDP (User Datagram Protocol‬‬ ‫ ‬ ‫מהיר יותר‪ ,‬אך אינו מבטיח שכל החבילות יגיעו‪.‬‬ ‫‪o‬‬ ‫שימושי בווידאו סטרימינג‪ ,‬משחקים אונליין‪.‬‬ ‫‪o‬‬ ‫‪UDP‬‬ ‫‪TCP‬‬ ‫פרמטר‬ ‫מהיר יותר‬ ‫איטי יותר‬ ‫מהירות‬ ‫לא מבטיח סדר או תיקון שגיאות‬ ‫מבטיח סדר תקין ותיקון שגיאות‬ ‫אמינות‬ ‫סטרימינג‪ ,‬שיחות קוליות‪ ,‬משחקים‬ ‫דפדפנים‪ ,‬אימייל‪ ,‬הורדות‬ ‫שימושים נפוצים‬ ‫‪:Socket.4‬‬ ‫‪ Socket‬הוא נקודת קצה לתקשורת בין שני משבים ברשת‪.‬נשתמש ב‪ Socket-‬על מנת לפתח לקוח‬ ‫(‪ )Client‬השולח בקשות‪ ,‬ושרת (‪ )Server‬אשר מאזין לבקשות ומגיב להן‪.‬קיימים שני סוגי ‪Sockets‬‬ ‫בהתאמה לשני סוגי הפרוטוקולים‪:‬‬ ‫)‪ – Stream Socket (TCP‬לתקשורת אמינה ומבוססת חיבור‪.‬‬ ‫ ‬ ‫דוגמה לשרת ‪ TCP‬בפייתון‪:‬‬ ‫‪import socket‬‬ ‫)‪server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM‬‬ ‫))‪server_socket.bind(('0.0.0.0', 12345‬‬ ‫)‪server_socket.listen(5‬‬ ‫)"‪print("Server is listening...‬‬ ‫‪while True:‬‬ ‫)(‪client_socket, addr = server_socket.accept‬‬ ‫)"}‪print(f"Connection from {addr‬‬ ‫)"!‪client_socket.send(b"Hello, Client‬‬ ‫)(‪client_socket.close‬‬ ‫דוגמה ללקוח ‪ TCP‬בפייתון‪:‬‬ ‫‪import socket‬‬ ‫)‪client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM‬‬ ‫))‪client_socket.connect(('127.0.0.1', 12345‬‬ ‫)‪message = client_socket.recv(1024‬‬ ‫))(‪print(message.decode‬‬ ‫)(‪client_socket.close‬‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬.‫ – לתקשורת מהירה אך לא אמינה‬Datagram Socket (UDP) :‫ בפייתון‬UDP ‫דוגמה לשרת‬ import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_address = ('0.0.0.0', 12345) server_socket.bind(server_address) print("UDP Server is up and waiting for messages...") while True: data, client_address = server_socket.recvfrom(1024) print(f"Received message from {client_address}: {data.decode()}") response = "Hello from UDP Server!" server_socket.sendto(response.encode(), client_address) :‫ בפייתון‬UDP ‫דוגמה ללקוח‬ import socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_address = ('127.0.0.1', 12345) message = "Hello, UDP Server!" client_socket.sendto(message.encode(), server_address) data, server = client_socket.recvfrom(1024) print(f"Received from server: {data.decode()}") client_socket.close() :‫תהליך הממשק בין השרת ללקוח‬ ‫פקודה בקוד‬ ‫שלב‬ socket(AF_INET, SOCK_STREAM) Socket TCP ‫יצירת‬.1 bind((IP, PORT)) ‫ לכתובת ולפורט‬Socket-‫קשירת ה‬.2 listen() ‫האזנה לבקשות חיבור מלקוחות‬.3 ‫שרת‬ accept() ‫קבלת חיבור מלקוח‬.4 recv() / send() ‫קבלת ושליחת נתונים דרך החיבור‬.5 TCP close() ‫סגירת החיבור כשהוא לא נחוץ יותר‬.6 socket(AF_INET, SOCK_STREAM) Socket TCP ‫יצירת‬.1 connect((SERVER_IP, PORT)) ‫חיבור לשרת‬.2 ‫לקוח‬ send() / recv() ‫שליחת וקבלת נתונים דרך החיבור‬.3 close() ‫סגירת החיבור לאחר סיום התקשורת‬.4 socket(AF_INET, SOCK_DGRAM) Socket UDP ‫יצירת‬.1 bind((IP, PORT)) ‫ לכתובת ולפורט‬Socket-‫קשירת ה‬.2 recvfrom() ‫קבלת הודעות מלקוחות‬.3 ‫שרת‬ sendto() ‫שליחת תגובה ללקוח‬.4 )‫ להמתנה להודעות נוספות (ללא חיבור קבוע‬3 ‫חוזר לשלב‬ UDP socket(AF_INET, SOCK_DGRAM) Socket UDP ‫יצירת‬.1 sendto() )‫שליחת הודעה לשרת (ללא חיבור קודם‬.2 ‫לקוח‬ recvfrom() )‫קבלת תגובה מהשרת (אם נשלחה‬.3 close() ‫אם לא נדרש יותר‬-Socket ‫סגירת ה‬.4 ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫השוואה בין השיטות‪:‬‬ ‫ ‬ ‫‪UDP‬‬ ‫‪TCP‬‬ ‫)‪socket(AF_INET, SOCK_DGRAM‬‬ ‫)‪socket(AF_INET, SOCK_STREAM‬‬ ‫סוג ה‪Socket-‬‬ ‫כן‪ ,‬יש צורך בקריאה ()(‪ )connect‬בצד הלקוח‬ ‫לא‪ ,‬הנתונים נשלחים ללא יצירת חיבור‬ ‫האם נדרש חיבור (‪?)handshake‬‬ ‫ובקבלה ()(‪ )accept‬בצד השרת‬ ‫)(‪sendto() / recvfrom‬‬ ‫)(‪send() / recv‬‬ ‫שיטת שליחת הנתונים‬ ‫לא מובטח – ‪ UDP‬שולח נתונים ללא בדיקות‬ ‫מובטח – ‪ TCP‬דואג להעברה מסודרת ותיקון‬ ‫אמינות העברת הנתונים‬ ‫תיקון‬ ‫שגיאות‬ ‫מהיר יותר‪ ,‬אין מנגנון תיקון שגיאות‬ ‫איטי יותר‪ ,‬בגלל בקרת השגיאות וניהול החיבור‬ ‫מהירות התקשורת‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪( Multi-Processing‬הרצאה ‪)5‬‬ ‫‪& Multi-Threading‬‬ ‫‪.1‬תהליכים (‪:)Processes‬‬ ‫תהליך )‪ (Process‬הוא הרצה של תוכנית במערכת ההפעלה‪.‬‬ ‫ ‬ ‫כל תהליך כולל זיכרון עצמאי שבו נשמרים הקוד‪ ,‬הנתונים והמשתנים שלו‪.‬‬ ‫ ‬ ‫מערכת ההפעלה מנהלת תהליכים ומקצה להם משאבי ‪ ,CPU‬זיכרון וקבצים‪.‬‬ ‫ ‬ ‫תהליך יכול להיות באחד המצבים הבאים‪:‬‬ ‫ ‬ ‫‪( New )1‬חדש) – נוצר אך טרם רץ‪.‬‬ ‫‪( Ready )2‬מוכן) – מחכה למשאב ‪.CPU‬‬ ‫‪( Running )3‬רץ) – התהליך פעיל ומבוצע ע"י המעבד‪.‬‬ ‫‪( Waiting )4‬ממתין) – מחכה לקלט או למשאב אחר‪.‬‬ ‫‪( Terminated )5‬מושבת) – הסתיים או נעצר בכוח‪.‬‬ ‫‪:Multi-Processing.2‬‬ ‫בעזרת הפקודות )(‪ ,fork(), exec‬אנו יכולים ליצור תהליכים חדשים ולנהל את הקוד בהם‬ ‫ ‬ ‫)(‪Exec‬‬ ‫)(‪Fork‬‬ ‫מאפיין‬ ‫החלפת קוד בתהליך קיים‬ ‫יצירת תהליך חדש‬ ‫מטרת הקריאה‬ ‫נמחק מהזיכרון‬ ‫נשאר זהה בשני התהליכים‬ ‫מה קורה לקוד המקורי?‬ ‫אם מצליחה לא מחזירה‪ ,‬אחרת מחזירה (‪)-1‬‬ ‫מחזירה ‪ PID‬לתהליך האב‪ 0 ,‬לילד‬ ‫מחזירה ערך?‬ ‫הרצת תוכנית חיצונית‬ ‫עבודה מקבילה (‪)Parallelism‬‬ ‫שימוש נפוץ‬ ‫כתיבת מעטפת ‪bash‬‬ ‫שרת שמטפל במספר חיבורים בבת אחת‬ ‫דוגמה לשימוש‬ ‫עלול לא לעבוד‪ ,‬נקפיד לבדוק האם הפעולה הושלמה‬ ‫שימוש לא נכון ייצור ‪( Fork bomb‬יותר מדי‬ ‫סיכונים‬ ‫בהצלחה (נשווה ל‪)-1‬‬ ‫תהליכים)‬ ‫הפקודה ‪:fork‬‬ ‫ ‬ ‫{ )(‪int main‬‬ ‫;)(‪pid_t pid = fork‬‬ ‫{ )‪if (pid == 0‬‬ ‫קוד שמתבצע בתהליך הילד ‪//‬‬ ‫;))(‪printf("Child Process: PID = %d, Parent PID = %d\n", getpid(), getppid‬‬ ‫{ ‪} else‬‬ ‫קוד שמתבצע בתהליך ההורה ‪//‬‬ ‫;)‪printf("Parent Process: PID = %d, Child PID = %d\n", getpid(), pid‬‬ ‫}‬ ‫;‪return 0‬‬ ‫}‬ ‫הפקודה ‪:exec‬‬ ‫ ‬ ‫{ )(‪int main‬‬ ‫;)"‪printf("Before exec()\n‬‬ ‫החלפת התהליך הנוכחי ‪//‬‬ ‫;)‪execl("/bin/ls", "ls", "-l", NULL‬‬ ‫שורה זו לא אמורה לרוץ‪ ,‬שכן התהליך כבר לא מריץ את הקוד המוצג כאן לאחר השינוי ‪//‬‬ ‫;)"‪printf("This will not be printed if exec() works!\n‬‬ ‫;‪return 0‬‬ ‫}‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫שילוב הפקודות‪:‬‬ ‫ ‬ ‫{ )(‪int main‬‬ ‫;)(‪pid_t pid = fork‬‬ ‫{ )‪if (pid == 0‬‬ ‫;)"‪printf("Child process replacing itself with ls -l\n‬‬ ‫;)‪execl("/bin/ls", "ls", "-l", NULL‬‬ ‫;)"‪printf("This will not print if exec() works\n‬‬ ‫{ ‪} else‬‬ ‫;)"‪printf("Parent process waiting for child\n‬‬ ‫מחכה לסיום הילד ‪wait(NULL); //‬‬ ‫;)"‪printf("Child finished\n‬‬ ‫}‬ ‫;‪return 0‬‬ ‫}‬ ‫‪.3‬תהליכונים (‪:)Threads‬‬ ‫תהליכון (‪ )Thread‬הוא יחידה הרצה בתוך ה‪ ,Process-‬והוא משתף איתו ועם התהליכונים הנוספים‬ ‫ ‬ ‫בתוכו זיכרון ומשאבים‪.‬‬ ‫נעשה השוואה בין תהליכים לתהליכונים‪:‬‬ ‫ ‬ ‫תהליכונים (‪)Threads‬‬ ‫תהליכים (‪)Process‬‬ ‫זיכרון משותף לכל התהליכונים בתהליך‬ ‫לא משותף (זיכרון נפרד לכל תהליך)‬ ‫שיתוף זיכרון‬ ‫קל לתקשר דרך משתנים משותפים‬ ‫דורש ‪( IPC‬כמו ‪)pipes, shared memory‬‬ ‫תקשורת בין ישויות‬ ‫לרוב רץ באותה ליבה‬ ‫יכול לרוץ על ליבות שונות‬ ‫ניצול ליבות מעבד‬ ‫יצירת תהליכונים קלה וזולה‬ ‫יצירת תהליכים יקרה יחסית‬ ‫יצירת ישויות חדשות‬ ‫‪.4‬יצירת תהליכונים‪:‬‬ ‫ישנן מספר דרכים ליצור תהליכונים‪:‬‬ ‫ ‬ ‫הפקודה ‪pthread_create‬‬ ‫הממשק ‪Runnable‬‬ ‫המחלקה ‪Thread‬‬ ‫‪C/C++‬‬ ‫‪( Java‬יש מקבילות בשפות אחרות)‬ ‫‪( Java‬יש מקבילות בשפות אחרות)‬ ‫שפות תכנות‬ ‫פונקציה חיצונית המופעלת ע"י‬ ‫מחלקה מיישמת ‪ Runnable‬ומועברת‬ ‫מחלקה יורשת ‪ Thread‬ומממשת )(‪run‬‬ ‫צורת מימוש‬ ‫)(‪pthread_create‬‬ ‫ל‪Thread-‬‬ ‫יצירת אובייקט ‪ Runnable‬והעברתו ל‪-‬‬ ‫שימוש ישיר ב‪pthread_create()-‬‬ ‫קריאה ל‪ start()-‬במחלקת ‪Thread‬‬ ‫יצירת תהליכון‬ ‫‪Thread‬‬ ‫שליטה ישירה על יצירת תהליכונים‬ ‫הפרדה בין לוגיקה לתהליך‬ ‫פשוט וקל לכתיבה‬ ‫יתרונות‬ ‫כתיבה מורכבת וניהול משאבים ידני‬ ‫דורש יצירת ‪ Thread‬נפרד‬ ‫גמיש (יורשים מחלקה אחת בלבד)‬ ‫חסרונות‬ ‫יצירת תהליכון בעזרת המחלקה ‪:)Java( Thread‬‬ ‫ ‬ ‫{ ‪class MyThread extends Thread‬‬ ‫{ )(‪public void run‬‬ ‫;)"‪System.out.println("Thread is running...‬‬ ‫}‬ ‫{ )][‪public static void main(String args‬‬ ‫;)(‪MyThread t1 = new MyThread‬‬ ‫יצירת והפעלת תהליכון ‪t1.start(); //‬‬ ‫}‬ ‫}‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ :)Java( Runnable ‫יצירת תהליכון בעזרת הממשק‬ class MyRunnable implements Runnable { public void run() { System.out.println("Thread is running..."); } public static void main(String args[]) { Thread t1 = new Thread(new MyRunnable()); t1.start(); // ‫יצירת תהליכון והפעלתו‬ } } :pthread_create() ‫יצירת תהליכון בעזרת הפקודה‬ #include #include #include void *print_message(void *ptr) { printf("Thread is running...\n"); return NULL; } int main() { pthread_t thread; pthread_create(&thread, NULL, print_message, NULL); pthread_join(thread, NULL); // ‫מחכה שהתהליכון יסתיים‬ return 0; } :CRITICAL CODE & RACE CONDITION.5 ‫ מה שעלול לגרום‬,‫זמנית‬-‫ מתרחש כאשר שני תהליכונים ניגשים לאותו משתנה בו‬Race Condition :‫ לדוגמה‬.‫להתנהגות בלתי צפויה‬ class Counter { static int count = 0; public static void increment() { count++; } public static void main(String args[]) { Thread t1 = new Thread(() -> increment()); Thread t2 = new Thread(() -> increment()); t1.start(); t2.start(); } }.‫ עלול להיות שגוי‬count ‫ ערכו הסופי של‬,‫בגלל ששני התהליכונים ניגשים לאותו המשתנה במקביל‬ ‫ – מנגנון סנכרון המונע גישה של מספר תהליכונים או‬Mutex-‫ נשתמש ב‬,‫על מנת לפתור בעיה זו‬.‫ מניעה זו מאפשרת לתהליכון יחיד לגשת למשאב בכל רגע נתון‬.‫זמנית‬-‫תהליכים למשאב משותף בו‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ :mutex ‫דוגמה למימוש‬ pthread_mutex_t lock; int counter = 0; void *increment(void *arg) { pthread_mutex_lock(&lock); counter++; pthread_mutex_unlock(&lock); } int main() { pthread_t t1, t2; pthread_mutex_init(&lock, NULL); pthread_create(&t1, NULL, increment, NULL); pthread_create(&t2, NULL, increment, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_mutex_destroy(&lock); printf("Final Counter Value: %d\n", counter); return 0; } :Thread Pool.6 ‫ המוקצים למשימות בצורה חכמה וחסכונית‬,‫ הוא אוסף של תהליכונים מוכנים מראש‬Thread Pool.‫במקום ליצור תהליכון חדש בכל פעם‬ :Thread Pool ‫תהליך העבודה עם‬.)Task queue( ‫ היא נכנסת לתור המשימות‬,‫) כאשר יש משימה חדשה‬1.‫ מקצה תהליכון פנוי לביצוע המשימה‬Thread pool-‫) מנהל ה‬2.‫ הוא חוזר לבריכה ולא מושמד‬,‫) לאחר שהתהליכון מסיים את המשימה‬3.‫ המשימה מחכה בתור עד שהתהליכון הבא יתפנה‬,‫) אם אין תהליכונים פנויים‬4 :Thread pool ‫דוגמה למימוש‬ #include #include #include #include #define THREAD_POOL_SIZE 3 #define TASK_COUNT 5 void *task_function(void *arg) { int task_id = *((int *)arg); printf("Task %d is running in thread %lu\n", task_id, pthread_self()); sleep(1); // ‫סימולציה של עבודה‬ return NULL; } int main() { pthread_t thread_pool[THREAD_POOL_SIZE]; for (int i = 0; i < TASK_COUNT; i++) { pthread_create(&thread_pool[i % THREAD_POOL_SIZE], NULL, task_function, &i); pthread_join(thread_pool[i % THREAD_POOL_SIZE], NULL); } return 0; } ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ )6 ‫ (הרצאה‬Web Server :Web server.1 ‫ אפליקציות או‬,‫ דפדפנים‬- clients( ‫ מלקוחות‬http ‫ הוא רכיב תוכנה המטפל בבקשות‬Web server.‫שרתים אחרים) ושולח תשובות חזרה‬ :‫הפרמטרים המופיעים בבקשה הם‬.)'‫ וכו‬GET, POST, PUT, PATCH, DELETE( ‫ – כל שיטה מבצעת פעולה אחרת‬HTTP ‫) שיטת‬1.‫ שפנייה אליו תפעיל את הבקשה‬route ‫ – לכל בקשה יש‬URL ‫) כתובת‬2 HTTP/1.1, HTTP/2 – ‫) גרסה הפרוטוקול‬3.)‫ ועוד‬cookies ‫ צירוף‬,‫) – מספקות מידע נוסף על הבקשה (סוג התוכן‬headers( ‫) כותרות‬4 :‫תשובת השרת ללקוח תכלול את הפרמטרים הבאים‬.)‫ ועוד‬200 OK, 404 not found( ‫) סטטוס ביצוע הבקשה‬1.‫) – מספקות מידע על התשובה שסופקה‬headers( ‫) כותרות‬2.‫ של התשובה‬body-‫ הערך יוחזר ב‬,)‫ תמונה וכדומה‬,Json( ‫) תוכן – אם הבקשה החזירה תוכן‬3 :‫ בסיסי‬web server ‫ יצירת‬.2 :‫ בפייתון‬web server-‫דוגמה ל‬ from socket import socket, AF_INET, SOCK_STREAM server_socket = socket(AF_INET, SOCK_STREAM) server_socket.bind(('', 8080)) server_socket.listen(5) while True: client, addr = server_socket.accept() request = client.recv(1024) response = b"HTTP/1.1 200 OK\n\nHello, World!" client.send(response) client.close() :Nodejs-‫ ב‬web server-‫דוגמה ל‬ const http = require("http"); function handleRequest(request, response) { response.writeHead(200, {"Content-Type": "text/html"}); response.write("Hello, World!"); response.end(); } const server = http.createServer(handleRequest); server.listen(8080); console.log("Server running on http://localhost:8080"); :‫ לניהול שרתים‬frameworks-‫ שימוש ב‬.3 ‫ קיימים סוגים רבים‬.‫ נשתמש במסגרות מוכנות לניהול הבקשות מראש‬,‫במקום לכתוב שרתים מאפס‬.Express ‫ אנו מעמיקים בקורס בתבנית‬,‫של תבניות לניהול בקשות‬.‫ גולמי ומאפשר ניהול קל של ניתובים ונתונים‬http ‫ חוסך לנו עבודה עם‬Express‫שימוש ב‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫דוגמה למימוש שרת בעזרת ‪:Express‬‬ ‫ ‬ ‫;)"‪const express = require("express‬‬ ‫;)(‪const app = express‬‬ ‫{ >= )‪app.get("/", (req, res‬‬ ‫;)">‪res.send("Hello from Express.js!= )( = ‪exports.getArticles‬‬ ‫;‪return articles‬‬ ‫;}‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪ – View )2‬אחראי על הצגת הנתונים למשתמש‪.‬לדוגמה‪:‬‬ ‫>‪"‪ Toast.makeText(this, "Button clicked!",‬‬ ‫;))(‪Toast.LENGTH_SHORT).show‬‬ ‫;)‪layout.addView(myButton‬‬ ‫פיתוח ‪ GUI‬בעזרת ‪:)android( XML‬‬ ‫ ‬ ‫‪ XML‬היא שפת סימון שמגדירה מבנה נתונים בצורה היררכית‪.‬‬ ‫‪o‬‬ ‫נגדיר את הממשק בעזרת אוסף של תגיות המייצגות אובייקטים שונים (>‪,‪ , Toast.makeText(this, "Button clicked!", Toast.LENGTH_SHORT).show()); :web-‫ ב‬listener ‫דוגמה להגדרת‬ document.getElementById("myButton").addEventListener("click", () => { alert("Button clicked!"); }); :React.6 ‫ ומשמשת ליצירת ממשקי‬Facebook (Meta) ‫ שפותחה ע"י‬JavaScript ‫ היא ספריית‬React.js.)Component-Based( ‫משתמש דינאמיים בצורה רכיבית‬ :‫ריאקט בנויה על כמה עקרונות מרכזיים‬.‫ – כל ממשק מחולק לרכיבים עצמאיים‬Component-Based Architecture )1.‫ ומעדכן רק את מה שהשתנה‬DOM-‫ – עוקב אחרי שינויים ב‬Virtual DOM )2.state-‫ ו‬props ‫ – זרימת מידע מסודרת דרך‬One-Way Data Flow )3 ‫ מבלי להשתמש במחלקות‬,)useEffect( ‫) ואפקטים‬state( ‫ – דרך קלה לנהל מצב‬Hooks )4.)Class Components( :‫ קלאסית‬React Component-‫נראה דוגמה ל‬ import React, { useState } from "react"; function Counter() { const [count, setCount] = useState(0); return ( Counter: {count} setCount(count + 1)}>Increase ); } export default Counter; :‫ רגיל‬web ‫ לבית פיתוח‬React ‫נשווה בין‬ react ‫פיתוח מבוסס‬ )html, css, JS( ‫פיתוח רגיל‬ )Components( ‫מבוסס רכיבים‬ ‫ לטיפול באירועים‬JavaScript ‫ עם‬HTML + CSS ‫מבוסס‬ UI ‫ניהול‬ ‫ לעדכון חכם‬Virtual DOM-‫שימוש ב‬ ‫ ושינויים ידניים‬document.getElementById() ‫ישירות עם‬ DOM ‫עבודה עם‬ ‫ ניווט דינמי‬,‫ – כל האתר נטען פעם אחת‬SPA ‫כל דף נטען מחדש מהשרת‬ ‫טעינת דפים‬ ‫ לניהול מורכב‬useState, useEffect, Redux localStorage ‫ עבודה עם‬/ ‫משתנים גלובליים‬ state ‫ניהול‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪( Android‬הרצאה ‪)10‬‬ ‫‪.1‬פרויקט אנדרואיד מורכב ממספר תיקיות וקבצים שמבנה ברור שלהם מאפשר סדר וארגון בקוד‪.‬‬ ‫תיקיות מרכזיות בפרויקט‪:‬‬ ‫ ‬ ‫‪ - /manifests )1‬מכיל את קובץ ‪ ,AndroidManifest.xml‬שמגדיר מידע על האפליקציה ( ‪package‬‬ ‫‪ name, activities, permissions‬ועוד)‪.‬‬ ‫‪ - /java )2‬מכיל את קבצי הקוד (‪.)Activities, Fragments‬‬ ‫‪ - /res )3‬מכיל משאבי עיצוב וגרפיקה‪:‬‬ ‫‪ – /layout‬קבצי ‪ xml‬המגדירים את ממשק המשתמש של ה‪.activities‬‬ ‫▪‬ ‫‪ – /drawable‬תמונות ואייקונים‪.‬‬ ‫▪‬ ‫‪ – /values‬צבעים‪ ,‬מחרוזות‪ ,‬גדלים סטנדרטיים‪.‬‬ ‫▪‬ ‫‪.2‬מרכיבי המערכת באנדרואיד‪:‬‬ ‫‪ – Activity‬מסך עצמאי שמציג ממשק משתמש למשתמש‪.‬‬ ‫ ‬ ‫‪ – Fragment‬חלק ממסך שניתן לשלב במספר ‪.Activities‬‬ ‫ ‬ ‫‪ – Intent‬מאפשר תקשורת בין רכיבים‪ ,‬כגון פתיחת ‪ Activity‬אחרת או שליחת מידע‪.‬‬ ‫ ‬ ‫‪ – Service‬תהליך רקע שרץ ללא ממשק משתמש (למשל‪ ,‬ניגון מוזיקה)‪.‬‬ ‫ ‬ ‫‪ – Broadcast Receiver‬מנגנון להאזנה לאירועים מערכתיים (כמו סוללה חלשה‪ ,‬התחברות לרשת)‪.‬‬ ‫ ‬ ‫‪.3‬מחזור החיים של ‪:Activity‬‬ ‫לכל ‪ Activity‬באנדרואיד יש מחזור חיים‪ ,‬שמגדיר כיצד היא מגיבה לשינויים כמו פתיחה‪ ,‬סגירה‪,‬‬ ‫ ‬ ‫וחזרה ממסכים אחרים‪:‬‬ ‫דוגמה לשימוש‬ ‫מה קורה בפועל‬ ‫תזמון‬ ‫מתודה‬ ‫יצירת ‪ ,View‬טעינת מסדי נתונים‪,‬‬ ‫נטענים משאבים ראשוניים‪ ,‬מוגדרים‬ ‫כאשר ה‪ Activity-‬נוצר לראשונה (או‬ ‫)(‪onCreate‬‬ ‫בדיקת הרשאות‬ ‫רכיבים גרפיים‬ ‫אחרי סיבוב מסך)‬ ‫חידוש חיבורים ל‪ ,API-‬רענון מידע‬ ‫ה‪ Activity-‬מוצג אך עדיין לא מקבל‬ ‫כשה‪ Activity-‬הופך לגלוי‪ ,‬לפני שהוא‬ ‫)(‪onStart‬‬ ‫מהשרת‬ ‫אינטראקציה‬ ‫פעיל לחלוטין‬ ‫הפעילות עדיין רצה אך לא נמצאת‬ ‫כשה‪ Activity-‬מאבד פוקוס זמני (חלון‬ ‫השהיית וידאו‪ ,‬ביטול חיישנים מיותרים‬ ‫)(‪onPause‬‬ ‫בחזית‬ ‫צף או מעבר זמני לאפליקציה אחרת)‬ ‫הפעלת אנימציות‪ ,‬חידוש‬ ‫מוכן לקליטת קלט משתמש‬ ‫כשה‪ Activity-‬מקבל שליטה מלאה‬ ‫)(‪onResume‬‬ ‫וידאו‪/‬מוזיקה‪ ,‬הפעלת חיישנים‬ ‫שחרור משאבים לא חיוניים‪ ,‬שמירת‬ ‫אינו גלוי יותר למשתמש אך עדיין קיים‬ ‫כשה‪ Activity-‬מוסתר לחלוטין (עברנו‬ ‫)(‪onStop‬‬ ‫נתונים‬ ‫בזיכרון‬ ‫למסך אחר או למערכת הבית)‬ ‫ניקוי חיבורים פתוחים‪ ,‬שמירה אחרונה‬ ‫כל המשאבים משתחררים‪ ,‬הפעילות‬ ‫כשה‪ Activity-‬נסגר סופית‬ ‫)(‪onDestroy‬‬ ‫של מידע‬ ‫מוסרת מהזיכרון‬ ‫‪.4‬בניית ממשק משתמש באנדרואיד‪:‬‬ ‫הצגנו בפרק הקודם את הדרכים ליצירת ‪ GUI‬באנדרואיד (פיתוח ‪ GUI‬בעזרת קוד דינמי ובעזרת‬ ‫ ‬ ‫‪.)xml‬נתאים לכל ‪ activity‬קובץ ‪ xml‬המייצג את ממשק המשתמש העוטף אותו‪.‬‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ :‫ ניהול נתונים באנדרואיד‬.5 :‫ – שמירת נתונים פשוטה‬SharedPreferences.‫מנגנון מובנה באנדרואיד לאחסון נתונים פשוטים בצורה פרסיסטנטית‬ o ‫כתיבה מהירה של משתנים כמו הגדרות‬/‫ ומאפשרים קריאה‬XML ‫הנתונים נשמרים בקובץ‬ o.'‫ מצב משחק וכו‬,‫משתמש‬ ‫ לא מתאים‬.'‫בהיר וכו‬/‫ מצב כהה‬,‫) כמו שם משתמש‬Key-Value( ‫מתאים לשמירת נתונים קלים‬ o.‫לאחסון נתונים גדולים או מורכבים‬ :‫דוגמה לשמירת ערך‬ o SharedPreferences prefs = getSharedPreferences("MyPrefs", MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putString("username", "JohnDoe"); editor.apply(); // ‫שומר את השינוי‬ :‫דוגמה לקריאת ערך‬ o SharedPreferences prefs = getSharedPreferences("MyPrefs", MODE_PRIVATE); String username = prefs.getString("username", "Guest"); // ‫"מחזיר‬Guest" ‫אם אין ערך שמור‬ Log.d("SharedPreferences", "Username: " + username); :‫ – בסיס נתונים מובנה‬SQLite ‫ הוא מסד נתונים רלציוני קל משקל שמובנה באנדרואיד המאפשר אחסון נתונים מובנה‬SQLite o SELECT, INSERT, ( ‫ רגילות‬SQL ‫באפליקציה ללא צורך בשרת חיצוני ומשתמש בפקודות‬.)UPDATE, DELETE.)‫ עדיף במקרים רבים‬Room( ‫ אך ניהולו עשוי להיות מסורבל‬,‫מתאים לאחסון נתונים מורכבים‬ o :‫ לניהול מסד נתונים‬SQLiteOpenHelper ‫הגדרת מחלקת‬ o public class DatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "mydatabase.db"; private static final int DATABASE_VERSION = 1; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { String createTable = "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)"; db.execSQL(createTable); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS users"); onCreate(db); } } ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ :‫הוספת נתונים לטבלה‬ o SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("name", "Alice"); values.put("age", 25); db.insert("users", null, values); :‫שליפת נתונים‬ o SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = db.rawQuery("SELECT * FROM users", null); while (cursor.moveToNext()) { Log.d("SQLite", "User: " + cursor.getString(1) + ", Age: " + cursor.getInt(2)); } cursor.close(); :Room Database – ORM ‫ ומאפשרת ניהול נתונים באמצעות‬SQLite ‫ היא ספרייה המספקת ממשק קל לעבודה עם‬Room o :Room Database ‫ שלבי העבודה עם‬.‫ ישיר‬SQL ‫) במקום‬Entities( ‫אובייקטים‬ :)‫ (מודל טבלאי‬Entity ‫) יצירת‬1 @Entity public class User { @PrimaryKey(autoGenerate = true) public int id; @ColumnInfo(name = "name") public String name; @ColumnInfo(name = "age") public int age; } :DAO (Data Access Object) ‫) יצירת‬2 @Dao public interface UserDao { @Insert void insertUser(User user); @Query("SELECT * FROM user") List getAllUsers(); } :Database Class ‫) יצירת‬3 @Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); } :‫ באפליקציה‬Room Database-‫) שימוש ב‬4 AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "mydatabase").build(); UserDao userDao = db.userDao(); User user = new User(); user.name = "Bob"; user.age = 30; userDao.insertUser(user); ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ :‫ – ניהול תהליכונים באנדרואיד‬Threads & runOnUiThread.6 ‫ אם נריץ עליו פעולות‬.‫ באנדרואיד הוא התהליך המרכזי שמנהל את הממשק הגרפי‬UI Thread-‫ה‬.‫ נביא לכך שהאפליקציה תקפא‬,‫כבדות‬ ‫ נשתמש‬.‫ על מנת להריץ ברקע את התהליכים הכבדים‬Threads-‫ נשתמש ב‬,‫על מנת למנוע מצב זה‬.UI-‫ ל‬Thread-‫ על מנת להחזיר את תוצאת ה‬runOnUiThread()-‫ב‬ :runOnUiThread()-‫ וב‬Thread-‫דוגמה לשימוש ב‬ new Thread(() -> { String data = fetchDataFromServer(); // ‫)קריאה לרשת(משימה כבדה‬ runOnUiThread(() -> { textView.setText(data); // ‫עדכון‬UI ‫בבטחה‬ }); }).start(); :‫ חיצוני‬API ‫ לחיבור‬Retrofit-‫ שימוש ב‬.7 ‫ היא מאפשרת שליחת‬.‫) באנדרואיד‬HTTP( ‫ לניהול בקשות רשת‬Java/Kotlin ‫ היא ספריית‬Retrofit ‫ נראה דוגמה‬.‫ לאובייקטים‬JSON ‫ תוך מיפוי אוטומטי של תשובות‬,‫ בצורה פשוטה וקריאה‬API ‫בקשות‬ :‫למימוש‬ :build.gradle ‫ לקובץ‬Retrofit ‫) הוספת תלות‬1 dependencies { implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' } :API ‫) יצירת ממשק‬2 public interface ApiService { @GET("users") Call getUsers(); } :‫ באפליקציה‬Retrofit ‫) אתחול‬3 Retrofit retrofit = new Retrofit.Builder().baseUrl("https://jsonplaceholder.typicode.com/").addConverterFactory(GsonConverterFactory.create()).build(); ApiService apiService = retrofit.create(ApiService.class); :API-‫) ביצוע קריאה ל‬4 Call call = apiService.getUsers(); call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { Log.d("Retrofit", "Data received: " + response.body()); } @Override public void onFailure(Call call, Throwable t) { Log.e("Retrofit", "Error: " + t.getMessage()); } }); ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ )11 ‫ (הרצאה‬Data access :)Data Access( ‫ מבוא לגישה לנתונים‬.1 ‫ מעדכנת ומוחקת מידע‬,‫ שומרת‬,‫) היא הדרך שבה תוכנה מאחזרת‬Data Access( ‫גישה לנתונים‬.API ‫ או שירותי‬,‫ קבצים‬,‫ כגון מסדי נתונים‬,‫ממקורות נתונים שונים‬ :‫קיימות שתי קטגוריות עיקריות למסדי נתונים‬ MySQL, PostgreSQL, SQL ‫ כמו‬,‫ – מסדי נתונים מבוססי טבלאות‬Relational Databases )1.Server ,MongoDB, Firebase, DynamoDB ‫ כמו‬,‫ – מסדי נתונים לא רלציוניים‬NoSQL Databases )2.‫שמתאימים למידע גמיש יותר‬ :‫ עם גישה לנתונים‬Web ‫ פיתוח‬.2 ‫ עם‬Web ‫ סט טכנולוגיות פופולרי לפיתוח‬- MERN (MongoDB, Express, React, Node.js) Stack.NoSQL ‫מסד נתונים‬ ‫ נוכל לפתח מערכת אינטרנטית שלמה‬,MERN-‫באמצעות ארבעת הכלים המרכיבים את מחסנית ה‬.‫ ושרת המבצע לוגיקה על הנתונים‬,‫ לשליטה בנתונים‬API ‫ ממשק‬,‫הכוללת ממשק משתמש‬ :‫ עם גישה לנתונים‬Web ‫שלבים למימוש מערכת‬ :Mongoose ‫ באמצעות‬MongoDB ‫ עם‬Node.js ‫) חיבור‬1 const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost:27017/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true }).then(() => console.log("Connected to MongoDB")).catch(err => console.error("Could not connect to MongoDB", err)); :MongoDB‫) הגדרת מבנה סכמה ב‬2 const mongoose = require('mongoose'); const articleSchema = new mongoose.Schema({ title: String, author: String, published: { type: Date, default: Date.now } }); const Article = mongoose.model('Article', articleSchema); :‫ לדוגמה‬,Express ‫ בעזרת‬CRUD ‫ לניהול פעולות‬API ‫) הגדרת ממשק‬3 const Article = require('./models/article'); // ‫ מודל‬Mongoose app.get("/articles", async (req, res) => { const articles = await Article.find(); res.json(articles); }); ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪.3‬ניהול קשרים ב‪:MongoDB-‬‬ ‫ניהול קשרים ב‪ MongoDB-‬מאפשר לנו להציג את הקשר שבין שתי ישויות (לדוגמה‪ ,‬בפרויקט‬ ‫ ‬ ‫הגדרנו את הישויות קטגוריה וסרט‪ ,‬כאשר סרט משויך לקטגוריה‪/‬קטגוריות)‪.‬‬ ‫קיימות שתי דרכים מרכזיות להצגת הקשרים ב‪:MongoDB-‬‬ ‫ ‬ ‫‪:Embedding )1‬‬ ‫נגדיר את טיפוס השדה המקשר להיות סכמת ‪ ,Mongoose‬והשדה יכיל את האובייקט המלא‪.‬‬ ‫▪‬ ‫במצב זה‪ ,‬כל ישות תכיל את כל המידע שלה‪ ,‬וכל תת אובייקט יופיע פעם אחת‪.‬‬ ‫▪‬ ‫נראה דוגמה‪.‬נתחיל ביצירת הסכמה הפנימית‪:‬‬ ‫▪‬ ‫{(‪const commentSchema = new mongoose.Schema‬‬ ‫‪user: String,‬‬ ‫‪text: String‬‬ ‫;)}‬ ‫לאחר מכן‪ ,‬ניצור את הסכמה הראשית‪:‬‬ ‫▪‬ ‫{(‪const articleSchema = new mongoose.Schema‬‬ ‫‪title: String,‬‬ ‫‪author: String,‬‬ ‫סכמה אחת מוטמעת בתוך שדה בסכמה אחרת ‪comments: [commentSchema] //‬‬ ‫;)}‬ ‫ולבסוף‪ ,‬נראה תהליך הכנסת נתונים לדוגמה‪:‬‬ ‫▪‬ ‫;)‪const Article = mongoose.model("Article", articleSchema‬‬ ‫{(‪const newArticle = new Article‬‬ ‫‪title: "MongoDB Embedding",‬‬ ‫‪author: "John Doe",‬‬ ‫[ ‪comments:‬‬ ‫‪{ user: "Alice", text: "Great explanation!" },‬‬ ‫} "!‪{ user: "Bob", text: "Helped a lot, thanks‬‬ ‫]‬ ‫;)}‬ ‫;))"!‪newArticle.save().then(() => console.log("Article with embedded comments saved‬‬ ‫‪:Referencing )2‬‬ ‫נגדיר את טיפוס השדה המקשר להיות ‪.mongoose.Schema.Types.ObjectId‬‬ ‫▪‬ ‫בצורה זו‪ ,‬כל אובייקט הוא עצמאי‪ ,‬והקישור נעשה בעזרת ה‪ id-‬של האובייקט המשויך בלבד‪.‬‬ ‫▪‬ ‫מימוש זה מאפשר לכל אובייקט להיות עצמאי (קטגוריה וסרט הן ישויות עצמאיות)‪ ,‬וכך נוכל‬ ‫▪‬ ‫לבצע פעולות גם על סרטים וגם על קטגוריות ללא תלות ישירה ביניהן‪.‬‬ ‫יתרון נוסף למימוש זה‪ ,‬הוא היכולת לשייך אובייקט מסוים למספר אובייקטים ( ‪one to‬‬ ‫▪‬ ‫‪.)many‬לדוגמה‪ ,‬מימוש זה מאפשר לשייך קטגוריה אחת למספר סרטים‪.‬‬ ‫נראה דוגמה להגדרת סכמה מקושרת‪:‬‬ ‫▪‬ ‫{(‪const commentSchema = new mongoose.Schema‬‬ ‫‪content: String,‬‬ ‫} "‪articleId: { type: mongoose.Schema.Types.ObjectId, ref: "Article‬‬ ‫;)}‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫נבצע השוואה בין ‪ Embedding‬לבין ‪:Referencing‬‬ ‫ ‬ ‫‪Referencing‬‬ ‫‪Embedding‬‬ ‫נתונים נשמרים במסמכים נפרדים עם קישור דרך‬ ‫נתונים מוטמעים בתוך המסמך הראשי במערך של‬ ‫צורת מימוש‬ ‫‪ObjectId‬‬ ‫אובייקטים‬ ‫חיסכון בגודל מסמכים‪ ,‬ניהול קשרים מורכבים ולמנוע‬ ‫שליפה מהירה יותר – כל הנתונים זמינים מיידית‬ ‫יתרון מרכזי‬ ‫כפילויות‬ ‫מצריך )(‪ populate‬או ‪ JOIN-like‬שאילתות לשליפת‬ ‫גודל מסמך מוגבל‪ ,‬קושי בביצוע חיפושים נפרדים‬ ‫חסרון מרכזי‬ ‫נתונים‬ ‫כאשר הנתונים משותפים בין מסמכים רבים ויכולים‬ ‫כאשר הנתונים משויכים תמיד למסמך הראשי ואין צורך‬ ‫מתי להשתמש‬ ‫להשתנות בנפרד‬ ‫לגשת אליהם בנפרד‬ ‫כאשר כל שאילתה דורשת )(‪ ,populate‬מה שיכול לגרום‬ ‫כאשר הנתונים גדולים או משותפים למסמכים רבים‬ ‫מתי לא להשתמש‬ ‫לביצועים איטיים‬ ‫כל סרט יכיל רשימת ‪ ids‬של הקטגוריות המשויכות אליו‪.‬‬ ‫כל קטגוריה תכיל בתוכה את כל הסרטים המשויכים‬ ‫חיבור סרטים‬ ‫משיכה של סרט ללא )(‪ populate‬תראה רק את ה‪id-‬‬ ‫אליה‪.‬שיוך סרט מסוים לשתי קטגוריות ייצור כפילות‬ ‫וקטגוריות‬ ‫של הקטגוריות ולא את השמות שלהן‬ ‫‪.4‬גישה למסדי נתונים רלציוניים‪:‬‬ ‫מסדי נתונים כמו ‪ MySQL‬ו‪ PostgreSQL-‬שומרים נתונים בטבלאות עם שדות מוגדרים מראש‪.‬ניהול‬ ‫ ‬ ‫הטבלאות יעשה בעזרת שאילתות ‪.SQL‬‬ ‫דוגמה ליצירת טבלה ב‪:SQL-‬‬ ‫ ‬ ‫( ‪CREATE TABLE articles‬‬ ‫‪id SERIAL PRIMARY KEY,‬‬ ‫‪title VARCHAR(255),‬‬ ‫‪author VARCHAR(100),‬‬ ‫‪published DATE DEFAULT CURRENT_DATE‬‬ ‫;)‬ ‫דוגמה לשליפת כל הנתונים מהטבלה‪:‬‬ ‫ ‬ ‫;‪SELECT * FROM articles‬‬ ‫‪.5‬פיתוח )‪ Java (android‬עם גישה לנתונים‪:‬‬ ‫בעת פיתוח מערכות ג'אווה‪ ,‬ניתן לנהל גישה למסדי נתונים באופן ישיר באמצעות ‪ ,JDBC‬או באופן‬ ‫ ‬ ‫אבסטרקטי יותר באמצעות )‪.ORM (Object-Relational Mapping‬‬ ‫‪:JDBC – Java Database Connectivity‬‬ ‫ ‬ ‫‪ JDBC‬הוא ‪ API‬מובנה בג'אווה לחיבור ולביצוע שאילתות מול מסדי נתונים רלציוניים (‪)SQL‬‬ ‫‪o‬‬ ‫המספק תקשורת ישירה מול מסד הנתונים באמצעות פקודות ‪ SQL‬גולמיות‪.‬‬ ‫בעת עבודה עם ‪ JDBC‬נבצע חמש פעולות מרכזיות‪:‬‬ ‫‪o‬‬ ‫‪ )1‬התחברות למסד נתונים (‪:)MySQL‬‬ ‫;‪import java.sql.Connection‬‬ ‫;‪import java.sql.DriverManager‬‬ ‫;‪import java.sql.SQLException‬‬ ‫{ ‪public class DatabaseConnection‬‬ ‫{ )‪public static void main(String[] args‬‬ ‫;"‪String url = "jdbc:mysql://localhost:3306/mydatabase‬‬ ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ String user = "root"; String password = "password"; try { Connection conn = DriverManager.getConnection(url, user, password); System.out.println("Connected to database successfully!"); } catch (SQLException e) { e.printStackTrace(); } } } :‫ להוספת נתונים לטבלה‬INSERT ‫) ביצוע‬2 try (Connection conn = DriverManager.getConnection(url, user, password); PreparedStatement pstmt = conn.prepareStatement("INSERT INTO users (name, age) VALUES (?, ?)")) { pstmt.setString(1, "Alice"); // 1 is the serial number of the relevant field pstmt.setInt(2, 30); pstmt.executeUpdate(); System.out.println("User added successfully!"); } :‫ וקבלת נתונים‬SELECT ‫) ביצוע שאילתת‬3 import java.sql.*; public class FetchData { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydatabase"; String user = "root"; String password = "password"; try (Connection conn = DriverManager.getConnection(url, user, password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM users")) { while (rs.next()) { System.out.println("User: " + rs.getString("name") + ", Age: " + rs.getInt("age")); } } catch (SQLException e) { e.printStackTrace(); } } } :‫) עיבוד ומעבר על הנתונים שהתקבלו בתשאול‬4 Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT id, name, age FROM users"); while (rs.next()) { int id = rs.getInt("id"); // ‫שליפה לפי שם העמודה‬ String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println("User ID: " + id + ", Name: " + name + ", Age: " + age); } // Select return ResultSet, which is a table array of data ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ :‫) מחיקת רשומה‬5 String sql = "DELETE FROM users WHERE id = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt(1, 3); // ‫מוחק את המשתמש עם‬id = 3 int rowsAffected = pstmt.executeUpdate(); System.out.println(rowsAffected + " rows deleted."); !‫ תוביל למחיקת הטבלה כולה‬WHERE ‫נשים לב! ביצוע פעולת מחיקה ללא‬ o String sql = "DELETE FROM users"; // ‫!מוחק את כל המשתמשים‬ Statement stmt = conn.createStatement(); stmt.executeUpdate(sql); :ORM – Object-Relational Mapping ‫ היא טכניקה שמאפשרת למפות טבלאות במסד‬ORM (Object-Relational Mapping) o.‫הנתונים לאובייקטים בג'אווה‬ SQL ‫ במקום לכתוב‬,‫ וכך‬,Java ‫ מבצע המרה אוטומטית בין מבנה הטבלה לאובייקטי‬ORM o.‫ לניהול הנתונים‬Methods ‫ נעבוד עם אובייקטים ועם‬,‫ישירות‬ ‫ היא‬Java-‫ כאשר הנפוצה ביותר לשימוש כללי ב‬,‫ יש מספר שיטות‬ORM-‫לשימוש ב‬ o ‫ (מנגנון ייעודי של‬Room Database ‫ היא‬android-‫ והנפוצה ביותר לשימוש ב‬,Hibernate.)android ‫ עבור‬ORM :android ‫ בפרויקט‬Room ‫ בעזרת‬ORM-‫נראה דוגמה לשימוש ב‬ o :Room-‫ ב‬Entity ‫) יצירת‬1 import androidx.room.Entity; import androidx.room.PrimaryKey; @Entity public class User { @PrimaryKey(autoGenerate = true) public int id; public String name; public int age; // ‫בנאי‬ public User(String name, int age) { this.name = name; this.age = age; } } :DAO (Data Access Object) ‫) יצירת‬2 import androidx.room.*; import java.util.List; @Dao public interface UserDao { // ‫הוספת משתמש חדש‬ @Insert void insertUser(User user); ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ // ‫שליפת כל המשתמשים‬ @Query("SELECT * FROM User") List getAllUsers(); // ‫עדכון נתונים לפי‬id @Query("UPDATE User SET name = :newName, age = :newAge WHERE id = :userId") void updateUser(int userId, String newName, int newAge); // ‫מחיקת משתמש לפי‬id @Query("DELETE FROM User WHERE id = :userId") void deleteUserById(int userId); // ‫מחיקת כל המשתמשים בטבלה‬ @Query("DELETE FROM User") void deleteAllUsers(); } :RoomDatabase ‫) יצירת מחלקת‬3 @Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); } :‫) הוספת משתמש חדש למסד הנתונים‬4 new Thread(() -> { User user = new User("Alice", 28); DatabaseClient.getDatabase(context).userDao().insertUser(user); }).start(); :‫) קבלת כל המשתמשים ממסד הנתונים‬5 new Thread(() -> { List users = DatabaseClient.getDatabase(context).userDao().getAllUsers(); for (User user : users) { Log.d("RoomDB", "User: " + user.name + ", Age: " + user.age); } }).start(); :id=1 ‫) עדכון שם וגיל של משתמש עם‬6 new Thread(() -> { DatabaseClient.getDatabase(context).userDao().updateUser(1, "Updated Name", 30); }).start(); :id=2 ‫) מחיקת משתמש עם‬7 new Thread(() -> { DatabaseClient.getDatabase(context).userDao().deleteUserById(2); }).start(); :‫) מחיקת כל המשתמשים במסד הנתונים‬8 new Thread(() -> { DatabaseClient.getDatabase(context).userDao().deleteAllUsers(); }).start(); ‫סמסטר א' תשפ"ה‬ ‫תכנות מערכות מתקדם‬ ‫‪( Branching‬הרצאה ‪)11‬‬ ‫‪Strategies‬‬ ‫‪.1‬מבוא לאסטרטגיות ניהול ענפים (‪:)Branching Strategies‬‬ ‫‪ Branches‬הם כלי מרכזי בניהול קוד ב‪ ,Git-‬המאפשר פיתוח מקבילי ואינטגרציה של קוד חדש‪.‬‬ ‫ ‬ ‫אסטרטגיות ניהול ענפים מסייעות להבטיח שינויים מבוקרים‪ ,‬בדיקות לפני שילוב ל‪,Production-‬‬ ‫ ‬ ‫ושיתוף פעולה יעיל בין מפתחים‪.‬‬ ‫בחירת אסטרטגיית ‪ Branching‬מתבססת על סוג הפרויקט‪ ,‬גודל הצוות‪ ,‬ותהליך העבודה הרצוי‪.‬‬ ‫ ‬ ‫‪:Trunk-Based Development.2‬‬ ‫‪ Trunk-Based Development‬היא שיטה שבה כל המפתחים עובדים ישירות על הענף הראשי‬ ‫ ‬ ‫(‪ trunk‬או ‪.)main‬‬ ‫במקום ליצור ענפים נפרדים לכל פיצ'ר‪ ,‬המפתח?