Czy w ciągu ostatnich 20 lat tak naprawdę nie było nic, co zapewniłoby ogromne korzyści z rozwoju oprogramowania? [Zamknięte]


45

W „ No Silver Bullet” Fred Brooks przedstawia różne prognozy dotyczące przyszłości inżynierii oprogramowania, najlepiej podsumowane przez:

Nie ma jednego rozwoju, ani w technologii, ani w technice zarządzania, który sam w sobie obiecuje poprawę wydajności, niezawodności i prostoty nawet o jeden rząd wielkości .

Jego argument jest bardzo przekonujący. Brooks pisał w 1986 roku: czy miał rację? Czy programiści w 2014 r. Produkują oprogramowanie w tempie mniej niż 10-krotnie szybszym niż ich odpowiedniki w 1986 r.? Według jakiejś odpowiedniej miary - jak duży był rzeczywiście wzrost wydajności?


4
Komentarze nie są przeznaczone do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Inżynier świata

Odpowiedzi:


58

Czy programiści w 2014 r. Produkują oprogramowanie w tempie mniej niż 10-krotnie szybszym niż ich odpowiedniki w 1986 r.?

Wyobrażam sobie, że od tamtej pory wydajność wzrosła przynajmniej o rząd wielkości. Ale nie poprzez wykorzystanie jednego rozwoju, zarówno w technologii, jak i technice zarządzania.

Wzrost wydajności wynika z kombinacji różnych czynników. Uwaga: To nie jest pełna lista:

  1. Lepsze kompilatory
  2. Kolosalnie mocniejsze komputery
  3. Intellisense
  4. Orientacja obiektowa
  5. Orientacja funkcjonalna
  6. Lepsze techniki zarządzania pamięcią
  7. Sprawdzanie granic
  8. Analiza kodu statycznego
  9. Mocne pisanie
  10. Testów jednostkowych
  11. Lepszy projekt języka programowania
  12. Generowanie kodu
  13. Systemy kontroli kodu źródłowego
  14. Ponowne użycie kodu

I tak dalej. Wszystkie te techniki łączą się w celu zwiększenia wydajności; nie ma ani jednej srebrnej kuli, która kiedykolwiek spowodowałaby przyspieszenie rzędu wielkości.

Należy zauważyć, że niektóre z tych technik istniały od lat sześćdziesiątych, ale ostatnio zaobserwowano ich powszechne uznanie i przyjęcie.


15
Nie zapomnij o lepszych systemach kontroli wersji / wersji.
Doval,

7
Ah, tak. Wyobrażam sobie, że moglibyśmy dodać jeszcze kilkanaście (lub sto) rzeczy do tej listy.
Robert Harvey

44
@ user61852: Ponieważ oczekiwania zawsze przekraczają rzeczywistość.
Robert Harvey


1
@RossPatterson: W tej chwili mamy właściwie wszystko, czego potrzebujemy do narzędzi programistycznych. Robimy nawet głupio marnotrawstwo rzeczy przy naszych kompilujących cyklach procesora tylko dlatego, że możemy --- spojrzeć na metaprogramowanie szablonu. Pamiętaj, że porównujemy z latami 80-tymi; chociaż z pewnością nie byłem programistą, nauczyłem się kodować na maszynie zbudowanej w 1990 roku.
tmyklebu

71

Odpowiedź Roberta Harveya jest dobra, ale myślę, że pominął to, co może być największym powodem, dla którego programiści są bardziej wydajni niż kiedykolwiek: powszechna dostępność bibliotek oprogramowania.

Kiedy zaczynałem swoją karierę, nie było STL, .NET, QT itp. Miałeś surowe C lub C ++, i tyle.

Rzeczy, które kiedyś zajmowały dni lub tygodnie (parsowanie XML, połączenia TCP / IP, komunikacja HTTP), można teraz wykonać za pomocą kilku wierszy kodu C #. To tutaj poprawiliśmy rząd wielkości pod względem ogólnej wydajności programistów.

Nasz obecny produkt korzysta z frameworku okna dokowania, który kupiliśmy od dostawcy. To pozwala mi mieć w pełni funkcjonalny interfejs okna dokowania w ciągu kilku minut. Drżę na myśl o tym, co trzeba zrobić w czasach korzystania z interfejsu API win32.


