Dokumentacja na co i po co ?

0

Czytam sobie wasze posty i zastanawiam się do czego niby ma służyć dokumentacja . Przecież jeśli projekt jest dobrze napisany to wszystko wynika z nazw zmiennych i nazw klas. Np. taki c# wszystkie bilioteki są ładnie posegregowane do czego tutaj miała by być dokumentacja ?

0

Ja Ci tego nie wytłumaczę, bo nie potrafię, ale przyjdzie bswierczynski i opowie wszystko :)

Powiem Ci, że nie zawsze wszystko wynika z nazw zmiennych i nazw klas. Poza tym, lepiej zapisać co dana funkcja robi, do czego służy - wtedy widać od razu, nie trzeba się domyślać.

0

Ja znam tylko c# na średnim poziomie, ale funkcje raczej mają dość wyraźne nazwy np. Substring tego się po prostu nie da nie zrozumieć.

0

Ale w dokumentacji jest nie tylko opis co co robi, ale jeszcze jak tego używać i jak powiązać to z innymi funkcjami/klasami/strukturami.

0

Co robi ta metoda klasy BufferedImage?
int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
Bez zaglądania do dokumentacji.

Napiszesz coś większego niż hello world to zrozumiesz.

0
wpisałem nick napisał(a)

Co robi ta metoda klasy BufferedImage?
int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
Bez zaglądania do dokumentacji.

Napiszesz coś większego niż hello world to zrozumiesz.

Nie o to mi chodzi ale o to że albo nazwa tej funkcji jest zła a więc jest to błąd w programie a nie brak dokumentacji. Albo po prostu podałeś funkcje bez klasy np. Ekran.Pixel.GetRgb razem dało by faktycznie więcej informacji.

0

@kubARek
Uśmiałem się. Zobaczyłem sam temat i mówię "o, tutaj to od razu przejdę do pisania odpowiedzi". Patrzę, a tu Twój post -- prorok, czy jak? Dobrze, że nie zaznaczyłeś, czy moja odpowiedź będzie sensowna, to przynajmniej wiem, że nie zawiodę.

@StudentX:
Tak, dokumentacja jest potrzebna praktycznie zawsze gdy kod ma być używany przez kogoś, kto nie należał do ekipy programistów, którzy go stworzyli.

Niektóre metodologie programowania (np. słynne ostatnio programowanie zwinne, ang. agile) przywiązują do dokumentacji bardzo małą wagę. Praktycznie umożliwiają całkowite jej olanie na rzecz innych, ważniejszych wg nich rzeczy. Jednocześnie nawet te metodologie nie mówią, że dokumentacja jest zła. Wg nich fajnie, gdy jest, ale gdy jej nie ma -- trudno.

Ale trzeba zaznaczyć, że takie programowanie zwinne stworzone jest z myślą o sytuacjach, w których kod pisze mała grupa osób. Oni znają mniej więcej cały kod, a swój moduł znają szczegółowo. W razie (rzadkich) wątpliwości, mogą zapytać kumpla z teamu. I wszystko gra.

Gdy jednak piszesz kod, który będzie używany przez kogoś innego, to dokumentacja jest już "bardzo mile widziana" (a jej brak jest bardzo niemile widziany).

Pamiętaj, że kod "wewnętrzny" nie zawsze jest dostępny. Gdy tworzysz bibliotekę, to nie musisz dostarczać jej źródeł. Wystarczą same binarki. Użytkownik Twojej biblioteki dysponuje więc tylko sygnaturami metod (ogólnie: "obiektów") i nie widzi ich wewnętrznego kodu.

I jak teraz przekażesz, że funkcja indexOf zwraca -1, gdy niczego nie znajdzie? Oczywiste? Cóż, w takim języku jak PHP niektóre tego typu funkcje w momencie niepowodzenia zwracają nie -1, tylko FALSE!

