RESTful Services – שירותי הרשת של המחר, החל מאתמול (1)

פוסט ראשון מתוך שניים. את ההמשך אפשר למצוא כאן.

REST הוא עוד באזז של השנים האחרונות: חברות אינטרנט רבות אימצו אותו, ספרים רבים נכתבו, גוגל יצרה וריאציה משלה בשם GDATA ומנסה להפוך אותו לסטנדרט. מייקרוסופט מצידה הגדירה אלטרנטיבה בשם [ODATA[1.

על מה כל המהומה?? – אנסה לענות במאמר זה.

מהו בעצם REST?
טוב, קחו נשימה עמוקה: REST הוא סגנון ארכיטקטוני (Architectural Style) ממש כמו Pipes & Filters, Layered Architecture או (SOA (Service Oriented Architecture.
סגנון ארכיטקטוני הוא לא ארכיטקטורה, אבל אם אתם יודעים מהו הסגנון הארכיטקטוני של מערכת (וגם הסגנון הזה נשמר לאורך הפיתוח) – תוכלו לדעת דיי הרבה על איך המערכת נראית ומה העקרונות שעומדים בבסיסה. ממש כמו שאם אתם הולכים לראות מבנה שאתם יודעים שהוא בסגנון גותי, סיני או ערבי – תדעו פחות או יותר למה לצפות.

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

REST הוא סט חוקים שמערכת יכולה לבחור ולאמץ. ב High Level הוא אומר שני דברים עיקריים:

  • תיאור ממשק המערכת כעולם של Entities (כ"א instance של אובייקט) כבעל מזהה (URL) ייחודי, דרכו ניתן לבצע פעולות. ממערכות כאלו נקראות Resource-Based Distributed System – שכל entity הוא כאילו משאב מסמך עצמאי עליו עושים פעולות[2].
  • הצמדות מדויקת לפרוטוקול HTTP – פרוטוקול שיש בו הרבה חוכמה שאנו נוטים לפספס.
ה API שנחשף החוצה, הוא התוצר – לא העיקר.

איך אני יודע אם אני משתמש ב REST

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

על מנת להשתמש ב REST API (נקרא גם RESTful Service) לא צריך לדעת כמעט שום דבר: פשוט פותחים connection של HTTP, שולחים פרמטרים ע"פ התיעוד של ה API ומקבלים תשובה בפורמט שתואר.
מצד אחד קצת חבל שכמעט כל מי שמשתמש ב REST לא מודע לעקרונותיו היפים, אבל מצד שני: היי – זה דבר נהדר! הכמסה (Encapsulation) במיטבה! אל תסבכו את הצרכן שלכם בידע מיותר.

אז…הדרך הנפוצה לדעת אם אתם צורכים ב REST הוא לקרוא האם בתיעוד כתוב "REST" ולקוות שמי שכתב את התיעוד מבין על מה הוא מדבר : )

אם אתם כותבים מערכת REST, יש הרבה מה לדעת – המשיכו לקרוא.

קצת היסטוריה

תחום האינטגרציה של מערכות ארגוניות (EAI – Enterprise Application Integration) הוא תחום מסובך ויקר במיוחד. רכשת מערכת כספים מספק א' ומערכת ניהול קשרי לקוחות מספק ב' – על מנת לנצל את היתרון שהמערכות ממוחשבות וניתן להצליב בניהן נתונים, אתם צריכים לגרום למערכות לדבר אחת עם השנייה. בגלל שהמערכות מדברות בשפה (Conceptual Model) שונה ובגלל שהארכיטקטורות שלהן שונות – המאמץ הוא אדיר. כשאנחנו נזכרים בסיפורים בהם משרדי ממשלה לא מצליחים להצליב נתונים (ביטוח לאומי ומס הכנסה, או ארגוני ביון אמריקאים לפני שנת 2001) אנו נוטים לחשוב שזהו מצב של חלם, אבל בפועל עלות האינטגרציה היא אדירה ולעתים קרובות עולה על מחיר המערכות עצמן[3].

כך נראה פרוייקט EAI של ארגון בגודל בינוני

בתחילת שנות האלפיים חברו כמה חברות בראשן BEA, Microsoft, IBM ו SAP ליצור סטנדרט בתעשייה שיקל על פעולות האינטגרציה של מערכות. תקן זה ידוע כ "Web Services" הכולל Stack של פרוטוקולים שהעיקריים שבהם הם: SOAP, WSDL, UDDI ו XML (שהיה כבר קיים אך אומץ ע"י הסטנדרט). תוך כדי התפתחה מאוד ההתעסקות ב (Service Oriented Architecture (SOA. העיקרון אינו חדש: זה תיאור של מערכת מבוססת services ו מבני נתונים המחזיקים את המידע העובר בין ה services, ממש כמו שתכנתנו פעם בפאסקל או C. גם היום חלק גדול ממערכות ה .NET וה Java בנויות כך, לעתים מתוך החלטה, לעתים "כי פשוט יצא ככה". החידוש ב SOA היה הידע שנצבר והתפתח עבור אותה פרדיגמה במערכת מבוזרת.

יוצרי ה Web Services היו זקוקים לשם מפוצץ ("SOA") וצבא של יועצים-מומחים בכדי לשכנע את השוק לאמץ את גישתם. על פני השטח זה נראה כמו וויתור על פרדיגמת ה Object-Oriented (אותה, אותם יועצים ממש, מכרו כמה שנים לפני כן כ "חובה לכל ארגון") וחזרה לסגנון התכנות הפרוצדורלי (ברמת המערכת) שהיה שם קודם לכן. הם ניסו לשכנע שזו לא התדרדרות אחורה – אלא התקדמות קדימה. האמת – הם צדקו [4].

עם השנים (כמה שנים בודדות, לא יותר) תקן ה Web Services הסתבך לעשרות תקני משנה, הידועים כ WS-* (כוכבית = wildcard כמו WS-RPC, WS-Security וכו') שניסו לפתור עוד ועוד היבטים של אינטגרציה בין מערכות תוך כדי שהם נהיים מורכבים יותר ויותר לשימוש. קשה היה לאדם בודד להכיר את כל התקנים ובטח לא להתמצא בהם. בעיה נוספת הייתה performance: בגלל שהתקן מאוד כללי (בנוי לקשר בין מערכות מספקים שונים, הכתובים בשפות תכנות שונות ובין גרסאות שונות) ובגלל שהוא מבוסס על קבצי XML גדולים, פורמט המרבה במילים (verbose) – תקשורת מבוססת Web Services הייתה צוואר בקבוק גם של הרשת, אבל בעיקר של צריכת זיכרון (בשל ה parsing של קבצי xml ענקיים). עניין זה היה מטרד למערכות ארגוניות, ומכת מוות למערכות אינטרנט High Scale.

חברות האינטרנט הקטנות והיעילות יצאו למלחמה רבתי: "REST נגד SOA" – ראה [5]
הם הציגו את REST כאלטרנטיבה פשוטה, מהירה ונוחה למתכנת לייצר Web Services. הם גם נתנו לשירותים אלו שם מפוצץ משלהם: "RESTful Services". אני זוכר שהייתי בכנס QCON בלונדון בשנת 2008, ורבים מה sessions היו על נושאים ב REST או ב SOA (למשל, אני זוכר session שנקרא "REST eye for a SOA guy"). כל פעם באו אנשי המחנה השני, קראו קריאות ביניים והפריעו למרצה ב Session. מהר מאוד למדתי להדיר רגלי מכל Session באחד משני הנושאים הללו.

מכיוון שפוסט זה עוסק ב REST ולא ב Web Services אתם יכולים להסיק, בצדק, ש REST ניצחה במלחמה. השימוש ב Web Services הצטמצם משמעותית ונותר בעיקר בנישה של מערכות שונות של ספקים שונים. אפילו החברות אשר יזמו וקידמו ללא ליאות את הסטנדרטים (עבדתי ב SAP – אני יודע) הוציאו הנחיות פנימיות לצמצם שימוש ב Web Services למינימום ההכרחי.

הפשטות ניצחה את ה Coverage.

הבנת ההבדל בין Web Service ל REST
גם REST וגם Web Service הם אמצעי תקשורת בין מערכות שונות המבוססים על XML העובר על [HTTP[6 – היכן ההבדל הגדול?

עדכון: תודה לארנון רותם-גל-עוז שהאיר את עיני לכך ש REST אינו coupled ל HTTP ואותם עקרונות יכולים להיות  מיושמים על גבי פרוטוקולים אחרים (אישית, לא נתקלתי בכזה מימוש).

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

getOrderDetails()
updateOrder()
Subscribe()
cancelSubscription()
findMatchingOrder()
listOrderProviders()

פונקציות כמו ()Subscribe או ()ListOrderProviders אינן קשורות בדיוק להזמנה, הן בתחום. את ה interface השירות חושף בעזרת XML שנקרא WSDL כך שמי שצורך אותו יוכל בקלות לבצע import ל IDE אשר ייצר proxy לוקלי לקריאה לשירות כאילו מדובר באובייקט מקומי. Visual Studio, כבר מימיו הראשונים של .NET עושה זאת בצורה נהדרת.
כאשר מתבצעת קריאה ל Web Service בפועל, נוצר XML עם הפרמטרים הרלוונטיים. XML זה נעטף ב XML נוסף הנקרא Envelope של פרוטוקול ה SOAP (ה envelope מוסיף נתונים העוזרים ל cross platform interoperability אך ייתכן ויהיה גדול משמעותית מההודעה עצמה). אם ה Web Service תומך או דורש שימוש בכל מיני שירותים נלווים (WS-* למיניהם) יש להתייחס אליהם וייתכן שהם יוסיפו תוכן או ישנו את צורת ההתקשרות.

RESTful Web Services
REST, כפי שאמרנו, מתאר Resource-Based Distributed System. הגישה היא ל resource (או האובייקט) עצמו ולא לשירות. לרוב מדובר על המון משאבים (הממופים כ"א ב URL), אשר כל כ"א סט מצומצם וקבוע של פעולות המוגדרות  בפרוטוקול HTTP.

על מנת לקרוא את פרטי ההזמנה אבצע קריאת HTTP GET ל URL:

על מנת לעדכן את ההזמנה אבצע קריאת HTTP PUT ל URL:

את נערכים שאני רוצה לעדכן אשלח כ Post Parameter בפורמט XML או JSON הכולל את הערכים הרלוונטיים.
על מנת לבצע שאילתה על כל ההזמנות בשנת 2009 של לקוח AMEX אני אבצע קריאת HTTP GET ל URL:

האובייקט הוא orders, אני מבצע קריאה ושולח פרמטרים ל Query בשם year ו customer.

כמובן שאני לא יכול לשלוח מה שבא לי – רק מה שהוגדר ע"י ה שAPI ומתועד ב API Documentation.

ועל מנת לבצע שאילתה של listOrderProviders נגשים ל"אובייקט" ה OrderProviders, כמובן:

אם ביצעתי קריאת GET להזמנה שאינה קיימת אקבל כנראה שגיאת HTTP 404, המוגדר בפרוטוקול HTTP כ "Not Found". אם ביצעתי קריאת POST (הוספת ערך חדש) אצפה באופן טבעי לתשובת HTTP 201 המוגדרת בפרוטוקול HTTP כ "Created". עבור ביצוע אסינכרוני אצפה ל 202 "Accepted" וכו'

כפי שאתם מבינים על מנת לעבוד ב REST אני צריך להשתמש נכון בפרוטוקול HTTP, אבל מי שצריך להבין את הפרוטוקול הוא מי שמגדיר את ה REST API – המשתמש ב API פשוט עוקב אחרי התיעוד ושולח / מצפה למה שנאמר בתיעוד.

קשה לי לתאר במילים כמה פרוטוקול REST פשוט יחסית לפרוטוקול WS-*. אחד הטיעונים נגדו היה שזהו Hack שלא יחזיק מים במערכות גדולות ומורכבות (טעות). פעם בקורס על Web Services ב SAP ישבנו שעתיים רק לסקור את סוגי השירותים השונים של WS-* וזה היה על קצה המזלג.

חשוב להבין ש RESTful API (כלומר, מימוש נכון של REST) משפיע רבות על המבנה הפנימי של המערכת. עצם העובדה שכל instance של אובייקט הוא נגיש החוצה וניתן לבצע עליו סט סגור של פעולות הוא עיקרון שיצליח אם מערכת בנויה בצורה X אך יכול להיכשל אם מערכת בנויה בצורה Y.

המשמעות של הוספת RESTful API למערכת קיימת שאינה בנויה בצורה REST-friendly היא לרוב להוסיף שכבת Adapting עשירה או לא להצליח להנות בפועל מיתרונות ה REST. ייתכן וכל מה שאתם מחפשים הוא לחשוף API בצורה שהמשתמשים רגילים (REST like) ולכן יתרונות ה REST האחרים הם לא חשובים. לגיטימי.

הקשר בין REST לפרוטוקול ה HTTP וארכיטקטורה של Resource-Based Distributed System אינו מקרי.
בפוסט ההמשך ארחיב על נושאים אלו יותר לעומק.

[1] Open Data. מכיוון שהצלחה נראתה כיעד אסטרטגי מהותי – היא שיחקה עם גוגל במגרש שלה, פתחה את התקן כ Open Source ושחררה ספריות התומכות ב .NET כמובן, אך גם PHP, Java ו JavaScript.

[2] היסטורית מקובל לחלק מערכות מבוזרות ל 4 סוגים:

  • Object-Based Systems: מערכות שמאפשרות לגשת מרחוק ולהפעיל אובייקטים עשירים בפרדיגמת Object-Oriented. דוגמאות הן Corba, DCOM או EJB כאשר עובדים עם Remote Interface.
  • Distributed Database / Storage System – כאן נכנסים כל מערכות ה NoSQL שתיארתי בפוסט על Big Data או מערכות קבצים מבוזרות נוסח Gopher, WebDAV או HDFS ו GFS המודרניים.
  • Distributed Coordination-Based Systems: מערכות תיאום מבוזר כמו Rendezvous או Jini של ג'אווה שנכשל ונולד מחדש כ Apache River. דוגמה מודרנית יכולה להיות פרוטוקול Gossip או מערכות peer 2 peer.
  • ומה שחשוב לפוסט זה: מערכות Resource-Based (לעתים נקראים גם "Document-Based") מבוזרות אשר ניגשים ל Resources ("מסמכים") אחד אחד לצורך פעולות קריאה, כתיבה וכו'. דוגמה אחת: האינטרנט (מסמכי HTML). דוגמה שנייה: מערכות REST.

[3] זה הסיפור העיקרי עליו מבוססת מכירת מערכות ERP של חברות כמו SAP או Oracle: "אין לנו את ה CRM הטוב ביותר או ה SCM הטוב ביותר – אבל אתה קונה את האינטגרציה built-in".

[4] שנים רבות Object Oriented Programming נחשב לשם נרדף לקדמה ומקצועיות, אבל בפועל הוא לא היה Silver Bullet – כלומר לא הביא לשיפור חד משמעי בעולם התוכנה. לתכנות פרוצדורלי יש הרבה יתרונות ונראה שיש לו עוד מקום של כבוד בעולם התוכנה בשנים הבאות. כמובן שעדיף להבין את היתרונות והחסרונות המעשיים של כל גישה ולבחור בחירה מודעת. סימן אחד לכוחה של הפרדיגמה הפרוצדורלית היא שהרבה מאוד פרויקטים שניסו לייצר מודל OO כשלו וגמרו עם מודל פרוצדורלי. כלומר: OO הוא קשה למימוש, פרוצדורלי הוא קל. חישבו על כך – זהו יתרון משמעותי.
תכנון מונחה עצמים Object Oriented Design, לעומת זאת, הוכיח את עצמו יפה והוא מוצלח משמעותית מכל מיני פרדיגמות עתיקות כמו DFD (השם ירחם!) או ERD שנהגו להשתמש בהם בשנות השמונים (או בסוף שנות התשעים באקדמיה – אותה תקופה בה למדתי את התואר הראשון). יהיה זכרם ברוך.

[5] SOA היא ארכיטקטורה טובה, הם בעצם התכוונו לצאת נגד Web Services. עקרונית REST הוא סוג של SOA.

[6] REST לא מגדיר מה פורמט ההודעה, XML נפוץ מאוד וכך גם JSON ואפשר גם להשתמש בפורמט אחר כלשהו.