Programistyczne WTF jakie Was spotkały

Programistyczne WTF jakie Was spotkały
SA
  • Rejestracja:około 12 lat
  • Ostatnio:około godziny
  • Postów:1427
0
Kopiuj
 var query = _session.Query<Model>();
 var any = query.Single().Id == id; // Id generowane Fluent NHibernate, Guid.Comb, porównanie zwraca true
 var model = query.SingleOrDefault(x => x.Id == id); // a to daje null

Dawno nie miałem takiego WTFa nie wynikającego bezpośrednio ze słabych umiejętności, a ze specyfiki użytej bazy i naiwności, że ORM umożliwia bezbolesną podmianę bazy danych.

AreQrm
A tam nie powinieneś mieć query.Single(x => x.Id == id).Id == id?
SA
@AreQrm: no nie, ja wiem, że tam jest jeden rekord to sobie zrobiłem do debugowania single. No i Twój pomysł to null reference (patrz 3. linia). Różnica jest taka, że w drugiej linii porównujemy lokalnie, a w drugiej porównanie jest w SQL.
BE
  • Rejestracja:około 7 lat
  • Ostatnio:około 4 lata
  • Postów:35
12

może nie do końca programistyczny wtf, ale dziś w projekcie znalazłem tablice statusów które są randomowo używane jako wiadomości przy health-checkach:D

Kopiuj
    var statusesForDOWN = [
		'Pacjent w stanie krytycznym',
		'Wymaga reanimacji',
		'Ma dałna',
		'Ma raka',
		'Głowa urwana',
		'Brak mózgu',
		'Noga urwana',
		'Ręka urwana',
		"Jebnął o zol",
		"Brak macicy",
		"Członek nie wstaje",
		"Umarł",
		"Zdechł",
		"Sypnął kepa",
		"Leży",
		"Nie kopać leżącego",
		"Przerwa w życiu",
		"Smierć kliniczna",
		"Czeka na karawan",
		"Czeka na księdza",
		"Czeka na swoje 72 dziewice",
		"Osiągnął nirwanę",
		"Poszedł w diałby",
		"Poszło w pizdu",
		"Stan stabilny, terminalny",
		"Situation normal - all fucked up",
		"Podzielił los tupoleva",
		"Przedawkował",
		"Zalał się w trupa",
		"Ostatnie pożegnanie",
		"Przegrał z rakiem",
		"Przegrał z DESem",
		"Przegrał z apgrejdem",
		"Brak Intertnetu",
		"Zaliczył zgon",
		"Wyjebał się",
		"Wyjech do Sosnowca",
		"Oddany na złom",
		"Oślepł, ogłuchł i stracił czucie w palcach",
		"Porażenie mózgu",
		"Brak organów",
		"Poparzenie 100%",
		"Spalony żywcem",
		"Porwany przez kosmitów",
		"Porwany przez UFO",
		"Ma delirkę",
		"Wyjechał na Wyspy",
		"Zamknięty w Rybniku",
		"Zamknięty w Toszku",
		"Zamknięty w Tworkach",
		"Zamknięty w Lublińcu",
		"A kto umarł ten nie żyje",
		"Wącha kwiatki od spodu",
		"Kopnął w kalendarz",
		"Wyjechał nogami do przodu",
		"Zwolniony",
		"Oberwał granatem",
		"Zaginiony w akcji",
		"Przejechany ciężarówką",
		"Przejechany czołgiem",
		"Zahaczył o brzozę",
		"Wybuchło",
		"Jebło",
		"Padło",
		"Nie odbiera",
		"Poza zasięgiem",
		"Wyszedł na prostą",
		"Zatrzymenie pracy serca",
		"Trafił do piachu",
		"Zreanimowany przez łódzkie pogotowie",
		"Urwał kabel od Internetu",
		"Wypadł przez balkon",
		"Wypadł z okna",
		"Ubrał betonowe buty",
		"Przywitał się z kostuchą",
		"Zabrał go szatan",
		"Śpiewa w anielskich churkach",
		"Ostatnie namaszczenie",
		"Trafił go piorun",
		"Spadł w przepaść",
		"Szuka mózgu",
		"Zaatakowany przez zombie",
		"Zwinął interes",
		"Dostał nożem w oko",
		"Leży na cmentarzu",
		"Zeżarł go smok",
		"Rypnął go meteoryt",
		"Dobranoc!",
		"Mózg mu nie styka"
		
    ];
Kopiuj
var statusesForOOS = [
        'Ma zatwardzenie',
        'Ma kaca',
        'Złamał nogę',
        "Zaniemógł",
        "Boli go pośladek",
        "Ma czkawkę",
        "Ma okres",
        "Ma zły dzień",
        "Boli go głowa",
        "Ogarneły smuteczki",
        "Nie bo nie bo tak!",
        "Jak tak jak nie",
        'Dzwoń po łódzkie pogotowie',
        "Ale o sso si chosi",
        "Podaj pavulon",
        "Zbakany",
        "Przegrał życie",
        "Przegrał w piłkarzyki",
        "Przegrał w rzutki",
        "Płacze",
        "Kwiczy",
        "Piecze w dupie",
        "Ma przerwę",
        "Poszedł na obiad",
        "Poszedł do toalety",
        "Zapuszcza brodę",
        "Działa jak DMZ",
        "Ofiara losu",
        "Potrzebuje klina",
        "Potrzebuje RedBulla",
        "Wygrał w koło niefortuny",
        "Obszczał go pies",
        "Wpadł do hasioka",
        "Przejęty przez Avengers",
        "Pobrany do testów",
        "W dializach",
        "Ma konwulsje",
        "Ma sraczkę",
        "Rzyga",
        "Czyści go",
        "Dał dupy",
        "Puszcza się",
        "Jest wczorajszy",
        "Nie jest up-to-date",
        "Spóźnił się na stan dupy",
        "Poszedł na spacer",
        "Rodzice go nie kochają",
        "Kot go obsrał",
        "Potrąciło go Seicento",
        "Stracił jądra",
        "Wypadł dysk",
        "Wypadł z behlohu",
        "Wpadł w pokrzywy",
        "Został sierotą",
        "Stracił obie nogi",
        "Stracił obie ręce",
        "Złamał kręgosłup",
        "Zwija asfalt",
        "Zabłądził do domu",
        "Alleluja i do przodu",
        "Ubrał hełmofon"
    ];
edytowany 4x, ostatnio: bertie
Zobacz pozostałe 4 komentarze
BE
@Desu: prawa autorskie należą do Bogusia Sz.
BE
@Desu: btw. po przeczytaniu twojego nicku zorientowałem się że jeden ze statusów jest 'przegrał z desem' :D
hzmzp
fajne to zaimplementuje sobie apki :D
Azarien
mam nadzieję że tekst nie jest jedynym wyznacznikiem statusu, bo trudno spamiętać zwłaszcza takie nieoczywiste jak Szuka mózgu czy Został sierotą.
vpiotr
Lista operacji wspieranych przez umowe ubezpieczeniowa jest ciekawsza (bo mimo wszystko realna).
LU
  • Rejestracja:około 11 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Gdańsk
