Ta strona zawiera szczegółowe informacje na temat projektu technicznego przyjęta do programu Sezon Dokumentów Google.
Podsumowanie projektu
- Organizacja open source:
- Matplotlib
- Pisarz techniczny:
- brunobeltran
- Nazwa projektu:
- Poprawa wykrywalności funkcji przez standaryzację dokumentacji typów niejawnych
- Długość projektu:
- Długotrwałe (5 miesięcy)
Opis projektu
Motywacja
W przeszłości interfejs API matplotlib w dużej mierze opierał się na „ciągach pośrednich” typu „implicit type” („typy niejawne”). Ciągi parametrów, oprócz imitowania interfejsu API matlab, pozwalają użytkownikowi na przekazywanie wartości o dużej semantyce w postaci argumentów funkcji matplotlib bez konieczności importowania lub szczegółowego poprzedzania rzeczywistej wartości wyliczeniowej w celu przekazywania podstawowych opcji wykresu (np.plt.plot(x, y, linestyle='solid')
jest łatwiejszy do wpisania i mniej nadmiarowy niż np. plt.plot(x, y,
linestyle=mpl.LineStyle.solid)
).
Od tego czasu wiele z tych typów pośrednich typu „ciąg znaków jako wyliczenie” ewoluowało bardziej zaawansowane funkcje. Na przykład obiekt linestyle
może być ciągiem tekstowym lub 2 kropkami sekwencji, a element znaczniki Style może być teraz ciągiem tekstowym lub matplotlib.path.Path
. Choć dzieje się tak w przypadku wielu typów niejawnych, jako jedyny (o czym wie) jedyna dostępna w Pythonie klasa Pythona.
Ponieważ te typy niejawne nie są klasami własnymi, w Matplotlib występowały własne rozwiązania w celu scentralizowanej dokumentacji i weryfikacji typów niejawnych (np. wzorca interpolacji docstringu docstring.interpd.update
i wzorca walidatora cbook._check_in_list
), a nie standardowych łańcuchów narzędzi dostarczanych przez klasyfikujące wzorce (np. ciągi znaków w klasach prawidłowego poprawności__init__
).
Te rozwiązania się sprawdziły w naszym przypadku, ale brak wyraźnej lokalizacji, w której można by udokumentować każdy typ niejawny, oznacza to, że często trudno jest znaleźć odpowiednią dokumentację. W dokumentacji powtarzają się duże tabele dozwolonych wartości, a często w dokumentacji brakuje wyraźnego zakresu typu niejawnego. Zobacz dokumentację plt.plot
, na przykład w sekcji „Notes” opis metody stylu ciągu znaków formatu przypominającego matlab zawiera opcje linestyle
, color
i markers
. Istnieje wiele innych sposobów przekazywania tych 3 wartości, niż wskazujemy na to, ale dla wielu użytkowników jest to jedyne źródło wiedzy o wartościach dostępnych w przypadku tych opcji, dopóki nie natrafią na jeden z odpowiednich samouczków. Tabela atrybutów Line2D
ma na celu pokazanie czytelnikowi opcji kontroli fabuły. Mimo że wpis linestyle
dobrze sprawdza się jako połączenie z elementem Line2D.set_linestyle
(wymagane są 2 kliknięcia), gdy opisane są możliwe dane wejściowe, wpisy color
i markers
nie. color
po prostu łączy się z usługą Line2D.set_color
, która nie inspiruje użytkownika pod kątem dozwolonych rodzajów danych wejściowych.
Można by argumentować, że ten problem można rozwiązać, po prostu usuwając poszczególne ciągi w dokumencie, które powodują problemy, ale niestety jest to problem o wiele bardziej systemowy. Brak centralnego miejsca do przeszukiwania dokumentacji sprawia, że po prostu mamy więcej kopii coraz bardziej szczegółowej dokumentacji powtarzanej wszędzie tam, gdzie używany jest każdy z typów niejawnych, co utrudnia początkującym użytkownikom po prostu znalezienie potrzebnego parametru. Jednak obecny system, który zmusza użytkowników do stopniowego łączenia modeli myślowych każdego z nich, korzystając z opisanych w naszej dokumentacji stylów wiki oraz elementów z przykładów StackOverflow, również nie jest zrównoważony.
Cel końcowy
W idealnej sytuacji każda wzmianka o typie niejawnym powinna prowadzić do jednej strony, która zawiera opis wszystkich możliwych wartości, które może przyjąć, uporządkowana od najprostszej, najpowszechniejszej do najbardziej zaawansowanej lub ezoterycznej. Zamiast używać cennej przestrzeni wizualnej w głównej dokumentacji interfejsu API do szczegółowego wyliczania wszystkich możliwych typów danych wejściowych dla danego parametru, możemy użyć tego samego miejsca, aby w prosty sposób opisać, jaką abstrakcje nanoszenia ma sterować dany parametr.
Ponownie spójrzmy na przykład z tabelą linestyle
. Dokumenty LineCollection
powinny wyglądać tak:
- Link do pełnej dokumentacji dotyczącej dozwolonych danych wejściowych (kombinacji tych pochodzących z
Line2D.set_linestyle
i samouczka dotyczącego stylu linii). - Jasny opis celu, do którego służy dany parametr. W przypadku zaawansowanych użytkowników matplotlib jest to jasne na podstawie nazwy parametru, ale w przypadku nowych użytkowników nie musi tak być.
W rzeczywistych dokumentach LineCollection
wyglądałoby 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 Sphinx rozpoznałby odniesienie do typu LineStyle
, by wskazać pojedynczy, rzetelny i kompletny zestaw dokumentacji dotyczącej sposobu, w jaki Matplotlib traktuje style linii.
Zalety
Oto kilka zalet tego podejścia:
- Pełne obliczenie właściwości każdej funkcji w sposób oczywisty w postaci zwykłego tekstu (nie trzeba więc klikać żadnych kliknięć).
- Pokazywanie opcji domyślnej (bez kliknięć). Zauważenie opcji domyślnej często wystarcza, aby „wydobyć” z pamięci powracających użytkowników.
- Stwórz pełny opis „najczęstszych” i „najprostszych” opcji parametru, które są łatwo dostępne podczas przeglądania danych (jednym kliknięciem).
- Odkrywanie bardziej zaawansowanych funkcji i metod wprowadzania danych może być bardzo łatwe – wystarczy kliknąć „przewiń w dół”, aby zobaczyć bardziej zaawansowane opcje.
- Udostępnij scentralizowaną strategię łączenia dokumentów najwyższego poziomu dotyczących interfejsu API z odpowiednimi samouczkami.
- Unikaj eksplozji dokumentów w interfejsie API, ponieważ przeglądanie wielu możliwych opcji każdego z parametrów sprawia, że poszczególne ciągi dokumentów stają się nieporęczne.
Inne zalety tego podejścia w porównaniu z obecnymi dokumentami:
- Dokumenty rzadziej staną się nieaktualne dzięki centralizacji.
- Stosowanie kanonicznej liczby „dorozumianych standardów” (takich jak „granice” i „zakresy”) matplotlib, których należy się obecnie opanować poprzez odczytanie kodu.
- Proces ten wskazuje problemy ze spójnością interfejsu API w sposób, który można łatwiej śledzić za pomocą narzędzia do śledzenia problemów na GitHubie, co usprawnia proces ulepszania API.
- Szybsze tworzenie dokumentów ze względu na znaczne zmniejszenie ilości tekstu do przeanalizowania.
Implementacja
Opisane wyżej ulepszenia będą wymagały 2 dużych starań, w których bezcenny będzie cenny autor pracy technicznej. Pierwszym z nich jest utworzenie 1 scentralizowanej strony „tutorial” na każdy typ niejawny. Wymaga to współpracy z głównym zespołem programistów w celu opracowania konkretnej listy typów niejawnych, których dokumentacja będzie przydatna dla użytkowników (zwykle dlatego, że zawierają one zaawansowane, ukryte funkcje naszej biblioteki, której dokumentację można obecnie znaleźć tylko w samouczkach złożonych z trudnościami). W przypadku każdego typu niejawnego łączę różne odpowiednie samouczki, dokumenty API i przykładowe strony w jedno wiarygodne źródło dokumentacji, która może być połączona z dowolnymi odwołaniami do konkretnego typu.
Po zakończeniu scentralizowanej dokumentacji danego typu niejawnego rozpoczyna się drugi główny cel: zastąpienie dotychczasowej dokumentacji interfejsów API linkami do nowej dokumentacji w taki sposób, aby korzystanie z nowej dokumentacji było jak najprostsze zarówno dla użytkowników korzystających z wbudowanego narzędzia help()
w Pythonie, jak i dla osób przeglądających naszą dokumentację online.
Chociaż dokładny format proponowanej dokumentacji może się zmieniać w miarę rozwoju projektu, podczas cotygodniowych „rozmów z deweloperem” Matplotlib współpracowałem z podstawowym zespołem Matplotlib w celu ustalenia, że proponowana tu strategia jest najskuteczniejszym, przydatnym i technicznie możliwym rozwiązaniem do rozpoczęcia dokumentowania tych „typów” (dostępne są informacje na temat tych połączeń).
Na początkowych etapach tworzenia scentralizowanej dokumentacji dla każdego typu domyślnego będę korzystać z istniejącej infrastruktury „samouczki”, aby móc łatwo odwoływać się do tych stron w następujący sposób, bez konieczności tworzenia nowych klas publicznych (ponownie, na przykład z 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 moglibyśmy z łatwością zmienić pisownię tych odniesień, gdy główny zespół programistów ustali najlepszą długoterminową strategię włączania nowej dokumentacji „types” do rzetelnych klas Pythona, na przykład zaproponowanego przeze mnie w ramach propozycji rozszerzenia Matplotlib ">3030<br class="ph-1-1.
Na koniec wstępna lista rodzajów niejawnych, które proponuję udokumentować w tym sezonie Dokumentów Google, to:
capstyle
joinstyle
bounds
extents
linestyle
colors
/lists of colors
colornorm/colormap
tick formatters
Aktualizowaną wersję tego dokumentu można znaleźć na naszym dysku.