Programistyczne WTF jakie Was spotkały

Programistyczne WTF jakie Was spotkały
Potat0x
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 372
1
Kopiuj
function cos() {
    //...
}

Nie, nie chodzi o trygonometrię.

isAllSelected (checkboxy)
isExist(...)
YyyDto y = service.setYyyDto(String id)
datepicker1, datepicker2

hauleth
  • Rejestracja: dni
  • Ostatnio: dni
0

Teraz pracuję nad testami w aplikacji, by były one niezależne od reszty systemu (więc wszystkie zewnętrzne zapytania są mockowane). Co jest w tym takiego ciekawego? No test wygląda mniej więcej tak:

Kopiuj
assert {:ok, credits} = Service.get_credits(user)
assert {:ok, new_credits} = Service.set_credits(user, credits + 1)
assert new_credits - credits == 1

Niby wszystko spoko, ale Service.get_credits/1 oraz Service.set_credits/2 to funkcje wygenerowane z WSDL, więc czemu na bogów testujemy to po stronie klienta, a nie serwisu? I teraz siedzę i piszę te wszystkie stuby jak debil.

Marooned
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
2

ups ;-) ktoś wrzucił na produkcję developerską wersję google maps ;-)

https://www.airport-poznan.com.pl/pl/polaczenia-lotnicze/mapa-polaczen
screenshot-20200222233953.png

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
2

Kolejny dowód na to że autorzy PHP są orangutanami którzy nie biorą niczego pod uwagę

Kopiuj
function(...$array); // works

ale już to:

Kopiuj
return [1, 2, ...$array];

To już od PHP 7.4 haha :D

Serio, jak można wprowadzić jeden feature po kawałku w różnych wersjach? ;| (podobnie jest z type hintami, array w PHP 5.3, int/string w 7.0 do parametrów, w 7.1 do return-type'ów, w 7.4 do property'sów).

FA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: warszawa
  • Postów: 315
7

Słowa kluczewe w c#
screenshot-20200224212553.png

Marooned
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
3

To jest pierwszy rok, gdzie urząd skarbowy odmówił pomocy w rozliczeniu mojego pita. Do tej pory wpadałem tam na kwadrans i jakaś miła pani kazała kliknąć tu i tam i było gotowe. Teraz kazano mi to zrobić samamu przez neta.

Wbiłem na https://epit.podatki.gov.pl/yourpit/current i mym oczom ukazały się 4 możliwe pity, które oczywiście niewiele mi mówiły. Udało mi się jednak odkopać swój sprzed roku i wyszło na to, że mam PIT-37.
Szybkie szukanie potwierdziło, że potrzebuję 37 za umowę o pracę.
screenshot-20200225150258.png

I jakie mam możliwości na tej rządowej stronie?
screenshot-20200225150549.png

Czyli niby sekcja PIT-37, ale mogę złożyć tylko 36 dla prowadzących działalność gospodarczą (której od lat nie mam). Nawet URL brzmi jednoznacznie: https://www.podatki.gov.pl/pit/e-deklaracje-pit/dla-osob-prowadzacych-dzialalnosc-gospodarcza/#PIT-36
Czyli wynika z tego, że nie mogę złożyć 37, a muszę, a w US tego już mi nie zrobią. Co dalej? :D

Dla mnie to jeden wielki WTF (niekoniecznie programistyczny, choć częściowo też).

Koziołek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Stacktrace
  • Postów: 6823
2

Auto-merge to idealne narzędzie dla języków dynamicznie typowanych w czasach CID&D. Przykład z dzisiaj. Mamy dwa zadania, które dotykają tego samego pliku, w którym, co ważne, są zapisane schematy dla graphQL. W obu przypadkach musimy modyfikować tę samą sekcję, dodają różne mutacje. Wygląda to mniej więcej tak:

Kopiuj
defmodule App.Schema do
# …
   mutation do
      @desc "Jakaś tam mutacja"
      field :nazwa, :typ do