10

estimated


Azarien
normalka. (ale u nas nikt nie patrzy na estimated, a często jest 0 albo wartość z kosmosu)
Riddle
Standard. Estimated to często jest czas samego development'u pierwszej wersji. Wszystkie poprawki, story bugi, spotkania, obiady, konsultacje z QA'mi i reporterami to nie jest developent więc nie idzie do estimate :D ale zalogować trzeba.
TR
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 lata
  • Postów:731
0

Mam projekt na utrzymaniu. Spotkałem ostatnio klasę, która ma 2 metody: jedna metoda ma ponad 800 linii, z czego efektywnego może jakieś 500, reszta to komentarze. Druga metoda zwraca null.
gdzieś pośrodku tłuściutkiej metody napotkałem takie cóś:

Kopiuj
Boolean sprOSPOW65 = null;

a commit message: "Sprzątanie kodu"


musica curat corpus at animam
cerrato
Ciesz się, że nie wiesz, co było przed tym sprzątaniem
TR
try-catch(Exception e) {.... return null; } w tym kodzie to jest norma, ja ciągle się zastanawiam jak to działa na produkcji ¯_(ツ)_/¯
OK
Naprawdę ludzie piszą commit msgi po polsku, i to jeszcze z polskimi znakami? xD
TR
@okmanek: ano tak to w tym projekcie jest porobione. Jeden z ciekawszych jakie widziałem, to jakiś if-else z msg: "bagno"
Koziołek
@okmanek: jeżeli cały projekt jest robiony lokalnie i dla lokalnego klienta, to nawet kod jest po polsku.
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:około 3 godziny
  • Postów:8399
3

Boolean sprOSPOW65 = null;

co to może oznaczać? Może to pisał patriotyczny programista(aka "czy wybrano psa") i miało to oznaczać coś w stylu "sprawdź - OSoby POWyżej 65 lat"? o.O Może to miało sprawdzać, czy ktoś jest seniorem?


Zobacz pozostałe 16 komentarzy
vpiotr
Zwykla logika trojwartosciowa, uzywana takze w SQLu.
superdurszlak
@vpiotr: z tym, że null to nie jest najszczęśliwszy wybór jeśli chodzi o trzecią wartość, nawet jeśli świetnie oddaje nieokreśloność, bo np. w takiej Javie rzuci NPE przy każdej okazji
LukeJL
@vpiotr w sumie... brak wartości może mieć też sens semantyczny jako "nie wiadomo". Z drugiej strony potem trzeba obsługiwać edge case'y i sprawdzać, czy coś jest false, czy nullem (nie wiem jak to w Javie wygląda, ale w JS zarówno false, jak i null czy undefined są wartościami, które dają fałsz w warunkach, więc jeśli jest potrzeba odróżniania ich, to trzeba dodatkowe warunki pisać).
superdurszlak
@LukeJL w Javie trzeba się nakombinować żeby ten null w warunku nie skończył się w NPE. Poeksperymentowałem z ciekawości i zakładając że we flag jest null, to if(flag), if(flag == true), if(true == flag)... rzucają NPE. Chcesz nie mieć NPE? Nic prostszego: if(Objects.equals(flag, true)) czy if(Boolean.TRUE.equals(flag)) załatwiają sprawę. To ja chyba podziękuję za taką logikę trójwartościową :D
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:minuta
7

Fragment testu jednostkowego o nazwie PeriodicSchedulerTest

Kopiuj
    //start of the first task

    std::this_thread::sleep_for(m_snapshotDelay/2);     //0ms + m_snapshotDelay/2
    EXPECT_EQ(value1, 1);
    EXPECT_EQ(value2, 100);

    //start of the second task

    std::this_thread::sleep_for(m_expectedInterval);    //100ms + m_snapshotDelay/2
    EXPECT_EQ(value1, 2);
    EXPECT_EQ(value2, 101);

    std::this_thread::sleep_for(m_expectedInterval);    //200ms  + m_snapshotDelay/2
    EXPECT_EQ(value1, 3);
    EXPECT_EQ(value2, 102);

    //call reschedule on the first task in the middle of the interval
    std::this_thread::sleep_for(m_expectedInterval/2);  //250ms + m_snapshotDelay/2

Za robienie synchronizacji przez Sleep powinno się zsyłać do gułagu.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
Zobacz pozostałe 7 komentarzy
Sarrus
a potem rzuć kostką i jak wypadnie 1,3,5 to testy przechodzą.
MarekR22
po pierwsze w teście jednostkowym nie powinno być żadnych sleep w jakiejkolwiek formie. Jeśli kod produkcyjny używa jakiegoś sleep to testy powinny użyć mock'ów, żeby tylko udawać, że sleep się wykonuje. Celem jest, by testy wykonywały się w oka mgnieniu. Po drugie synchronizowanie rzeczy wielowątkowych za pomocą sleep jest sygnałem, że ktoś nie ma pojęcia o tym temacie. Powinno być użyte std::condition_variable. Po trzecie trafiłem na ten test, bo oczywiście pojawił się losowy fail testu.
LU
jeszcze powiedz, że to jakiś senior pisał :)
CZ
może to było wymagane gdzieś, pierwszy raz się z takim czymś spotykam xD
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10051
4

Nie moje, i nie do końca programistyczne (tzn tak, ale nie) WTF, ale na pewno jedno z dziwniejszych. Jadłem sobie obiad obok kolegi który robił aplikację.

Aplikacja ta miała podmieniać pewne placeholdery w wielu plikach w innym projekcie - robił taki tool CLI. Refaktorował sobie właśnie jakiś kod, działając na swojej lokalnej wersji projektu w którym to CLI miało podmieniać placeholdery. W trakcie refactoru, wkurzyło go to że PyCharm podpowiadał mu "code duplicated" z jego kodu oraz z kodu który był w venv. Tymczasowo więc usunął go, i podpiął swojego lokalnego pythona.

I bam. Program się włącza, ale debugger nie łapie breakpointów :o Co teraz. Poustawiał breakpointy w innych miejscach, dalej nic. Breakpointy odpalane z testów się łapią, z programu uruchomionego normalnie nie :o

Ściągnął przez homebrew inną wersję pythona i podpiął, również nie. Zainstalował od nowa to venv, z powrotem i niespodzianka... nadal nie działa :O Oglądałem biednego gościa jak chyba z 45 minut próbował odpalić ten debugger.

Odpowiedź:

  • podczas jego refaktoru, zmienił funkcję renderującą tak że nie doklejała początkowych spacji przed placeholderem.
  • Ale w regexpie szukającym placeholderów był również bug, który łapał tylko placeholdery przed którymi jest conajmniej jedna spacja (było \s+ zamiast \s*).
  • 80% kodu w aplikacji nawet się nie odpala gdy w pliku nie ma żadnego placeholdera, więc te breakpointy które poustawiał byłby złapane normalnie

