Prawdziwi programiści używają debuggerów? [Zamknięte]


15

Jeśli doświadczeni programiści faktycznie używają debuggerów, a jeśli tak, to w jakich okolicznościach. Chociaż w odpowiedzi na to pytanie powiedziałem „miesiące” temu prawdopodobnie miałem na myśli „lata” - tak naprawdę nie używam debugera. Więc moje konkretne pytanie, na które można odpowiedzieć, brzmi: w jakich okolicznościach jako doświadczony programista używałbyś debugera?


14
To tak, jakby zapytać, czy doświadczeni programiści używają klawiatury ... Nie rozumiem, co ma z tym wspólnego doświadczenie - czy uważasz, że są Bogami i od samego początku tworzą doskonale działający kod? A nawet jeśli tak, co to oznacza dla Ciebie - czy przestaniesz używać debugera, kiedy będziesz potrzebować, i powiedz: „Nie używam debugera, więc jestem programistą” ... :) BTW. Wątpię, czy jakikolwiek profesjonalista odpowie na takie pytanie ...

3
@Wooble: podstawowe pytanie „czy doświadczeni programiści używają debuggerów” jest dobre. Zaskoczyło mnie to, że rozpoczęła mini świętą wojnę.
Kevin

19
Prawdziwi programiści używają oczywiście motyli
Rein Henrichs

4
Większość istniejących debuggerów jest staromodna, ma kiepskie interfejsy i wymaga od programisty znajomości i zrozumienia pojęć i paradygmatów, które są trudne do opanowania, a obecnie niesprawiedliwe jest oczekiwanie, że większość programistów będzie używać lub wiedzieć. W rezultacie większość współczesnych, doświadczonych programistów dokłada wszelkich starań, aby nauczyć się umiejętności potrzebnych do pisania kodu, który rzadko musi być debugowany w debugerze, aby uniknąć bólu związanego z tym doświadczeniem. Tak więc „tak używają” i „tak mało, jak to możliwe”
blueberryfields

7
Doświadczeni programiści, którzy „nie używają debuggerów” prawdopodobnie myślą w kategoriach gdb / SoftICE i nigdy nie używali rzeczywistego zintegrowanego debuggera (i prawdopodobnie nie używają IDE do tego celu). Są tak daleko w tyle za czasami, które są bolesne.
BlueRaja - Danny Pflughoeft

Odpowiedzi:


44

Powiedziałbym, że nie używanie debuggera jest oznaką braku doświadczenia. Przechodzenie między wierszami kodu jest najlepszym sposobem na śledzenie przebiegu wykonywania.


30
dziwne, że po ponad 30 latach programowania w asemblerze, fortranie, C, C ++ itd. itd. nie mam ochoty go używać.

59
Robienie czegoś przez długi czas niekoniecznie czyni cię w tym dobrym.
ceejayoz

31
Brak możliwości korzystania z debugera jest oznaką braku doświadczenia. Zrozumienie przepływu programu przez samo czytanie kodu nie jest. Oczywiście doświadczeni programiści będą od czasu do czasu potrzebowali debuggera, ale jeśli potrafisz odczytać kod, nie ma takiej potrzeby i nie przyspieszy to również procesu debugowania.
GolezTrol

10
@Karl Bielefeldt: Pozwól mi wymienić kilka znanych przykładów programistów, którzy nie używają debugerów do debugowania. Linus Torvalds, autor systemu Linux. Larry Wall, autor Perla. Wystarczająco skomplikowane oprogramowanie dla Ciebie?
btilly

9
@ Neil: ile czasu spędzasz na pracy nad własnym kodem, a ile na utrzymywaniu kodu napisanego przez innych ludzi? A w szczególności, ile utrzymywania kodu napisanego przez inne osoby, które nigdy nie powinny były mieć dostępu w pobliżu języka programowania?
Carson63000,

28

Często używam debuggera, ponieważ pracuję na dużym systemie i dlatego jestem do kitu. http://steve-yegge.blogspot.com/2007/06/rich-programmer-food.html

Bez względu na to, jak krótki i często czyta się twój kod, zawsze będzie możliwość, że będzie zawierał błędy. http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html

