Projekt Matplotlib

Ta strona zawiera szczegółowe informacje o projekcie polegającym na pisaniu tekstów technicznych, który został zaakceptowany w ramach Google Season of Docs.

Podsumowanie projektu

Organizacja open source:
Matplotlib
Pisarz techniczny:
brunobeltran
Nazwa projektu:
Poprawa wykrywalności funkcji dzięki ujednoliceniu dokumentacji typów „implicytywnych”
Długość projektu:
Długotrwałe (5 miesięcy)

Opis projektu

Motywacja

Wcześniej interfejs API matplotlib w dużej mierze polegał na łańcuchach znaków jako typach „implikowanych”. Poza naśladowaniem interfejsu API matlab te ciągi znaków parametrów umożliwiają użytkownikowi przekazywanie funkcji matplotlib wartości semantycznie bogatych jako argumenty bez konieczności importowania lub stosowania skomplikowanych prefiksów wartości enumeracji tylko po to, aby przekazać podstawowe opcje wykresu (np.plt.plot(x, y, linestyle='solid') jest łatwiejszy do wpisania i mniej zbędny niż np. plt.plot(x, y, linestyle=mpl.LineStyle.solid)).

Wiele z tych typów domyślnych ciągu jako listy zamieniono później na bardziej zaawansowane funkcje. Na przykład linestyle może być teraz ciągiem znaków lub 2-elementową parą uporządkowaną sekwencji, a MarkerStyle może być ciągiem znaków lub matplotlib.path.Path. Chociaż dzieje się tak w przypadku wielu typów niejawnych, według mojej wiedzy MarkStyle to jedyna klasa, która została uaktualniona do właściwej klasy Pythona.

Te niejawne typy nie są klasami, więc w Matplotlib musieliśmy wprowadzić własne rozwiązania do centralizacji dokumentacji i weryfikacji tych niejawnych typów (np. wzór interpolacji docstring.interpd.update w opisie funkcji i wzorzec weryfikatora cbook._check_in_list) zamiast korzystać ze standardowych narzędzi udostępnianych przez klasy Pythona (np. opisy funkcji i wzorzec validate-at-__init__).

Chociaż te rozwiązania sprawdzają się w naszym przypadku, brak wyraźnego miejsca w dokumentacji dotyczącej każdego typu domyślnego sprawia, że dokumentacja jest często trudna do znalezienia. Duże tabele dozwolonych wartości są powtarzane w dokumentacji, a w dokumentacji często brakuje wyraźnego określenia zakresu typu domyślnego. Na przykład w dokumentach plt.plot: w polu „Notes” znajdziesz opis metody stylizacji ciągów znaków, podobnej do formatu matlab, wzmianki o opcjach linestyle, color i markers. Istnieje znacznie więcej sposobów przekazywania tych 3 wartości, niż sugerują to sugerowanie, ale dla wielu użytkowników jest to jedyne źródło informacji o tym, jakie wartości są możliwe w przypadku tych opcji, dopóki nie natkną się na jeden z odpowiednich samouczków. Dołączyliśmy tabelę atrybutów Line2D, aby pokazać czytelnikowi, jakie ma możliwości sterowania działką. Mimo że wpis linestyle dobrze sprawdza się w połączeniu z Line2D.set_linestyle (wymagane są dwa kliknięcia), tam gdzie opisane są możliwe dane wejściowe, wpisy color i markers nie. color zawiera tylko link do strony Line2D.set_color, która nie informuje o tym, jakie dane wejściowe są nawet dozwolone.

Można argumentować, że można to naprawić, po prostu uporządkowując poszczególne opisy funkcji, które powodują problemy, ale problem jest niestety dużo bardziej systemowy. Jeśli nie będzie centralnego miejsca, w którym można znaleźć dokumentację, będzie coraz więcej kopii coraz bardziej obszernej dokumentacji, która będzie się powtarzać w miejscach, w których używane są te niejawne typy. W rezultacie początkujący użytkownicy będą mieli jeszcze większy problem z odnalezieniem potrzebnego parametru. Jednak obecny system, który zmusza użytkowników do stopniowego tworzenia modelu umysłowego każdego typu za pomocą przeglądania naszej dokumentacji w stylu wiki lub z przykładów w StackOverflow, również nie jest trwały.

Cel końcowy

W idealnej sytuacji każda wzmianka o typie domyślnym powinna zawierać link do jednej strony, na której opisane są wszystkie możliwe wartości tego typu, począwszy od najprostszych i najczęstszych do najbardziej zaawansowanych i specyficznych. Zamiast przeznaczać cenny obszar wizualny w dokumentacji interfejsu API na stopniowe wymienianie wszystkich możliwych typów danych dla danego parametru, możemy wykorzystać ten sam obszar na opis słowny tego, jaką abstrakcję funkcji wyświetlania ma kontrolować dany parametr.