Nie wiem czy bardziej WTF z takiego regexpa, czy z tego że nie zapiął breakpointa np w main'ie, żeby zobaczyć czy faktycznie nie działa ten debugger.

cerrato
Niech ten, kto przez jakąś głupotę nigdy nie stracił pół dnia życia, pierwszy rzuci kamieniem w dinozaura ;)
CZ
gdyby takich rzeczy nie było to każdy sprint trwałby max trzy-cztery dni
Marooned
Administrator
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 11 godzin
  • Lokalizacja:Poznań
3

Poniekąd ociera się o programistyczne WTF:

Próba złożenia wniosku o nowy dowód przez Internet:

  1. "złóż wniosek"
  2. loguję się na profil zaufany (zakładało się DG to się ma)
  3. error: "Potwierdź swój profil zaufany, aby skorzystać z tej usługi." - czyli mam profil zaufany, który nie jest zaufany (a był, bo wtedy osobiście do skarbówki musiałem się fatygować)
    "Zgłoś się do punktu potwierdzającego lub załóż nowy profil zaufany online"
  4. wybieram online, jest mBank, git
  5. klikam, loguję się w mBanku, przenosi mnie do jednej strony, a potem do https://online.mbank.pl/errors/404.html "Strona o takim adresie nie została odnaleziona."
  6. kurtyna

PA
To jest jakiś ogólniejszy problem, ja mam profil w PKO BP (tam zakładałem), i kiedyś przy jakiś urzędowych sprawach chciałem autoryzować sie mBankiem i nie poszło, żonie natomiast z mBanku pszeszło bez problemów...
Marooned
Ciąg dalszy. Na stronie banku jedyny formularz pozwala na założenie nowego PZ. Wpisałem więc ten sam mail i id, co stary. Dostałem komunikat, że wszystko ok. Dostałem maila od pz.gov.pl, że PZ założony poprawnie. Wbiłem na stronę ..gov.pl, wybrałem logowanie PZ, poprosiło mnie o id i hasło (co ciekawe, nigdzie nowego hasła nie dało się wpisać ani nie wygenerowało, więc skąd ktoś może je mieć?) - wpisałem mój stary/nowy id i stare hasło, zalogowało mnie i wywaliło, że mam niepotwierdzony PZ i nic nie załatwię... dramat w 3 aktach
Marooned
Dobra, udało się zalogować z pz.gov.pl przez bank, ale na kij miałem podawać id w takim razie, to nie ma sensu, bo pod tym id mam jakby inny PZ. Można zwariować.
KR
Ja musiałem kiedyś ciasteczka wyczyścić. Strona z jakiegoś powodu zapamiętywała, że mam niepotwierdzony profil założony przez login i hasło i próbowała mnie logować ta ścieżką, a nie przez bank. Wywalenie ciastek naprawiało to.
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:około 2 godziny
  • Lokalizacja:Wrocław
5

Po dopracowaniu rozwiązania każdy będzie mógł założyć własny drzewiasty wątek.
Zobacz pozostałe 12 komentarzy
AreQrm
Tylko ta 2 opcja, jak posortować alfabetycznie (intelliSense) to ciężko coś znaleźć, przy pierwszej trochę czytelniej i łatwo wklepać z numerem pisząc np .404
GS
A ja w zasadzie usunąłbym i "status" i numer z nazwy. Bo w zasadzie po co numer w nazwie? Po to się zastępuje numery stałymi, żeby interpretować wartości jako "Continue" albo "OK" a nie jako liczby. Kiedyś ktoś wymyśli, że trzeba wszystkie numery przesunąć i wyjdzie potworek w stylu const int Status200_OK = 300;
Azarien
Akurat w tym przypadku numer jest uzasadniony, bo są te numery w powszechnym użyciu. @GutekSan nikt tych numerów nigdy nie przesunie, albo to nie będzie już HTTP.
somekind
No właśnie, numery są w powszechnym użyciu, więc się je pamięta. HttpStatusCodes istnieje w normalnym frameworku i sprawdza się dobrze. No, ale w Core musieli coś "lepszego" wymyślić w ramach udawanej rewolucji. A jak już robią taaaaaaaaką rewolucję, to niech poprawią przy okazji język, żeby mogli zrobić to z numerem i nazwą, ale bez durnego prefiksu.
Marooned
Też nie znałem połowy żargonu, w tym smerfów. Link z komentarza lepszy niż z postu (jest na to jakiś hashtag?)!
Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 6 godzin
  • Lokalizacja:Laska, z Polski
  • Postów:10051
2

Może nie do końca wtf, kolega go zauważył w moim kodzie.

Mam plik case.py w którym są metody do konwersji typów np z PascalCase to snake_case. Kolega mówi że chyba mam literówkę bo klasa do testów nazywa się CaseTest (zamiast TestCase).

edytowany 3x, ostatnio: Riddle
Marooned
Administrator
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 11 godzin
  • Lokalizacja:Poznań
6

Zagadka!

  1. odpowiedz sobie "co OLX zwraca na zapytanie dłuta"? (można wrzucać odpowiedzi w komentarze, ale bez spoilerów)
  2. kliknij i porównaj swoją odpowiedź z wynikami

edytowany 1x, ostatnio: Marooned
Zobacz pozostałe 9 komentarzy
Marooned
Też myślałem o podobieństwie (zobacz https://pl.wikipedia.org/wiki/Odleg%C5%82o%C5%9B%C4%87_Levenshteina + https://pl.wikipedia.org/wiki/Soundex) ale poza jedną literą nijak nie widzę podobieństwa.
Silv
@Koziołek: czyli mniej-więcej dobrze myślę w tym pseudokodzie powyżej czy nie?
Koziołek
@Silv: mniej więcej tak, choć działa to inaczej. Coś w stylu index.all().map(i =>i.similarTo(searchText)).order().asList() gdzie index.all zwraca wszystkie używane sposoby porównywania.
Silv
OK, dzięki.
no_solution_found
też mi się wydaje, że siedzi tam jakiś elastic. "Zwykła" baza by nie pociągnęła takiego ruchu + poprawy literówek. Tym bardziej, że dla frazy "długo" to podaje lepsze wyniki.
cerrato
Moderator Kariera
  • Rejestracja:około 7 lat
  • Ostatnio:około 13 godzin
  • Lokalizacja:Poznań
  • Postów:8758
4

Bug OR feature? ;)

screenshot-20200128121521.png


hzmzp
Jak pierwszy raz przeczytałem to nie zajarzyłem tego or, ale to się robi wszystko naturalne...
cerrato
Mi akurat od razu się to rzuciło w oczy, jak tylko wszedłem na stronę. Przy czym w pierwszej chwili nie wiedziałem, w czym jest problem - po prostu coś mi nie pasowało, dopiero za 2-3 razem zauważyłem, co jest źle.
hzmzp
Dałem chłopakom z roboty do przeczytania, mieli to samo co Ty :p
satirev
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 4 lata
2

