דעה: 5 תחומי-המומחיות ש"עושים" ארכיטקט

מקצוע ארכיטקט התוכנה הוא מקצוע שאינו מוגדר בצורה טובה. רק חשבו על הווריאציות הרבות (או השמות השונים) של התפקיד:
  • Development architect
  • System architect
  • Enterprise Architect
  • Solution architect
  • Application Architect
  • Integration architect
  • Data architect
האם מישהו יכול לומר מה ההבדל בין התפקידים הנ״ל בצורה ברורה?
האם מישהו יכול לתת לאחד התפקידים הנ״ל הגדרה מעשית ויציבה?
חוסר בהירות – הוא כנראה חלק מהתפקיד.


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

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

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





מומחיות מספר 1: מומחיות טכנולוגית

\"ארכיטקט\" הוא קודם כל תפקיד טכני. ללא הבנה טכנית סבירה במערכת / שיטות וכלי העבודה – אני לא רואה כיצד ארכיטקט יכול לבצע את העבודה.

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

לארכיטקט חשובה יותר הבנה כיצד הדברים עובדים – מאשר היכולת \"לקחת מקלדת ולבצע\". יש הרבה ידע ו skill שנדרש כדי לבצע (quirks של סביבת העבודה וה build, להכיר היטב את תהליכי העבודה המעשיים – ולא התאורטיים, ידע מעשי של השימוש בכלים קצה לקצה) – skill שיש להשקיע בכדי לשמר.

חשוב שארכיטקט יוכל, מדי פעם, \"לקחת מקלדת\" ולכתוב קוד: לראות ולהבין את המערכת כפי שהיא. בסופו של דבר המערכת היא קוד שרץ – ולא רעיונות או תרשימים.
חשוב לעשות זאת \"just enough\", ופחות חשוב – לעשות זאת מעבר ל \"just enough\".

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

תמונה נחמדה, לפני הקטע המבלבל הבא…