19
Dodałbym do tego dostępność dokumentacji i pomocy. Dwadzieścia lat temu miałeś listę mailingową i swoich bezpośrednich współpracowników. Teraz światowa wiedza programistyczna w prawie każdym temacie jest dostępna natychmiast za pośrednictwem jednego interfejsu.
NWard

15
@NWard, więc w zasadzie przepełnienie stosu =)
Chris

2
@tmyklebu people just found other (generally better) solutions[potrzebne źródło]. Używanie bibliotek do szybkiego analizowania „gór” XML jest pod wieloma względami lepsze niż ręczne kodowanie unikalnych rozwiązań. XML z pewnością może być zbyt zwięzły i powtarzalny, ale biblioteki sprawiają, że korzystanie z niego jest proste w większości sytuacji.
WernerCD

5
@tmyklebu Jakkolwiek bolesne może być parsowanie dużych ilości XML, spróbuj parsować duże ilości danych binarnych w nieudokumentowanym zastrzeżonym formacie, tak jak by to było w przypadku większości aplikacji napisanych około 1986 roku.
James_pic

2
@tmyklebu Nikt nie potrzebował gigabajtów czegokolwiek w ciągu dnia (ani nawet megabajtów!). To, co generuje taką ilość XML, to fakt, że przechowujemy i śledzimy znacznie więcej danych niż kiedykolwiek wcześniej. james_pic ma rację, XML jest o wiele lepszy niż posiadanie bazillionowych formatów binarnych. XML może być niewygodny, ale jest wieloplatformowy, czytelny dla człowieka i bardzo elastyczny. To są wszystkie cenne cechy.
17 z 26

62

Dla argumentu nie zgadzam się z twierdzeniem Freda Brooksa .

Nastąpiła poprawa technologii, która pozwoliła na poprawę produktywności o rząd wielkości: internet , a dokładniej stopniowa dostępność połączenia internetowego w każdym domu w ciągu ostatnich dwóch dekad.

Zdolność natychmiastowego znalezienia odpowiedzi na prawie każdy problem, jaki możesz napotkać jako programista, umożliwia ogromny wzrost wydajności. Nie wiesz, jak wybrać n-ty element w JQuery? Wyszukiwarka Google prowadzi do odpowiedzi na dokładne pytanie dotyczące przepełnienia stosu . Nie wiesz, jak korzystać overflowz CSS? MDN Mozilli jest tutaj . Zapomniałeś, co virtualoznacza słowo kluczowe w C #? Google znowu pomaga .

Kiedy zacząłem programować, nie miałem internetu. Miałem książki, a także lokalną dokumentację w formacie cyfrowym, ale przeszukiwanie książek i dokumentacji było procesem powolnym i bez względu na to, ile książek miałem, było wiele problemów, o których nie wspomniano.

Co ważniejsze, prawie każdy napotkany problem był już wcześniej napotykany przez kogoś innego. Internet pomaga znaleźć osoby, które miały ten błąd i pomyślnie go rozwiązały. To nie jest rodzaj informacji, którą można znaleźć w książkach lub oficjalnej dokumentacji, takiej jak MSDN. Zamiast tego zwykle można znaleźć takie informacje:

  • Oczywiście przy przepełnieniu stosu. Na przykład nie widziałem żadnej książki, która wspominałaby o tym problemie .

  • Na blogach. Znalazłem wiele pomocy na blogach, gdy miałem szczególne problemy, czy to przy konfiguracji WCF lub serwera proxy, który się nie uruchamia, czy też tajemniczym błędzie podczas używania określonego interfejsu API na maszynie o kulturze innej niż en-US.

  • W raportach błędów dotyczących oprogramowania open source. Na przykład ostatnio bardzo mi się pomogło, kiedy próbowałem użyć MAAS Ubuntu i kiedy użyłem PXE. Tego rodzaju informacji nie znajdziesz także w książkach.