Błędem jest człowiek i nigdy nie można udowodnić, że program jest poprawny, więc dlaczego nie skorzystać z narzędzi takich jak debugger / automatyczne testowanie, aby pomóc sobie w tym trudnym biznesie?

Jeśli kod jest wystarczająco krótki, zrobią to proste testy. Ponadto, jeśli jest krótki i znasz naturę błędu, odczyt kodu może wystarczyć. Jednak gdy baza kodu jest duża, obejmuje kilka języków zmieszanych razem, plus 3 poziomy, wtedy po prostu musisz mieć dobry zasięg testowy na wielu poziomach oraz bardzo dobry debugger - w przeciwnym razie będziesz marnować dużo czasu.

Kiedy więc nie potrzebuję debuggera?

Nie jestem najmądrzejszym programistą ani najbardziej doświadczonym, ale czasami nie muszę korzystać z debuggera. To jest, kiedy:

  • Kod jest mój lub dobrze napisany ORAZ
  • Jest napisany w czytelnym języku ORAZ
  • Ogólny projekt jest niewielki.

Kiedy mocno polegam na debugerze?

  • Krótka odpowiedź: często .
  • Gdy aplikacja ulega awarii. Zwłaszcza gdy jest wdrożony. Zainstalowanie VS2010 na tym komputerze może odróżnić „Nieznany błąd” i FileNotFoundException.
  • Gdy biblioteka innej firmy ulega awarii lub zachowuje się nieprawidłowo.
  • Gdy kod jest źle napisany. Zwłaszcza jeśli w ciągu ostatnich 10 lat ten sam plik został dotknięty przez 10 różnych osób, z których 7 nie jest już związanych z firmą.
  • Gdy projekt jest duży
  • Gdy kod jest raczej monolityczny.
  • Gdy w grę wchodzi kilka warstw (GUI, SQL, BL).

Zauważ, że „debugger” może odnosić się do więcej niż jednego narzędzia. Używam debugera Visual Studio, debugera SQL (głównie dla przechowywanych proc) i profilera SQL (aby dowiedzieć się, które SP są wywoływane). Czy potrzebowałbym narzędzi tego kalibru, pisałem szybki skrypt Pythona sysadmin? Nie. Jeśli stworzę własne małe narzędzie oparte na GUI? Zależy. Jeśli to jest .Net WinForms - prawdopodobnie nie. Jeśli jest to WPF - tak.

Co w ogóle definiuje „prawdziwego” programistę? Który jest szybki? bywały? Czy jest dobry w algorytmach? Pisze dobrą dokumentację? Kiedy dokładnie jeden absolwent tego nowego tytułu? Kiedy ktoś przekracza magiczną linię?

Powiedziałbym, że programista, który nie pobrudził sobie rąk w ciągu trwającego ponad 100 osobolat wysiłku, nie miał szansy na pokorę złożonością i własnymi ograniczeniami (a także sfrustrowaną jakością kodu).

Osobiście staram się używać najlepszego dostępnego dla mnie debuggera i często go używam. Jeśli zadanie jest wystarczająco proste i nie wymaga debuggera - wtedy go nie używam. Nie trzeba długo zastanawiać się, czy go potrzebuję, czy nie.

...

Teoretycznie mogłem tak długo czytać bazę kodu, że po prostu ją otrzymałem. Jednak praktyczne podejście działa najlepiej, a ponadto często chcę ponownie napisać ten głupi kod, który widzę. Niestety oczyszczenie bazy kodu, w której się znajduję, zajęłoby mi ponad 10 lat. Używanie debugera to oczywisty pierwszy krok. Dopiero gdy dowiem się, który z 5 milionów wierszy kodu działa w górę, zeskanowałbym plik w górę i w dół, aby dowiedzieć się, co robi ta klasa.


+1, doskonała odpowiedź, w szczególności zgadzam się z aspektem „gdy w grę wchodzi kilka poziomów”, o którym rzadko wspominają „poprostu przeczytaj kod i znajdź błąd”.
Carson63000,

Cieszę się, że mogłeś przeczytać całość.
Job

+1 za świetną odpowiedź i zbadanie definicji „prawdziwego programisty”. Użycie tego wyrażenia sprawiło, że OP był chytry, interesujący i potencjalnie zapalny (z powodu poniżających implikacji lub insynuacji).
Smandoli