Podobnie z parametrami. Nawet w języku o silnej typizacji sam nagłówek funkcji nie przekaże wszystkiego. Przykład:

// pseudokod!
int String::indexOf(string search, int fromIndex = 0)

Okay, wszystko jasne, nie? Jeśli w bieżącym (this) łańcuchu znajduje się podłańcuch search, to funkcja zwraca numer znaku, od którego się zaczyna. Można się domyślić, że w razie gdy łańcucha nie ma, to zwraca -1, bo taka konwencja. No i widać, że wyszukiwanie rozpoczyna się od znaku o numerze fromIndex. Okay. Ale nie domyślisz się już, że gdy podasz ujemny fromIndex, to wyszukiwanie zacznie się fromIndex znaków przed końcem stringu! Czyli jeśli podasz -5, to sprawdzone zostanie tylko 5 ostatnich znaków.

Albo funkcja sort, która sortuje tablicę zgodnie z podanym kryterium porównawczym. Kryterium porównawczym jest funkcja zwracająca int, a przyjmująca dwa porównywane elementy. Pewnie, być może ktoś się domyśli, że funkcja ta powinna zwracać wartości jak strcmp, ale jak to tak naprawdę miało być? Gdy pierwszy argument ma być przed drugim, to trzeba było zwrócić liczbę dodatnią, czy ujemną?

Nic nie stoi na przeszkodzie, by podobnego wzorca w zupełnie innym kontekście, który nie będzie pasował do strcmp. I wtedy trzeba to opisać w dokumentacji.

Przeglądałeś np. dokumentację biblioteki standardowej Javy? Nazewnictwo jest przeważnie całkiem niezłe, ale czy po przeczytaniu sygnatur każdej klasy i metody od razu wiesz, do czego to w ogóle służy?

Nawet mając kod źródłowy aplikacji nie jest tak, że można bez problemu go odczytać i zrozumieć. I że można to zrobić tak samo szybko, jak szybko przegląda się dokumentację.

Jest jeszcze kwestia dokumentacji wewnętrznej. Czyli komentarzy do implementacji. Tych małych wyjaśnień stojących przy niektórych linijkach kodu. To jest kretyński komentarz:

i++; // inkrementacja i

On tylko szkodzi. Przecież to widać! Komentarze wewnętrzne nie mają opisywać tego, co widać wyraźnie w kodzie, tylko wyjaśniać niejasności i zawiłości.

// przeskakujemy jeden znak, bo poprzedni
// znak rozpoczął sekwencję ucieczki
charIndex++;
0

Napisz jeszcze raz, bo kompletnie nie rozumiem sensu powyższego posta.

0

Powyższa wypowiedź skierowana jest oczywiście do Studentx'a.

0
bswierczynski napisał(a)

@kubARek
Uśmiałem się. Zobaczyłem sam temat i mówię "o, tutaj to od razu przejdę do pisania odpowiedzi". Patrzę, a tu Twój post -- prorok, czy jak? Dobrze, że nie zaznaczyłeś, czy moja odpowiedź będzie sensowna, to przynajmniej wiem, że nie zawiodę.

@StudentX:
Tak, dokumentacja jest potrzebna praktycznie zawsze gdy kod ma być używany przez kogoś, kto nie należał do ekipy programistów, którzy go stworzyli.

Niektóre metodologie programowania (np. słynne ostatnio programowanie zwinne, ang. agile) przywiązują do dokumentacji bardzo małą wagę. Praktycznie umożliwiają całkowite jej olanie na rzecz innych, ważniejszych wg nich rzeczy. Jednocześnie nawet te metodologie nie mówią, że dokumentacja jest zła. Wg nich fajnie, gdy jest, ale gdy jej nie ma -- trudno.

Ale trzeba zaznaczyć, że takie programowanie zwinne stworzone jest z myślą o sytuacjach, w których kod pisze mała grupa osób. Oni znają mniej więcej cały kod, a swój moduł znają szczegółowo. W razie (rzadkich) wątpliwości, mogą zapytać kumpla z teamu. I wszystko gra.