Znaczenie natychmiastowej dostępności odpowiedzi na większość problemów, które można napotkać, jest szczególnie zauważalne, jeśli weźmiemy pod uwagę, że zespół poświęca większość czasu na projekt, aby ją utrzymać .

  • Internet nie pomaga zbyt wiele na etapie architektury i projektowania (Programmers.SE może pomóc, ale byłoby znacznie cenniejsze dla architekta, aby czytał książki o architekturze i projektowaniu, uczył się wzorców projektowych itp.).

  • Zaczyna być pomocny na etapach testowania i wdrażania, gdy pojawiają się rzeczywiste problemy.

  • Ale większość problemów pojawiających się podczas konserwacji, pojawia się, gdy pomoc innych osób przez Internet wydaje się kluczowa . Podstawowy przykład: usługa WCF działa doskonale na moim komputerze , ale zawiesza się bez wyjątku, gdy jest wdrożona w produkcji, podczas gdy działała przez ostatnie dwa tygodnie. Tak się stało i jestem wdzięczny autorom blogów i społeczności Stack Overflow za pomoc w rozwiązaniu problemu w ciągu kilku godzin, a nie tygodni.

Czy uzasadniałoby to wzrost wydajności x10? Trudno powiedzieć.

  • Z jednej strony zdarzają się sytuacje, w których odpowiedź znajduje się od razu, a Ty możesz spędzić kilka dni na szukaniu odpowiedzi samodzielnie (lub być zmuszonym do przepisania dużej części aplikacji).

  • Z drugiej strony ogólna produktywność poprawiona w oparciu o wiele czynników, takich jak lepsze zarządzanie projektami (Agile, TDD itp. Przychodzi na myśl), lepsze zarządzanie zespołem ( przychodzi na myśl Radical Management Stephena Denninga), lepsze narzędzia (debuggery, profilery , IDE itp.), Lepszy sprzęt (nie, nie będę bardzo produktywny, jeśli będę zmuszony pisać w asemblerze dla wolnego procesora i bardzo ograniczonej pamięci RAM) itp.


4
„Internet” też nie jest pojedynczym rozwinięciem.
Ben Voigt,

1
@BenVoigt: Kwalifikowałbym ją jako technologię z cytatu Brooksa. Ale zgadzam się, że warunki mogą nie być oczywiste: po pierwsze, czy byłby to Internet (wczesne lata 80.) czy World Wide Web (1989)? Po drugie, nie tylko sama technologia była niezbędna, ale także jej popularność.
Arseni Mourzenko

Ale rzeczy, które stosujemy pod pojęciem „Internetu”, obejmują wiele różnych technologii. Istnieje wiele generacji sieci WWW (DHTML / Javascript / browser). Udoskonalenia światłowodowe umożliwiają połączenia w skali centrum danych. Istnieją ulepszenia procesu CMOS, które pozwalają serwerom mieć terabajt pamięci RAM i przeprowadzać wyszukiwanie danych. Algorytmy indeksujące milion pytań na temat programowania i zapewniające 10 najbliższych trafień w pewnym sensie języka naturalnego.
Ben Voigt,

5
Ludzie pracujący z systemami zaprojektowanymi przez Brooks nie potrzebowali Google, aby pamiętać, jak napisać JCL. Systemy te były dostarczane z dobrze udokumentowanymi środowiskami programistycznymi, które były stale wykorzystywane / ulepszane stopniowo przez dziesięciolecia. Czy to z powodu planowanego starzenia się, czy z czegoś mniej złowrogiego, odeszliśmy od tego. W każdym razie waham się nazywać to, co mamy teraz ulepszeniem, i zupełnie nie chcę ogłosić, że to „srebrna kula”.
user1172763,

Złożoność jest wrogiem. Możesz trzymać JCL w głowie i trzymać instrukcję w dłoni; pojedyncza półka może dokumentować cały system. Teraz nastąpiła ogromna eksplozja wielkości systemów i leżącego u ich podstaw tempa zmian.
pjc50,

13

Powiedziałbym, że Internet jest całkiem dobrym kandydatem. StackOverflow i Google to najpotężniejsze narzędzia współczesnego programisty. Natychmiastowe dzielenie się wiedzą na całym świecie! W dzisiejszych czasach nie musisz znać odpowiedzi, musisz tylko wiedzieć, jak poznać odpowiedzi - i jest to całkowicie adekwatny zamiennik, który pozwala programistom spędzać mniej czasu na czytaniu, a więcej na kodowaniu, a tym samym na produktywności. Oznacza to, że każdy programista na świecie ma dostęp do wszystkich odpowiedzi, a wszystko, co muszą zrobić, to umieć zadawać właściwe pytania.