Kilka ciekawostek z jednej ze znanych konsol:

  • implementacja STL'a jest dość słaba i miejscami można spotkać niespodzianki w stylu sizeof(std::unique_ptr<T>) == 16 (default deleter jak by ktoś pytał). Błąd wynika z tego, że ktoś zamiast utworzyć alias typu, zinstancjonował template. Bug zgłaszany wielokrotnie, oficjalnie "nie do naprawienia, bo złamie ABI, a dwóch ABI nie będziemy/nie chcemy wspierać"
  • unmapping zacommitowanego bloku, który jest połączeniem kilku, ciągłych commitów bez "łączenia" (no coalescing) skutkuje radosnym decommitem 1 bloku oraz innego, dowolnego(?) podmontowanego pod inny virtual range
  • system pozwala na użycie TLS dla non-POD. Co ciekawe obiekty tego typu trzeba zwolnić wołając osobną funkcję (to nie jest do końca wtf ale zaczyna się robić zabawnie, gdy weźmie się pod uwagę kompilację z -fno-c++-static-destructors)
  • systemowe libki są dostarczone w 2 rodzajach stubów przy czym dokumentacja od (przed)premiery konsoli mówi o tym, że działa tylko 1 wersja, a druga będzie dostępna "niedługo" ;>
axde
  • Rejestracja:prawie 6 lat
  • Ostatnio:prawie 5 lat
2

Free: a terrible programming language that targets an even worse programming language.

https://github.com/adam-mcdaniel/free

I decided to name this programming language free because there are absolutely no memory constraints whatsoever. It's basically impossible for a free program to segfault or anything like that: you can arbitrarily assign to any memory location. This isn't by design. It's just a byproduct of the target programming language: SMPL.

Honestly, I'm not sure I still understand the complete scope of how the entire compiler works. A lot of it seemingly works by magic. Nevertheless, I'll still try to give a meaningful explanation. Do not trust this software because I honestly have no idea why it works.

MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:minuta
4

Historia sprzed 5 minut:

Visual Studio 2019 Enterprise

  • piszę test
  • naciskam enter i nic
  • wciskam losowe litery, te się normalnie pojawiają,
  • chcę to skasować, więc bakcspace, ale brak reakcji
  • poruszanie się kursorami też nie działa
  • Ctrl-S też nie
  • enter i znowu brak reakcji
  • ale litery dalej mogę pisać
  • w takim razie zamykam aplikację
  • pytanie czy chcesz zapisać plik JakisTest.cpp? Nie!
  • pytanie czy chcesz zapisać plik CMakeLists.txt?

Że co? Nie dotykałem tego pliku. Patrzę i wszystkie "enter" i backspace (oraz strzałki) wylądowały w tym pliku (oknie)

Nie mam pojęcia jakaż to funkcjonalność spowodowała, że pisanie tekstu lądowało w jednym oknie (które widziałem), a enter i backspace w innym oknie.
Na razie nie mam pojęcia jak to odtworzyć.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 3x, ostatnio: MarekR22
Zobacz pozostałe 4 komentarze
MarekR22
Bez ReSharper VS raczej nie da się używać. To jedyny plugin.
Silv
Ja nawet nie wiem, co wpisać do Google, żeby wyszukać ten problem.
somekind
@MarekR22: a miałeś otwarty ten drugi plik na jakimś innym ekranie?
MarekR22
Tylko jeden ekran, jedna instancja VS, jedno główne okno VS, entery po prostu szły do innego taba. Dość intensywnie używam VS 2019 od paru miesięcy (wcześniej VS2017) i pierwszy raz zrobiło mis się coś takiego. Jedynie co mi się zmieniło ostatnio, to upgrade do z wersji Professional do Enterprise (dla potrzeby code coverage).
somekind
Dziwna sprawa w takim razie.
Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
4

Sytuacja z dzisiaj. Robimy system do wparcia procesu obsługi wsparcia mailowego dla klientów. W dużym skrócie piszesz na support@korpo.com, a mail magicznie ląduje u odpowiedniej osoby. Od pewnego czasu pojawiał się na monitoringu błąd, że Jason.Encoder nie ma wywołanej funkcji. Elixir językiem dynamicznym i czasami się tak zdarza, ale przyszło nam zająć się tym problemem. Zaczęliśmy grzebać w naszym kodzie i analizować kiedy pojawia się błąd.

Błąd pojawia się, jak przychodzi do nas wywołanie z MailGuna z informacją o błędzie dostarczenia.

Pierwsze podejrzenie – MailGun ma coś ze swoim API i generuje błędne jsony. Robimy więc zrzut i rzeczywiście wychodzi, że cholera nieprawidłowo obsługuje znaki nowej linii w wielolinijkowych stringach przesyłanych JSONem. Przykładowo z[1]:

Kopiuj
{
   "klucz": "Ten string
ma wiele
linii"
}

powinien wyprodukować[2]:

Kopiuj
{
   "klucz": "Ten string\\nma wiele\\nlinii"
}

a produkuje [3]:

Kopiuj
{
   "klucz": "Ten string\nma wiele\nlinii"
}

Czegoś takiego nie chwyta Jason, który jest domyślną biblioteką do obsługi JSONa w Phonixie. Ok… szybki ticket do twórców biblioteki z pytaniem „o co kaman”, ale okazuje się, że wszystko jest OK, bo to nie jest poprawny JSON. Co ciekawe Poison, czyli inna biblioteka do tego samego, potraktuje kod z [3] jako poprawny. No to mamy babola, puścimy jeszcze ze dwa testy i przejrzymy inne wystąpienia, by mieć pewność, ale oczywiście okazuje się, że to nie to. Grzebiemy dalej.

Ustawiliśmy sobie logowanie tego, co wychodzi z mailguna do ichniego bucketa, ale to gówniana opcja. Mailgun bucket to taki endpoint, na którego można w mailgunie dodatkowo przekierować maila. Będzie on wysyłany na nasz „głowny” endpoint, jak i do bucketa właśnie. Idea polega na tym, że w buckecie ląduje dokładnie to, co wychodzi z serwera. Tyle tylko, że zanim zostanie wyświetlone w GUI, to jest poddawane „obróbce wstępnej”. Tym samym zamiast danych w czystej postaci dostajemy coś przetworzonego. Przypominam, ze funkcjonalność służy do wyświetlania nieprzetworzonych danych. Super implementacja kurwo…

Lecimy dalej. Mijają kolejne dwie godziny, a ja z kolegą dzielnie blokujemy firmowy kanał wideo.

Kolejnego loga przeglądamy i nagle mnie olśniło.
– Te, prezes, a daj ciapka w tytule maila…
– OK – tak trochę patrząc na mnie jak na wariata…

