פרויקט Matplotlib

בדף הזה מופיעים הפרטים של פרויקט כתיבה טכנית שהתקבל בעונה של Docs ל-Google Docs.

סיכום הפרויקט

ארגון קוד פתוח:
Matplotlib
כותבים טכניים:
brunobeltran
שם הפרויקט:
שיפור יכולת הגילוי של תכונות באמצעות סטנדרטיזציה של תיעוד של סוגים 'משתמעים'
אורך הפרויקט:
Long running (5 months)

תיאור הפרויקט

למה בחרנו לעשות זאת?

בעבר, ה-API של matplotlib הסתמך במידה רבה על ""סוגים משתמעים"" של מחרוזת כ-enum. בנוסף לחיקוי של ה-API של matlab, מחרוזות הפרמטרים האלה מאפשרות למשתמש להעביר ערכים עשירים מבחינה סמנטית כארגומנטים לפונקציות של matplotlib, בלי צורך לייבא באופן מפורש או להוסיף תחילית מפורטת לערך enum בפועל, רק כדי להעביר אפשרויות תרשים בסיסיות (כלומר, קל יותר להקליד את הערך plt.plot(x, y, linestyle='solid') והוא פחות מיותר מאשר משהו כמו plt.plot(x, y, linestyle=mpl.LineStyle.solid)).

רבים מהסוגים המשתמעים מסוג 'מחרוזת כטיפוס' התפתחו מאז תכונות מתוחכמות יותר. לדוגמה, עכשיו אפשר להשתמש ב-linestyle כמחרוזת או כקבוצה של שתי רצפים, ואפשר להשתמש ב-MarkerStyle כמחרוזת או כ-matplotlib.path.Path. זה נכון לגבי סוגים משתמעים רבים, אבל MarkStyle הוא היחיד (למיטב ידיעתי) שקיבל סטטוס של שדרוג למחלקה מתאימה של Python.

מכיוון שהסוגים המשתמעים האלה הם לא כיתות בפני עצמן, בעבר היה צריך לפתח ב-Matplotlib פתרונות משלו כדי למרכז את המסמכים והאימות של הסוגים המשתמעים האלה (למשל, דפוס האינטרופולציה של docstring‏ docstring.interpd.update ודפוס המאמת cbook._check_in_list, בהתאמה) במקום להשתמש בכלי העבודה הרגילים שסופקו על ידי כיתות Python (למשל, docstrings ודפוס validate-at-__init__, בהתאמה).

הפתרונות האלה עזרו לנו מאוד, אבל בגלל שאין מיקום מפורש שבו מתועד כל סוג משתנה סמוי, לרוב קשה למצוא את המסמכים, טבלאות גדולות של ערכים מותרים חוזרות על עצמן במסמכים, ולרוב חסרה לגמרי הצהרה מפורשת על היקף של סוג משתנה סמוי. לדוגמה, במסמכי העזרה של plt.plot, בקטע Notes (הערות), בתיאור של שיטת הסטיילינג של מחרוזת הפורמט שדומה ל-Matlab, מופיעות האפשרויות linestyle,‏ color ו-markers. יש הרבה יותר דרכים להעביר את שלושת הערכים האלה ממה שצוין, אבל עבור משתמשים רבים, זה המקור היחיד להבנה של הערכים האפשריים לאפשרויות האלה, עד שהם נתקלים באחד מהמדריכים הרלוונטיים. הטבלה של המאפיינים Line2D כלולה כדי להראות לקורא אילו אפשרויות יש לו לשלוט בעלילת הסרט. עם זאת, בעוד שהרשומה linestyle מקשרת בצורה טובה אל Line2D.set_linestyle (נדרשים שני קליקים) שבו מתוארים הקלטים האפשריים, הרשומות color ו-markers לא עושות זאת. color פשוט מקשר ל-Line2D.set_color, בלי לתת שום אינטואיציה לגבי סוגי הקלט שמותר להזין.

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

יעד סופי

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

כדי להשתמש שוב בדוגמה של linestyle, מה שצריך להופיע במסמכים של LineCollection הוא רק:

  1. קישור למסמכים מלאים לגבי קלט מותאם (שילוב של המסמכים שמופיעים ב-Line2D.set_linestyle ובמדריך ל-linestyle).
  2. תיאור פשוט של המטרה של הפרמטר. למשתמשי matplotlib מתקדמים, זה ברור מהשם של הפרמטר, אבל למשתמשים חדשים זה לא תמיד ברור.