# …
      end
  end
end

I teraz jak ja dodałem mutacje i koleżanka dodała swoje mutacje, to po auto-merge wynik był:

Kopiuj
defmodule App.Schema do
# …
   mutation do
      @desc "Jakaś tam mutacja"
      field :nazwa, :typ do
# … moje
      end
  end
   mutation do
      @desc "Jakaś tam mutacja"
      field :nazwa, :typ do
# … jej
      end
  end
end

Czyli zamiast konfliktu mamy dwie takie same sekcje. W czym problem? Otóż w schemacie może być tylko jedna sekcja mutacji (i po jednej na subskrypcje i zapytania). Żaden kompilator tego nie wychwyci, bo język jest dynamiczny i jak babol wyjdzie dopiero po uruchomieniu i to w momencie gdy poleci pierwsze zapytanie.

A co z testami? Testy są, ale w żaden sposób nie dotykają pliku ze schematami, bo traktują go jak zewnętrze API i nakładają mocka, który oczywiście zawsze działa. A co do tego ma CID&D? Na całe szczęście można dzięki temu narzędziu dość szybko przywrócić aplikację do życia.

Morał z tego taki, że jak auto-merge mówi, że jest ok i udało mu się rozwiązać konflikt, to nie oznacza, że jest dobrze.

Koziołek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Stacktrace
  • Postów: 6823
6

Kocham mój obecny projekt. Powrót do niewyczerpanego źródła fakapów w wykonaniu naszego, swoją drogą doświadczonego, zespołu. Na froncie mamy reacta osadzonego w gmailu, ale nie to będzie najważniejsze w tej historii. Ogólnie metodyka pracy jest taka, że jak coś nie idzie, to zdzwaniamy się i razem kodujemy problem. Nasz problem wyglądał tak, że chcieliśmy mieć komponent, który będzie zmieniać swój stan w zależności od tego czy delikwent jest zalogowany, czy też nie oraz pobierając dane z GraphQL. Prosta sprawa, ale w jednym miejscu przebieg programu zahaczał o funkcję, której zadaniem było wyczyszczenie informacji o subskrypcjach, aktywnościach itp. duperelach. Normalnie funkcja ta jest wywoływana gdy:

  • użytkownik klika wyloguj;
  • użytkownik zamyka komponent;

Całość wygląda mniej więcej tak:

Kopiuj
function unmount() {
  if (!mounted) {
    console.log("RightSidebar is already unmounted, ignoring unmount()");
   }
  ReactDOM.unmountComponentAtNode(container);
  contentPanelView.close();
  ReactDOM.render(
    <LoginPanel onWindowMessage={prepareOnWindowMessage()} />,
    container
  );

  mounted = false;
}

W sumie nic niezwykłego… o ile użytkownik nie otworzy gmaila po dłuższej przerwie, gdy po stronie serwera zostanie usunięty jego token logowania. W tym momencie z serwera przybywa HTTP 401 i wywoływana jest akcja wylogowania. Tyle tylko, że komponent nie został jeszcze zamontowany, więc powyższy kod powinien zostać zignorowany. Nie był. Siedzieliśmy we dwóch nad kodem GQL dla komponentu i przy okazji produkując powyższą funkcję. Co jest źle? Cóż JS nie jest jeszcze na tym etapie, że jak go prosisz, by zignorował wszystko po zalogowaniu zdania z prośbą, to on to zrobi. Zapomnieliśmy o pewnej małej rzeczy:

Kopiuj
function unmount() {
  if (!mounted) {
    console.log("RightSidebar is already unmounted, ignoring unmount()");
    return;
   }
  ReactDOM.unmountComponentAtNode(container);
  contentPanelView.close();
  ReactDOM.render(
    <LoginPanel onWindowMessage={prepareOnWindowMessage()} />,
    container
  );

  mounted = false;
}