Gdy jednak piszesz kod, który będzie używany przez kogoś innego, to dokumentacja jest już "bardzo mile widziana" (a jej brak jest bardzo niemile widziany).

Pamiętaj, że kod "wewnętrzny" nie zawsze jest dostępny. Gdy tworzysz bibliotekę, to nie musisz dostarczać jej źródeł. Wystarczą same binarki. Użytkownik Twojej biblioteki dysponuje więc tylko sygnaturami metod (ogólnie: "obiektów") i nie widzi ich wewnętrznego kodu.

I jak teraz przekażesz, że funkcja indexOf zwraca -1, gdy niczego nie znajdzie? Oczywiste? Cóż, w takim języku jak PHP niektóre tego typu funkcje w momencie niepowodzenia zwracają nie -1, tylko FALSE!

Podobnie z parametrami. Nawet w języku o silnej typizacji sam nagłówek funkcji nie przekaże wszystkiego. Przykład:

// pseudokod!
int String::indexOf(string search, int fromIndex = 0)

> Okay, wszystko jasne, nie? Jeśli w bieżącym (this) łańcuchu znajduje się podłańcuch search, to funkcja zwraca numer znaku, od którego się zaczyna. Można się domyślić, że w razie gdy łańcucha nie ma, to zwraca -1, bo taka konwencja. No i widać, że wyszukiwanie rozpoczyna się od znaku o numerze fromIndex. Okay. Ale nie domyślisz się już, że gdy podasz ujemny fromIndex, to wyszukiwanie zacznie się fromIndex znaków przed *końcem* stringu! Czyli jeśli podasz -5, to sprawdzone zostanie tylko 5 ostatnich znaków.
> 
> Albo funkcja sort, która sortuje tablicę zgodnie z podanym kryterium porównawczym. Kryterium porównawczym jest funkcja zwracająca int, a przyjmująca dwa porównywane elementy. Pewnie, być może ktoś się domyśli, że funkcja ta powinna zwracać wartości jak strcmp, ale jak to tak naprawdę miało być? Gdy pierwszy argument ma być przed drugim, to trzeba było zwrócić liczbę dodatnią, czy ujemną? 
> 
> Nic nie stoi na przeszkodzie, by podobnego wzorca w zupełnie innym kontekście, który nie będzie pasował do strcmp. I wtedy trzeba to opisać w dokumentacji.
> 
> Przeglądałeś np. dokumentację biblioteki standardowej Javy? Nazewnictwo jest przeważnie całkiem niezłe, ale czy po przeczytaniu sygnatur każdej klasy i metody od razu wiesz, do czego to w ogóle służy?
> 
> Nawet mając kod źródłowy aplikacji nie jest tak, że można bez problemu go odczytać i zrozumieć. I że można to zrobić tak samo szybko, jak szybko przegląda się dokumentację.
> 
> Jest jeszcze kwestia dokumentacji wewnętrznej. Czyli komentarzy do implementacji. Tych małych wyjaśnień stojących przy niektórych linijkach kodu. To jest kretyński komentarz:
> 
> 
```cpp
i++; // inkrementacja i

On tylko szkodzi. Przecież to widać! Komentarze wewnętrzne nie mają opisywać tego, co widać wyraźnie w kodzie, tylko wyjaśniać niejasności i zawiłości.

// przeskakujemy jeden znak, bo poprzedni
// znak rozpoczął sekwencję ucieczki
charIndex++;

Zrobiło się trochę jaśniej. Chodzi mi TYLKO o dokumentacje zewnętrzną. Wewnętrzną rozumiem - jest potrzebna. Np. opis algorytmu.

Co do twojej wypowiedzi:
Chodzi ci o to że czasem niektóre zmienne i typy zwracane mogą mieć różne znaczenia i owszem tu faktycznie musze się z tobą zgodzić. Ale przejdźmy jeszcze wyżej do dokumentacji jeszcze bardziej ogólnej - możesz coś o niej powiedzieć ? Czy może takiej nie ma ? Klasy przecież nie mogą być różnie interpretowane, tak jak interfejsy zresztą.

Poza tym co uważasz za DOBRĄ dokumentacje może jakiś link ?

0

javadoc ;)

0
Studentx napisał(a)

Ale przejdźmy jeszcze wyżej do dokumentacji jeszcze bardziej ogólnej - możesz coś o niej powiedzieć ? Czy może takiej nie ma ? Klasy przecież nie mogą być różnie interpretowane, tak jak interfejsy zresztą.

Jasne, że jest taka dokumentacja. Można za taką uznać umieszczony zupełnie poza kodem (tzn. nawet nie w "javadocu" dla danego języka) opis architektury całej aplikacji. Opis słowny, to raz. A dwa -- wszystkie te diagramy, których nigdy nie chce nam się robić, a które wbijali nam do głów na Inżynierii oprogramowania. Taki diagram klas -- na pewno jest położony "wyżej" niż dokumentacja poszczególnych klas. Są też inne diagramy, np. diagram przypadków użycia. Też ogólny i abstrakcyjny.

Ja lubię też coś takiego jak opis pliku. Jeśli stosujesz zasadę "jeden plik -- jedna klasa" to jest to równoważne z opisem klasy. Przeglądając tak na luzie kod źródłowy jakiejś opensourcowej aplikacji często na początku po prostu skaczę sobie po plikach. Fajnie, gdy w każdym jest napisane parę słów o tym, co właśnie otworzyłem.

Kolejnym poziomem dokumentacji są po prostu... tutoriale. Zwykłe "how to". One odpowiadają zwykle na pytanie:

"Mam taki a taki problem/chcę zrobić to i to. Jak to najlepiej zrobić przy pomocy tej biblioteki?"

Jeśli tutoriale napisane są porządnie i zaadresowane są do dobrych programistów, to właśnie od nich można zacząć zapoznawanie się z biblioteką. Tutoriale zwykle są przydatne dla newbies, ale jeśli piszą je twórcy biblioteki (ogólnie: aplikacji) i adresują je do zawodowych koderów, którzy dopiero zaczynają przygodę z danym jej fragmentem, to też sprawdzają się znakomicie.

Taki tutorial podpowiada Ci choćby klasy, których powinieneś użyć by z pomocą biblioteki wykonać żądaną czynność. Normalny schemat działania jest taki, że zaczynasz od nich, a z nich przeskakujesz do specyfikacji poszczególnych klas.

Jest jeszcze jeden warty wzmianki sposób dokumentacji, choć nie jest aż tak ogólny. Testy jednostkowe. To naprawdę wspaniałe narzędzie, gdy jest dobrze użyte. Nie tylko dba o jakość kodu i utrzymuje licznik bugów na stosunkowo niskim poziomie, ale jeszcze samo w sobie jest dokumentacją. Zawsze aktualną, bo w razie jakichś większych zmian test po prostu zawodzi i programista musi go uaktualnić.

Dodam jeszcze, że w językach takich jak JavaScript dokumentacja jest niezbędna. To język bardzo elastyczny i dynamiczny, o słabej typizacji. Programowanie funkcyjne jest tam na porządku dziennym. Widzisz np. takie coś:

this.each = function(callback) {
  // ...
};

Sama sygnatura metody each daje Ci bardzo mało. Masz jedynie informacje, że bieżący obiekt jest jakimś kontenerem, a funkcja each wykonuje na każdym jego elemencie funkcję callback. Ale ze względu na cechy JavaScriptu sama sygnatura nie odpowiada na poniższe pytania:
-Jakie parametry otrzymuje funkcja callback? Na pewno bieżący element, ale czy również indeks tego elementu? A jeśli oba parametry, to w jakiej kolejności?
-Jak zostaje ustawiony kontekst (this) funkcji callback?
-Co powinna zwrócić funkcja callback? Czy w ogóle powinna zwrócić jakąś wartość?
-Czy jest możliwość, by z poziomu funkcji callback przerwać wykonywanie tego (pseudo)foreacha i nie sprawdzać kolejnych elementów?

Podam Ci jeszcze przykład z życia. Akurat napisany w JavaScripcie, ale język tutaj nie ma wielkiego znaczenia. Napisałem "klasę" (konstruktor -- w JavaScripcie nie ma klas) o nazwie bodajże SafePropertyAlterer, czy coś w tym stylu.

Kretyńska nazwa, nie? Jakże ogólna i nic nie mówiąca!

Ale klasa miała ogólne działanie. Cała aplikacja oparta była na architekturze wtyczek (pluginów). Zgodnie z zasadą luźnych powiązań, jedna wtyczka nie musiała nic wiedzieć o istnieniu drugiej. Jednak dwie wtyczki mogły manipulować jednocześnie tym samym obiektem. JavaScript jest dynamiczny, więc jakaś wtyczka mogła chcieć na chwilę zmienić jakiś zewnętrzny dla niej obiekt, a potem -- z grzeczności dla innych wtyczek -- cofnąć zmiany. Problem w tym, że inna wtyczka mogła również w międzyczasie zażądać własnych zmian. Nie będę się rozpisywał czemu, ale ciąg zdarzeń zmień()/przywróć() mógł być w sumie arbitralny i to powodowało, że gdy wtyczka chciała na chwilę zmienić własność o nazwie ppp, to nie mogła po prostu robić czegoś takiego:

var saved_ppp = obiekt.ppp;
obiekt.ppp = new_ppp;

// korzystaj z nowego obiekt.ppp
// ...

// przywróć poprzednią wartość:
obiekt.ppp = saved_ppp;

To nie działało, bo w międzyczasie mogło się okazać, że zapamiętana wartość saved_ppp była już nieaktualna.

Hermetyzacja nic tu nie mogła pomóc, bo zmieniana własność mogła należeć do drzewa dokumentu, a tego nie jestem w stanie w JavaScripcie ochronić.

No więc napisałem klasę SafePropertyAlterer, która pozwalała na bezpieczną zmianę własności, a potem jej bezpieczne przywracanie (gdy save własności był nieaktualny, to nie był przywracany). O tak:

var alterer = obiekt.propertyAlterer();
var ppp_save = alterer.alter('ppp', new_ppp);

// korzystaj z obiekt.ppp
// ...

// przywróć
alterer.restore(ppp_save);

A weź tak traf na taką klasę "SafePropertyAlterer" bez dokumentacji i bez opisu. Programistyczny WTF? Po co to? Jak tego używać? Po co tego używać?

Programiści wtyczek przecież nie musieli sobie zdawać sprawy z istnienia problemu "równoległego" żonglowania własnościami obiektu. W bodaj wszystkich bibliotekach problem ten jest olany.

Może ta klasa to jest WTF. Nie wiem, czasem na pewno tworzę WTF-y. Może mogłem to zaprojektować jakoś jaśniej i lepiej, ale do tej pory nic lepszego nie przyszło mi do głowy.

Tak czy siak, gdy pokazywałem ludziom dokumentację, to rozumieli zarówno istotę problemu, jak i potrzebę jego rozwiązania. Bez dokumentacji wątpię, by w ogóle rozpoznali problem.

edit: Przepraszam, że zapomniałem podać linku do dobrej dokumentacji. Wiesz, trudno takie coś wymyślić. Żadna dokumentacja nie jest idealna. Jedna ma lepsze to, inna tamto.

Dokumentacja Javy wydawała mi się IIRC całkiem niezła i kompletna, choć już jakiś czas jej nie używałem tak bardziej hardcorowo. Praktycznych przykładów, np. dotyczących GUI (swing/awt) szukałem jednak w innych miejscach.

Jeśli chodzi o JavaScript to mówią, że jQuery ma dobrą. Ale mi np. sam interfejs i grzebanie w niej nie pasuje, choć gdy już trafię na co trzeba, to jest to raczej dobrze opisane.

Czasem doceniam też dokumentację PHP. Tak, język jest "bloated" i strasznie tego nie lubię, a dokumentacja jest dość -- znowu muszę użyć brzydkiego, angielskiego słowa -- "casualowa". Czyli, tak jak język, sprawia wrażenie, że jest robiona na pałę. Ale dzięki temu, że PHP jest tak popularne i że dokumentacja jest w sporej części nastawiona na noobów, tłumaczy wszystko łopatologicznie i zwraca uwagę na pułapki i dobry styl programowania (częściej: przestrzega przed złym stylem). Właśnie to ostatnie mi się podoba.

Przyszły mi do głowy przykłady z branży webowej, bo akurat ostatnio akurat w niej robię. Także wcale się nie zdziwię, jeśli zapomniałem o czymś ważnym, a zupełnie z innej sekcji.

0

Dzięki wielkie za wyjaśnienie. Myślę że to mniej więcej sprawę dokumentacji wyjaśnia. Nie da się po prostu opisać działania klasy w postaci pojedynczej nazwy a zespołu klas tym bardziej.

0

Jednocześnie trzeba pamiętać o tym, o czym mówiłeś wcześniej: sam kod powinien o sobie sporo mówić, być jasny i czytelny. To przecież święta prawda, a fakt, że dokumentacja jest ważna wcale jej nie przeczy.

Nie piszę, że kod powinien o sobie mówić "zawsze wszystko", bo się z tym nie zgadzam. Jestem np. przeciwko notacji węgierskiej, szczególnie w językach o silnej typizacji. Zbyt szczegółowe nazwy czyta się IMO za trudno. Uważam, że nazwy części interfejsu (publicznych pól, metod) powinny być bardziej opisowe, ale już nazwy zmiennych lokalnych powinny być raczej zwięźlejsze. Z drugiej strony, używanie wszędzie pojedynczych literek też jest be.

Może dlatego to takie trudne, a naprawdę czytelny kod często jest stosunkowo niepozorny. Nic w nim nie przeszkadza w czytaniu, a jednocześnie masz pod ręką wszystkie najważniejsze informacje.

Nie można pozwolić sobie na to, by pisać niezrozumiały kod i zawsze odsyłać ludzi do dokumentacji. Ale nie wszystko da się przekazać samym kodem. Nie wszystko powinno się nim przekazać, np. w przykładzie z indexOf takie nazwanie drugiego parametru jest bezsensowne:

// (złamię linię, żeby nie rozwalić layoutu forum)
indexOf(szukanyPodłańcuch,
        indeksZnakuOdKtóregoZacznieSięPrzeszukiwanie
        _UjemnaWartośćPowodujeSprawdzenieTyluOstatnichZnaków)

(a można by jeszcze dodać, że indeksy zaczynamy od 0!)

Lepiej użyć krótszego indexOf(search, fromIndex) lub indexOf(search, position), która najważniejsze rzeczy podsumowuje jasno i zwięźle. A ten dość istotny, ale drugorzędny niuans z indeksem napisać w dokumentacji.

0
Studentx napisał(a)

Czytam sobie wasze posty i zastanawiam się do czego niby ma służyć dokumentacja . Przecież jeśli projekt jest dobrze napisany to wszystko wynika z nazw zmiennych i nazw klas. Np. taki c# wszystkie bilioteki są ładnie posegregowane do czego tutaj miała by być dokumentacja ?

napisz projekt na 100kloc, pozniej daj go innemu programiscie, powodzenia jak nie ma dokumentacji...

1 użytkowników online, w tym zalogowanych: 0, gości: 1