JEBUT!!! Mamy błąd. Z jakiegoś powodu Jason wywala się na JSONie z apostrofem w stringu. Szybka weryfikacja w iex, bo błąd wydaje się na tyle absurdalny, że aż niemożliwy… w iex działa bez zarzutu. Raz jeszcze zaczynamy grzebać w logu. Tym razem analizując śmieciową część stacktrace, czyli komunikat błędu. Tu uwaga, komunikat o błędzie w elixirze ma kilka części. Właściwa wiadomość oraz stos to jedno, ale zazwyczaj dołączany jest też zrzut komunikatu z erlanga, który jednak nie jest sformatowany i dość nieczytelny. I nagle odkrycie w jednym prawdziwym źródłem naszego błędu jest jeden z plugów phoenixa. Szybka przesiadka na źródła phoenixa i… dupa. Kompletnie nic nie znaleźliśmy. Po drodze jeszcze zrobiliśmy analizę zmian wersji bibliotek i wyszło, że po zmianie wersji phoenixa zaczęło się sypać.

Podsumowanko

  • wiemy, co powoduje problem – apostrof w tytule lub treści maila wysłanego na nieistniejący adres za pośrednictwem mailguna;
  • wiemy, gdzie mniej więcej jest wyrzucany wyjątek – z dokładnością, do wersji funkcji, ale to wystarczy, bo one używają wzorca łańcucha wywołań;
  • wiemy, że problem pojawił się po migracji z 1.4.11 na 1.4.12 – analiza zmian po naszej stronie i korelowanie ich z informacjami z loga;
  • wiemy, że nic nie wiemy – bo błąd nadal jest, ale nie wiadomo jak do niego podejść;
  • finalnie sprawę chyba olejemy, pisząc jakiegoś hacka.

Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
hauleth
Masz przykład i stacktrace? Może na coś trafię.
Koziołek
Soft zamknięty i niestety nie mogę się podzielić publicznie :(
hauleth
Żadnego PoC? To by wystarczyło. Dodatkowo nie zmieniliście np. przypadkiem wersji Elixira np.? Bo 1.10 powoduje problemy w niektórych loggerach, które były niezgodne ze specyfikacją (trochę z mojej winy). Przykładowo LoggerJson.
Koziołek
@hauleth: a będziesz na LambdaDays? Bo PoC niewiele by wniósł, bo tu chodzi o cały przepływ między nami, mailgunem i gmailem.
hauleth
W poniedziałek lecę do DE, więc niestety nie. Zapomniałem o tym nawet.
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:minuta
1

Testuje upgrade instalacji na mac OS, więc z linii poleceń leci:

Kopiuj
Mac-mini:Downloads ItsMe$ sudo installer -dumplog -verbose -pkg MyAppPackage.pkg -target /

To daje takie logi:

Kopiuj
installer: Package name is My Product
Feb 11 18:03:14  installer[15990] <Debug>: Product archive /Users/ItsMe/Downloads/MacOS_AgentInstallVersions/EEI_1.4.1277/MyAppPackage.pkg trustLevel=350
Feb 11 18:03:14  installer[15990] <Debug>: External component packages (1) trustLevel=350
installer: Installing at base path /
installer: Przygotowuję instalację….....
Feb 11 18:03:14  installer[15990] <Debug>: -[IFDInstallController(Private) _buildInstallPlanReturningError:]: location = file://localhost
Feb 11 18:03:14  installer[15990] <Debug>: -[IFDInstallController(Private) _buildInstallPlanReturningError:]: file://localhost/Users/ItsMe/Downloads/MacOS_AgentInstallVersions/EEI_1.4.1277/MyAppPackage.pkg#output.pkg
Feb 11 18:03:14  installer[15990] <Debug>: Set authorization level to root for session
Feb 11 18:03:14  installer[15990] <Info>: Administrator authorization granted.
Feb 11 18:03:14  installer[15990] <Debug>: Will use PK session
Feb 11 18:03:14  installer[15990] <Debug>: Using authorization level of root for IFPKInstallElement
Feb 11 18:03:14  installer[15990] <Info>: PackageKit: Skipping component "com.company.product" (1.4.1277-1.4.1277-*) because the version 1.4.1283-1.4.1283-* is already installed at /Users/ItsMe/repos/Component/Products/MyRepository/Src/Debug/My Product.app.

Logi ciągną się dalej, ale najciekawsza jest ostatnia załączona lina, którą można przetłumaczyć tak:

hej znalazłem komponent "com.company.product" w twoim prywatnym repozytorium, który jest nowszy, niż ten który chcesz zainstalować w katalogu systemowym, więc ci go nie zainstaluje. Mam gdzieś, że jest to daemon, który wskazywany jest przez jakiegoś xml-a do uruchomiania w odpowiednim wypadku (oczywiście nie uruchomi się, bo jest gdzie indziej), ale będę wciskał ci kit, że wszystko zakończyło się sukcesem.

Na dodatek to nie koniec WTF. Do deinstalacji napisałem sobie skrypt, który pobiera informację o zainstalowanej paczce i na tej podstawie usuwa pliki i katalogi (swoją drogą niezły WTF, że nie ma tego w systemowym automacie). Celem była elstyczność, że nieważne co zmienię nie muszę poprawiać deinstalatora.

Co widzę w logach deinstalatora? Próbuje skasować ten komponent, który stwierdził, że nie wymaga instalacji i robi to w miejscu, gdzie powinien być, więc leci "File not found: ".
Czyli nie zainstalował gdzie miał, ale zapisał sobie, że zainstalował poprawnie w tamtym miejscu.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22
katakrowa
  • Rejestracja:około 10 lat
  • Ostatnio:około 2 lata
  • Lokalizacja:Chorzów
  • Postów:1670
4

Taka zwykła historia co do której zastanawiam się czy tylko ja jestem takim debilem ...

Zwyczajna sytuacja siadam do komputera i piszę przez kilka godzin jakiś kod, jakąś większą klasę czy nawet kilka plików lub jakieś skrypty na serwer. Na koniec zadowolony, że skończyłem pracę przed zrobieniem backup'u i wyłączeniem komputera chcąc "posprzątać po pracy" bezmyślnie wywalam katalog z plikami, na których przed chwilą pracowałem!
Mam jeszcze taki kretyński nawyk, że pliki prawie zawsze wywalam z SHIFT ( czyli nie lecą do kosza tylko kasowane są bezpowrotnie ).
Po chwili nadchodzi ten moment kiedy orientuje się co zrobiłem ... W nadziei, że może tym razem shift'a nie nacisnąłem zaglądam do kosza ... a tam pusto...

Już kilka razy w życiu tak zrobiłem.


Projektowanie i programowanie. Hobbystycznie elektronika i audio oszołom.
edytowany 1x, ostatnio: katakrowa
Zobacz pozostałe 15 komentarzy
cerrato
Czyli rozumiem, że popierasz obowiązek zapinania pasów w samochodach?
Azarien
Nie mówimy o obowiązku, tylko o tym co powinno być ustawieniem domyślnym.
somekind
Jeśli ktoś nie patrzy, co robi, to nie jest wina systemu. Po to jest kosz, żeby użytkownika ochronić, czyszcząc kosz też trzeba myśleć. Żadne domyślnie włączone/wyłączone opcje nie sprawią, że ludzie będą myśleć.
AreQrm
"Już kilka razy w życiu tak zrobiłem." No i to jest WTF. Czemu jeszcze się nie nauczyłeś czegoś z tym zrobić? Zmienić nawyki albo robić kopie zapasowe...
PerlMonk
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Warszawa 🐪
  • Postów:1719
6

Skoro już przyznajemy się do drobnych pomyłek, http://bash.org.pl/26357/ . To było śmieszne dopóki nie zrobiłem tak sam. Na szczęście drugi plik mogłem sobie wygenerować w kilka minut.


Nie sztuka uciec gdy w dupie sztuciec. 🐪🐪🐪
Zobacz pozostałe 6 komentarzy
Silv
Dobrze, że piszesz bez kropki...
PerlMonk
Dwie napisałeś za mnie. Dziękuję :)
PerlMonk
:P
LukeJL
ja jak zaczynałem z linuxa korzystać, to myliło mi się przeznaczenie komendy rm. Myślalem, że to skrót od rename, a nie od remove...
cerrato
Moderator Kariera
  • Rejestracja:około 7 lat
  • Ostatnio:około 13 godzin
  • Lokalizacja:Poznań
  • Postów:8758