1
„nigdy nie można udowodnić, że program jest poprawny” To nieprawda.
GManNickG

1
@GMan, proszę rozwinąć swoje oświadczenie. Jak się dowiedziałem, wiele wcześniejszych prób udowodnienia poprawności krótkiego fragmentu kodu dla określonego języka nie powiodło się, np. Znaleziono kilka błędów po zakończeniu sprawdzania (przez profesora specjalizującego się w takich dowodach). Przypuszczam, że niektóre bardzo trywialne programy mogą być poprawne. Jestem ciekawy, jak mogę się tu dowiedzieć.
Job

17

„Nie lubię debuggerów. Nigdy nie, prawdopodobnie nigdy nie będzie.” - Linus Torvalds

Z drugiej strony nie ma konta Stack Overflow, więc nie jestem pewien, czy jesteś zainteresowany jego opinią :)


3
Niewielu z nas to Linus Torvalds, dla reszty z nas zwykłych ludzi potrzebujemy debuggera.
Nodey The Node Guy

7
jądra nie skłaniają się dobrze do debuggerów.

7
Tak, programowanie jądra to inne pole niż programowanie w przestrzeni użytkownika. Zwykle nie zgadzam się z opiniami Linusa dotyczącymi przestrzeni użytkownika, ale są one zdecydowanie godne szacunku, gdy mamy do czynienia z przestrzenią jądra.
alternatywnie

16
„Nie lubię debugerów” nie znaczy „Nie używam debugerów”. To, co naprawdę powiedział Linus, brzmiało: „Nie lubię debuggerów. Nigdy tego nie zrobiłem, prawdopodobnie nigdy. Nie używam gdb przez cały czas, ale zwykle używam go nie jako debuggera, ale jako deasemblera sterydów, które można zaprogramować”. (Wiem, że niektórzy spróbują to zmienić, co oznacza, że ​​Linus nie używa debugera, ale to nie jest dokładne.)
Kristopher Johnson

6
Wygląda na to, że Linus Torvalds i ja nigdy się nie zgadzam.
BlueRaja - Danny Pflughoeft

11

Więc moje konkretne pytanie, na które można odpowiedzieć, brzmi: w jakich okolicznościach jako doświadczony programista używałbyś debugera?

  • Gdy nie możesz „debugować” przez odczytanie kodu.
  • Gdy nie jesteś w stanie przewidzieć, jakie wartości mają określone zmienne w danym czasie.
  • Gdy twój mentalny model kodu nie pasuje do danych wyjściowych podanych przez kod

Edytować:

Miałem szczęście / nieszczęście, że nie wiem, jak używać debugera w mojej podróży programistycznej. Tak więc w przeszłości byłem zmuszony debugować bez debuggera. Jednak po nauczeniu się korzystania z debuggera -> stałem się 100 razy bardziej produktywny w wyszukiwaniu błędów.


+1 dla „Gdy model mentalny twojego kodu nie pasuje do danych wyjściowych podanych przez kod”
użytkownik

8

Aby dać nieco inną perspektywę niż obecne odpowiedzi; Jako inżynier oprogramowania wbudowanego pracujący na systemach, które często zawierają komponent czasu rzeczywistego, rzadko używam debugera.

Czasami debuger może być niesamowitym narzędziem, a ilekroć mogę zbudować i uruchomić kod na pulpicie, zawsze używałbym debugera.

Na chipie, z ograniczeniami w czasie rzeczywistym, istnieje duże obciążenie związane z próbą użycia debuggera. Gdy tylko wstrzymasz wykonywanie, prawdopodobnie zaburzysz, a może nawet śmiertelnie, harmonogram reszty systemu. Zasadniczo na chipie, printf w niekrytycznym kodzie i fluktuacje we / wy w kodzie krytycznym czasowo są najlepszym i faktycznie najprostszym narzędziem. Nie jest tak dobry jak debugger, ale znacznie taniej jest pracować z prawdziwym systemem.


1
możesz zbadać sprzętowe płyty debuggera
Steven A. Lowe

@Steven dzięki; niestety, podczas gdy niektóre systemy, nad którymi pracuję, mają odpowiednie wsparcie sprzętowe, inne nie. Chociaż na ogół mamy opcję analizatora logicznego, wydaje się ona być jeszcze droższa pod względem czasu.
Luke Graham