Jesteś jedyną osobą, która wskazuje srebrną kulę. Nie tylko sprawiło, że programiści byli bardziej produktywni o wielkość, ale w rzeczywistości o wiele wielkości rzędu.
Dunk

+1000 - możesz uzyskać pomoc w ciągu kilku minut zamiast pracować przez kilka dni nad niejasnym problemem.
jqa

7

Sugerowałbym, że trendy ciągnące nas w innym kierunku (tj. W kierunku niższej wydajności) są co najmniej tak silne, jak trendy, o które pytałeś. Doświadczenie w tworzeniu narzędzi do tworzenia klienta / serwera, takich jak VB6 lub PowerBuilder, zbliżyło się do ideału „Rapid Application Development” (RAD). Musisz narysować swoje formularze, a kod proceduralny lub SQL były oczywiste.

Tworzenie stron internetowych, przynajmniej początkowo, zniszczyło wiele technik i infrastruktury, które umożliwiły te rzeczy, a wielu deweloperów klient / serwer przestało być programistami lub desperacko przylgnęło do, powiedzmy, VB6.

Przejście na projektowanie stron internetowych w dużej mierze oparte na kliencie było kolejnym doświadczeniem typu slash and burn; Microsoft wracał do ideału RAD z WebForms, a potem szybko stracił przychylność. Zamiast tego oczekiwano, że programiści wykorzystają infrastrukturę (np. XMLHttpRequest, która jest rzadko używana w języku XML) i w inny sposób będą próbować uzyskać niski poziom abstrakcji, aby zwiększyć interaktywność swoich witryn internetowych.

Wszystkie te przejścia mają dobre powody i niesprawiedliwe jest porównywanie procesu, w wyniku którego natywny plik .EXE (wymagający instalacji i zarządzania u klienta indywidualnego) jest opracowywany w sieci, ani też porównywanie procesu, który w dużej mierze opiera się na postbackach z takim, który zapewnia bardziej płynne wrażenia. Ale powiem, że obecnie modne praktyki prowadzą do zaskakująco niskiego poziomu procesów myślowych wśród osób, które przegapiły klient / serwer, RAD i tym podobne. Przyciski klient / serwer po prostu działały i na pewno nie trzeba było martwić się o leżące u ich podstaw kanały danych, które przesyłały dane do procedur obsługi zdarzeń, które to spowodowały.

I odwrotnie, bardziej współcześni programiści myślą, że ci z nas, którzy zajmowali się tworzeniem klienta / serwera (lub nawet tworzeniem stron internetowych) mają tendencję do uciekania się do skrótów (i to źle). To zrozumiałe, ale nadal uważam, że sposób, w jaki dokonuje się współczesny rozwój, jest zaskakująco niski, a dni poszukiwania „srebrnej kuli” zdają się ustępować epoce kpienia z tych, którzy kwestionują mądrość wydobycia i wytapianie własnego ołowiu.


czy widziałeś Meteor.js?
strugee

2
@strugee Tak i myślę, że Meteor.js może być krokiem we właściwym kierunku. Jednak fakt, że zasadniczo „zaczęliśmy od nowa” technologicznie co najmniej 3-4 razy, odkąd Brooks napisał swoją książkę (odnosząc się tutaj do przejścia na PC, potem do klienta / serwera, potem do sieci, a następnie do AJAX) jest prawdopodobnie tym, co powstrzymało nas od znalezienia „srebrnej kuli”, a nawet wprowadzenia liniowej poprawy wydajności. Czas pokaże, jak długo trwają (i doskonalą) obecne techniki programistyczne. Jest kilka powodów do optymizmu ... wszyscy sięgają teraz po solidny, wieloplatformowy punkt.
user1172763,

5