8

W temacie WTF związanych z koszem (kwestia poruszana 2 posty wyżej) :

Mam taki odruch, że jak siadam do kompa i zobaczę, że coś w nim jest, to automatycznie prawym na koszu i "opróżnij". Tylko robię tak nie tylko na swoim kompie, ale na każdym, do którego (chociaż na chwilę) siadam. Kiedyś pomagałem w czymś koleżance w firmie, usiadłem do jej kompa i opróżniłem kosz. A ona zaczyna panikować, bo miała tam ważne dokumenty. Ja na to zupełny WTF, ona prawie płacze z przerażenia.

Okazało się, że pół dnia temu coś przypadkiem skasowała, ale była spokojna, bo to było w koszu. Nie odzyskała tych plików od razu, bo do zadania, z którym te pliki były związane planowała wrócić i dalej pracować nad nim za kilka godzin... Babska logika...

A z cytatem @katakrowa - "Po chwili nadchodzi ten moment kiedy orientuje się co zrobiłem ... " skojarzył mi się ten obrazek:

screenshot-20200214083211.png


edytowany 1x, ostatnio: cerrato
Zobacz pozostały 1 komentarz
cerrato
Też miałem parę razy, że siadam do jakiegoś kompa żeby coś komuś zrobić/naprawić i pojawia się konieczność restartu, a ta osoba panikuje, bo miała tam wszystko pootwierane. Norma :D
cerrato
Zresztą sam często jak kończę pracę, a nie chcę tracić zakładek, to w terminalu daję killall firefox - po ponownym odpaleniu pyta mnie, czy przywrócić sesję.
Marooned
2 dni temu w końcu znalazłem chwilę by przeczytać wszystkie otwarte zakładki na telefonie - od ~2 m-cy miałem ze 20 otwartych "na później" ;)
LukeJL
Kiedyś pomagałem w czymś koleżance w firmie, usiadłem do jej kompa i opróżniłem kosz urwis z ciebie xD
cerrato
@LukeJL: czytałem to zdanie kilka razy i za cholerę nie jestem w stanie dostrzec w nim podtekstów :D
Sarrus
  • Rejestracja:prawie 14 lat
  • Ostatnio:3 dni
  • Postów:2512
1

Tak w temacie przypadkowego usuwania. Chciałem wyczyścić folder tymczasowy w %appdata% i przez pomyłkę wyczyściłem cały folder nadrzędny - czyli %appdata% :). Kosz w tym przypadku nie pomógł, bo całkowity rozmiar był zbyt długi. Narobiłem sobie problemów, ale i tak dobrze, że nie kasowałem folderu Temp w Windows ;)

edytowany 1x, ostatnio: Sarrus
cerrato
Ten temp to jakiś żart, czy serio? Ja go czasami (jak mnie najdzie ochota albo jak się nudzę) czyszczę i nie wiedziałem, że to może być niebezpieczne...
Sarrus
No serio tylko pomyliłem katalogi i usunąłem katalog nadrzędny ;)
PerlMonk
@cerrato: Cały Windows to jakiś żart.
cerrato
@Sarrus: OK, bo już się bałem, że zaraz dowiem się o jakimś bug/ficzer w Windows, który powoduje, że czyszczenie TEMP zabija system :D
freemp3
  • Rejestracja:około 11 lat
  • Ostatnio:około 12 godzin
  • Lokalizacja:Miechów
  • Postów:284
3

To jak już jesteśmy w temacie wpadek. Tworzę od jakiegoś dłuższego czasu (z przerwami mniejszymi i większymi) prostą apkę w laravelu dla własnego użytku. Pierwotnie chodziło mi tylko o nauczenie się nowego FW, ale jako że apka działa dość fajnie to zacząłem trochę z niej korzystać i dalej rozwijać. Jakoś ponad pół roku temu przenosiłem się na inny hosting i podczas konfigurowania adresu pod apkę była możliwość odseparowania jej od innych aplikacji, co w zasadzie sprowadzało się do tego, że PHP nie mógł dołączać plików z poza katalogu root, czyli w laravelu był to public. Skutkowało to tym, że aplikacja nie działała bo nie mogła załadować nic, co było powyżej katalogu public. Zamiast wyłączyć tę blokadę to mój wspaniały geniusz stwierdził, żeby ustawić root-a na katalog wyżej, a w htaccess przekazać żądanie na plik public/index.php, bo przecież będzie bezpieczniej jak blokada będzie włączona ;) No i pewnie było by to spoko, gdyby nie warunek, że żądanie ma być przekazane tylko jeśli serwer nie znajdzie pliku ani katalogu. Aplikacja oczywiście zadziałała, więc cacy ;)

O tym jakie to miało skutki dowiedziałem się wczoraj. Próbując skorzystać z apki zamiast panelu logowania pojawiły się błędy z problemem dostępu do bazy. Po zalogowaniu do bazy okazało się, że bazy nie ma, jest jedynie tabela WARNING z informacją od włamywaczy, żeby im wpłacić ileś tam BTC to odzyskam bazę, a oni jej nie upublicznią ( może i bym się tym przejął gdyby nie to, że nie ma tam nic wartościowego, czego upublicznienie by jakoś mnie zabolało, a kopię bazy mam ;) )

Zapewne część z was się domyśla co się odwaliło. W logach oczywiście nic nie znalazłem oprócz zapytań na adresy typu wp, wp-admin, old, new itp. ale ciekawiło mnie skąd mieli dostęp do bazy więc sprawdziłem jak jest z dostępem do pliku .env. Tak plik .env był dostępny publicznie i każdy mógł sobie go ściągnąć po wpisaniu odpowiedniego adresu ;) Podobnie cały katalog vendor ze wszystkimi bibliotekami itp.