Jestem dokładnie odwrotnie. Często używam debugera w systemach wbudowanych. Zgadzam się jednak, że zakłóci to czas. Odfiltrowanie i / lub zminimalizowanie zmian spowodowanych umieszczeniem debugera w pętli wymaga sporo wysiłku.
Karl Bielefeldt

7

Myślę, że doświadczeni programiści prawie wyłącznie używają debuggerów, kiedy są potrzebne. Czy jest lepszy sposób na wyśledzenie błędu niż śledzenie wykonania kodu ...

Czy zakładasz, że motki świata nie popełniają błędów lub po prostu wszystko wiedzą? Wszystkie programy z wyjątkiem najbardziej trywialnych zachowują się w nieoczekiwanych okolicznościach. Jest rzeczą oczywistą, że problemy będą musiały zostać zbadane. Tak więc do wyboru są instrukcje drukowania na jednym końcu spektrum lub spojrzenie, zbadanie, co się wydarzyło, pośmiertne, na drugim lub spojrzenie w środku podczas wykonywania kodu i ustalenie, co się dzieje.

Być może lepszym sposobem myślenia o tym jest to, że doświadczeni programiści wiedzą, kiedy użyć debuggera. W kodzie z kilkoma zależnościami prawdopodobnie wystarczy śledzenie stosu, aby dowiedzieć się, co jest nie tak. Ale są skomplikowane scenariusze, w których Twój kod działa z innym kodem i potrzebujesz debuggera, aby zobaczyć rzeczy, których nie napisałeś.


4
Cóż, właśnie to próbuję zbadać - jestem niezwykle doświadczonym programistą i nigdy go nie używam.

5
@neil, może nie potrzebujesz. Zapewniamy, że nadejdzie czas, w którym debugger będzie najprostszym sposobem na dojście do sedna problemu, niezależnie od tego, czy faktycznie użyjesz jednego ...
hvgotcodes

Mogę czytać rzeczy, których też nie napisałem. A jeśli nie mogę, jest to użyteczne, ponieważ jest to zły kod. W innych przypadkach używam debugera.
GolezTrol

Jeśli używany język obsługuje wyjątki, a jeśli ich używasz + odpowiednio platforma rejestrowania (np. Log4j lub coś w tym stylu), zawsze znajdziesz ślad stosu wskazujący na linię błędu. W 99% przypadków jest to wyjątek wskaźnika zerowego, w którym się nie spodziewałeś. Co jeszcze powie ci debugger? Teraz, gdy programowałem w c, były rzeczy, których po prostu nie można znaleźć bez debuggera (np. Uszkodzenie stosu). Ale tego typu rzeczy po prostu już się nie zdarzają w językach wysokiego poziomu.
Kevin

1
@kevin, prawda, myślę, że istnieje klasa problemów między tymi dwoma, w których debuger jest najbardziej naturalnym sposobem na dojście do sedna problemu. Być może chcę zobaczyć dynamiczne właściwości nakładane na obiekt w dynamicznym środowisku językowym, takim jak grails. Może chcę zobaczyć dokładnie, gdzie coś, co myślę, że nie jest zerowe, jest zerowane (NPE mówi ci, gdzie jest wyjątek, a nie dlaczego to jest puste). Być może chcę, aby mój debugger zatrzymał się na wyjściu, aby zobaczyć, która kombinacja kodu spowodowała wyjątek, a nie tylko to, że wystąpił on w stacktrace.
hvgotcodes

4

Nie mam i programuję od ponad 10 lat. Kiedyś programowałem w c / c ++. Teraz programuję w Javie. Prawda jest taka, że ​​jeśli poprawnie logujesz, skończysz ze stosem śledzenia, który jest wystarczający dla najbardziej wykwalifikowanych programistów. Również jeśli piszesz (dobre) testy jednostkowe i testy funkcjonalne, co eliminuje całą klasę błędów.


Jeśli to wyjaśnia więcej, znam wielu programistów Java, którzy używają debuggera. W większości są tuż po szkole.
Kevin

1
Stacktrace nie pokazują danych - musisz sam je dodać - ale wtedy są one czystym złotem.