Co ciekawe wyszło nie przy wygaśnięciu logowania, ale przy pracy na kilku środowiskach naraz.

LS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 85
14

Zastanawiałem się, co mi się tak mój kombajn przycina i dziwnie buczy.
Okazało się, że zostawiłem dzisiaj na ok. 3h otwartego małego gifa na kompie, co najwyraźniej poskutkowało przeogromnym memory leakiem. :o

title

GS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1265
4

WTF na czasie

https://coronavirus.jhu.edu/map.html
Strona z przypadkami koronawirusa na świecie. Z jakichś powodów kliknięcie na Francji powoduje przeniesienie na Karaiby

screenshot-20200317124049.png

FA
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: warszawa
  • Postów: 315
6

Dlaczego? Po co? Naprawdę? Folder nazywa się test
screenshot-20200318132838.png

Update. Rozpoczęcie instalacji naprawiło problem WTF?

E9
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 216
6

Integruje nasz system z jakimś systemem bankowym, biorę sobie swaggera, generuje klasy i takie coś mi się rzuciło w oczy w wygenerowanym kodzie

Kopiuj
public enum SomeProperty {
    TRUE(true),
    FALSE(false);

    private Boolean value;

    SomeProperty(Boolean value) {
      this.value = value;
    }
}

I nie, to nie jest reużywany enum w wielu miejscach, jest SomePropertyX, Y, Z które wygląda identycznie. Rozumiem, że trzeba było owrappoawć booleana jakby w przyszłości doszła 3 wartość "MAYBE"?

Freja Draco
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3394
6

Pierwszy raz w życiu używałam natywnych suwaków z HTML5.
W teorii świetna sprawa, używasz wbudowanego rozwiązania i nie musisz go sobie własnoręcznie rzeźbić z 2-3 innych elementów.

W praktyce CSS-owy koszmar. Przypomniały mi się stare "dobre" czasy kompletnego braku kompatybilności przeglądarek :p
Szybciej bym to sobie chyba z div-ów zrobiła :p

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
11

WTF słabo wyszkolonego testera (zapewne nowy nabytek).

Dostałem buga, że instalator na MacOS nie działa.
Not to proszę o logi, wytłumaczyłem skąd je wziąć itp.
WTF 1: Dostałem logi i z nich wynika, że gość włączył instalatora w trybie UI i albo nie konturował instalacji (nie nacisnął "continue") albo wyeksportował logi przed pojawieniem się problemu, bo odtwarzam co do literki logi jeśli instlacja się rozpocznie i nie jest kontunowana.
Dałem mu więc linię poleceń, że wszystko powinno pójść automatem i zapisać wszystkie logi w pliku:

Kopiuj
sudo installer –pkg "MyInstaller.pkg" -verbose -target / > /path_to_log/logs.txt 2>&1

WTF 2 Mimo, że już od tygodnia wymieniamy emaile, a te logi mają ~2kB to wgrał te logi na sharepoint tak, że nie mam dostępu. Jak mu zwróciłem na to uwagę, to wgrał to znowu na share point ale tym razem do takiej domeny, że sharepoint nawet nie przyjmuje mojego email.

No to błagam by wysłał to po prostu jako załącznik do email.

WTF level expert, bo dostałem dwa logi, które zawierają dokładnie to samo (dwie próby instlacji), w których jest to:

Kopiuj
Sorry, try again.
installer: invalid option –pkg
Usage: installer [-help] [-dominfo] [-volinfo] [-pkginfo] [-allowUntrusted] [-dumplog]
                 [-verbose | -verboseR] [-vers] [-config] [-plist]
                 [-file <pathToFile>] [-lang <ISOLanguageCode>] [-listiso]
                 [-showChoicesXML] [-applyChoiceChangesXML <pathToFile>]
                 [-showChoicesAfterApplyingChangesXML <pathtoFile>]
                 -pkg <pathToPackage>
                 -target <[DomainKey|MountPoint]>