W między czasie stawiałem jeszcze jedną apkę na laravelu u siebie, ale tam zrobiłem to już jak należy, czyli katalog root na public i wyłączona blokada. Nie mam pojęcia, co mnie w tedy podkusiło, żeby to zrobić w taki dziwny sposób ;) W każdym razie apka jest już poprawnie skonfigurowana, stara nazwa bazy oraz użytkownik usunięci i założona nowa baza z nowym hasłem oraz nauczka na przyszłość, żeby nie kombinować ;)


Zobacz pozostałe 25 komentarzy
freemp3
Dokładnie tak jak napisał @cerrato, zamiast zrobić to tak jak Bóg przykazał i ustawić katalog publiczny na katalog public laravela to ustawiłem go na całą aplikację przez co atakujący bez problemu wyciągnął to czego szukał. Teraz konfiguracja została poprawiona i już tak łatwo nie będzie ;)
cerrato
Jedma uwaga - są duże szanse, że Bóg nie istnieje, więc podczas konfigurowania systemu, zamiast powoływać się na jego przykazania, lepiej opierać się na dokumentacji technicznej :D
freemp3
W takim razie jak dokumentacja przykazała ;)
hauleth
Pliki .env to rak, zwłaszcza w drzewie projektu. Z jakiegoś powodu mamy w systemd EnvFile.
Delor
Zawsze znajdzie się jakiś bug. W dokumentacji też może być.
xxx_xx_x
  • Rejestracja:prawie 13 lat
  • Ostatnio:9 dni
  • Postów:365
8

Tak mi sie przypomniało, kilka lat temu na serwerze odpaliłem jakiś skrypt instalacyjny dostarczony razem z paczką.Skrypt zaczynał się jakoś tak :

Kopiuj
rm -rf  $APP_ROOT/

Problem w tym że zmienna środowiskowa $APP_ROOT nie była ustawiona na serwerze, ani nie było informacji/zabezpieczeń na taka sytuacje.
W ten sposób zaorałem cały serwer :D

Zobacz pozostałe 5 komentarzy
cerrato
Wiecej wiary przyjacielu ;)
Sarrus
Steam na linuxa miało swego czasu podobny błąd
hauleth
GNU obecnie na to nie pozwoli, a macOS ma SIP, który nawet jak dasz sudo rm -rf / nie usunie plików systemowych.
Pipes
Po takiej instalce ile za to miejsca na dysku ^_^
MO
Stara szkoła zaleca: touch /-i; a jeśli chcesz usunąć taki plik to tak: rm -- /-i;
Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
4

Przypadkowe usunięcie tablicy alokacji partycji, bo wybrałem nie ten dysk. Zdjęcia z jakiś 8 lat poszły się paść. Do tego muzyka, filmy, dokumenty firmowe… tia a miał być szybki formacik pendriva.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
Zobacz pozostałe 15 komentarzy
Azarien
@perlMonk bo mi się nie chciało/nie miałem czasu się go pozbyć, a wymagało to dużo roboty (jak już pisałem, do niedawna był na nim jedyny bootloader) której tylko część na razie zrobiłem (zostało ogarnąć bootowanie FreeBSD albo jego reinstalka), a skoro dysk działa to niech sobie chodzi (komp ma łącznie 3 dyski). ostatnio jednak dysk zaczął sprawiać problemy.
KR
Akurat usunięcie tablicy partycji jest operacja w pełni odwracalna. Przecież sama partycja i jej dane nie zostały naruszone. Jedyne co skasowałeś to informację o tym gdzie partycje się zaczynają, gdzie kończą i jakiego są typu.
Azarien
tak w pełni to nie zawsze, ale jest duża szansa na jej odtworzenie narzędziami które znajdą i przeanalizują filesystemy na dysku. jeśli jednak na dysku były w plikach jakieś obrazy innych dysków, to może to namieszać przy detekcji.
KR
Większość instalacji ma jedną partycje w domyślnym miejscu, więc w zasadzie wystarczy tylko prawidłowo przywrócić jej początek, co nie powinno być trudne. Tak czy inaczej w takiej sytuacji najlepiej przemontowac dysk w trybie read-only I zrobić jego kopię za pomocą dd i działać na kopiach.
Azarien
Pamiętam że kiedyś odtworzyłem tablicę partycji ręcznie, licząc offsety i wpisując w jakimś disk editorze… ale partycja była chyba jedna.
renderme
  • Rejestracja:około 6 lat
  • Ostatnio:około 4 godziny
  • Postów:1461
8

Tez mialem jedno wtf. Firma chciala mvp na prosta gierke multiplayer. Zrobilem mvp- aplikacje mobilna nie umieszczona na storze i serwer websocket w node, ktory im odpalilem na localhoscie. Powiedzieli, ze chca testowac poza biurem.
Bylem u nich, wiec spytalem, czy maja vps/hosting z nodem. Nie mieli, ale mieli nasa ze 128 mb ram i jakas dziwna dystrybucja linuxa. Odpalilem im tam ten serwer node z pm2, nginx i ustawilem reverse proxy + letsencrypt. Do testow dzialalo. Nigdy nie zamowili finalnej wersji.
Po 1.5 roku zadzwonili do mnie, ze aplikacja przestala dzialac.
Ja sie pytam, jaka aplikacja, jak jej ostatecznie nie zamowili.
Oni na to, ze ta co im robilem (mvp) NIEPRODUKCYJNE, ktore oni uzywali na produkcji. Sprawdzilem, trzeba bylo zresetowac nginx, bo korzystal z nieodswiezonego certyfikatu, wiec po resecie serwer dziala dalej na NASie z 128 mb ram, oni uzywaja tego na produkcji, bo zal im bylo kasy na kompletny produkt.


Granie w gry i robienie gier ma tyle wspólnego, co uprawianie seksu z pracą ginekologa.
Zobacz pozostałe 7 komentarzy
dzek69
serwis mało używany i/lub dobrze napisany ;)
Marooned
Rozbudziłeś moją ciekawość co to za gierka :)
dzek69
Będziesz sprawdzał ile telefonów potrzebujesz, żeby położyć takiego NASa? ;)
renderme
To była gierka "eventowa", tj. firma na różnych pokazach/targach rozdawała tablety i użytkownicy mogli grać - musieli wykonać zadania/zebrać przedmioty/odpowiedziec na pytania przed innymi. Z tego co patrzyłem na logi, to chyba klienci też ją ściągali i sobie zwyczajnie grali, ale była tam opcja zalogowania sie jako game master i zwykły użytkownik. Całość rozgrywki może 3 minuty, kto zebrał najwięcej punktów dostawał jakąś nagrodę. Czy dobrze napisany serwer? Większość multiplayer robię na websocket i mam swoje rozwiązania, które delikatnie modyfikuje.
Azarien
@renderme: działa? działa. to znaczy że "kasa na kompletny produkt" byłaby zmarnowana na przekombinowany system. @Sarrus jakby skasował to skończyłoby się przegranym pozwem.
renderme
  • Rejestracja:około 6 lat
  • Ostatnio:około 4 godziny
  • Postów:1461