Technologia bardzo się rozwinęła i teraz mamy wszystkie rzeczy, które Robert Harvey wymienia w swojej odpowiedzi, ale:

  • Problemem wydają się być zmieniające się wymagania . Klient wie, że przy zmianie wymagań projektu oprogramowania nie będzie marnotrawstwa materiałów, więc tak robią. Tego rodzaju zmiany wymagań prawie nigdy nie zdarzają się, gdy projekt świata fizycznego, taki jak budynek, jest w połowie gotowy.

  • Innym ważnym aspektem jest to, że programowanie nadal jest bardzo ręczne . Rzadko, jeśli w ogóle, kod generowany przez RAD przechodzi do produkcji bez wcześniejszej modyfikacji ręcznie.

  • Kod jest nadal bardzo złożony , a złożoność ta nie wydaje się zmniejszać w przypadku nowych technologii.

  • Wskaźnik niedotrzymania terminów lub przekroczenia budżetów jest nadal wyższy niż w innych dyscyplinach, a często bywa zaciągnięty dług techniczny, aby je dotrzymać, generując ukryte koszty.

  • Coś, co bez wątpienia się wydarzyło, to to, że nastąpił podział na przedziały . Sama liczba technologii, które trzeba znać, polega na tym, że programiści musieli wyspecjalizować niewielką liczbę technologii, aby stać się w nich naprawdę dobrzy, wymagając różnego rodzaju ekspertów do ukończenia dużego projektu.

  • Jedną rzeczą, która mówi o złożoności oprogramowania jest to, że podczas gdy na świecie są dosłownie setki producentów samochodów, listę firm zdolnych do stworzenia i utrzymania systemu operacyjnego (stacjonarnego, mobilnego, wbudowanego lub innego) można policzyć palcami twoich rąk.

  • Wszystko to stworzyło sytuację, w której nie ma wystarczającej liczby osób studiujących na programistów , dlatego rządy stworzyły kampanie mające na celu zmotywowanie większej liczby studentów do podjęcia kariery zawodowej.

  • Jednym z dojrzałości branży oprogramowania jest to, że licencje na oprogramowanie nadal stwierdzają, że „<firmaX> nie składa żadnych oświadczeń na temat przydatności tego oprogramowania do określonego celu. Jest dostarczany„ w stanie, w jakim się znajduje ”, bez wyraźnej lub dorozumianej gwarancji”. Wyobraź sobie producenta sprzętu stwierdzającego, że jego produkt nie nadaje się do określonego celu. To jest teraz stan techniki.


2
Z pewnością istnieje ponad 10 firm zdolnych do tworzenia i utrzymywania własnego systemu operacyjnego, ale niewiele z nich decyduje się na to, ponieważ inne możliwości są bardziej dochodowe.
Ben Voigt,

@BenVoigt Oczywiście tworzenie i utrzymywanie systemu operacyjnego jest stosunkowo mniej lukratywne ze względu na samą złożoność, wymaga dziesięcioleci badań i rozwoju, które powinny być rozpoczęte najpóźniej w latach dziewięćdziesiątych, aby mieć dziś dojrzały produkt.
Tulains Córdova,

1
Również „zwrot” strony zwrotu z inwestycji nie jest tak dobry, ponieważ rynek jest już nasycony.
Ben Voigt,

2
Oczywiście wszystko, co zrobiłeś, to wymienić dobrze znane przeszkody w efektywnym programowaniu, które pojawiły się wkrótce po tym, jak Lady Lovelace podniosła ołówek. Jedyne, co różni się od 30 lat temu, to fakt, że sprawy stały się wykładniczo bardziej złożone.
Daniel R Hicks,

4

Podczas gdy można spierać się z konkretnymi wskaźnikami (tj. Czy rzeczy uległy poprawie o współczynnik 9,98?), Ja (mówiąc coś w stylu dawnego czasu) muszę się zgodzić z ogólnym sentymentem komentarza Brooksa.

Po pierwsze, istnieje niewiele naprawdę nowych technologii wynalezionych od roku 1970. Tak, układy scalone stały się dłuższe, niższe, szersze, a włókno szklane poprawiło prędkości komunikacji, ale na każdym kroku naprzód jest jeden.

Technologia kompilatora pozwoliła na około 10-krotną poprawę „wydajności” programisty w porównaniu z 1970 r., Kiedy wytworzona funkcja jednej liczby jest podzielona przez rzeczywisty czas kodowania, ale rozprzestrzenianie się nowych lub „poprawionych” języków programowania i środowisk oznacza, że ​​przeciętny programista wydaje coraz więcej czas w trybie „nadrabiania zaległości”, a mniej produktywności. Apple, Google i Microsoft wyrzucają nowe i zasadniczo niekompatybilne „uaktualnienia” do swoich środowisk w tempie nieco poniżej tego, co wywołałoby bunt wśród ich poddanych ... eee, programujących klientów. Podobnie HTML / CSS / JavaScript / cokolwiek staje się coraz bardziej skomplikowane.