Tak gość uruchomił komendę nie z tego katalogu, gdzie jest plik instalacyjny i nie sprawdził co wylądowało w tym pliku.
Oczywiście, do emaila dołączony był jeszcze screenshot w jaki sposób uruchomił te komendy.

Ręce opadają.


**Update:** Jak w końcu dostałem logi to się okazało, że jakaś zależność została zainstalowana w nieobsługiwanej wersji, co było wyraźnie opisane w ekranie powitalnym. Bug z instalatora MacOS nie pokazywał mojego komunikatu błędu, który dostarczyłem zgodnie z instrukcją od Apple. Żeby zapobiec takim problemom to dopisałem do instalatora obejście bug-a Apple, tak że komunikat jest wyraźnie prezentowany użytkownikowi na wczesnym etapie.
Freja Draco
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3394
2

Jak nie ukrywam jestem reakcyjnym anty-obiektowcem i niereformowalną wsteczniarą, która utknęła na etapie programowania imperatywnego.

No więc biorę sobie wczoraj na tapetę piękny obiektowy skrypt-demo obrazujący, jak w rozszerzeniu do chrome zrobić skrinszota.
Skrypt, elegancja-francja:

  • 50 linijek kodu,
  • jeden obiekt,
  • 2 właściwości,
  • 3 metody,
  • 7 tabów - maksymalny poziom zagnieżdżenia instrukcji kodu.

Ten sam skrypt, robiący dokładnie to samo po "zbarbaryzowaniu" go przeze mnie do postaci imperatywnej:

  • 16 linijek kodu,
  • jedna funkcja,
  • 3 taby - maksymalny poziom zagnieżdżenia instrukcji kodu.

A teraz wracam polować na dinozaury :p

p.s. Jak był uprzejmy zwrócić mi uwagę @Wibowit 22, mówiąc o oprogramowaniu imperatywnym, miałam na myśli proceduralne.

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
11

Nie do końca programistyczny ;)
Potrzebowałem dziś zresetować hasło w windowsie i jak sie okazuje, MS nie przewiduje takiej możliwości, o ile zawczasu nie wygenerowało sie jakiegoś magicznego pendrajwa na konkretnym systemie i użytkowniku którego planujecie resetować. Są niby jakieś livecd/liveusb które potrafią, ale próbowałem i coś nieszło, pewnie brak kompatybilności z nowym windowsem.

Finalnie trzeba było zrobić to metodą bliźniaczo podobną do tej której używało się 25 lat temu -> https://i.imgur.com/fqjnK.gif
Za pomocą jakiegoś linuxa z USB (ale nie jestem pewien czy nawet ta windowsowa konsola odzyskiwania systemu nie pozwoli tego zrobić...) podmieniamy sobie utilman.exe na cmd.exe i startujemy w trybie awaryjnym z opcja Wyłącz usługę wczesnej ochrony przed złośliwym kodem. Wchodzimy do ekranu logowania, klikamy na ikonkę "ułatwienia dostępu" która to ułatwia nam dostęp, odpalając nam zamiast utilmana root shella z którego możemy wygodnie ustawić hasło. "User friendly".

Freja Draco
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3394
2

T-mobile właśnie skasowało mi darmowe minuty i wiadomości.

Od jakichś 10 lat używam taryfy rodzina 20 za 20 zł miesięcznie i przez te lata praktycznie tyle właśnie płaciłam co miesiąc, ale od ostatniego doliczyli mi kilka zł za kilkanaście minut rozmowy. Cóż, chyba będę po prostu dopłacać te kilka złotych co miesiąc, bo przejrzałam aktualne taryfy i (jeśli nie zgodzę się na spamy reklamowe i fakturę elektroniczną) najtańsza z nich kosztuje... 55 zł / miesiąc.

Kurde, a myślałam, że w epoce szerokopasmowych połączeń i 5G usługi powinny być tańsze niż 10-20 lat temu :p

