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

Uploaded by JovialFlashback
Tags
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 במקום ליצור ענפים נפרדים לכל פיצ'ר ,המפתח?