1
@ Thorbjørn: Właściwie mogą wyświetlać dane: na przykład zobacz moduł cgitb Pythona . (CGI w nazwie jest przeważnie szczątkowe, pierwotnym celem modułu było przedstawienie użytecznych śladów stosu, gdy CGI się zawiesił.) Oczywiście, dzięki temu czasami otrzymujesz tyle danych, że trudno jest przejść do stosu rama zainteresowania. cgitb.enable(format='text')Mimo to kocham .
SamB

Tak naprawdę nie używam debugerów i używam C ++ ..
Nikko

@SamB Kevin mówił o Javie, która nie może tego zrobić

3

Rzadko.

Twoje metody powinny być na tyle małe / proste, aby można je było kompilować i uruchamiać w myślach, testy jednostkowe powinny obejmować funkcjonalność. Jeśli znajdziesz błąd, napisz test. Uruchom, napraw to.

Używam debugera tylko wtedy, gdy otrzymałem nieoczekiwane zachowanie z nieczytelnego kodu, takiego jak framework ASP.NET.


3
w tym wątku są naprawdę nienawidzący nooby ...

2
Nie ma powodu, by głosować w dół - ma rację.
wadesworld

11
-1, ponieważ roszczenie jest jak powiedzenie, że sposobem na zarabianie pieniędzy w Vegas jest po prostu wygrać każde rozdanie. To nie odzwierciedla rzeczywistości sytuacji, a twierdzenie, że cały kod będzie prosty, istnieje tylko w małych, odizolowanych problemach. Ponadto roszczenie „uruchom, napraw to” całkowicie ignoruje sposób naprawy. Zamierzałem pozwolić, by się ześlizgnęło, ale potem sugerowałem, że wszyscy, którzy się nie zgadzają, sprawiają, że warto zanegować.
whatsisname

2
-1: „Twoje metody powinny być na tyle małe / proste, aby można je było skompilować i uruchomić według własnego umysłu” nie ma związku z rzeczywistością. To tak, jakby powiedzieć, że funkcja dłuższa niż 20 linii jest za długa. Nonsens.
John Dibling,

3

W Smalltalk rozwijam prawie całkowicie debugger:

  1. Napisz test, który, jak wiem, zakończy się niepowodzeniem.
  2. Uruchom test. Kiedy zawiedzie, pojawia się debugger.
  3. Napisz w debuggerze kod niezbędny do zaliczenia testu.
  4. Wznów wykonywanie.
  5. Jeśli dostanę zielone światło, przejdź do kroku 1 z nowym testem negatywnym. W przeciwnym razie w debugerze dowiedz się, co zrobiłem źle i napraw to.

3

Kogo to obchodzi? Chcę wiedzieć, czy użycie debugera uniemożliwi mi bycie lepszym programistą na dłuższą metę? Być może debuggery były niższej jakości, kiedy wielu doświadczonych programistów zaczęło, więc utrudniały. Czy to kula, która uniemożliwia głębsze zrozumienie?

Niektórzy programiści, prawdopodobnie lepsi od nas wszystkich, znaleźli potrzebę debuggera i zbudowali go (nie mam pojęcia, kto stworzył pierwszy). Jestem pewien, że dzięki temu były bardziej produktywne. Wątpię, aby motywacją było umożliwienie mniejszym śmiertelnikom pisania kodu.


2

Używam debugera, kiedy jest to konieczne. To nie jest codzienne, ale zdarza się czasami. Czasami lepiej jest przejść przez kod, aby zobaczyć, co dokładnie się dzieje.

Muszę przyznać, że coraz mniej używam debuggerów. W Delphi rozwijam się od ponad 10 lat. Piszę również procedury składowane w języku PL / SQL. Od kilku miesięcy jestem również programistą PHP.

Debugera używam głównie w każdym z tych przypadków, jeśli znajdę kawałek niejasnego kodu, który został napisany lata temu i muszę go zmodyfikować. Czasami pomaga ustalić dokładny sposób działania programu, jeśli trudno jest odczytać kod. W PHP prawie nigdy nie jest to konieczne, ale w Delphi, która jest oparta na zdarzeniach, czasami pomaga, gdy masz złożoną strukturę.

Ale, jak mówisz, używanie debuggera jest wyjątkiem. Większość problemów rozwiązuje się po prostu czytając kod i naprawiając błędy, które popełniłeś (lub ktoś inny).