TO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 33
6

Zbiór WTFów: https://shitcode.net/

purrll
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kuala Lumpur
  • Postów: 241
0

str.islower()
Return True if all cased characters in the string are lowercase and there is at least one cased character, False otherwise.
str.isupper()
Return True if all cased characters in the string are uppercase and there is at least one cased character, False otherwise.

Kopiuj
ch_a = "Sasdneuneijmirjioeweij"
ch_b = "Seaxviijererijwrjnwija"

print(any(ch.isupper() for ch in ch_a))    // True
print(any(ch.islower() for ch in ch_b))    // True

&&

Kopiuj
str = "Sasdneuneijmirjioeweij"
print (str.isupper())                            // False
str = "Seaxviijererijwrjnwija"
print (str.islower())                            // False

Bython.

Korges
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 601
3

Konstrukcja tabeli w bazach danych po 100 kolumn, nazwa każdej kolumny skrótowce 6 literowe: NUMCHQ, DATREG, DATREJ, GUICHA itp, do tego wszystko w typie CHAR. Brak kolumny odpowiedzialnej za ID, mnóstwo stałych w kolumnach, klucz kompozytowy składający się z 6-10 kolumn (w zależności od tabeli). Wtedy też dowiedziałem się że CHAR na bazie sam dopisuje spacje do długości kolumny np NUMCHQ(32): "1234567890 .", i szukanie po findBy...() nie ma sensu, trzeba trimować kolumny na bazie albo jeszcze inne kombinacje...
Wkładając normalnie jakiś string, przy zapisie zostaną dodane spacje, przy wyciąganiu, trzeba je trimować.

Freja Draco
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3394
6
Freja Draco napisał(a):

T-mobile właśnie skasowało mi darmowe minuty i wiadomości.

No to się zdziwiłam. Napisałam tam do nich w zasadzie tylko po to, żeby sobie jadu trochę upuścić, a oni mnie przeprosili, napisali, że już naprawili problem i wystawili fakturę korygującą 8-O

Marooned
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
1

Właśnie trafiłem na kawałek kodu z września 2018 z komentarzem // todo: this code is written for temporary basis and will be removed before UAT ;-)

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
6

W PHP jest funkcja o nazwie: sodium_crypto_box_keypair_from_secretkey_and_publickey().

Trochę przydługa xd

PerlMonk
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa 🐪
  • Postów: 1719
Koziołek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Stacktrace
  • Postów: 6823
3

@TomRiddle, @PerlMonk: co wy tam wiedzie o długich nazwach:
https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/BoundTree/BoundTreeRewriter.cs#L100 → BoundTreeRewriterWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
https://gist.github.com/thom-nic/2c74ed4075569da0f80b → Lista długich nazw ze Springa

WhiteLightning
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3257
4

Urzedowo programistyczne WTF. Potrzebowalem rozliczyc podatek od dywidendy z USA, (do zaplaty mniej wiecej tyle ile kosztuje 0.5 l zwyklej wodki typu Wyborowoa). Kosztowalo mnie to caly wieczor. Jest sobie system Twoj E-pit ktory ladnie wszystko automatycznie wylicza, ale tylko na podstawie innych dokumentow PIT, wiec jak sie mialo umowe o prace ladnie wyliczy PIT - 37, spoko. ALE w Pit 37 nie ma mozliwosci zeby to dopisac, wiec trzeba zmienic na Pit 36. Na stronie jest nawet opcja konwersji do pit 36 ktora po kilku minutach sie wywala, w inspekcie strony leci jakis not found. No dobra, sciagam pierwszy lepszy program, jakies E-pity, a tam nie ma opcji zeby jakkolwiek dodac ten moj ogromny przychod, bo pola wyszarzone i nie ma opcji ktora mi to pozwoli zrobic. Instaluje E-deklaracje. Nie cierpie tego programu za nieprzyjaznosc i sposob w jaki jest robiona walidacja, czyli chcialbys wypelnic sobie w dowolnej kolejnosci pola, to jestes terroryzowany komunikatami ze nie wolno bo sie cos nie zgadza. No i trzeba jakies wynalzki typu Adobe-air czy Adobe Reader instalowac. Po prostu mozna sie poczuc jak w jakies zalosnej komedii.