12

Przypomniało mi się jeszcze jedno WTF.
Robiłem aplikację frontendową, całkiem sporą. Dostałem dokumentację backendu (swagger), ale beckend nie był zrobiony, chociaż powinien stać od pół roku.
Oczywiście firma dbała o bezpieczeństwo (hehe), więc nie miałem żadnych dostępów do ich serwera.
Powiedziałem, że ja chcę już mieć zapłaconą fakturę, bo swoje zrobiłem.
Ich menedżement odpowiedział, że muszę im przekazać działającą na ich stronie aplikację.
Ja im na to, że nie będzie działać, jak nie będzie backendu, a robi go ktoś inny.
Na to firma powiedziała mi, że zapłaci fakturę i jeszcze dopłaci sporo, jak przygotuje skrypty PHP, które będą zapisywać/odczytywać potrzebne dane w zaszyfrowanym tekście w plikach tekstowych, oczywiście z niedomyślnymi nazwami plików, a oni za tydzień jak skończą backend to sobie to przepną na bazę danych. (na tę chwilę pewne funkcję już backend miał, zarządzanie sesją, przekierowania, więc było to teoretycznie możliwe.)
Myślę sobie - wiocha na 100%, ale potrzebuję pieniędzy. Piszę z nimi aneks, że jak w wyniku takiego działania poniosą szkody, to nie jest na moją odpowiedzialność i przekazuję taką wersję + fakturę, wierząc, że to przepną za tydzień na właściwy backend.

Firma do mnie dzwoni po roku, że chce nową funkcję. Dogadujemy się na cenę. Sprawdzam, jak działa integracja z API - moja aplikacja dalej pracuje na plikach tekstowych z szyfrowaną treścią:D.
Pytam, WTF?
Menedżerka odpowiada, że jak przepieli na backend to nic nie działało, więc wrócili do systemu zapisu danych w plikach tekstowych, bo wszystko dobrze działało I NIE PLANUJĄ TEGO ZMIENIAĆ.
Super konwencja, przeszukiwać i edytować plik tekstowy zamiast bazy danych.
No i tak się żyje i IT.


Granie w gry i robienie gier ma tyle wspólnego, co uprawianie seksu z pracą ginekologa.
Zobacz pozostałe 5 komentarzy
xxx_xx_x
Zależy jaki jest sposób dostępu i zapisu danych. Pliki mogą być znacznie wydajniejsze od bazy danych w przypadku prostych operacji
renderme
W odczycie sa wydajniejsze, w zapisie zdecydowanie nie, ale wbrew pozorom latwiej zaimplementowac wielowatkowosc. Bazy nie moglem zainstalowac, bo nie mialem dostepow. Moglem robic jakiejs obrazy w dokerze, ale kto by za to placil...
xxx_xx_x
Baza też zapisuje do pliku więc na pewno plik może być równie wydajny, kwestia tego jak przechowuje się dane
jarekr000000
@Wibowit: powiedzmy, że jednak nie. Ale swoją drogą uważam, że całkiem spoko ćwiczenie - raz w życiu każdy sobie dla zabawy powinien zrobić trzymanie danych w plikach, żeby zobaczyć ile z tym jest roboty. Pozwala to docenić bazy danych, a jednocześnie czasem pokazuje, że często zupełnie tego całego narzutu nie potrzebujemy.... (np. jeśli aplikacja nie potrzebuje żadnych skomplikowanych raportów, wyszukiwać tylko wystarcza read, write by id).
AL
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 3 lata
  • Postów:1493
6

Serio zaczynam rozumieć czemu nowsze języki zabrały ludziom dostęp do pamięci.
Ogólnie to Message ma gazyliard bajtów (prealokowanych) ale de facto używanych może być ich wiele mniej, liczbę określa pole w strukturze.
Można było zrobić pole dynamiczne zamiast tego. Albo po prostu to olać, bo to przeca pecet, a nie małe embedded, i spokojnie by sobie poradził.
No ale nie. Zamiast tego jest odpowiednik malloca (customowy!) na dokładnie ile jest potrzebne i potem taki cud.

Kopiuj
    msg = reinterpret_cast<struct Message*>(
        reinterpret_cast<int>(msg) + 10 + MSG_HEADER_SIZE
    );

Na Odyna, to jest kod z zeszłego roku -_-

EDIT: jest i ciąg dalszy i wyjaśnienie co tam się podziało.
UB, hacki, dokładna specyfikacja - czy to w Delphi istnieje?

edytowany 2x, ostatnio: alagner
xxx_xx_x
Dla mnie sam z siebie taki zapis nie jest WTF, bardzo zależy do czego ten bufor jest docelowo używany. https://en.wikipedia.org/wiki/Flexible_array_member
rafal__
  • Rejestracja:ponad 18 lat
  • Ostatnio:11 miesięcy
0
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:minuta
3

Zastany fragment Jenkins pipeline

Kopiuj
bat (script: """@ECHO OFF
	set /p NEW_BUILD_NR=<%WORKSPACE%\\build_version.txt
	echo NEW_BUILD_NR:%NEW_BUILD_NR%
	echo env.NEW_BUILD_NR_VAR="%NEW_BUILD_NR%" > %WORKSPACE%\\properties.groovy
	""")

load('properties.groovy')

bat (script: """@ECHO OFF
	set /p MILESTONE=<%WORKSPACE%\\milestone.txt
	echo MILESTONE:%MILESTONE%
	echo env.MILESTONE="%MILESTONE%" > %WORKSPACE%\\milestone.groovy
	""")

load('milestone.groovy')

Wersja poprawiona, która robi to samo (no dobra nie wypisuje wartości):

Kopiuj
env.NEW_BUILD_NR_VAR = readFile "build_version.txt" 
env.MILESTONE = readFile "milestone.txt" 

Ja rozumiem, że ktoś się uczył groovy i Jenkins (sam jestem nadal w tej fazie), ale są jakieś granice absurdu.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
KamilAdam
Szkoda że w Perlu tego nie zrobił
WE
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 miesięcy
  • Postów:42
2

Dla jednej z poprzednich firm zrobiłem dodatkowy projekt. Początkowo byłem sceptyczny bo head developerem okazał się przeciętny frontend.... projekt zrobiłem i udostępniłem mu (php symfony). Po 2 dniach mi napisał, że projekt nie działa u niego i nie zapłacą mi. Okazało się, że ja lokalnie na dockerze postawiłem projekt na nginx a oni używali apache..... Wygenerowanie .htaccessa zajęło mi może z 2 minuty :)

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)