Ale to dotyczy przechodzenia przez kod. Dość często używam stosu wywołań, gdy występuje wyjątek, i czasami umieszczam gdzieś punkt przerwania, aby sprawdzić zmienną. Ale prawie zawsze w kodzie, który i tak wymaga gruntownego refaktoryzacji.


2

Czasami koduję bez debuggera, ale tylko wtedy, gdy jestem zmuszony do celowania, tj. starsze osadzone gunge na 8051 lub Z80.

IMHO, potrzebujesz debuggera i logowania do każdego złożonego zadania. Raz nie zastępuje drugiego. System rejestrowania nie może pomóc, jeśli aplikacja wpycha sterownik, na przykład, gdy jedyną rzeczą, jaką może zrobić kod, jest interakcja ze sprzętem i ustawienie semafora.

Debuger nie może pomóc z błędem systemowym, w którym aplikacje działają poprawnie zgodnie ze sposobem, w jaki je napisałeś, ale system nadal nie działa z powodu sporadycznego błędu protokołu comms.

Potrzebuję więc debugera, aby usunąć głupie, rażące błędy i kokpity sprzętowe. Potrzebuję dobrego logowania, aby wykryć sporadyczne błędy integracji systemu.

Muszę mieć oba - potrzebuję całej pomocy, jaką mogę uzyskać!


2
Z80 jest wystarczająco duży dla debuggerów. CP / M miał ZSID.

1

Używam debugera tylko wtedy, gdy te kroki nie powiodą się:

  1. Uzyskaj powtarzalny błąd. Myśleć. Często jest to wszystko, czego potrzeba.
  2. Sprawdź wszelkie ślady stosu i dzienniki.
  3. Dodaj więcej rejestrowania wokół szkodliwego kodu.

Kroki te obejmują 95% wszystkich przypadków. Oznacza to, że rzadko używam debugera, a kiedy to robię, zwykle mi to daje zbyt wiele informacji i wpadam w niepowiązane szczegóły. Jest to szczególnie prawdziwe, jeśli pracujesz na wielowątkowym systemie czasu rzeczywistego.

Rozsądnie umieszczone instrukcje rejestrowania przebiegają bardzo długo.


1

Czy to możliwe, że bardzo doświadczeni programiści są tacy sami jak bardzo starzy programiści i nauczyli się programować i ukształtowali swoje nawyki, kiedy debuggery nie zawsze były dostępne, a czasem niezbyt dobre?

Jeśli naprawdę dobrze radzisz sobie z debugowaniem printf (i jeszcze w latach osiemdziesiątych nie mieliśmy dużego wyboru, ale naprawdę byliśmy w tym dobrzy), być może debugger nie dodaje zbyt wiele.


0

To kwestia osobistego wyboru.

Szczerze mówiąc, myślę, że debuggery są przydatne w pewnych sytuacjach, w których bardzo pomaga wiedzieć, co dzieje się na twoim ramie na każdym etapie wykonywania programu.

Podstawową użytecznością debuggera jest zatrzymanie programu bez zaprojektowania go do zatrzymania się: ta funkcja jest dość ważna.

Oprócz tych dwóch funkcji nie sądzę, aby debugger był naprawdę potrzebny; każdy złożony program powinien mieć jakiś tryb „pełny”, tzn. informujący o wszystkim, co robi z printf lub std :: cout, jakie wybory dokonał i wiele innych parametrów.

Wyobraź sobie, że tworzysz program, a użytkownik ma problem z korzystaniem z niego: jak się dowiedzieć, czy używa go w sposób, w jaki został zaprojektowany, czy też coś, na co narzeka, może być błędem?

Debugery są jak elektryczny układ kierowniczy w twoim samochodzie: wygodniej jest go mieć, ale nie poprawi to twojej jazdy.

Programowanie dotyczy projektowania i logiki, a sposób, w jaki narzędzia mogą ci pomóc w śledzeniu rzeczy, nie czyni cię lepszym programistą.

Debugery Plus są przydatne w językach skompilowanych, a tym bardziej w językach zinterpretowanych.


2
Nie rozumiem, co ma z tym wspólnego kompilacja vs. interpretacja.
Michael Burr

dobre pytanie: ja też nie.
Jokoon
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.