כך זה ייראה במסמכי העזרה של LineCollection: python """""" linestyles: `LineStyle` or list thereof, default: :rc:`lines.linestyle` ('-') A description of whether the stroke used to draw each line in the collection is dashed, dotted or solid, or some combination thereof. """""", שם הפניה לסוג LineStyle תטופל על ידי Sphinx כדי להפנות לקבוצה אחת, מהימנה ומלאה של מסמכי עזרה לגבי האופן שבו Matplotlib מטפלת בסגנונות קו.

יתרונות

בין התכונות החזקות של הגישה הזו:

  1. להציג את כל היכולות של כל פונקציה בטקסט פשוט (בלי צורך ללחוץ על שום דבר).
  2. הגדרת אפשרות ברירת המחדל כגלויה (ללא קליקים). לרוב, מספיק לראות את אפשרות ברירת המחדל כדי להריץ את הזיכרון של משתמשים חוזרים.
  3. תיאור מלא של האפשרויות ""הנפוצות"" ו ""הקלות"" ביותר של פרמטר שזמין בקלות בזמן הגלישה (בלחיצה אחת).
  4. הפוך את תהליך הגילוי של תכונות ושיטות קלט מתקדמות יותר לקל יותר כמו "גלילה למטה", כדי לראות אפשרויות מתקדמות יותר (עדיין בלחיצה אחת בלבד).
  5. מספקים אסטרטגיה מרוכזת לקישור מסמכי 'API' ברמה העליונה ל'מדריכים' הרלוונטיים.
  6. נמנעים מפיצוץ של API-doc, כי הסריקה בין האפשרויות הרבות של כל פרמטר גורמת לעומס על מחרוזות docstring נפרדות.

יתרונות נוספים של הגישה הזו על פני המסמכים הנוכחיים:

  1. הסיכוי שהמסמכים יהיו לא מעודכנים נמוך יותר בגלל ריכוז המידע.
  2. קנוניזציה של הרבה מ'סטנדרטים משתמעים' של matplotlib (כמו 'גבולות' לעומת 'היקף') שצריך ללמוד כרגע מקריאת הקוד.
  3. התהליך ידגיש בעיות בעקביות ב-API כך שיהיה קל יותר לעקוב אחרי הבעיות באמצעות הכלי למעקב אחרי בעיות ב-GitHub, וזה יעזור בתהליך שיפור ה-API.
  4. זמני יצירה מהירים יותר של מסמכים, בגלל הפחתה משמעותית בכמות הטקסט שצריך לנתח.

הטמעה

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

אחרי שנסיים לכתוב את המסמכים המרכזיים של סוג סמוי מסוים, נתחיל במאמץ העיקרי השני: החלפת מסמכי התיעוד הקיימים של ה-API בקישורים למסמכי התיעוד החדשים, במטרה להפוך את השימוש במסמכים החדשים לפשוט ככל האפשר, גם למי שמשתמש בכלי help() המובנה של Python וגם למי שגולל במסמכי התיעוד שלנו באינטרנט.

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

""""""
linestyles: LineStyle or list thereof, default: :rc:`lines.linestyle` ('-')
    A description of whether the stroke used to draw each line in the collection
    is dashed, dotted or solid, or some combination thereof. For a full
    description of possible LineStyle's, see :doc:`tutorials/types/linestyle`.
""""""

בהמשך, נוכל לשנות בקלות את האיות של ההפניות האלה אחרי שצוות הפיתוח הבסיסי יגיע להסכמה על האסטרטגיה הטובה ביותר לטווח הארוך לשילוב של התיעוד החדש של ""types"" בתוך כיתות Python אמיתיות, למשל כפי שהצעתי בהצעה לשיפור של Matplotlib 30.

לסיום, הרשימה המקדימת של סוגי הנתונים המשתמעים שאציע לתעד במהלך Google Season of Docs היא:

  1. capstyle
  2. joinstyle
  3. bounds
  4. extents
  5. linestyle
  6. colors/lists of colors
  7. colornorm/colormap
  8. tick formatters

גרסה עדכנית של המסמך הזה זמינה בפורום שלנו ב-Discourse.