KR
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2964
10

Ponieważ za licencje trzeba płacić niemało, nasi klienci często próbują wyciskać z serwerów ile się da. I tak, mamy tam takie ustawienie kontrolujące liczbę wątków w pewnej puli. Domyślnie ustawione na coś zbliżonego do liczby rdzeni. Klient stwierdził, że więcej wątków będzie szybciej, więc ustawił tam 1000. Następnie przyleciał do naszego supportu, że system mu działa niestabilnie (problemy z niedostateczna ilością pamięci).

Support oczywiście sprawdził konfigurację i nakazał zmniejszyć liczbę wątków do rozsądnej wartości. Na to klient zaprotestował, bo "gdy jest mniej wątków to działa za wolno i się nie wyrabia z naszym obciążeniem i macie to poprawić tak aby działało z 1000 wątków". Ech. Współczuję ludziom z pomocy technicznej.

Sarrus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2512
8

Ja miałem przypadek, gdzie firma wdrażająca nasz system, oszczędzała na sprzęcie. W efekcie musiałem optymalizować coś co optymalizacji nigdy nie potrzebowało, bo serwer radził sobie gorzej niż laptop.
W podobnym temacie koledzy aktualizowali jeden z modułów. Po tej zmianie zaczęły się problemy z pamięcią. Pierwsza myśl to jakiś wyciek, ale nie. Okazało się, że "serwer" na którym to stało miał 1 GB pamięci RAM. Czasem przetwarzamy na starcie dość spore ilości danych więc tyle to moduł jeden potrafi sam zeżreć...

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
1

Home office powoduje, że używam intensywnie Remote Desktop (RD) (z MacOS na Windows, ale to nieważne).
Zauważyłem ciekawego bug-a.

Normalnie jak RD jest podłączony i zdalna maszyna długo nie jest w użyciu, "ekran" na zdalnym komputerze ulega zablokowaniu zgodnie z ustawieniami. RD pokazuje ekran blokady tak jakby siedzieć bezpośrednio przy komputerze i trzeba podać hasło, by odblokować zdalny komputer. Nie jest to zaskoczenie, choć wygodniej by było polegać na blokowaniu ekranu komputera, z którego się użytkownik łączy. Samo połącznie RD nie jest zerwane i nie wymaga ponownego uwierzytelnienia.

Jednak z drugiej strony wczoraj/dziś stał się coś takiego:

  1. korzystałem ze zdalnej maszyny (przez VPN)
  2. wróciłem do lokalnej maszyny (RD w tle zalogowany)
  3. Odłączyłem VPN (klient RD próbuje odzyskać połączanie)
  4. Uśpiłem lokalną maszynę
  5. 12h później, przywróciłem lokalna maszynę
  6. włączyłem VPN
  7. Przełączyłem się na klienta RD, który odzyskał połączanie do maszyny zdalnej

EFEKT:
Jestem zalogowany do zdalnej maszyny bez podawania hasła. Ekran się nie zablokował (coś mrugnęło jak taki ekran). Żadnego ekranu blokowania, podawania hasła lub użytkownika, stan poprzedniej sesji się nie zmienił.

IMO to jest bug po stronie Windows.
Tyle, że jest pytanie: czy bugiem jest to, że automatyczne blokowanie ekranu się włącza?
Czy może jako bug, należy traktować to, że blokowanie ekranu nie włącza się po 12 godzinach, jeśli był problem z połączaniem?

Osobiście wolałbym wersję 1.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.