Kiedyś tempo, w jakim dokumentacja mogłaby być produkowana i rozpowszechniana, ograniczyłoby i skorygowało całą tę „innowację”, ale dzięki Internetowi rygorystyczna dokumentacja nie jest już tak naprawdę potrzebna - wystarczy wyrzucić funkcje i polegać na blogerach, aby ujawnij szczegóły i udostępnij je.

Dodano: Myślałem o tym od wczoraj, a zwłaszcza o projekcie, nad którym pracowałem od około 1978 r. Do 2008 r. Ten projekt (IBM System / 38 i jego następcy) był w pewnym stopniu wyjątkowy, ponieważ od samego początku starania były stworzony, aby kontrolować jego złożoność (jedną z nich jest podział oprogramowania na dwie w przybliżeniu równe części, z interfejsem „maszynowym” między nimi). W konkretnym obszarze, w którym pracowałem, kilku moich współpracowników podobnie zajmowało się kontrolowaniem złożoności (chociaż wtedy nie używaliśmy tego terminu zbyt często). Rezultatem był produkt, który (na początku) był dość solidny i „hitem” wśród klientów od samego początku. Praca nad nią była przyjemnością - jak gra w dobrze wyszkolonej orkiestrze.

Oczywiście z biegiem lat wkradała się złożoność, zwykle na żądanie planistów rynku i menedżerów, którzy nie docenili kontrolowania złożoności (co w pewien sposób różni się od utrzymywania prostoty). Nie mam poczucia, że ​​było to nieuniknione, ale nie można było zapobiec w tym przypadku bez kierownika (jak pierwotnie Glenn Henry) odpychającego siły dezorientacji.


2
Przypomina mi się jednak coś, co przyszło mi do głowy (i bez wątpienia wiele innych) 20-30 lat temu - istnieje coś w rodzaju zasady programowania Petera (a może druga zasada termodynamiki programowania), która stwierdza, że ​​złożoność nieuchronnie wzrasta do punkt niezrozumiałości. Rzeczy nigdy nie stają się prostsze.
Daniel R Hicks

3

Wiele z tego, czego nauczyliśmy się w praktyce inżynierii oprogramowania w ciągu ostatnich 30 lat, ma postać „technologia X może przyspieszyć początkowy rozwój nowego oprogramowania, ale jeśli nie poświęcisz tyle czasu lub więcej na zastanawianie się, jak i kiedy używać go tak, jak zaoszczędziłeś, korzystając z niego, na dłuższą metę zamieni twoją aplikację w zasysające bagno długu technicznego, co będzie kosztować cię o rząd wielkości więcej czasu i wysiłku w utrzymaniu. ”

Technologie, które podlegają tej maszynce to: ręcznie kodowany język asemblera, kompilatory, interpretatory, biblioteki procedur, programowanie imperatywne, programowanie funkcjonalne, programowanie obiektowe, ręczne przydzielanie pamięci, odśmiecanie, typy statyczne, typy dynamiczne, zakres leksykalny, zakres dynamiczny , „bezpieczne” wskaźniki, „niebezpieczne” wskaźniki, brak wskaźników jako koncepcja języka, formaty plików binarnych, formaty plików ze znacznikami strukturalnymi, makra, szablony, unikanie makr i szablonów, pamięć współdzielona, ​​przekazywanie wiadomości, wątki, coroutines, asynchroniczne pętle zdarzeń, scentralizowane usługi zdalne, usługi rozproszone, lokalnie zainstalowane oprogramowanie, tablice, listy połączone, tabele skrótów i drzewa.

Fakt, że wiele pozycji z powyższej listy występuje w grupach, które razem wyczerpują przestrzeń znanego rozwiązania, jest bardzo celowy i powinien sam w sobie coś powiedzieć. Można argumentować, że jedynymi jednoznacznymi, ogólnymi poprawkami w praktyce, jakie mieliśmy od czasu pierwszego włączenia Z3, są programy o strukturze blokowej (w przeciwieństwie do kodu spaghetti) i ochrona pamięci (chłopcze, czy ja nigdy nie tęsknię dni, w których literówka może zdjąć cały mój komputer).

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.