מדד מעניין לידע \"Architect-like\" הוא היחס בין \"מה שאני יודע שאיני יודע\" (בקיצור: \"לא.יודע\") לבין \"מה שאני לא-יודע שאיני יודע\" (בקיצור: \"אין.מושג\").

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

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

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

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

  • SQL ו noSQL
  • Open Source ו Commercial Software
  • שפות typed (כמו ג\'אווה או ++C) ושפות דינאמיות (Python או javaScript)
  • ארכיטקטורת מונחית Data / שירותים וארכיטקטורה של components או Object-Oriented.
  • UI צד-לקוח, UI צד-שרת או Desktop UI [א]
קיים יתרון אמיתי לארכיטקט ש\"מאמין\" ביכולת לפתור בעיות ב-2 האלטרנטיבות, ארכיטקט שאינו \"משוחד\" לפתרון מסוג מסוים.
אמנם לא קל להגיע למצב שמכירים, ומאמינים (להכיר בכדי לנגח – זה לא מספיק) שני צדדים ויותר – ובמספר תחומים.
זוהי שאיפה ארוכת-טווח.

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

\"הכל זה trade-offs\" — משפט של ארכיטקטים.

מומחיות מספר 2: תקשורתיות טכנית

היכולת להסביר מערכת, בצורה ברורה, לעצמך ו/או לאחרים.
ארכיטקט שמבין הכל מצוין, ויש לא רעיונות נ-ה-ד-ר-י-ם, שלא יוצאים החוצה – לא יעשה כמעט כלום (אלא אם יעשה הכל לבדו).

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

    במידה מסוימת, ארכיטקטים הם ה \"חומר מגשר\" בין צוותים, קבוצות, פרויקטים או גופים שונים. לצוות או שניים – אין בד\"כ בעיה לעבוד היטב ביחד. כשהמערכת גדלה ויש עוד ועוד אנשים מעורבים – נושאים חשובים נופלים בין הכיסאות ולא מטופלים. יש יותר ויותר \"Local Optimizations\" – צוותים שעושים מה שטוב לרכיב שלהם, או לתחום האחריות הצר שלהם, אבל לא מה טוב לכלל המערכת – קרי \"Global Optimization\".

    ארכיטקטים הם (או: אמורים להיות) החומר המגשר שיאפשר לצוותים הבודדים לעבוד, בצורה טובה יותר, ולמען מטרה גדולה יותר. ניתן לראות שרבים מן ה titles השונים של הארכיטקטים – קשורים בעצם לקבוצות שבניהן הם מגשרים ומחברים:

    סוגי ארכיטקטים שונים, כחומרים מגשרים בין גופים שונים.

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

    מומחיות מספר 3: תקשורתיות אנושית והנעת אנשים

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

    תקשורת אנושית היא לא פחות חשובה מתקשורת טכנית. הנה מטאפורה [ב] שאני אוהב על ההבדל בין \"ארכיטקטורה תאורטית\" ל\"ארכיטקטורה מעשית\":
    ארכיטקטורה תאורטית היא התקפה בשח-מט שתוכננה היטב, 5 מהלכים קדימה.
    אבל… כאשר מפעילים באופן מעשי ומורים לחייל להתקדם משבצת אחת קדימה – הוא מתקדם שתיים. לא הבין? לא הסכים? רצה \"לעשות יותר\"? לא היה יכול? – זה לא משנה עכשיו: כל האסטרטגיה הלכה.
    ארכיטקטורה מעשית היא להבין את החיילים, לדבר איתם, לאמן אותם – ורק אז לצאת למתקפה.

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

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

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

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

    אפשר לומר שיכולת הארכיטקט להשפיע מורכבת מ:  יכולות טכניות x יכולות אנושיות.

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

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

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

    מקור התמונה

    מומחיות מספר 4: Domain knowledge

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

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

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

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

    ארכיטקט שלא מבין שום דבר ב\"ביזנס\", ב domain – יוכל רק להציע חלופות הנדסיות: \"אולי נחליף את גוף המטוס לחומר עמיד ג\'\"
    ארכיטקט שמבין בביזנס, אפילו בצורה חלקית – יכול להציע חלופות עסקיות, שלפעמים יהיו מספיק טובות – ולהגדיל בכך את מרחב הפתרונות הטכניים האפשריים.

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

    על כן, הבנת ה domain – היא שאיפה חשובה לארכיטקט. כלי עבודה ממשי.
    ה domain לא קל להבנה: בדר\"כ אין לא מומחה יחיד / \"גורו\" נגיש, אין לו ספרות מסודרת (לפחות בראיית high level) או הדרכות. הדרך ללמוד את ה domain היא ארוכה – וקשה. אבל גם משתלמת.

    מומחיות מספר 5: כלים של \"ארכיטקטורת תוכנה\"

    המומחיות האחרונה: כל אותם כלים טכניים שנועדו להתמודד עם מערכות גדולות ומורכבות:

    • מערכות של עקרונות הנדסת תוכנה כגון SOLID או GRASP. [כתבתי עליהן קצת בפוסט הזה, ובאופן עקיף גם בפוסט ההוא]
    • UML/sysML – שפות לתיאור פשוט של מערכות (מורכבות).
    • Quality Attributes – כלי להבנת ה non-function requirements של המערכת [כתבתי עליו בפוסט הזה]
    • ATAM – כלי להבחנה בין Trade-offs בהם נעשה שימוש במערכת.
    • \"Architecture Styles\" ו \"Architectural Patterns\" (שלעתים עושים יותר נזק מתועלת). הם שימושיים לתקשורת יעילה יותר בין אלו שמכירים אותם.
    • עוד כמה כלים… שאני פשוט לא מאמין בהם: למשל CBAM או Architectural Views אדוקים – שמעולם לא סייעו לי.
    • מתודולוגיה: סקראם, Lean Startup או Continuous Delivery. לא רק עניינם של ארכיטקטים, אבל גם. 
    • הרבה Buzz words ותחכומים – להתחבא מאחוריהם.

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

    מכל חמשת המומחיויות שציינתי – זו כנראה המומחיות שהכי מזוהה עם תפקיד ה\"ארכיטקט\", אך בפועל – אולי הכי פחות חשובה. אם אתה לא מבין בטכנולוגיה, לא מבין אנשים או לא מבין ב domain – אף אחד כנראה לא יקשיב לך כשתבוא לדבר על ניתוח של Quality Attributes. וגם אם כן: ללא הבנת הטכנולוגיה או ה domain – קשה להאמין שזה יהיה ניתוח איכותי.

    קטרוג: \"לא צריכים ארכיטקט\"

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

    \"מדוע עדיף שלא יהיה ארכיטקט\"

    ביקורת לא כ\"כ מבוססת או עניינית:

    1. ארכיטקט, כהגדרה, הוא לא מעודכן בטכנולוגיה. כשהוא היה היה מתכנת, COBOL (או ג\'אווה – אולי \"הקובול הבא\") הייתה השפה – ועכשיו הכל אחרת והוא לא מבין שומדבר.
    2. ארכיטקט רק אוהב לצייר ריבועים ולסבך מערכות. הוא מזיק ולא תורם. דיי כבר עם SOA, MDA, EJB או Software Factories!
    3. ארכיטקטים עסוקים בליצר Job Security ולדאוג שכולם יהיו תלויים בהם – ובדרך רק עושים נזק.
    לא שאין ארכיטקטים כאלו: פשוט תעמידו אותם במקום או אל תעסיקו אותם. זה לא טיעון רציני כנגד רעיון הארכיטקט ככלל. 

    ביקורת יותר עניינית:

    1. עצם קיומו של ארכיטקט, פוגע בעצמאות של המתכנתים: אם זה מישהו להישען עליו בפתרונות טכנולוגיים או קבלת החלטות, ואם בהבנת התמונה המלאה של כלל-המערכת. 
    2. ארכיטקט שלא ממש חי את הקוד, אפילו אם הוא מבין פחות או יותר את הטכנולוגיה, עלול להוביל את המתכנתים למקומות לא נכונים. רק הבנה מלאה בפרטים – מספיקה כדי לקחת החלטות שמשפיעות על הקוד.
    3. ארכיטקט הוא לא גוף ביצועי (לפחות לא כמו מתכנתים) – ולכן הוא יכול להרשות לעצמו להטיל ביקורת על המבצעים ללא היכר. התוצאה: ניכור ומורל נמוך בקרב המתכנתים – שיוצר יותר נזק מסה\"כ התועלת של הארכיטקט.
    4. ארכיטקט, מעצם קיומו או תפקידו, יכול לייצר מתח נוסף בקרב המפתחים ו / או אנשי המוצר (גם QA, Performance וכו\'). חבל.
    5. כשהארכיטקט הופך להיות middleman – הוא יוצר שכבה מיותרת ומסרבלת של תהליכי הפיתוח.

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

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

    סיכום

    עברנו על 5 תחומי-המומחיות שמבדלים בין \"מתכנת מומחה\" ל \"ארכיטקט\". ארכיטקט הוא אינו תפקיד מוגדר היטב: הפוסט מתאר את פרופיל הארכיטקט שאני מכיר – ולא פרופילים אחרים. למשל, פעם התראיינתי לתפקיד ארכיטקט בחברה ישראלית \"מובילה\". שאלתי מה יהיה אופי האינטרקציה שלי עם הפיתוח. התשובה הייתה: \"כן… תהיה. כשתעביר להם מסמכי ארכיטקטורה, תשבו כולכם ממש באותו החדר – ותדברו על הדברים. זה קורה כל כמה חודשים\". התשובה הזו הבהירה לי במקום – שזה תפקיד שאוותר עליו. נתקלתי בעוד כמה דוגמאות כאלו.

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

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

    שיהיה בהצלחה!

    —-

    [א] המקבילה המודרנית של Desktop UI היא native mobile app.

    [ב] במקור זו מטאפורה על אסטרטגיה עסקית – אבל היא מתאימה מאוד גם לארכיטקטורת תוכנה.

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

    תוכנה רב-לשונית – חלק ב\'

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

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

    מטרת הפוסט (ביחד עם הפוסט הקודם) היא לספק מקור משמעותי וטוב לנושאי המרת תוכנה לרב-לשוניות: בעיות – ופתרונות.

    מבוא ל Unicode

    בגדול, ישנן 4 משפחות נפוצות של קידודי טקסט:

    • ASCII, קידוד 7 ביט. עליו דיברנו בפוסט הקודם.
    • ANSI, הרחבות ל ASCII ול 8 ביט כאשר מוסיפים 128 תווים המתארים לרוב שפה נוספת לאנגלית.
      עד כמה שידוע לי אין שום תקן רשמי של ארגון התקנים האמריקאי (ANSI) לגבי קידוד. משום מה השם \"ANSI\" דבק בסדרה זו של תקנים שדווקא מתחילים בשמות כגון Windows או ISO (אלו ספציפית – באמת תקני ISO).
    • כל מיני קידודים שונים של שפות אסייתיות (GB, EUC, Big5 ועוד), כאשר הגיוון שלהן רחב מאוד.
    • Unicode – תקן יחיד המתאר מספר רב מאוד של שפות (בפועל: כל השפות המוכרות) תחת מרחב אותיות/סימנים אחד. כבר כמה שנים הוא משמש כתקן הבולט.
    בעוד שבמסמכים המקודדים ב ASCII או ANSI מוגבלים במספר השפות שיופיעו במסמך (אנגלית + שפה נוספת כגון עברית או רוסית), ב Unicode ניתן לכתוב מסמך המכיל טקסט בכל השפות. בנוסף, שימוש ב Unicode מאפשר לכתוב תוכנה רב-לשונית בעוד הקוד (או המתכנתים) צריכים להכיר קידוד אחד בלבד – ולא עשרות קידודים שונים.
    הותיקים ביננו בטח זוכרים כיצד אתרי אינטרנט בעברית שלא הצהירו על הקידוד שלהם אלצו את המשתמש לנסות קידוד אחר קידוד עד שראו עברית.
    \"אולי הפעם זה ISO-VISUAL…?!\"
    תקן Unicode יש רק אחד.
    בתוך עולם ה Unicode הגדירו מרחב של אותיות / סימנים (כ 110,000 מהם – נכון לשלב זה), המתארים, פחות או יותר, את כל השפות / תחבירים המוכרים לאדם.
    תקן ה Unicode ממשיך להתפתח (לינק: מה חדש בגרסאות אחרונות). בעוד רוב העדכונים כוללים שפות ביזריות נוספות (למשל: ארמית עתיקה), הם כוללים גם פה ושם הוספה של סימנים לשפות קיימות, או סימנים כלליים (צורות מיוחדות, סימנים או מטבעות וכו\'). סימן המטבע \"רופי\", למשל, נכנס לתקן בגרסה 6 ולא זמין עדיין ברוב המערכות.

    כל סימן ב Unicode מתואר ע\"י קוד שנקרא Code Point ונכתב בצורה U+xxxx, כאשר x מתאר ספרה הקסדצימלית. למשל: ה code point של הסימן  הוא U+0164 וה code point של הסימן  ﴿  (סוגריים מעוטרים בערבית?!) הוא U+FD3F.
    בגלל צורת הכתיבה הכוללת 4 ספרות ניתן להסיק ש Unicode מוגבל ל 65K סימנים – אך זה לא נכון: מעבר למרחב הבסיסי המתאר את הסימנים של השפות ה \"נפוצות\", הנקרא BMP (קיצור של Basic Multilingual Plane), ניתן להיתקל באותיות וסימנים ממרחבים נוספים (נקראים supplementary planes) – שם מרחב הסימנים, בפועל, איננו מוגבל.

    קידודים

    Unicode יש אחד, אבל דרכים לקודד אותו (Encodings) – יש כמה וכמה:
    הנפוצים שבהם הם: UTF-32, UTF-16, UTF-8 ואולי גם נתקלתם ב UTF-7.
    המחשבה שב UTF-8, קידוד 8 ביט, יש פחות אותיות מאשר ב UTF-32, קידוד 32 ביט, היא שגוייה: בעצם מדובר ב-2 דרכים לתאר את אותו מרחב סימנים של תקן ה Unicode.

    הקידוד שהכי פשוט להסביר הוא UTF-32: כל אות מיוצגת ע\"י אורך קבוע – 4 בתים / 32 ביט. קידוד זה הוא פשוט ומאפשר לבצע כמה פעולות חישוביות על הטקסט בצורה פשוטה למדי (לדוגמה: לקפוץ לאות ה n-ית). מצד שני, הוא \"בזבזני\" למדי במקום, מכיוון שהרוב הגדול של הסימנים שבשימוש (BMP) יכולים להיות מתוארים ע\"י 16 ביט בלבד.

    UTF-8, לעומת זאת הוא יותר חסכוני (והנפוץ מבין השלושה). את האותיות הנפוצות ביותר (בעת הגדרת הסטנדרט: לטיניות, מבוססות ASCII) – מתארים בעזרת בית אחד (8 ביט). אותיות נפוצות פחות (שפות מזרח אירופאיות, עברית ועוד), מתארים בעזרת שני בתים. אותיות יותר נדירות – בעזרת 3 או 4 בתים [א].
    מצד אחד חוסכים מקום, מצד שני אורך האותיות הוא משתנה (1 עד 4 בתים) – מה שגורם להתעסקות נוספת.

    UTF-16 הוא פתרון ביניים (הוא אגב, הקידוד הראשון שהופיע): כל סימן Unicode מיוצג ע\"י 1 או 2 \"words\" של 16 ביט.
    כאשר סימן אינו חלק מה BMP ואינו יכול להיות מתואר ע\"י \"מילה\" בודדת של 16 ביט, UTF-16 ישתמש ב2 מלים של 16 ביט בכדי לתאר את הסימן. צמד מלים נקרא Surrogate Pair (תרגום לעברית של Surrogate: \"בא-כח\"), כאשר יש lead Surrogate ו trail Surrogate (או high ו low – גם מינוח שבשימוש). למרות שהרעיון של UTF-8 דומה מאוד, לא משתמשים שם, משום מה, במונח Surrogate.
    שפת ג\'אווה וסביבת NET. מקודדות את כל המחרוזות ב UTF-16 וכך גם מערכת ההפעלה Windows.

    UTF-7, מקדד הכל ב 7-ביט בכדי לתאום למערכות ישנות שהניחו הנחות על אורך אות של 7 ביט בהתבסס על קידוד ה ASCII. השימוש הסביר היחידי שלו הוא לקידוד הודעות אימייל, אם השתמשתם בו לצורך אחר – קרוב לוודאי שעשיתם משהו לא נכון.

    הערך המספרי הסופי של אות יכולה להיות זהה או שונה בין קידודים שונים. למשל, אומגה בתרשים לעיל זהה בין UTF-16 ו UTF-32, אבל שונה בין UTF-8 ל UTF-16.

    שאלה: באיזה סדר שולחים את הערכים על הרשת? בשניהם, כמובן!
    בימים הראשונים של Unicode התעקשו שיהיה גם ייצוג BE (קיצור של Big Endian) וגם ייצוג LE (קיצור של Little Endian, או \"אינדיאני קטן\" – כמו שקראנו לו באוניברסיטה) כדי לנצל מעבדי LE ו BE בצורה יעילה יותר. על כן נוסף לתקן זוג סימנים מיוחד הנקרא BOM (קיצור של Byte Order Mark) – המופיע בתחילת הטקסט ומתאר את הכיוון.
    ב UTF-16, לדוגמה, 0xFEFF מתאר את BE ו 0xFFEF מתאר את LE.

    יש גם גרסאות של UTF המצהירות מראש את מיקום ה Endian, למשל UTF-16LE או UTF-16BE (אם אתם נתקלים אי פעם בשמות הללו).

    לעתים מתייחסים ל UTF-16 ו UTF-32 כ UCS-2 ו UCS-4, בהתאמה. UCS הוא קיצור של Universal Character Set.

    את התפריט הזה של ++TextPad אתם אמורים להבין, בשלב זה

    לינק: טבלת Code Points של Unicode

    השפעות בקוד – עיבוד מחרוזות

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

    נתחיל עם תרגיל ראשון: charAt.
    אנו יודעים שבג\'אווה השיטה (charAt(n מחזירה את הסימן ה n-י במחרוזת (כל אות היא 16 ביט).
    זה נכון לאנגלית, רוסית, יוונית ותאילנדית – אבל יכול להיות לא-נכון עבור שפות אסייתיות (יפנים, סינית בתחביריהם השונים) או סימנים שונים של שפות שונות – שם אנו משתמשים ב Surrogate Pair של 2 chars לתאר סימן בודד!
    כלומר, אם יש סימן המיוצג כ Surrogate Pair במקום ה n-4 וה n-3 (זהו זוג סימנים), אזי הפקודה (charAt(n תחזיר בעצם את האות ה n-1. אאוץ של באג!

    דוגמה נוספת: אם אתם רוצים לספור כמה אותיות יש במחרוזת – לא ניתן לסמוך על התוצאה של השיטה ()length – אולי רק כערך מקסימום (וגם זה לא כ\"כ פשוט… יש סימנים ב Unicode שבהגדרה צריכים לתפוס מקום של 2 אותיות, אבל זה עניין נדיר אחר).

    סיפור מהחיים: היה לנו קוד בו הגבלנו את הקלט בשדה מסוים ל25 תווים – משיקולי מקום לפלט על המסך.
    לקוח יפני פתח לנו באג שהוא לא מצליח להכניס בשדה הזה יותר מ 10-12 תווים, ובכלל נראה לו מאוד מוזר שבמילה מסוימת אחת – המערכת חוסמת אותו פעם אחרי 10 אותיות, ובמילה אחרת – רק אחרי 12 אותיות.

    כנראה שכל התווים בהם השתמש היו surrogate pairs – ועל כן בדיקת ()length החזירה 26 כאשר הוא כתב מילה בת 13 אותיות. כיצד length קיבל ערך של 25 כאשר יש 10 אותיות בלבד? – על זה נדבר בהמשך.

    מה עושים? הפתרון פשוט:

    כאשר עובדים עם מחרוזות טקסט בשפה שאיננה אנגלית (אלו כנראה מיעוט המחרוזות בקוד), עברו להשתמש בשיטות של String שהן Unicode Aware: למשל codePointAt או CodePointCount.

    ביתר פירוט:

    1. חיברנו 2 אותיות יפניות שדורשות לתאורן Surrogate Pairs, כלומר 2 chars כ\"א. בג\'אווה ניתן לקודד מילים של UTF-16 בעזרת u\\.
    2. שימוש ב length יציג אורך 4, למרות שיש לי במחרוזת רק 2 אותיות.
      codePointCount סופר את מספר הסימנים (codePoints) של Unicode בתת-מחרוזת של ה String. אני רוצה לספור את התווים בכל המחרוזת.
    3. בעיה: charAt במקום ה 0 מחזיר סימן מוזר! גם charAt במקום ה 1, 2 או 3!
      הסיבה לכך היא שאין משמעות לחצי של Surrogate Pair, סוג של \"חצי סימן\" – וריבוע חלול הוא הודעת השגיאה של חלונות למצב שגוי שזה.
      codePointAt יתנהג כפי שהיינו מצפים מ charAt להתנהג במחרוזת אנגלית (ASCII/ANSI) טיפוסית.

    עוד טיפ שאזרוק על הדרך הוא השימוש ב toUpperCase / toLowerCase.

    לא לכל השפות יש Case (למשל: עברית) – וזו לא בעיה.

    מצד שני, יש שפות בהן חוקי ה Case שונים מאנגלית – ואז שימוש בשיטות הנ\"ל ייצר שגיאות.
    שפה לדוגמה היא טורקית בה upperCase של i הוא לא I, אלא מין i גדול. מצד שני, ה lowerCase של I הוא לא i אלא מין I קטן. אני לא יודע להסביר מדוע זה כך – אבל זו ההתנהגות הרצויה.
    הפתרון הוא פשוט: להשתמש בחתימה של ()toUpperCase עם אובייקט Locale. יש כזו – והיא תעשה את העבודה.

    עיבוד מחרוזות Unicode – הפתעות לא צפויות

    בכדי להבין את התכונה הבאה של Unicode, נפתח בניסוי הקטן הבא:

    1. פתחו אפליקציית notepad והקלידו משפט בעברית.
    2. העמידו את סמן העכבר לאחר אחת האותיות.
    3. וודאו שכפתור NUM LOCK דלוק (כלומר: יש אור).
    4. החזיקו את מקש ה Alt למטה והקלידו את המספר 0198 (כולל האפס לפני).
    מה קיבלתֶם?

    אם הניסוי עבר בהצלחה, אות שלפני הסמן אמורה לקבל ניקוד סֶגול. זו איננה יכולת של Notepad אלא של \"חלונות\" (ניתן לקרוא עוד פרטים ושיטות לנקד בלינק הבא)
    מה שמעניין אותנו הוא דווקא כיצד מייצג תקן Unicode את האות המנוקדת.
    אפשרות אחת הייתה ליצור פרמוטציה של כל האותיות העבריות (27 כולל סופיות) וכל הניקודים (15, על כל הצורות) – מה שידרוש כ 400 תווים ב Unicode.

    מילא עברית, אבל מה עם הינדית – לה פי 3 אותיות, והרבה צורות חיבור שונות? מה עם סינית, יפנית, קוריאנית?!

    דוגמה לכתיב הודי

    מגדירי ה Unicode החליטו להימנע מהכפלת פרמוטציות ויצרו מכניזם יעיל יותר: מה שעשוי להראות למשתמש כאות/סימן אחד על המסך יכול להיות בעצם הרכבה של כמה סימני Unicode (כלומר code points) שונים.

    שימו לב: זהו לא Surrogate!
    יכול להיות code point יחיד המתואר ע\"י שני characters – זהו Surrogate.
    יכול להיות סימן ויזואלי אחד (מה שנקרא בעולם הזה grapheme), המתואר ע\"י כמה code points, חלקם אולי surrogate – ואחרים לא.

    מבלבל? הנה כמה דוגמאות:

    • grapheme של \"A\" מתואר ע\"י char אחד
    • grapheme של האות היפנית \"姶\" מתואר ע\"י 2 chars – כלומר surrogate Pair, מכיוון שהאות לא נמצאת במרחב הסימנים הבסיסי, ה BMP.
    • הסימן המוזר \" X͏֞ \" הוא grapheme המתואר ע\"י שני chars (בעצם, שני code points) אחד הוא האות X שכולנו מכירים, והשני הוא מין גרשיים שמתלבשים על האות הקודמת במקום שהוקצה לה, מה שנקרא combining character – סימן ה\"מתנחל\" במרחב של הסימן שקדם לו.
    הנה כמה דוגמאות ל combining characters:

    Graphemes המורכבים מ 2, 3 וארבעה אותיות/סימנים. איך בדיוק הרכיבו את הדוגמה האחרונה – אני לא מבין, אבל אני מאמין שזה נכון.

    שימו לב שלסימן ë יש 2 ייצוגים שונים: או כסימן (code point) בודד, או כהרכבה של שתי סימנים, האות e ועוד combining character (כל אחד הוא code point עצמאי).

    כדי לסבך מעט העניין, grapheme שונים מצוירים לעתים בצורה שונה ע\"פ ההקשר בו הם מופיעים. למשל יכלו להחליט לתאר אותיות סופיות (ם,ן,ץ,ף) בשפה העברית כ glyph (ייצוג ויזואלי מסוים ל grapheme) – אך לא עשו זאת, במקרה.
    בשפות שונות יש כל סימנים שמוצגים אחרת ע\"פ המיקום שלהם במילה/משפט/אותיות שכנות – למרות שזהו אותו ה code point או אותו ה grapheme. עניין זה נוגע יותר לפונטים ולא לייצוג של Unicode – אך כדאי להכיר את התופעה ולדעת שאם האות נראית אחרת – היא לא בהכרח סימן שונה ב Unicode.

    משמעות מיידית למפתחים: עיבוד מחרוזות בשפות-שונות

    ראינו קודם איך לבדוק את מספר ה Code Point – ושיטה זו אכן תעבוד ב 95% מהמקרים. מעטים מאוד המקרים בהם משתמשים ב combining characters לכתוב בשפה אירופאית (משתמשים בגרסה המשולבת, למשל ë), אבל בשפות אסייתיות לפעמים אין ברירה אחרת. לפעמים מישהו השתמש בכלי שיצר לו צרופים כאלו.

    מה עושים?

    הנה מתודה שכתבתי בג\'אווה שעושה את העבודה:

    המפתח לפתרון הוא שימוש ב breakIterator מסוג Character שהולך תו נראה (grapheme) אחרי תו נראה על המחרוזת, יהיה זה combining character, surrogate או שילוב של שניהם, עד שהוא מגיע לסופה (ואז הוא מחזיר מין ערך ריק – לכן ה 1-).

    השימוש ב breakIterators עשוי להיות חשוב מאוד – אין לכם מושג אלו שפות מוזרות יש בעולם:

    • יש שפות, כמו אמהרית או בורמזית, בהן רווח הוא לא המפריד בין מילה למילה. נסו להשתמש ב (\" \")split – והגורל יצחק לכם בפנים.
    • בטיבטית, למשל, יש סימן מיוחד לרדת שורה. מי שכותב טיבטית לא יקליד n\\ כי אם סימן אחר.
    • ביפנית וסינית משתמשים ברווחים להפריד בין ביטויים / משפטים, ולא בין מלים.
    יש breakIterators לרמות תחביריות שונות: מילים, משפטים, שורות וכו\'. אם אתם רציניים לגבי i18n ועיבוד מחרוזות בשפות שונות – כדאי שתשתמשו בכלי זה.
    אני ממליץ גם להציץ על הטבלה המעניינת הבאה, המציגה רשימת \"פיצ\'רים\" של שפות. אלו הפתעות צפויות – והיכן. הרשימה איננה מלאה.

    חיפוש ו Normalization

    טוב, בשלב זה עניין ה unicode אמור להיות דיי מובן. אנסה לכסות בקצרה עוד כמה pitfalls אפשריים.
    נניח שיש לנו אפליקציית TODO List בה המשתמש מקליד משימות שעליו לבצע. המשימות נשמרות בבסיס נתונים, והמשתמש יכול מאוחר יותר לחפש ע\"פ הטקסט שהקליד.

    אנו יכולים לספק exact match search – חיפוש שעובד ע\"פ שיוון רצפים של characters במחרוזת. מימוש נאיבי שכזה ייכשל למצוא את \"Do\" כאשר אנו מחפשים את \"do\".

    הנירמול הבסיס ביותר אם כן עבור חיפוש הוא מעבר ל upper case (או lower – לא משנה). כפי שראינו קודם, חשוב לבצע אותו עם אובייקט Locale עם השפה הנכונה.
    למשל: מהו ה upper case של Fuβ? אם אתם זוכרים β הוא קיצור של שני s (ב lower case) בגרמנית. צורת ה UpperCase בגרמנית היא לכן FUSS – טקסט בעל אורך אחר של אותיות.

    עוד הבחנה מעניינת ב Unicode היא בין שוויון קאנוני ושוויון תאימות (או סמטני):

    אם המשתמש שלכם מחפש אחר טקסט עם הסימן Ä, האם אכפת לו איך הוקלד הטקסט במקור / כיצד הוא מיוצג בבסיס הנתונים??
    האם כ U+00C4, או כ combination sequence של U+0041 ו U+0308? – כנראה שלא.

    אם הוא לא ימצא את הטקסט ויגלה שמשהו שנראה בדיוק אותו הדבר נמצא ברשימה – הוא פשוט יפתח לכם באג. \"התוכנה לא עובדת כמו שצריך\".

    הערה: כאשר אנשים מקלידים את הטקסט אין ממש סיבה שיהיה שימוש ב combination sequence, אלא אם הם יכולים לכתוב את הטקסט בעורך טקסט לא ידוע. כלומר: מבחינת ניהול סיכונים, אם אתם כותבים אפליקציה ל iPhone – יש סיכוי טוב שאתם יכולים להימנע מטיפול normalization. אם המערכת שלכם היא מערכת שאותו טקסט משמש משתמשים רבים, שיכולים לכתוב אותו בעורכים שונים – אזי עניין זה נהיה ממשי.

    לגבי שוויון תאימות (compatibility equivalence), שהוא סוג של שוויון סמנטי – ייתכן ומשתמשים רבים יקבלו את רוע הגזרה: חוץ מהאמריקאים, כנראה שכל העמים חווים תוכנות שלא עבודות בצורה מושלמת עם השפה שלהם. בכל זאת, אם כבר עושים טיפול – שווה לכסות כבר את האזור הזה גם כן.
    קחו לדוגמה את השפה הערבית, בה יש סימנים שונים של Unicode לאותיות מחוברות () ולא מחוברות (ﻦ , ﻨ). דיי מרגיז לבצע חיפוש ולא למצוא מילה כי אות אחת הייתה מחוברת או לא מחוברת.
    עוד דוגמה נפוצה (ומעצבנת) היא ההבדל הסמנטי בין מרכאות ניטראליות ( \" ) למרכאות בעלות כיוון ( , ‟ ). יש להן code points שונים בתכלית – אך משמעות סמנטית זהה.

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

    תקן ה Unicode מגדיר 4 צורות לנרמל טקסט:

    מקור: וויקיפדיה

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

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

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

    קישור: FAQs אודות normalization ב Unicode.

    BiDi ו RtL ב Unicode

    נושא זה הוא לא כ\"כ בסיסי, אך בגלל שאנו דוברי עברית – החלטתי לתאר בקצרה כיצד עניין ה Bi-Directional (בקיצור BiDi) עובד בקידוד של Unicode.
    מילת המפתח היא Bi-Directional ולא RtL (קרי Right-to-Left). עברית וערבית הן שפות שנכתבות מימין לשמאל, אך מספרים וקטעי טקסט לטיני (למשל: אנגלית) – נכתבים בהן משמאל לימין.

    תקן Unicode ממפה את כל האותיות / סימנים ל 3 קבוצות:

    • סימנים שהם LtR – רובם המכריע של הסימנים.
    • סימנים שהם RtL – עברית, ערבית ואולי עוד כמה שפות (בעיקר עתיקות?!)
    • סימנים ניטראליים – כמו סימני פיסוק (\"!\"), רווחים ועוד.
    ברגע שהמחשב נתקל ברצף סימני ה Unicode הבא (סדר לוגי):
    פייל40טסאל
    הוא מציג אותו על המסך בצורה הבאה (סדר ויזואלי):
    לאסט40לייפ

    מי שמטפל בקידוד ה Unicode מזהה את טווח הסימנים העבריים שמסומן כ RtL ומציג אותם על המסך מימין לשמאל. כאשר הוא נתקל בסימן \"4\", המסומן כ LtR הוא הופך את כיוון התצוגה, כנ\"ל לגבי האות \"ל\" לאחר ה \"0\".

    מה קורה עם סימנים ניטראליים? הם מקבלים את הכיוון האחרון שיושם.

    ומה אם \"כוונת המשורר\" היא אחרת (כזו שנשלטת ע\"י עורך הטקסט – כמובן)?

    ישנם מספר סימנים \"בלתי נראים\" ב Unicode הקובעים סדר ויזואלי.
    למשל:

    A?ג

    יתפרש באופן טבעי כ ג?A, אך אם נוסיף סימן מפורש של RtL:

    A\\u200F

    אזי הטקסט יוצג כ ?גA. כלומר: ציינו ש \"?\" מסודר ויזואלית מימין לשמאל.

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

    לינק רלוונטי (זהירות: hardcore): תיאור מלא של האלגוריתם לפענוח BiDi ב Unicode.

    סרגל להמרת מידות. משהו שהיה בשימוש עד שנות ה-70

    מידות ומדידות

    הנושא הבא נוגע יותר לאזורים גאוגרפיים, מאשר שפות.
    הביטו בביטוי המספרי הבא:

    1,000

    בכמה מדובר?
    קרוב לוודאי שתאמרו שזהו \"אלף\". כך גם יאמר האמריקאי או היפני, אך סביר שגרמני דווקא יסיק שמדובר במספר \"אחד\". אחד?! … כן.

    ישנן 3 צורות נפוצות לתאר את המספר 10000 (עשר אלף):

    1. 10,000.00
    2. 10.000,00
    3. 000,00 10
    הצורה הראשונה מקובלת בישראל, ארה\"ב, יפן, אנגליה, אוסטרליה ועוד.

    הצורה השנייה מקובלת בגרמניה, איטליה, ספרד, ברזיל ועוד.
    הצורה השלישית מקובלת ברוסיה, צרפת ועוד.
    ויש לפחות עוד כמה צורות אחרות… בשוויץ, כותבים עשר-אלף כך: 000.00\'10

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

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

    החכמה פה, כמו בדוגמאות אחרות – היא בעיקר להכיר את הבעיה, ולהיערך אליה נכון.

    דוגמה נוספת: תאריך ושעה.
    תאריך מושפע מ 3 גורמים עקריים:

    1. לוח השנה: למשל, גרוגאני (מערבי), עברי , יפני ,סיני ועוד.
    2. ה Time zone – היכן נמצא המשתמש הספציפי על הגלובוס, וה day light saving.
    3. הפורמט בו בקובל לכתוב תאריך באותו האזור (region).

    יש מדינות בהן היום האחרון במילניום ייכתב כ 31/12/1999 או 12/31/1999 או 1999/12/31.
    כאשר מדובר ביום וחודש ששניהם קטנים מ12 – הטעות יכולה להיות קריטית.
    יש מדינות בהן יש העדפה ברורה לצורת ההפרדה: נקודה, קו נטוי, מקף או רווח. הנה סיכום יפה של האפשרויות השונות.

    בג\'אווה, האובייקטים Calendar, TimeZone ו DateFormat יעשו עבורכם את העבודה.

    כאשר שומרים תאריך/זמן שייקרא אח\"כ פוטנציאלית ע\"י משתמש אחר / אותו המשתמש באזור זמן אחר – כדאי לשמור את כל הזמנים ע\"י אזור זמן אחיד (בד\"כ UTC) ולהתאים אח\"כ, בזמן ריצה, לכל משתמש ע\"פ הלוקאל הנוכחי שלו.

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

    השלמה: תרגום טקסט עם פרמטרים.

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

    כמה דוגמאות לטקסט באנגלית, וצורת העברה לתרגום (i18n) – שהיא בעייתית:

    1. \"Do you want to delete item \" + getId() + \" ?\"  –> \"{KEY_DEL_APPROVAL_TRNSLT} {0} ?\", getId()
    2. \"An error occurred with \" + \"the cooling system\" –> \"{ERROR_OCCR_W_TRNSLT} {COOLING_SYS_TRNSLT}\"
    3. \"There are 2 more steps for completion\" –> \"{TRNSLT_1} 2 {TRNSLT_2}\" 

    מה הבעיה?

    1. בדוגמה זו יש משתנה שנכנס למשפט. המתכנת (הדמיוני) חילק את המשפט ל\"קטע מתורגם\", \"מספר\" ו\"סימן שאלה\".
      אבל…. בשפות שונות מבנה שאלה הוא אחר:
      בתאילנדית (סתם אני זוכר מהטיול) – על המשפט להתחיל במילת שאלה.
      בגרמנית – הפועל \"מחיקה\" הוא המילה האחרונה במשפט.
      בספרדית – בנוסף לסימן השאלה, המשפט יכול להתחיל בסימן שאלה הפוך (¿).הכי גרוע: המתרגם עלול לאבד את ההקשר.
    2. במקרה זה המתכנת ניסה לעשות \"שימוש חוזר\" בחלק המשפט שחוזר על עצמו, אולי בכדי לחסוך בתרגום (מתכנת דמיוני – זוכרים?). חלוקה זו ל 2 משפטים יכולה להתפרק בקלות בשפות שאינן אנגלית, ושוב – המתרגם מאבד את ההקשר של המשפט השלם.
    3. המספר 2 אינו אוניברסלי לכל שפה, ואינו מופיע באותו המקום באותו השפה.
      מספרים ותאריכים – כדאי שיהיו חלק מהטקסט המתורגם.
    תרגום לצרפתית של משפטים פשוטים, הכוללים מספרים. אולי לא מה שהייתם מצפים.

    על כן, הדרך המומלצת היא להכיל את כל המשתנים בתוך הטקסט המתורגם:

    1. \"Do you want to delete item {ITEM_ID} ?\"  –> \"{TRANSLATED_TEXT1}\"
    2. \"An error occurred with the cooling system\" –> \"{TRANSLATED_TEXT2}
    3. \"There are {NUMBER} more steps for completion\" –> \"{TRANSLATED_TEXT3}\" 

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

    ווב ו SEO

    אם מדובר במערכת ווב, זה פשוט: וודאו שיש לכם תגיות lang ו charset תקינות.

    סיכום

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

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

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

    שיהיה בהצלחה!

    —-

    לינקים רלוונטיים

    כיצד Etsy מציגה כסף (במדינות שונות בעולם) https://codeascraft.com/2016/04/19/how-etsy-formats-currency/

    —-

    [א] פעם התקן של UTF-8 אפשר עד 6 בתים בכדי לתאר סימן, אך פישטו אותו למקסימים של 4 בתים בלבד.

    לכבוש את העולם: תוכנה רב-לשונית

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

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

    אנגליה: השפה היא כמו שפת המערכת הקיימת, אנגלית. גרמניה: יש לכם מתרגם שיתרגם בקלות לגרמנית ומישהו בחברה שיודע ספרדית היטב. תוך כמה ימים אתם יוצרים אקסל עם כל הודעות המערכת למשמש (\"user strings\") בכל 4 השפות.
    סביבת הפיתוח מאפשרת ניהול מספר שפות ל User Strings (תהיה זו ג\'אווה עם Resource Bundle property files או iOS עם NSLocalizedString).
    האם זה יותר מעניין של כמה ימים – בכדי לכבוש את העולם המערבי המפותח? (פרגון לישראל)

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

    אחד מחברי הפודקאסט סיפר שאפליקציית מובייל שהם כתבו הצליחה באופן מפתיע בשוק הרוסי והשוק הסיני – והם החליטו לתרגם את האפליקציה לשפות אלו. אני מכיר את נושאי רב-הלשוניות (Multi-lingual) מעולם ה Enterprise, אך נראה שהוא רלוונטי למדי גם לאפליקציות מובייל.

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

    אני אנסה לשנות זאת… 🙂

    מושגים

    בתחום זה יש 3 מושגים מבלבלים:

    • Internationalization (בקיצור: i18n)
    • Localization (בקיצור: l10n)
    • Globalization (בקיצור: g11n)
    ראשית הסבר על מהות הקיצורים המשונים:
    המינוח Internationalization הוא דיי ארוך. מכיוון שאנשים מזהים מילים בעיקר בעזרת האות הפותחת והמסיימת, אפשר לקצר ל \"i—n\" ולשמור על היכולת של לקשר את הקיצור למילה המקורית. כמה אותיות יש באמצע? 18. לכן: i18n. (לא מאמינים? תספרו).
    מה הקשר בין שלושת המושגים? האם Globalization הוא ההיפך מ Localization? האם זה אותו הדבר?

    אפשר לסכם את הקשר בעזרת הנוסחה הבאה: g11n = i18n + l10n.

    Internationalization הוא התהליך של הכנת התוכנה לריבוי שפות ואזורים (regions).

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

    Globalization הוא התהליך הכולל של Internationalization ו Localization, הכולל הכנה לריבוי-שפות ואז התאמה למספר שפות/אזורים ספציפיים.
    שיטה אחרת (עמוד 2 במסמך) מתארת את הקשרים מעט אחרת ומדברת גם על Localizability, L12y). אם האנשים שעובדים אתכם נוהגים ע\"פ המודל השני, פשוט הפכו את שמות המושגים i18n ו g11n – כל השאר נשאר בערך אותו הדבר.
    מונח נפוץ אחר, בעיקר ב API של שפות תכנות, הוא Locale (תרגום לעברית: מקום).

    Locale הוא אובייקט המתאר קומבינציה של שפה (\"עברית\"), אזור (\"קנדה\") ולעתים גם codeset (שזה בעצם encoding, כמו UTF-8 – נושא שאפשר להקדיש לו פוסט משלו). בד\"כ יהיה לנו על ה session אובייקט locale שבעזרתו נדע כיצד לשרת את המשתמש הנוכחי.

    נהוג לקדד את ה Locale בעזרת שפה ע\"פ תקן ISO 639-1 ואזור ע\"פ תקן ISO 3166-1.
    למשל: en_US (אנגלית, ארה\"ב), en_GB (אנגלית, ארה\"ב) או zh_CN (סינית בסין) או אפשר גם he_CN (עברית בסין).

    Locale, אפרופו, מבטאים כ\"לו-קאל\" (כמו \"לוראל\" – חברת קוסמטיקה) ולא \"לוקייל\", כפי שלעתים נהוג.

    חזרה ל FlappyWare

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

    • הישראלים רוצים שכל התפריטים ועימודי הדף יהיו מימין לשמאל. העימוד הנוכחי פשוט לא מתאים!
      אולי למתכנת, עימוד משמאל לימין לא מפריע (או עדיף), אך פועל במפעל, או אמא שיש לה מספיק נושאי-עניין בחיים – פשוט רוצים שהממשק יהיה קל ונוח (\"למה לא עשו את זה בסדר? הם לא רואים שזה עקום?\").
    • הבריטים רוצים שהמערכת תשאל: \"?what is your favourite colour\" ולא \"?what is your favorite color\". הבדל בין אנגלית-אמריקאית לאנגלית-בריטית, שנתפס אצל הבריטים כמאוד-לא-קטנוני.
    • ישנם באגים לא צפויים במערכת בספרדית בתחום החיפוש. משום מה גם הטבלאות התחרבשו… מה זה קשור לתרגום?!
    • הגרמנים פשוט לא מרוצים ונמנעים משימוש באפליקציה. לא הצלחתם לייצר איתם קשר טוב מספיק להבין מה בכלל הבעיה (?!).

    כאשר המשתמשים שלכם מגיעים מתרבות שונה ודוברים שפה שונה, גם הטיפול בכל case/bug נהייה קשה יותר. כשלקוח טוען ש\"בהונגרית זה צריך להיות ככה…\", ואתם לא מבינים על מה הוא מדבר / למה זה יצא אחרת – זה יכול להיות מאמץ לא קטן להבין ולתקן.

    להבין את תהליך התרגום

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

    1. תוכן מערכת – כל הודעות טקסט במסופקות כחלק מהאפליקציה: כותרות, תפריטים, הודעות שגיאה וכו\'. סוג זה הוא הנפוץ ביותר.
    2. תוכן לקוח – תוכן שהלקוח יצר בעצמו והוא רוצה לתרגם. סוג זה של תוכן רלוונטי כנראה רק לתוכנה עסקית, ורק לחלק קטן ממנה. לדוגמה: מערכת שיווק אונליין הנמכרת ללקוח (קמעונאי כלשהו) רוצה למכור סחורה במדינות שונות – לכן עליו לתרגם את קטלוג המוצרים, כתבי אחריות, מפרטים וכו\' – תוכן שהוא יצר.
    שני סוגי התוכן הם:
    1. מחרוזות (Strings), קרי \"טקסט נטו\" – אותן קל למדי לתרגם.
    2. כל סוג אחר של מדיה: תמונות, מסמכים (למשל PDF), קישורים וכו\'.
      תמונות (כמו ה screenshot ב appstore או כפתורים באפליקציה) לעתים מכילות טקסט – ועל כן יש גם ליצור להן עותק מתורגם. ייתכנו תמונות שונות ללוקאלים שונים, למשל תמונה שונה לשוק החרדי ולשוק החילוני בארץ (כן… ניתן לראות את השוק החרדי כסוג של Locale שונה, למרות שהוא במדינת ישראל).
      לעתים אלו קישורים (URLs) לאתרים שונים, כאשר נקשר אתרים שונים לשפות / לוקאלים שונים.
    את התרגום נוהגים לעשות מתוך ה Master Language. כלומר, בוחרים שפה \"מובילה\" (בארץ זו תהיה בד\"כ אנגלית, אך במדינות אירופיות זו עשויה בהחלט להיות השפה המקומית) בה ייכתבו הטקסטים המקוריים וממנה יתורגמו כל השפות – בכדי לצמצם טעויות.

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

    לרוב זה לא יהיה נוח מ 2 סיבות:
    א. למתרגם לא תמיד תהיה גישה למערכת ה Online.
    ב. כלי התרגום מספקים יתרונות משמעותיים (למשל מילון-מונחים שכבר בשימוש במערכת, Thesaurus ועוד) – והמתרגמים עשויים דווקא לגבות מחיר גבוה יותר על שימוש במערכת אונליין.

    בעיניים עצומות

    פרט קטן לגבי התרגום לא ציינתי: המתרגמים לרוב עושים את עבודתם ללא שהם מכירים לעומק את האפליקציה שהם מתרגמים.
    \"לעומק\"? תנו לי לתקן: הרבה פעמים הם מעולם לא ראו אותה או לא אפילו לא יודעים מהי.

    רוצים להימנע מתרגום נוסח Google Translate או תרגומים מביכים כגון \"רפידת הטקסט\" (TextPad)? – אם כן, כדאי שתעזרו למתרגמים.

    מקור: גיקטיים

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

    מה שעושים בדרך כלל (כשרוצים תוצאות יותר טובות) הוא מפרקים את הטקסטים מתוך קבצי המדיה השונים ושולחים אותם כ Strings. משאירים את הטיפול בפורמטים השונים של קבצי המדיה in-house.
    אם המערכת שלכם מספקת יכולת לתרגם תוכן-לקוח – זה אומר לאפשר להוסיף מחרוזות שלא נמצאות במערכת.

    דבר שני וחשוב יותר הוא הוספת תיאור קצר שמספק את ההקשר לכל מחרוזת. לדוגמה על \"Hall of Fame\" ניתן לציין שזוהי כותרת מסך עם תוצאות המשחק הטובות ביותר או דף באתר האינטרנט המאתר את מורשת החברה. התרגום – יהיה שונה ע\"פ ההקשר שיסופק.

    את ההערות מוסיפים פעמים רבות המתכנתים תוך כדי שהם כותבים את הקוד. כל מחרוזת שהיא טקסט לתרגום (לא כל המחרוזות בתוכנה הן כאלו, כמובן) – מתווספת עם הערה. יש סביבות בהן מוסיפים את ההערות בקוד (iOS?) וכאלו שבעזרת כלים נלווים ב IDE (למשל בג\'אווה).

    אחרי שמסיימים פרויקט תרגום, נראה הגיוני מאוד לסמן את המחרוזות למשתמש (\"User Strings\") בפרויקט הבא מהיום הראשון, כך שלא יהיה צריך לעבור מחרוזת-מחרוזת בקוד ולאתר את כל הטקסטים למשתמש. כך גם הומלץ בפרק של \"מובייל ובירה\" שעסק בנושא.
    מניסיוני, אפשר לעשות זאת אם כלי הפיתוח באמת נוחים. Localization הוא קצת מעבר ל User Strings ולא כדאי להתחיל להשקיע לפני שברור שזו המטרה.

    את המחרוזות לתרגום, נוהגים לנהל באחד מ-2 פורמטים נפוצים:
    PO/POT – שמקובל בעולם ה Unix. מערכת WordPress, למשל משתמשת בו.
    XLIFF – מקובל יותר בעולם הג\'אווה / אנטרפרייז. אפשר להמיר בקלות קבצי properties שמייצר Eclipse ל XLIFF.

    עוד בסיס מידע חשוב הוא ה Translation Memory, מין \"בסיס נתונים\" (קובץ TMX או TBX) של המונחים בהם השתמשו במערכת. כאשר מתרגם יקבל מכם עוד עבודה אחרי חצי שנה שלא נגע במערכת (כאילו שהוא זוכר אותה) – ה Translation Memory יזכירו לו באלו מונחים הוא השתמש בעבר והוא יוכל לשמור על קונסיסטנטיות.

    כדי שהמתרגמים יוכלו להיות עקביים, גם עליכם להיות עקביים במונחים בהם אתם משתמשים בשפת ה Master Language, כמובן.

    כיצד נראה התרגום בקוד

    זה כמובן תלוי בשפת וסביבת הפיתוח. אני אצמד לדוגמאות ב Java – השפה בה אני מכיר את הנושא בצורה הטובה ביותר.
    בג\'אווה יש מנגנון בשם Resource Bundles שעוזר לנהל user strings בשפות שונות.
    את ה Resource Bundle ניתן לייצר בעזרת Wizard ב Eclipse:

    באותו הרגע נוצרים הקבצים הבאים:

    • קובץ plugin.properties שכולל את טקסטי ברירת-המחדל / ה Master Language.
    • לכל שפה, אזור או צימוד של השניים שהגדרנו – ייווצר קובץ נוסף, לדוגמה plugin_en.properties או plugin_en_GB.properties.

    לאחר מכן ניתן לערוך את קבצי ה properties, כאשר כל key מייצג מחרוזת בכל שפה.

    הערה: אצלנו בחברה היה Editor אחר, אולי פרי פיתוח פנימי. אנא סלחו אם אני מפספס פה איזה פרט.

    בזמן ריצה של הקוד ישלוף את המחרוזת המתורגמת המתאימה:

    ResourceBundle bundle = ResourceBundle.getBundle(\"properties.namespace\", someLocale);

    String translatedString = bundle.getString(\"someKey\");

    שימו לב שלג\'אווה יש מנגנון fallback אם הוא לא מוצא את הלוקאל המדויק:
    אם למשל הלוקאל הוא \"en_US\" אך אין קובץ כזה, הוא ינסה להשתמש ב \"en\". אם אין גם קובץ כזה – הוא ילך לקובץ ברירת המחדל (למשל: plugin.properties).

    מה יכול להשתבש ב Localization?  – מיון

    אם האפליקציה שלכם מקבלת קלט בשפה שאיננה אנגלית ומנסה למיין אותו – היא עלולה להיכשל.
    נתחיל בכך שמתודת ()compareTo של המחלקה String בג\'אווה עלולה כבר לגרום לטעות, אפילו בשפה האנגלית.
    מדוע? בגלל הקידוד (להלן כמה יסודות שחשובים בכדי להבין).

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

    הקידוד הבסיסי ביותר הוא קידוד בשם ASCII:
    ASCII הוא קידוד 7-ביט. כלומר: כל אות יכולה להיות אחת מתוך 128 סימנים או אותיות.
    32 התווים הראשונים הם control characters: טאב, רווח, מחיקה ועוד סימנים שרובם חסרי משמעות גרפית (למשל: סוף שורה). שאר התווים הם מספרים, אותיות וכמה סימני-שפה.
    ישנן הרחבות לASCII של 8-ביט המוסיפות עוד כ 128 תווים המותאמים לשפות נוספות (כל הרחבה – לשפה אחרת). כלומר כל סימן/אות (character) הוא בית אחד / 8-ביט.

    משפחת הסימנים הנראים של ASCII 8bit, בהתאמה לעברית (סימנים במסגרת הירוקה), מוצגים בתוכנת Character Map של \"חלונות\".

    מיון בסיסי בשפת ג\'אווה (וברוב השפות האחרות) מתבסס על הערך המספרי של האותיות במחרוזת.
    כפי שניתן לראות, הערך המספרי של האות \"Z\" (גדולה) הוא 90, בעוד שהערך של \"a\" (קטנה) הוא גבוה יותר (97) – ולכן מיון יסדר מחרוזות בסדר הבא:

    1. Ant
    2. Zoo
    3. ambulance
    …למרות שהיינו מצפים שהמילה ambulance תהיה במקום הראשון (סדר לקסיקוגרפי – כמו מילון).
    פתרון נפוץ לאנגלית: לעשות מיון ע\"פ צורת ה upperCase של המחרוזות.

    אך זה לא עובד בשפות רבות אחרות….
    • בשוודית, ישנה אות הנכתבת כ ae (או סימן æ) – מקומה בסדר הלקסיקוגרפי הוא אחרי האות \"z\".
    • בגרמנית, כאשר האות s מופיעה ברצף פעמיים – מקצרים את הצמד לכתיבת ß (כמו ביטא). סידור ע\"פ ערכי ASCII ימיין את המילה groß (שקול ל gross = \"גדול\") לאחר המילה grost – מכיוון שערך ה ASCII של ß גדול יותר. זו כמובן טעות צורמת לדובר גרמנית.
    • ע\"פ חוקי הדקדוק של שפות אירופאיות שונות, אותיות מוטעמות (\"accent\") צריכות לבוא אחרי אותיות דומות לא מוטעמות. צרפתית גרועה אפילו יותר: אות מוטעמת מאוחרת היא חזקה יותר, כלומר: יש לבדוק את האותיות המוטעמות מימין לשמאל.
    הצרפתים, כידוע, רגישים לשפה שלהם. לא תרכשו ידידות עם לקוח צרפתי בניסיון להסביר לו שמיון ע\"פ הטעמה בחוקים הצרפתיים זו דקות מוזרה או קטנה – ושיסתדר.
    אז מה עושים?
    אפשר להתייאש. להגיד ללקוחות שככה זה אצלכם ושיעברו לאנגלית, אם זה מפריע להם.
    אפשר לנסות ללמוד את כל הבעיות בכל השפות השונות – ולממש אלגוריתם מיון, אך לא כדאי.
    אפשר להשתמש בכלי קיים להתמודד עם בעיות ה internationalization – וזה מה שאמליץ לעשות.

    ג\'אווה, כבר מגרסאות מוקדמות, כללה סט כלים עשיר ל i18n, רובם תחת החבילה java.text.
    במשך השנים, התחזוקה והעדכון של ספריות אלו מעט הוזנח וכיום הן נחשבות עדיין טובות – אך לא \"state of the art\".
    אם נושא ה i18n חשוב לכם באמת – הייתי ממליץ להשתמש בספריית ICU של IBM – ספריית open source בג\'אווה (יש גם גרסת ++C) ל g11n המתוחזקת ברמה טובה.
    יש גם רשימה של ספריות ג\'אווהסקריפט לתמיכה ב i18n – אולם אין לי ניסיון עמן ואני לא יודע להמליץ.

    בג`אווה, הביטוי הבא יבצע השוואה נכונה, ע\"פ השפה הנתונה:

    Collator.getInstance(Locale.FRENCH).compare(stringA, stringB)



    ל ICU יש גרסה משלה ל Collator – מדויקת יותר.

    אם אתם מתכוונים לעשות הרבה השוואות על אותה קבוצת מחרוזות (למשל: מיון תכוף), collator איננו מאוד יעיל ועדיך להשתמש ב CollatorKeys.

    סיכום

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

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

    כמובן שיש לתהליך globalization מלא יש עלות, במיוחד אם מתחילים לעשות שינויים בקוד (עבור חיפוש, מיון וכו\'). כדאי להכיר את הנושאים ולהשתמש בפוסט(ים) כ reference לאלו בעיות יכולות לצוץ, ולבחור ע\"פ מצב השוק – כמה רחוק ללכת.

    שיהיה בהצלחה!

    —-

    לינקים רלוונטיים:

    סקירה מקיפה על פורמטים וכלים על תרגום (אם המערכת שלכם תנהל תרגום): http://edutechwiki.unige.ch/en/Software_localization
    התרגומיה, בלוג עברי על תרגום :http://yaeltranslation.com

    Enterprise Architecture: Authorization

    קשה להגדיר מהי Enterprise Architecture, לרוב זוהי ארכיטקטורה של / ועבור ארגונים גדולים.

    אחד מנושאי-הליבה שחוזר על עצמו ב Enterprise Architecture הם נושאי ה Authentication ו Authorization (בקיצור: A&A):

    • Authentication – אימות הזהות של משתמש (\"האם הוא מי שהוא טוען שהוא?\")
    • Authorization – כיצד שולטים בהרשאות מה המשתמש, לאחר שאימתנו את זהותו, יכול לעשות.
    ישנם מעט Enterprise שלא כוללים A&A, למשל כמעט כל הגישות בווב יהיו על גבי HTTPS (הדורשת הזדהות) ולא HTTP.

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

    בפוסט זה אני רוצה להתמקד בתחום ה Authorization ולהציג עקרון מעניין, שאני מניח שלא מוכר בקרב רבים, הנקרא Role-Based Authorization (בקיצור: RBA, נקרא גם Role-Based Access Control קרי RBAC).

    הקדמה: המודל הנאיבי

    ניהול המשתמשים הפשוט (והנאיבי) ביותר כולל טבלה בבסיס הנתונים של המשתמשים וססמותיהם. כשהמשתמש מתחבר למערכת עליו להקליד שם משתמש (כלומר: user id) וסיסמה ואז משווים את הפרטים למידע בטבלה. אם המידע נכון – שומרים את זהות המשתמש על ה session (באם זה server-side session, cookie וכו\').
    כמובן שכדאי שהססמאות יהיו \"מגובבות\" (hashed) ואולי גם \"מטושטשות\" (מה שנקרא salted [א]). נושא זה הוא תחום ה Authentication, אימות זהות המשתמש, נושא שאנני מתכוון לעסוק בו בפוסט זה.

    עבור ה authorization, ניהול ההרשאות של כל משתמש, יוצרים טבלה נוספת \"הרשאות\" הכוללת user id, resource id, permission type (להזכיר: מימוש נאיבי לחלוטין). כל פעם שמשתמש ייגש למשאב, נבדוק בטבלה אם יש לו הרשאה לפעולה (למשל: read, write וכו\') ואז נאפשר לו / נמנע ממנו את הפעולה.

    ניתן לתאר את המודל הנאיבי באופן הבא:

    מודל נאבי זה אינו scalable לניהול כאשר יש הרבה מאוד אובייקטים ו/או משתמשים. כדי שמודל Authorization \"יעבוד כראוי\" חשוב מאוד שיהיה נהיל (maintainable) ופשוט. מבחן בסיסי הוא לענות על שתי שאלות:

    1. \"האם ניתן להבין בקלות מה בדיוק משתמש x מורשה לעשות?\" במקרה שלנו – ממש לא. הוא יכול לקבל הרשאות לעשרות, מאות, אולי אלפי אובייקטים. גם אם יש לנו את רשימה של האובייקטים זמינה בקלות – יכול לקחת זמן מה לפענח ולהבין מה הוא בדיוק כל אובייקט. לדוגמה: אם אלו מסמכים – מה מכילים המסמכים השונים שיש למשתמש הרשאות.
    2. \"כאשר אני מספק למישהו הרשאה, האם קל להבין למה בדיוק אני מספק לו הרשאה?\" במקרה הזה – כן, זהו אובייקט ספציפי.

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

    עוד בעיה של המודל הוא software scalability. הטבלה בבסיס הנתונים עלולה לצמוח במהירות. למשל: חשבו על שרת קבצים המאכסן כמיליון קבצים עבור כמה מאות משתמשים (תסריט סביר של חברה בינונית). אם עבור כל גישה לכל אובייקט נצטרך לסרוק טבלה של מיליוני שורות (אובייקטים x משתמשים) – אנחנו בבעיה.

    יתרון של המודל שהוא בהחלט פשוט וקל להבנה – זוהי תכונת מפתח של המצופה ממודל Authorization.
    למה אני חוזר ומדגיש נקודה זו? כי בסוף את ניהול ההרשאות עושים בני-אדם. מודל \"מעולה מתמטית\" שהמשתמשים לא מבינים  – שקול למודל גרוע. הנה 2 דוגמאות אופייניות:

    1. משתמש א\' מנסה להגדיר הרשאות למשתמש ב\' – אך לא מצליח לעשות זאת. אחרי כמה ניסיונות הוא נשבר, בוחר את הקבוצה \"Everyone\" ומסמן כל checkbox שהוא רואה ב UI בכדי לאפשר למשתמש ב\' את הגישה המיוחלת.
      התוצאה: המידע חשוף לכולם ואיננו מאובטח.
    2. מנהל האבטחה / איש IT שאחראי על ההרשאות לא מצליח לעקוב למי יש גישה למה. עובדים עוברים תפקידים, עוזבים, מידע נוסף – אבל אין יכולת לעקוב אחרי מה שמתרחש. אין יכולת לאכוף חוקים אבטחה ארגוניים. מערכת האבטחה מסתמכת בעיקר על עובדים ללא הבנה בענייני אבטחה, שאבטחה היא בעיקר מעצור בשבילם \"to get the job done\".
      התוצאה: חוסר שליטה. לעתים מוסיפים מערכת אבטחה חיצונית שמגבילה את צעדי המשתמשים באופן דרקוני – בניסיונות להחזיר את השליטה.
    מה הוא רואה: הכל, או כלום? 

    מודל: Access Control List

    בואו נתקדם מהמודל הנאיבי 2 צעדים קדימה:

    1. ננהל את המשתמשים בקבוצות (בעזרת מערכת x.509/LDAP/Active Directory וכו\') וננהל הרשאות לקבוצות, לא בודדים. התוצאה: הרבה פחות הרשאות לנהל.
    2. נקבע היררכיה בין המשאבים, כך שאם נתנו הרשאה למודל אב – האובייקטים הבנים יורשים אותה (אלא אם הוגדר אחרת במפורש) – שוב: פחות משאבים לנהל עליהם הרשאות.
    המודל יראה בערך כך:

    מודל זה פישט משמעותית את כמות הרשומות ב\"טבלת ההרשאות\" ושיפר את ה scalability של הניהול: במקום עשרות משאבים / משתמשים, אנו יכולים כעת לנהל מאות. במידה ויש אחידות גבוהה של המשתמשים / משאבים – אולי אפילו אלפים.
    מודל ה Access Control Lists (בקיצור: ACL) – מפשט את יכולת הניהול אפילו קצת יותר: הוא מאגד את ה Permissions לאובייקט אחד שנקרא ACL. נובעים מכך כמה יתרונות:
    1. ה ACL הוא חלק מהמשאב. אם מזיזים את המשאב – ה ACL זז איתו, ואין צורך לנהל (ברמת הקוד) מעקב ושינויים בטבלת ההרשאות.
    2. בגלל שה ACL הוא אובייקט יחיד, יש פחות רשומות לנהל (יותר software scalability) / ניתן לנהל cache יותר יעיל.
    יתרונות אלו נראים קטנים – אך הם, בסופו של דבר, חשובים.

    לאחר התוספות, המודל יראה כך:

    היכן משתמשים במודל זה?
    • מערכות קבצים כמו Windows NT או Unix
    • IBM Tivoli, Cisco Network Infrastructure ומערכות Enterprise אחרות
    כמובן שיש וריאציות מעט-שונות של המודל.

    עקרון מוסכם כיום הוא שהרשאות חייבות להיות חיוביות (positive) בלבד – כלומר: \"מה המשתמש יכול לעשות\" ולא \"מה המשתמש לא יכול לעשות\". זאת, בכדי למנוע סיבוכיות / דו-משמעות של ההרשאות שניתנו. במערכת הקבצים של \"חלונות\" עברו על כלל זה – מה שמסבך מאוד את ניהול ההרשאות.

    1. \"האם ניתן להבין בקלות מה בדיוק משתמש x מורשה לעשות?\" – לא. מודל ה ACL שיפר את ה scalability של המודל הנאיבי, אך הוא עדיין נחשב מודל מאותגר-scalability מבחינת ניהול.
      ארגונים גדולים נוהגים לרכוש כלי ניתוח שסורקים את ה ACLs במערכות הקבצים, ומייצרות דוחות המקלים על ההבנה מה כל משתמש יכול לעשות.
    2. \"כאשר אני מספק למישהו הרשאה, האם קל להבין למה בדיוק אני מספק לו הרשאה?\" – פחות או יותר כן, כל עוד המשאבים מנוהלים היררכית בצורה הגיונית (מה שלעתים קרובות קורה).
    חולשה של מודל ה ACL הוא טיפול בהסרה של הרשאות – מה שעלול לדרוש עדכון של ACLs רבים והלוגיקה מאחוריו עלולה להיות בלתי-מובנת לחלק מהמשתמשים.

    מודל: Policy-Based Authorization

    במשך השנים ניסו ליצור מודל קל יותר לניהול, שיתאר יותר את צורכי האבטחה של הארגון ופחות ייצמד למבנה המשאבים הטכני במערכת. זהו מודל ה Policy-Based Authorization (בקיצור: PBA או PBAC).
    הרעיון הוא שהארגון יקבע סט של כללי-אבטחה / מדיניות אבטחה (Policies), יכיל אותם על משאבים, והמערכת תאכוף אותם.
    למשל: \"לחשבוניות שנוצרו בשבוע האחרון יש הרשאות קריאה למשתמשים מסוג x, המתחברים מתוך הרשת הארגונית\".
    בהפשטה, המודל יכול להראות משהו כזה:
    במודל זה יש וריאציות רבות יותר ממודלים אחרים.
    היכן משתמשים במודל זה?
    מודל זה מקובל בעולם ה Enterprise במערכות רבות, נפוץ גם בעולם אבטחה (דוגמה מאוד פשוטה: Firewall)
    1. \"האם ניתן להבין בקלות מה בדיוק משתמש x מורשה לעשות?\" – !Hell No: למרות שיש הרבה פחות חוקים (policies) מ Permission במודלים הקודמים – הם עכשיו מורכבים הרבה יותר ומסובכים למעקב. ליתר דיוק ניתן לומר שמודל זה עשוי להיות מוצלח במקרים מסוימים, במיוחד כאשר כללים בסיסיים יכולים לתאר אוסף גדול מאוד של מקרים, משאבים או משתמשים (למשל: \"אסור לגשת ל port 1433 בלי רשות של רגע ודודלי\").
      קל במודל להגדיר Policies באופנים שונים, ברמות הפשטה שונות, ובסגנון שונה שיקשה על ההבנה שלהן.
    2. \"כאשר אני מספק למישהו הרשאה, האם קל להבין למה בדיוק אני מספק לו הרשאה?\" – שוב, מאוד תלוי.
    סה\"כ, מודל ה PBA הוא שנוי במחלוקת לגבי היכולת שלו לפשט את ניהול ההרשאות במערכת ה Enterprise Scale.
    כיצד אם כן מערכות אבטחה רבות משתמשות במודל זה? התשובה שלי היא שאנשי אבטחה רבים סובלים ממודל מסובך שקשה לנהל ולעקוב אחריו. עבור כמה מקרים – המודל היה מוצלח, ועבור רבים אחרים – הוא נבחר מ\"סיבות היסטוריות\".

    מודל ה PBA יכול גם לסבול מבעיות software scalability קשות, כאשר מספר ה policies עולה. בחלק מהמערכות, \"מקמפלים\" את ה policies לאוטומט שיוכל לבצע את אימות ה policies בצורה יעילה יותר.

    מודל ה Role-Based Authorization

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

    מודל ה Role-Based Authorization (בקיצור: RBA) הוא מודל נוסף שמנסה לתאר את הארגון וצרכיו, ולא רק להיצמד למבנה המשאבים הטכני.

    במודל ה RBA ממדלים Role (\"תפקיד\") כסט של מטלות (Tasks) לביצוע. אנשים שאמורים לבצע מטלות דומות, לרוב יהיו בתפקידים זהים או דומים. לאותם בעלי תפקידים דומים נותנים סט של הרשאות על משאבים.

    בצורה הפשוטה ביותר ניתן לבטא את מודל ה RBA באופן הבא:

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

    סמנטיקה: עצם כך שהקבוצה נקראת \"Role\" מעודדת את המשתמשים לייצר קבוצות ע\"פ התפקידים הקיימים בארגון: { רופאים, אחיות, אחיות בכירות } או { קניין, קניין חוץ, מנהל חשבונות }. צורה זו עוזרת לארגן את המשתמשים בשפה/סמנטיקה מרכזית בארגון – שכולם מכירים ומבינים.

    ריכוזיות: לעתים רבות משייכים את המשאבים ל Role ולא להיפך, כך שאובייקט ה Role הוא בעצם זה ש\"מחזיק\" את ההרשאות. גישה ריכוזית זו עוזרת לעקוב בקלות אחר ההרשאות – במיוחד במערכות מבוזרות בהן המשאבים נמצאים במערכות שונות.

    אחידות: מכיוון שמספר התפקידים בארגון הוא לא מאוד גדול (לא יותר מכמה עשרות, ברוב הארגונים), יחידת ההרשאות (שהן ה Role) הן Coarse-Grained, כלומר: מעט קבוצות המכילות הרבה משאבים.
    לגישה זו יש מספר תוצרים:
    1. למשתמשים תהיה גישה למשאבים שהם לא זקוקים להם (כי עמיתים מקבילים להם היו זקוקים להם לעבודתם). כלומר: ההרשאות הן לא \"מינימליות\".
    2. הרבה יותר קל ופשוט לנהל את ההרשאות:
      1. אם ל\"רופא\" אחר יש הרשאה למשאב, מספיק שאוסיף אותך ל Role \"רופא\", כדי שתקבל \"אותן הרשאות. \"שכפול הרשאות\" הוא פעולה דיי מסובכת עד בלתי-אפשרית במערכת שמנהלת הרשאות כ ACLs. 
      2. כשעובדים מבצעים מעברי פרויקטים / תת-תפקיד, סיכוי גבוה שההרשאות שמוגדרות להם עכשיו – מספיקות. ==> תחזוקה קלה.
      3. מכיוון שיש מעט קבוצות, והן מתמפות ל\"שפה הטבעית של הארגון\", למי שמגדיר את ההרשאות ברור הרבה יותר טוב למי הן מיועדות.
      4. כאשר רוצים לבצע סקירה של המשאבים שזמינים לרופאים, קל מאוד לבדוק את ה Role של הרופאים ולראות מה זמין להם.

    בואו נבחן את המודל:

    1. \"האם ניתן להבין בקלות מה בדיוק משתמש x מורשה לעשות?\" – כן. ה Role מוכר בארגון ויש הרבה נקודות התייחסות.
    2. \"כאשר אני מספק למישהו הרשאה, האם קל להבין למה בדיוק אני מספק לו הרשאה?\" – כן, ניתן לסקור את ה Role בקלות ולמצוא את כל המשאבים. סביר שהמשתמש מכיר את המשאבים כי הוא בעצמו חבר ב Role.
    היכן ניתן למצוא את המודל?
    שרתי ווב, JEE, Windows, .NET, מערכות שונות של SAP, Oracle, IBM ועוד.
    סה\"כ מודל ה RBA נחשב כ \"Best Practice\" בתעשיית ה Enterprise וכמודל מוצלח במיוחד. הוא מספק פשטות ניהול שהיא הדרך הכמעט-יחידה של ארגון לשלוט ולהבין אילו הרשאות יש לעובדים, מבלי לטרטר אותם יותר מדי. 
    הנה גרסה מעט יותר מורכבת של המודל (בכדי לסבר את העין):

    כמובן שלמודל ה RBA יש גם כמה חסרונות:
    1. המודל לא מספק שליטה במידע רגיש שאמור להיות זמין לקבוצה קטנה של אנשים. במקרים אלו מספקים מודל הרשאות נוסף (למשל: ACL למשאבים רבים – כמו קבצים, PBA למקרים רוחביים / מופשטים כמו Ethical Wall [ב]) על גבי קבוצה מסוימת של משאבים ב Role, כלומר: מגבילים חלק מהמשאבים המשויכים ל Role לתת קבוצה של ה Role.
    2. מה קורה בארגון שבו אין בעלי תפקידים ברורים? ארגונים בהם מידע מוגש על בסיס \"need to know\"? – מודל ה RBA פשוט לא מתאים.

    סיכום

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

    שיהיה בהצלחה!

    ליאור

    [א] הנה הסבר מוצלח בנושא: https://crackstation.net/hashing-security.htm

    [ב] המקרה בו 2 בעלי תפקידים לא מורשים לגשת למידע אחד של השני מסיבות אתיות. לדוגמא: משרד עו\"ד שמייצג שתי חברות מתחרות בתיקים שונים. עדיין, אסור לעו\"ד שמייצג את חברה א\' למצוא מידע על החברה המתחרה ב\'.

    ארכיטקטורה: Quality Attributes (חלק ב\' – כיצד משתמשים)

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

    כיצד בוחרים מאפייני איכות?
    ראשית, על מנת לעזור לנו להגדיר את מאפייני האיכות של המוצר / רכיב שלנו, יש כמה \"רשימות\" נפוצות של מאפייני איכות – שיוכלו לעזור לנו להתחיל. אני מתבסס על רשימה של קארל ויגרס מספרו העוסק בדרישות תוכנה, אך יש גם רשימות אחרות.

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

    Usability – ב\"עידן התפוח\" לא צריך להסביר כבעבר את החשיבות של השימושיות. שימושיות נובעת מה UI, ומהמהירות בו הוא מגיב, אך גם משפיעה על פנים המערכת: דרישה של שאילתות שקשות לביצוע אך מועילות למשתמש, זמינות נתונים וכו\'. השאלה המעניינת, בעידן התפוח, היא מה יותר חשוב במערכת שלכם מ Usability – וסביר שבמערכות רבות יהיו שיקולים שכאלו.

    Security (נקרא במקור Integrity) – עד כמה מוגבלת / מאובטחת צריכה להיות הגישה לנתונים / שירותים של המערכת.

    Efficiency – עד כמה יעילה המערכת בניצול משאבי החומרה העומדים לרשותה, או בניצול שירותים אחרים (כגון SOA) – והחומרה העומדת לרשותם.

    Portability – היכולת של המערכת לרוץ בסביבות ריצה שונות, קרי מערכות הפעלה, סביבות ענן, תצורות רשת וכו\'.

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

    Interoperability – היכולת להחליף נתונים בקלות עם מערכת אחרת. באופן אישי לא מצאתי מאפיין זה שימושי. Interoperability נראה לי יותר כמו פיצ\'ר נקודתי מאשר יכולת רוחבית. אני משאיר אזכור לצורך שלמות הרשימה המקורית.

    Maintainability – עלות תפעול (Administration / Operations) נמוכה של המערכת. מה שנקרא TCO (Total Cost of Ownership). מאפיין זה יכול להצביע על הוספת \"פ\'יצרים של ניהול המערכת\". עוד נושא שנכנס לקטגוריה זו היא קלות ההתקנה של המערכת, לעתים מתייחסים אליה כמאפיין איכות עצמאי: Installability.
    דוגמה: כלי monitoring שיסייעו לנטר בעיות במערכת. השקעה ב Upgrade קל וכו\'.

    Developability (נקרא במקור Flexibility) – היכולת לפתח את המערכת בקלות, לבצע בה שינויים או לתקן באגים. מה שנקרא TCD ((Total Cost of Development מאפיין איכות זה עוזר לאפיין את הדילמה שבין איכות שמוסיפה סיבוכיות למערכת (Portability או Efficiency, למשל) למול היכולת לפתח מהר וביתר קלות.

    Extensibility – היכולת להרחיב ולהוסיף יכולות חדשות למערכת, בעזרת Plug-in, API וכו\'. כמובן שיכולת ההרחבה היא ליכולות / אזורים ספציפיים במערכת.

    Supportability – היכולת לתמוך במוצר בקלות, אם מדובר בגוף המייצר את התוכנה או גוף שלישי. כלי Monitoring, לוגים קריאים, יכולת לבצע Dumps של זיכרון או נתונים, דו\"ח על תצורת המערכת וכו\'.

    Scalability – היכולת של המערכת של המערכת לטפל במספר הולך-וגדל של בקשות ו/או היכולת של המערכת לגדול על מנת להמשיך ולהתמודד עם גדילה זו. לרוב עושים הבחנה בין Vertical Scalability – יכולת לצרוך ביעילות חומרה יותר חזקה ו Horizontal Scalability – היכולת של המערכת להתפרס על מספר שרתים פיסיים (cluster).

    Testability – היכולת לבצע בדיקות למערכת. באופן אישי, מאפיין זה נראה לי כמו אמצעי להשגת Reliability או Developablity – ולא מטרה בפני עצמה.

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

    Availability – מאפיין זה תקף בעיקר לשרתים (או שירותים) והוא מורכב מזמינות (אחוז הזמן שהשרת / שירות זמין ללקוחותיו) או תדירות הכישלונות (מה שנקרא MTBF). שרת יכול להיות זמין 99% מהזמן אך לכשול לשנייה אחת – כל יום, מה שיגרום לתקלות כואבות. (MTBF (Mean Time Between Failures עוזר להשלים את התמונה שנתון הזמינות לבדו לא מספק היטב.

    רשימת \"מאפייני איכות\" ממקורות שונים.  מקור: http://www.clarrus.com/documents/Software%20Quality%20Attributes.pdf

    כמה הערות על הרשימה:
    שימו לב שבהכללה גסה Reusability, Developability ו Testability הם איכויות פנימיות (משפיעות על הפיתוח) בעוד היתר הן איכויות חיצוניות (משפיעות על הלקוח).

    Extensibility, Maintainability ו Supportability הם סוג של \"פיצ\'רים\" שאולי מנהל המוצר לא ייזום ולכן על הארכיטקט להציע ולקדם. לכאורה נראה שהם שונים משאר מאפייני האיכות מכיוון שהם \"פיצ\'רים נוספים למערכת\". בפועל – השקעה בכל מאפייני איכות (למשל Availability או Safety) דורשת עבודה וההבדל בין שלושת מאפייני איכות אלו לשאר היא קטנה משנדמה במבט ראשון.

    בחירת מאפייני איכות

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

    מכיוון שכל מאפייני האיכות הם \"דברים טובים\" האתגר הוא להבחין מה יותר חשוב ממה.

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


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


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

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

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

    במשך שנים, נושא חם בשוק ה IT היה בעיית ה Lock-In: בחרת ספק מסוים, לו יש API מסוימים. השתמשת בהם והיית מרוצה, אך ביום בו הספק מעלה מחירים / מחפף בשירות / קמים מתחרים עדיפים – \"אין לכם שום דרך לבצע שינוי\".
    האמירה של \"אין שום דרך\" היא אמירה לא מדויקת – אך מכיוון שהסיפור (אלמנטים טרגיים של בגידה?) הוא סיפור מוצלח – הוא הושרש והשאיר חותמו על אנשים רבים.

    אחד ה \"Best Practices\" שנבעו מכך הוא לכתוב קוד \"בלתי תלוי בספק (vendor)\" בכלל, ו\"בלתי תלוי בספק בסיס-הנתונים\" בפרט. עבדתם עם מערכת אורקל ומחר אתם רוצים לעבור ל MS-SQL? אין בעיה – מחליפים רק את ה \"connection string\" – והכל עובד.

    ראיתי כמה מערכות שנעשה בהן שיקול שכזה[ב]. האנשים המעורבים הרגישו שהם עושים \"הנדסת תוכנה טובה יותר\" והחליטו \"להקפיד ולכתוב קוד שלא תלוי בבסיס הנתונים\". בפועל:

    • באף אחת מהמערכות הללו לא החליפו בסיס נתונים, עד היום (עד כמה שידוע לי).
    • הצוות הקפיד להשתמש ב ANSI SQL – וכך התעלם מרוב היכולות של בסיס הנתונים. אי-השימוש ביכולות הקשה בצורה משמעותית על הפיתוח ועל שיפורי ביצועים.
    • בכמה פעמים, המוצר נזנח / נכתב מחדש – אך בסיס הנתונים נותר. כלומר: בסיס הנתונים היה חלק יציב יותר מהקוד שהשתמש בו.

    בפועל, ההחלטה המעשית הייתה לבחור במאפיין האיכות \"no DB vendor lock-in\", על פני \"Developability\" ועל פני \"Scalability\".

    רק להבהיר: אני מדבר על מקרה בו אתם מוכרים Appliance או Hosting. כאשר הלקוח צריך לטפל בבסיס נתונים בעצמו, ברור למדי שלחברות רבות יש העדפה ברורה איזה בסיס נתונים הם רוצים להתקין: אולי יש להן DBA מוכשר שמכיר אותו, אולי הן כבר ביצעו השקעה מסוימת בטכנולוגיה (כלי ניהול, אבטחה וכו\') ספציפית לספק בסיס-נתונים זה.
    מתן האופציה להתקין כל DB, עבור לקוחות רבים – יכולה להחשב כאיכות של Maintainability – כי אז הם יוכלו להתקין את בסיס הנתונים שהם מעדיפים.
    הבחירה של פלטפורמות ג\'אווה וNET. לבצע הפשטה שכזו (בעזרת ODBC ו JDBC) באה לתמוך במי שרוצה להשיג Maintainability.
    אם כל מה שאני שומר בבסיס הנתונים היא טבלה או 2 של נתונים פשוטים – אין לי רווח רב משימוש בבסיס נתונים ספציפי.


    בכל מקרה – אין פה תשובה נכונה או שגויה. עצם העניין הוא הבחינה המודעת של האלטרנטיבות. ההבנה שכתיבת קוד \"Database Agnostic\" הוא מאפיין איכות אפשרי שמגיע עם תג מחיר, ולא בהכרח \"הנדסת איכות טובה יותר\".
    כניסה לפרטים
    גפרור הוא מוצר דיי קטן. מערכת ERP היא גדולה יותר וכנראה שלא סביר להגדיר, באופן גורף, ש\"דיוק עדיף על נוחות\" או \"יכולת אחזור עדיפה על מהירות\" לגבי מערכת שכזו. הרי החלטה זו, יכולה להיות נכונה עבור חלק אחד במערכת – ושגויה עבור חלק אחר.


    דרך מומלצת 
    על מנת להשתמש במאפייני איכות בצורה יעילה כדאי לבחור כמה תסריטים עיקריים במוצר ולהדגיש אותם:
    \"בתחום ה X אנו מעדיפים d על c ומעדיפים b על a\".

    אפילו כדאי לצרף דוגמאות ספציפיות, מה שנקרא \"תסריט\":

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

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

    Reusability

    עוד תחום בו סקירת מאפייני האיכות יכול לסייע רבות הוא בהחלטה האם לעשות שימוש חוזר בקוד או \"איחוד\" של 2 מודולים בעלי פונקציונליות דומה.
    לעתים רבות יש לנו 2 ספריות / מודולים שרשימות היכולות שלהן, כ checklist היא דומה או אולי זהה. לדוגמה: ספרייה לשליחת הודעות דוא\"ל. שאלה מתבקשת היא \"מדוע אנו מתחזקים 2 ספריות שעושות אותו הדבר? האם זה לא בזבוז?\"
    לפני שאתם רצים לאחד את הקוד לספרייה יחידה, כדאי לבחון מהם מאפייני האיכות של כל ספרייה.
    אם ספרייה אחת מקפידה על reliability (מכיוון שהיא משמשת לשליחת התרעות מערכת חמורות), בעוד השנייה מתמקדת ה customizability (היכולת להגדיר הודעות דואר יפות ומותאמות-אישית) – ייתכן ואין סתירה וניתן לשלב אותן בהצלחה. כלומר, ספרייה אחת לא תוכל להחליף מייד את השנייה, אך הגיוני לקחת חלקים מכל ספרייה ולאחד אותן. חשוב להבין אלו הנחות נעשו על מנת לאפשר את מאפייני האיכות העיקריים של כ לספרייה ולראות שהם לא מתנגשים.
    לעומת זאת, אם אחת מתמקדת ב customizability והשנייה ב performance/scalability (שליחת אלפי הודעות בדקה) – קרוב לוודאי שטוב תעשו אם תשמרו אותן כ2 ספריות נפרדות.
    לעתים דיי קרובות, ספריות שאיחודן נראה כ no brainer במבט ראשון, מתגלות במהרה כלא סבירות לאיחוד לאחר שבוחנים את מאפייני האיכות שלהן.

    זכרו ש\"מאפייני איכות\" היא בעיקר דרך לחשוב על מערכת / על חלקיה. יש דרכים רבות לספק את הדרישות ה\"פונקציונליות\" של מוצר (\"כלי רכב בעל 4 מושבים, שמסיע אנשים ממקום למקום ויש לו מזגן ורדיו\") – אך יש הרבה פחות דרכים כאשר הגדרתם גם את מאפייני האיכות של המוצר.
    מאפייני איכות מסייעים להגדיר ארכיטקטורה עבור \"משהו\" – ולא ארכיטקטורה \"סתם\".
    זכרו שבארכיטקטורה, כמו בארכיטקטורה, \"קוד שעובד\" היא נקודת האפס. \"קוד שעובד יעיל[ג]\" הוא הדבר בעל המשמעות.

    נ.ב. – חלק מהספרות הפורמלית בנושא מתאר את \"מאפייני האיכות\" קצת אחרת – אני התייחסתי אליהן בצורה שהייתה שימושית עבורי והוכיחה את עצמה. חפשו בגוגל \"Quality Attributes\" ותוכלו למצוא חומר רב.







    [א] הגפרור שאנו מכירים.


    [ב] אני מכחיש בתוקף!, אך בפועל ייתכן שפעם אני הוא זה שיזם את המהלך.


    [ג] Effective, לא efficient.