Wracając do przykładu linestyle, w dokumentach LineCollection powinny się znaleźć te informacje:

  1. Link do kompletnych dokumentów dotyczących dozwolonych danych wejściowych (kombinacja tych, które znajdują się w Line2D.set_linestylesamouczku na temat stylu linii).
  2. Opis w prostych słowach, do czego służy dany parametr. Dla zaawansowanych użytkowników matplotlib jest to oczywiste z nazwy parametru, ale nowi użytkownicy mogą nie zdawać sobie z tego sprawy.

W rzeczywistych dokumentach LineCollection wygląda to tak: 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. """""" gdzie odwołanie do typu LineStyle jest rozwiązywane przez Sphinxa, aby wskazywać na jeden wiarygodny i pełny zestaw dokumentacji dotyczącej sposobu, w jaki Matplotlib traktuje style linii.

Zalety

Do zalet tego podejścia należą

  1. Ujawnienie w prostym tekście pełnego zakresu działania każdej funkcji (bez konieczności klikania).
  2. Uczynienie opcji domyślnej widoczną (bez kliknięć). Wyświetlanie opcji domyślnej często wystarczy, aby przypomnieć użytkownikom, którzy wracają do aplikacji.
  3. Przygotuj pełny opis „najczęstszych” i „najprostszych” opcji danego parametru, które są łatwo dostępne podczas przeglądania (za pomocą jednego kliknięcia).
  4. Ułatwienie odkrywania zaawansowanych funkcji i metod wprowadzania danych do tego stopnia, że wystarczy przewinąć w dół, aby wyświetlić bardziej zaawansowane opcje (nadal z jednym kliknięciem).
  5. Opracuj scentralizowaną strategię łączenia dokumentacji najwyższego poziomu „API” z odpowiednimi „samouczkami”.
  6. Unikaj tworzenia dużej liczby dokumentów API, ponieważ przeglądanie wielu możliwych opcji dla każdego parametru powoduje, że poszczególne opisy są niepraktyczne.

Inne zalety tego podejścia w porównaniu z obecnymi dokumentami:

  1. Dokumenty rzadziej się dezaktualizują ze względu na centralizację.
  2. Kanonizacja wielu „pośrednich standardów” matplotlib (takich jak „granice” i „zakresy”), których trzeba się obecnie nauczyć, odczytując kod.
  3. Proces ten miałby wskazywać problemy z spójnością interfejsu API w sposób, który ułatwia śledzenie ich za pomocą narzędzia do śledzenia problemów w GitHub, co ułatwiałoby nam ulepszanie interfejsu API.
  4. szybsze tworzenie dokumentów dzięki znacznemu zmniejszeniu ilości tekstu wymagającego przeanalizowania;

Implementacja

Opisane powyżej usprawnienia będą wymagały 2 głównych wysiłków, w ramach których nieoceniony będzie odpowiedni specjalista ds. technicznych. Pierwsza to utworzenie jednej scentralizowanej strony „samouczka” dla każdego typu niejawnych. W tym celu będziemy współpracować z głównym zespołem programistów, aby określić konkretną listę typów domyślnych, których dokumentacja byłaby przydatna dla użytkowników (zazwyczaj dlatego, że zawierają one potężne, ukryte funkcje naszej biblioteki, których dokumentacja jest obecnie dostępna tylko w trudnych do znalezienia samouczkach). Następnie dla każdego typu domyślnego połączę różne samouczki, dokumentację interfejsu API i strony z przykładami w jedno źródło dokumentacji, do którego można się odwoływać w dowolnym miejscu, w którym jest ono przywoływane.

Po utworzeniu scentralizowanej dokumentacji danego typu niejawnego rozpocznie się drugi główny wysiłek: zastąpienie obecnej dokumentacji API linkami do nowej dokumentacji w celu jak najprostszego sposobu korzystania z tej nowej dokumentacji zarówno dla osób korzystających z wbudowanego narzędzia help() w języku Python, jak i dla osób przeglądających naszą dokumentację online.

Dokładny format proponowanej tu dokumentacji może ulec zmianie w miarę rozwoju projektu. Współpracowaliśmy z głównym zespołem Matplotlib podczas ich cotygodniowych spotkań „dev calls”, aby osiągnąć konsensus, że zaproponowana tu strategia jest najbardziej praktycznym, przydatnym i technicznie wykonalnym podejściem do rozpoczęcia dokumentowania tych „typów domyślnych” (notatki z tych rozmów są dostępne na hackmd). W początkowych etapach tworzenia scentralizowanej dokumentacji dla każdego typu domyślnego użyję istniejącej infrastruktury samouczków, co pozwoli mi łatwo odwoływać się do tych stron bez konieczności tworzenia nowych publicznych klas (ponownie używając jako przykładu dokumentów 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`.
""""""

W przyszłości będziemy mogli w przyszłości łatwo zmienić sposób pisowni tych odwołań, gdy główny zespół programistów uzgodni najlepszą długoterminową strategię uwzględniania naszej nowej dokumentacji „typów” w rzetelnych klasach Pythona, na przykład tak jak zaproponowałam w artykule Propozycja ulepszenia w Matplotlib 30.

Na koniec przedstawiam wstępną listę typów niewypowiedzianych, które proponuję udokumentować w ramach 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

Bieżąca wersja tego dokumentu znajduje się w naszej dyskusji.