eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programming › Dlaczego w branży rozrywkowej najsłabiej płacą?
Ilość wypowiedzi w tym wątku: 172

  • 161. Data: 2011-10-12 23:03:44
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Wojciech Jaczewski <w...@o...pl>

    Andrzej Jarzabek wrote:

    > Powiedzmy
    > masz licznik czegośtam w postaci inta, który musi być podbijany z
    > kilku różnych wątków, więc dodajesz mutex i komentarz, że ten mutex
    > służy do zabezpieczania licznika, który jest podbijany z kilku wątków.
    > A może zamiast tego lepiej zrobić klasę i nazwać ją ThreadSafeCounter,
    > to komentarz przestanie być potrzebny.

    Ten przykład jest bezsensowny.
    Jeśli jest użyty mutex, to wiadomo że jest synchronizacja między wątkami i
    nie trzeba tego dodatkowo komentować.
    Natomiast jeśli komentarz zawiera "licznik jest modyfikowany przez wątki A,B
    oraz X", to użycie ThreadSafeCounter tego komentarza nie zastąpi.

    Swoją drogą... jaki interfejs do ThreadSafeCounter uznałbyś za właściwy:
    atomic_inc(counter) / synchronized_inc(counter), czy ++counter ?

    > Nie uważam, że to jest jakaś złota zasada czy srebrna kula, ale jednak
    > zauważyłem, że często tak faktycznie jest: mam do czynienia z funkcją,
    > w której bez komentarzy trudno byłoby rozkminić jakiś istotny aspekt,
    > dzięki komentarzom jest to możliwe, ale jednak jest możliwe i byłoby
    > lepiej, gdyby te aspekty były wprost wyrażone w kodzie.

    Czasem zdarza mi się (nie w ramach pracy) używać jakichś bardzo
    specyficznych algorytmów, np. z zakresu przetwarzania sygnałów. Robię to
    bardzo rzadko i bez komentarzy absolutnie nie domyśliłbym się dlaczego jest
    tak a nie inaczej, bo czasem ciężko zrozumieć jakim cudem dany algorytm w
    ogóle działa i kroki do osiągnięcia celu wydają się na prawdę dziwne
    (polecam np. "band edge component maximization").


  • 162. Data: 2011-10-13 00:31:21
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Andrzej Jarzabek <a...@g...com>

    On 12/10/2011 23:51, Wojciech Jaczewski wrote:
    > Andrzej Jarzabek wrote:
    >>
    >> Do pisania oprogramowania niezawodnego potrzebna jest abstrakcja i
    >> czytelność kodu. Kod, który sobie po cichu zakłada, że int ma 32 bity ma
    >> niedobory w jednym i drugim.
    >
    > Mowa o funkcjach systemowych, a nie zakładaniu ile bitów ma int. Trudno mi
    > sobie wyobrazić, aby ktoś korzystał z tego założenia, mając do dyspozycji
    > alternatywę w postaci int32_t.

    Ja mówię o tym i o tym. A przykład z intem z życia wzięty: profesor to
    właśnie napisał ledwie kilka dni temu.

    > Bardzo jest dla mnie zagadkowe, że tak wiele osób uważa, iż interfejs
    > opracowywany i testowany przez kilka dziesięcioleci koniecznie wymaga
    > opakowania w jakąś abstrakcję, bo inaczej korzystać z niego nie należy...

    Cała sztuka porządnego pisania większych programów polega na przejściu
    między końcową funkcjonalnością a wykorzystywanymi bibliotekami przez
    wiele warstw abstrakcji - i wyrażeniu tych abstrakcji w kodzie.

    > Nie wiem jak jest z interfejsami windowsowymi, bo z nimi doświadczenie
    > miałem znikome, ale interfejsy POSIX-owe są bardzo dobre. Abstrakcja w
    > postaci deskryptora pliku - coś wspaniałego.

    Właśnie kaszanka. Przykładowo, jeśli mówimy o niezawodności, to sam
    fakt, że deskryptor jest typem liczbowym ułatwia popełnienie błędu
    polegającego na tym, że jako deskryptora używasz liczby, która
    deskryptorem nie jest.

    Kolejny problem z deskryptorami jest taki, że łatwo przez pomyłkę o kod,
    który w pewnych sytuacjach nie zamyka deskryptorów, które otwiera, np.
    na wskutek early return czy rzucenia wyjątkiem.

    Dalej, jeśli np. próbujesz zrobić formatowane wyjście na deskryptor
    przez ręczne babranie się z alokowaniem buforów, kopiowaniem i
    sklejaniem stringów, jakimiś dodatkowymi funkcjami do formatowania
    liczb, to masz całą masę pomyłek, które łatwo popełnić z katastrofalnymi
    skutkami: dangling pointers, bufer overflow, memory leaks, czy dany
    string jest null-terminated czy nie itd. itp.

    > Również dla krytykowanych przez niektórych uniksowych sygnałów daje się
    > czasem znaleźć fajne zastosowanie, gdzie bez sygnałów program byłby dużo
    > bardziej zawiły.

    Również dla sygnałów unixowych są abstrakcje, które będą zwykle
    sensowniejsze do stosowania niż systemowe API, na przykład w modelu
    programu, który obsługuje jakieś zdarzenia sygnał może wsytępować po
    prostu jako jeden z typów "zdarzeń".

    Kolejne unixowe API którego łatwo przez pomyłkę użyć nieprawidłowo i
    rozwalić program to choćby pthreads.

    > Oczywiście w każdym API dałoby się wskazać jakieś wady, ale na jakiej
    > podstawie miałbym przypuszczać, że zrobiona w dużo krótszym czasie
    > abstrakcja będzie istotnie lepsza?

    Dlaczego zakładasz, że w dużo krótszym czasie? Jeśli mówimy o
    generycznych abstrakcjach na system operacyjny, to jak pisałem są to
    albo istniejące i szeroko stosowane biblioteki third party, albo też
    rozwiązanie in house stosowane w wielu produktach danej firmy i często
    rozwijane latami.

    > Dla mnie "opakowywanie systemowego API" to takie wynalazki jak np. QSocket z
    > Qt. Dla programów międzyplatformowych - może ma sens. Dla programów na jedną
    > platformę - żadnego.

    Nie znam Qt, więc się nie wypowiem. Zapewne ewidentną zaletą tago
    rozwiązania jest to, że nie da się pomylić inta zawierającego deskryptor
    z intem zawierający liczbę przeczytanych bajtów.

    > Interfejs udostępniany przez system (POSIX) jest
    > lepszy. Testowałem też kiedyś Boost::Asio - nieczytelny w porównaniu z tym,
    > co można zrobić korzystająć bezpośrednio z POSIX. I ciężki do integracji,
    > jeśli program ma reagować jednocześnie na zdarzenia innego typu.

    Nie mam doświadczenia z tym, ale pracowałem kiedyś z event handling
    frameworkiem opakowującym unixowe API i praktyka jednak była taka, że
    nowy typ zdarzeń był do niego dodawany dużo, dużo rzadziej niż pisanie
    programów, które korzystały tylko z już obsługiwanych typów.

    >> Pracowałem przy kilku większych projektach i normą było korzystanie z
    >> biblioteki opakowującej API, chociaż nie takiej, która jest tworzona pod
    >> konkretny projekt: albo były to biblioteki third party, albo robione w
    >> firmie na potrzeby wielu projektów. To, czy korzystają czy nie
    >> korzystają ze wszystkich funkcji API nie ma znaczenia - istotne jest, że
    >> reprezentują wyższy poziom abstrakcji.
    >
    > Czy wyższy poziom abstrakcji w sensie np. baza danych zamiast bezpośredniego
    > czytania z plików i synchronizowania przy pomocy fcntl/flock? czy tylko
    > pozbierane kilka funkcji systemowych do kupy i pozamykane w obiekty?

    Można mieć różne poziomy abstrakcji do różnych rzeczy. Dla pliku
    chociażby możesz mieć poziom abstrakcji mówiący, że jest strumieniem, że
    po zakończeniu działań na nim jest zamykany, na innym poziomie
    abstrakcji możesz mieć wyrażony fakt, że jest fizycznym plikiem na
    dysku, że np. program zapisuje określone dane do pliku o określonej
    ścieżce, na wyższych poziomach masz semantykę: plik może być bazą
    danych, logiem, dokumentem o zadanym formacie, plikiem konfiguracyjnym
    itd. Brak odpowiedniego opakowania może choćby spowodować błąd
    polegający na tym, że ktoś potraktuje plik XML z fiflakami jako plik
    binarny zawierający bazę danych fiflaków lub odwrotnie.


  • 163. Data: 2011-10-13 00:39:50
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Andrzej Jarzabek <a...@g...com>

    On 13/10/2011 00:03, Wojciech Jaczewski wrote:
    > Andrzej Jarzabek wrote:
    >
    >> Powiedzmy
    >> masz licznik czegośtam w postaci inta, który musi być podbijany z
    >> kilku różnych wątków, więc dodajesz mutex i komentarz, że ten mutex
    >> służy do zabezpieczania licznika, który jest podbijany z kilku wątków.
    >> A może zamiast tego lepiej zrobić klasę i nazwać ją ThreadSafeCounter,
    >> to komentarz przestanie być potrzebny.
    >
    > Ten przykład jest bezsensowny.
    > Jeśli jest użyty mutex, to wiadomo że jest synchronizacja między wątkami i
    > nie trzeba tego dodatkowo komentować.

    Ale nie wiadomo, co konkretnie dany mutex synchronizuje.

    > Swoją drogą... jaki interfejs do ThreadSafeCounter uznałbyś za właściwy:
    > atomic_inc(counter) / synchronized_inc(counter), czy ++counter ?

    Z zasady nie lubię skrótów typu 'inc'. Zrobiłbym ++counter albo
    counter.increment(), ale raczej nie traciłbym czasu na zastanawianie się
    nad tym zbyt długo.

    > Czasem zdarza mi się (nie w ramach pracy) używać jakichś bardzo
    > specyficznych algorytmów, np. z zakresu przetwarzania sygnałów. Robię to
    > bardzo rzadko i bez komentarzy absolutnie nie domyśliłbym się dlaczego jest
    > tak a nie inaczej, bo czasem ciężko zrozumieć jakim cudem dany algorytm w
    > ogóle działa i kroki do osiągnięcia celu wydają się na prawdę dziwne
    > (polecam np. "band edge component maximization").

    Ale co ci tutaj dają komentarze? Czy może są to komentarze typu:
    /* Wiem, że to wygląda bez sensu, ale uwierz mi, tak właśnie ma być */
    ?


  • 164. Data: 2011-10-13 09:10:53
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Wojciech Jaczewski <w...@o...pl>

    Andrzej Jarzabek wrote:

    >> Nie wiem jak jest z interfejsami windowsowymi, bo z nimi doświadczenie
    >> miałem znikome, ale interfejsy POSIX-owe są bardzo dobre. Abstrakcja w
    >> postaci deskryptora pliku - coś wspaniałego.
    >
    > Właśnie kaszanka. Przykładowo, jeśli mówimy o niezawodności, to sam
    > fakt, że deskryptor jest typem liczbowym ułatwia popełnienie błędu
    > polegającego na tym, że jako deskryptora używasz liczby, która
    > deskryptorem nie jest.

    Teoretycznie możliwe, w praktyce jeszcze tego nie widziałem.

    > Kolejny problem z deskryptorami jest taki, że łatwo przez pomyłkę o kod,
    > który w pewnych sytuacjach nie zamyka deskryptorów, które otwiera, np.
    > na wskutek early return czy rzucenia wyjątkiem.

    Jeśli akurat mi w danym momencie na czymś takim zależy i akurat używam C++,
    to robię klasę o nazwie fd_guard_t (analogiczną do lock_guard z nowego
    standardu). I dalej operuję na nie-opakowanym deskryptorze.

    > Dalej, jeśli np. próbujesz zrobić formatowane wyjście na deskryptor
    > przez ręczne babranie się z alokowaniem buforów, kopiowaniem i
    > sklejaniem stringów, jakimiś dodatkowymi funkcjami do formatowania
    > liczb, to masz całą masę pomyłek, które łatwo popełnić z katastrofalnymi
    > skutkami: dangling pointers, bufer overflow, memory leaks, czy dany
    > string jest null-terminated czy nie itd. itp.

    Do formatowania do pliku, czy na stdout, rzeczywiście może być wygodniejsze
    użycie FILE* lub iostream. Natomiast ich interfejs nie pasuje do sensownej
    obsługi np. połączeń sieciowych, gdzie przed wywołaniem funkcji nie wiadomo
    ile bajtów będzie się dało w tej chwili odczytać/zapisać. W takim wypadku
    lepszy jest jawny podział na dwie części: formatowanie do pamięci, a
    następnie przerzucenie w jednym lub wielu etapach przez deskryptor.

    >> Również dla krytykowanych przez niektórych uniksowych sygnałów daje się
    >> czasem znaleźć fajne zastosowanie, gdzie bez sygnałów program byłby dużo
    >> bardziej zawiły.
    >
    > Również dla sygnałów unixowych są abstrakcje, które będą zwykle
    > sensowniejsze do stosowania niż systemowe API, na przykład w modelu
    > programu, który obsługuje jakieś zdarzenia sygnał może wsytępować po
    > prostu jako jeden z typów "zdarzeń".

    Można. Z tym że nie wiem, czemu miałoby to być "sensowniejsze". Jest tak
    samo sensowne jak POSIX-owe, tylko z innym interfejsem.

    > Kolejne unixowe API którego łatwo przez pomyłkę użyć nieprawidłowo i
    > rozwalić program to choćby pthreads.

    Wątków akurat unikam jak mogę. Łatwiej się testuje dwa współpracujące
    procesy, niż dwa współpracujące wątki. API opakowujące pthreads nie
    wniosłoby mi w tej kwestii absolutnie nic.

    >> Oczywiście w każdym API dałoby się wskazać jakieś wady, ale na jakiej
    >> podstawie miałbym przypuszczać, że zrobiona w dużo krótszym czasie
    >> abstrakcja będzie istotnie lepsza?
    >
    > Dlaczego zakładasz, że w dużo krótszym czasie?

    Porównuję do czasu od którego istnieją systemy Uniksowe. Większość założeń
    jest już bardzo starych, ale jednak przez bardzo wiele lat standard się
    jeszcze rozwija.

    >> Dla mnie "opakowywanie systemowego API" to takie wynalazki jak np.
    >> QSocket z Qt. Dla programów międzyplatformowych - może ma sens. Dla
    >> programów na jedną platformę - żadnego.
    >
    > Nie znam Qt, więc się nie wypowiem. Zapewne ewidentną zaletą tago
    > rozwiązania jest to, że nie da się pomylić inta zawierającego deskryptor
    > z intem zawierający liczbę przeczytanych bajtów.

    Nie widziałem jeszcze przypadku pomylenia inta zawierającego deskryptor z
    intem zawierającym liczbę przeczytanych bajtów. Ta zaleta jest czysto
    teoretyczna.


  • 165. Data: 2011-10-13 09:58:40
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Wojciech Jaczewski <w...@o...pl>

    Andrzej Jarzabek wrote:

    >>> Powiedzmy
    >>> masz licznik czegośtam w postaci inta, który musi być podbijany z
    >>> kilku różnych wątków, więc dodajesz mutex i komentarz, że ten mutex
    >>> służy do zabezpieczania licznika, który jest podbijany z kilku wątków.
    >>> A może zamiast tego lepiej zrobić klasę i nazwać ją ThreadSafeCounter,
    >>> to komentarz przestanie być potrzebny.
    >>
    >> Ten przykład jest bezsensowny.
    >> Jeśli jest użyty mutex, to wiadomo że jest synchronizacja między wątkami
    >> i nie trzeba tego dodatkowo komentować.
    >
    > Ale nie wiadomo, co konkretnie dany mutex synchronizuje.

    Synchronizuje ten fragment, wokół którego jest użyty. To w kodzie widać.

    >> Swoją drogą... jaki interfejs do ThreadSafeCounter uznałbyś za właściwy:
    >> atomic_inc(counter) / synchronized_inc(counter), czy ++counter ?
    >
    > Z zasady nie lubię skrótów typu 'inc'. Zrobiłbym ++counter albo
    > counter.increment(), ale raczej nie traciłbym czasu na zastanawianie się
    > nad tym zbyt długo.

    Wg mnie słówko atomic, bądź synchronized jest konieczne - aby wyraźnie
    oznaczyć, że to jest operacja z synchronizacją między wątkami. I że w razie
    problemów z wydajnością na wielu procesorach, należy się przyjrzeć także
    temu fragmentowi.

    >> Czasem zdarza mi się (nie w ramach pracy) używać jakichś bardzo
    >> specyficznych algorytmów, np. z zakresu przetwarzania sygnałów. Robię to
    >> bardzo rzadko i bez komentarzy absolutnie nie domyśliłbym się dlaczego
    >> jest tak a nie inaczej, bo czasem ciężko zrozumieć jakim cudem dany
    >> algorytm w ogóle działa i kroki do osiągnięcia celu wydają się na prawdę
    >> dziwne (polecam np. "band edge component maximization").
    >
    > Ale co ci tutaj dają komentarze? Czy może są to komentarze typu:
    > /* Wiem, że to wygląda bez sensu, ale uwierz mi, tak właśnie ma być */
    > ?

    Np. "Filtr pasmowo-przepustowy wokół częstotliwości 2400Hz, ale ze
    współczynnikami zespolonymi, tak aby w jego widmie częstotliwościowym były
    niezerowe wartości wyłącznie dla częstotliwości dodatnich".


  • 166. Data: 2011-10-13 14:13:02
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Andrzej Jarzabek <a...@g...com>

    On Oct 13, 10:58 am, Wojciech Jaczewski <w...@o...pl> wrote:
    > Andrzej Jarzabek wrote:
    >
    > > Ale nie wiadomo, co konkretnie dany mutex synchronizuje.
    >
    > Synchronizuje ten fragment, wokół którego jest użyty. To w kodzie widać.

    Przecież defnicja mutexa jest gdzie indziej niż kod, gdzie jest
    używany.

    > > Z zasady nie lubię skrótów typu 'inc'. Zrobiłbym ++counter albo
    > > counter.increment(), ale raczej nie traciłbym czasu na zastanawianie się
    > > nad tym zbyt długo.
    >
    > Wg mnie słówko atomic, bądź synchronized jest konieczne - aby wyraźnie
    > oznaczyć, że to jest operacja z synchronizacją między wątkami. I że w razie
    > problemów z wydajnością na wielu procesorach, należy się przyjrzeć także
    > temu fragmentowi.

    Według mnie jeśli klasa nazywa się ThreadSafeCounter i można ją tylko
    np. inkrementować, resetować i sprawdzać wartość, to oczywistym jest,
    że te wszystkie operacje są thread-safe.

    > > Ale co ci tutaj dają komentarze? Czy może są to komentarze typu:
    > > /* Wiem, że to wygląda bez sensu, ale uwierz mi, tak właśnie ma być */
    > > ?
    >
    > Np. "Filtr pasmowo-przepustowy wokół częstotliwości 2400Hz, ale ze
    > współczynnikami zespolonymi, tak aby w jego widmie częstotliwościowym były
    > niezerowe wartości wyłącznie dla częstotliwości dodatnich".

    Nie znam się na tym, ale zasadniczo wydaje mi się, że tak jak liczba
    zespolona może być wyrażona odpowiednim typem, tak możesz mieć typ
    generyczny Współczynnik (być może zdefiniowany wewnątrz klasy filtra
    czy przestrzeni nazw 'Filtr', żeby było jasne, że chodzi o
    współczynnik filtra), możesz mieć konkretną klasę
    WspółczynnikZespolony parametryzującą szablon FiltrPasmowoPrzepustowy,
    który ma konstruktor przyjmujący argument typu Częstotliwość i tak
    dalej.


  • 167. Data: 2011-10-13 16:12:38
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Andrzej Jarzabek <a...@g...com>

    On Oct 13, 10:10 am, Wojciech Jaczewski <w...@o...pl> wrote:
    > Andrzej Jarzabek wrote:
    >
    > > Kolejny problem z deskryptorami jest taki, że łatwo przez pomyłkę o kod,
    > > który w pewnych sytuacjach nie zamyka deskryptorów, które otwiera, np.
    > > na wskutek early return czy rzucenia wyjątkiem.
    >
    > Jeśli akurat mi w danym momencie na czymś takim zależy i akurat używam C++,
    > to robię klasę o nazwie fd_guard_t (analogiczną do lock_guard z nowego
    > standardu). I dalej operuję na nie-opakowanym deskryptorze.

    Lock guard jest specjalnie tak zrobiony, żeby ten sam lock mógł być
    używany po wyjściu z zakresu, gdzie jest zalockowany przez tego
    guarda. Zastosowanie tego samego narzedzia do deskryptora, gdzie
    takich wymagań nie ma (nie masz sytuacji, gdzie po zamknięciu
    deskruptora próbujesz go jeszcze raz otworzyć albo coś w tym stylu)
    jest suboptymalne - co prawda rozwiązuje ci bezpośrednio ten problem,
    ale umożliwia powstanie różnych błędów, które bez tego byłyby
    niemożliwe - choćby że w trakcie modyfikacji kodu ktoś zmodyfikuje
    zakresy tak, że deskryptor będzie zdefiniowany w innym niż jego lock,
    albo ktoś gdzies wstawi zamykanie tego deskryptora ręcznie.

    > > Dalej, jeśli np. próbujesz zrobić formatowane wyjście na deskryptor
    > > przez ręczne babranie się z alokowaniem buforów, kopiowaniem i
    > > sklejaniem stringów, jakimiś dodatkowymi funkcjami do formatowania
    > > liczb, to masz całą masę pomyłek, które łatwo popełnić z katastrofalnymi
    > > skutkami: dangling pointers, bufer overflow, memory leaks, czy dany
    > > string jest null-terminated czy nie itd. itp.
    >
    > Do formatowania do pliku, czy na stdout, rzeczywiście może być wygodniejsze
    > użycie FILE* lub iostream. Natomiast ich interfejs nie pasuje do sensownej
    > obsługi np. połączeń sieciowych, gdzie przed wywołaniem funkcji nie wiadomo
    > ile bajtów będzie się dało w tej chwili odczytać/zapisać. W takim wypadku
    > lepszy jest jawny podział na dwie części: formatowanie do pamięci, a
    > następnie przerzucenie w jednym lub wielu etapach przez deskryptor.

    streambuf ma buforowanie, więc tak to właśnie raczej powinno działać.
    Jednak musisz przyznać, że z punktu widzenia kogoś, kto chce
    sfotmatować komunikat i przesłać go po połączeniu albo z kolei
    odczytać komunikat zakończony np. CR-LF, niekoniecznie takie szczegóły
    implementacyjne są interesujące.

    > > Również dla sygnałów unixowych są abstrakcje, które będą zwykle
    > > sensowniejsze do stosowania niż systemowe API, na przykład w modelu
    > > programu, który obsługuje jakieś zdarzenia sygnał może wsytępować po
    > > prostu jako jeden z typów "zdarzeń".
    >
    > Można. Z tym że nie wiem, czemu miałoby to być "sensowniejsze". Jest tak
    > samo sensowne jak POSIX-owe, tylko z innym interfejsem.

    Sensowniejsze o tyle, że masz rodzieloną logikę mówiącą jak na jakieś
    zdarzenie trzeba reagować z samą obsługą i rozstrzyganiem tego, na co
    jak trzeba zareagować. W związku z tym komuś dodającemu nowy typ
    zdarzenia do obsługi trudniej będzie zepsuć jakiś aspekt istniejącej
    logiki, niż jeśli modyfikuje dużą pętlę z 'jeśli sygnał to tamto,
    jeśli coś na sockecie to śmamto, jeśli minęło tyle czasu to owamto".

    > > Kolejne unixowe API którego łatwo przez pomyłkę użyć nieprawidłowo i
    > > rozwalić program to choćby pthreads.
    >
    > Wątków akurat unikam jak mogę. Łatwiej się testuje dwa współpracujące
    > procesy, niż dwa współpracujące wątki. API opakowujące pthreads nie
    > wniosłoby mi w tej kwestii absolutnie nic.

    W rzeczywistości wątków się używa bo to wydajny i elastyczny sposób na
    zrównoleglenie aplikacji. W przypadku stosowania oddzielnych procesów
    samo kszta związane z narzutem na ich odpalanie, IPC itd. często
    zabijają wszelkie korzyści ze zrównoleglenia.

    > >> Oczywiście w każdym API dałoby się wskazać jakieś wady, ale na jakiej
    > >> podstawie miałbym przypuszczać, że zrobiona w dużo krótszym czasie
    > >> abstrakcja będzie istotnie lepsza?
    >
    > > Dlaczego zakładasz, że w dużo krótszym czasie?
    >
    > Porównuję do czasu od którego istnieją systemy Uniksowe. Większość założeń
    > jest już bardzo starych, ale jednak przez bardzo wiele lat standard się
    > jeszcze rozwija.

    Owszem, standard się rozwija, ale zachowanie wsteczniej
    kompatybilności z latami 70-tymi jest ważniejsze niż tworzenie
    lepszych abstrakcji. Raczej bym powiedział, że rozwój koncentruje się
    na dostarczaniu nowej funkcjonalności, słusznie zakładając, że
    potrzeba abstrakcji będzie zaspokojona przez biblioteki opakowujące.
    Już nie mówiąc o tym, że API jest w C, a to język dosyć kiepsko
    nadający sie do wyrażania abstrakcji czy budowania struktur
    wspierających niezawodność.

    > > Nie znam Qt, więc się nie wypowiem. Zapewne ewidentną zaletą tago
    > > rozwiązania jest to, że nie da się pomylić inta zawierającego deskryptor
    > > z intem zawierający liczbę przeczytanych bajtów.
    >
    > Nie widziałem jeszcze przypadku pomylenia inta zawierającego deskryptor z
    > intem zawierającym liczbę przeczytanych bajtów. Ta zaleta jest czysto
    > teoretyczna.

    Ja widziałem wiele przypadków błedów spowodowanych pomyleniem x-a
    robiącego A z x-em robiącym B przez kogoś, kto nigdy przedtem nie
    widział takiego przypadku. Mnie też to oczywiście wiele razy
    dotyczyło.


  • 168. Data: 2011-10-15 21:51:59
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Wojciech Jaczewski <w...@o...pl>

    Andrzej Jarzabek wrote:

    >> > Kolejny problem z deskryptorami jest taki, że łatwo przez pomyłkę o
    >> > kod, który w pewnych sytuacjach nie zamyka deskryptorów, które otwiera,
    >> > np. na wskutek early return czy rzucenia wyjątkiem.
    >>
    >> Jeśli akurat mi w danym momencie na czymś takim zależy i akurat używam
    >> C++, to robię klasę o nazwie fd_guard_t (analogiczną do lock_guard z
    >> nowego standardu). I dalej operuję na nie-opakowanym deskryptorze.
    >
    > Lock guard jest specjalnie tak zrobiony, żeby ten sam lock mógł być
    > używany po wyjściu z zakresu, gdzie jest zalockowany przez tego
    > guarda. Zastosowanie tego samego narzedzia do deskryptora, gdzie
    > takich wymagań nie ma (nie masz sytuacji, gdzie po zamknięciu
    > deskruptora próbujesz go jeszcze raz otworzyć albo coś w tym stylu)
    > jest suboptymalne - co prawda rozwiązuje ci bezpośrednio ten problem,
    > ale umożliwia powstanie różnych błędów, które bez tego byłyby
    > niemożliwe - choćby że w trakcie modyfikacji kodu ktoś zmodyfikuje
    > zakresy tak, że deskryptor będzie zdefiniowany w innym niż jego lock,

    Mało prawdopodobne, aby w wyniku zwykłej pomyłki a nie celowego psucia
    rozdzielić taką sekwencję do osobnych bloków:

    int fd = jakas_tam_metoda_tworzenia_fd();
    fd_guard_t fd_guard(fd);

    > albo ktoś gdzies wstawi zamykanie tego deskryptora ręcznie.

    Opakowanie deskryptora w obiekt też wiele na to nie pomoże, bo np. dalsza
    część funkcji chciała coś wysłać przez deskryptor, a on zamknięty.

    > streambuf ma buforowanie, więc tak to właśnie raczej powinno działać.
    > Jednak musisz przyznać, że z punktu widzenia kogoś, kto chce
    > sfotmatować komunikat i przesłać go po połączeniu albo z kolei
    > odczytać komunikat zakończony np. CR-LF, niekoniecznie takie szczegóły
    > implementacyjne są interesujące.

    Są interesujące, jeśli nie chce aby użytkownik przy jego programie ćwiczył
    swoją cierpliwość - gdy akurat przywiesiło się połączenie.
    Albo załóżmy, że mamy prosty protokół, gdzie każda ze stron, na przemian
    wysyła po jednej lub więcej linii tekstu. Za pomocą interfejsów istream tego
    się nie odbierze, bo nie wiadomo ile linii zostało przysłanych.

    > Sensowniejsze o tyle, że masz rodzieloną logikę mówiącą jak na jakieś
    > zdarzenie trzeba reagować z samą obsługą i rozstrzyganiem tego, na co
    > jak trzeba zareagować. W związku z tym komuś dodającemu nowy typ
    > zdarzenia do obsługi trudniej będzie zepsuć jakiś aspekt istniejącej
    > logiki, niż jeśli modyfikuje dużą pętlę z 'jeśli sygnał to tamto,
    > jeśli coś na sockecie to śmamto, jeśli minęło tyle czasu to owamto".

    Wszystko zależy od przypadku. Czasem lepiej widać co się dzieje, gdy
    wszystkie te zdarzenia obsłużone są w jednym miejscu.

    >> > Kolejne unixowe API którego łatwo przez pomyłkę użyć nieprawidłowo i
    >> > rozwalić program to choćby pthreads.
    >>
    >> Wątków akurat unikam jak mogę. Łatwiej się testuje dwa współpracujące
    >> procesy, niż dwa współpracujące wątki. API opakowujące pthreads nie
    >> wniosłoby mi w tej kwestii absolutnie nic.
    >
    > W rzeczywistości wątków się używa bo to wydajny i elastyczny sposób na
    > zrównoleglenie aplikacji. W przypadku stosowania oddzielnych procesów
    > samo kszta związane z narzutem na ich odpalanie, IPC itd. często
    > zabijają wszelkie korzyści ze zrównoleglenia.

    Pamięci dzielonej da się używać także między procesami. Jedyne ograniczenie:
    nie można między jednym a drugim przekazywać wprost wskaźników. Czy tak
    często jest to problemem... nie wiem. Narzut odpalania występuje także dla
    wątków. Nieprzypadkowo istnieją thread-pool, więc mogą i process-pool.
    Oczywiście lepiej, jeśli zadania są ze sobą na tyle mało splecione, że można
    nie używać pamięci dzielonej, a np. potoków do komunikacji.

    >> Porównuję do czasu od którego istnieją systemy Uniksowe. Większość
    >> założeń jest już bardzo starych, ale jednak przez bardzo wiele lat
    >> standard się jeszcze rozwija.
    >
    > Owszem, standard się rozwija, ale zachowanie wsteczniej
    > kompatybilności z latami 70-tymi jest ważniejsze niż tworzenie
    > lepszych abstrakcji. Raczej bym powiedział, że rozwój koncentruje się
    > na dostarczaniu nowej funkcjonalności, słusznie zakładając, że
    > potrzeba abstrakcji będzie zaspokojona przez biblioteki opakowujące.

    W samym Linuksie dodawane są też wywołania systemowe, które nowej
    funkcjonalności tak na prawdę nie wprowadzają, tylko zapewniają inny
    interfejs do funkcjonalności już istniejących. Np. timerfd_create, signalfd.
    Dla frameworka to bez większej różnicy, natomiast jest różnica dla programów
    operujących bezpośrednio na tym API.
    [Wymienione przeze mnie przykłady są Linux-specific, ale w końcu to też jest
    uniksowego API].


  • 169. Data: 2011-10-15 21:59:37
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Wojciech Jaczewski <w...@o...pl>

    Andrzej Jarzabek wrote:

    >> > Ale co ci tutaj dają komentarze? Czy może są to komentarze typu:
    >> > /* Wiem, że to wygląda bez sensu, ale uwierz mi, tak właśnie ma być */
    >> > ?
    >>
    >> Np. "Filtr pasmowo-przepustowy wokół częstotliwości 2400Hz, ale ze
    >> współczynnikami zespolonymi, tak aby w jego widmie częstotliwościowym
    >> były niezerowe wartości wyłącznie dla częstotliwości dodatnich".
    >
    > Nie znam się na tym, ale zasadniczo wydaje mi się, że tak jak liczba
    > zespolona może być wyrażona odpowiednim typem, tak możesz mieć typ
    > generyczny Współczynnik (być może zdefiniowany wewnątrz klasy filtra
    > czy przestrzeni nazw 'Filtr', żeby było jasne, że chodzi o
    > współczynnik filtra), możesz mieć konkretną klasę
    > WspółczynnikZespolony parametryzującą szablon FiltrPasmowoPrzepustowy,
    > który ma konstruktor przyjmujący argument typu Częstotliwość i tak
    > dalej.

    Nie będę podejmował próby tłumaczenia tego, bo sam za słabo tę tematykę
    znam, a jednocześnie nie jest to tematyka grupy.
    Być może gdybym znał się na tym lepiej, to znałbym również ogólne określenie
    filtrów o takiej charakterystyce (z którą się nie spotkałem nigdy poza tym
    przypadkiem BECM) i sama nazwa by wystarczyła... Filtry często się tworzy
    przy pomocy wzoru, z którego na pierwszy rzut oka częstotliwości nie
    widać... ale pomińmy ten temat.


  • 170. Data: 2011-10-16 21:26:25
    Temat: Re: Dlaczego w branży rozrywkowej najsłabiej płacą?
    Od: Andrzej Jarzabek <a...@g...com>

    On 15/10/2011 22:51, Wojciech Jaczewski wrote:
    > Andrzej Jarzabek wrote:
    >
    >> niemożliwe - choćby że w trakcie modyfikacji kodu ktoś zmodyfikuje
    >> zakresy tak, że deskryptor będzie zdefiniowany w innym niż jego lock,
    >
    > Mało prawdopodobne, aby w wyniku zwykłej pomyłki a nie celowego psucia
    > rozdzielić taką sekwencję do osobnych bloków:
    >
    > int fd = jakas_tam_metoda_tworzenia_fd();
    > fd_guard_t fd_guard(fd);

    Nie jest to aż tak mało prawdopodobne, żeby dla wielu takich mało
    prawdopodobnych zdarzeń te prawdopodobieństwa nie skumulowały się do
    czegoś zbliżonego do pewności.

    >> albo ktoś gdzies wstawi zamykanie tego deskryptora ręcznie.
    >
    > Opakowanie deskryptora w obiekt też wiele na to nie pomoże, bo np. dalsza
    > część funkcji chciała coś wysłać przez deskryptor, a on zamknięty.

    Kompilator wyłapie, że obiektu nie ma w zakresie.

    >> streambuf ma buforowanie, więc tak to właśnie raczej powinno działać.
    >> Jednak musisz przyznać, że z punktu widzenia kogoś, kto chce
    >> sfotmatować komunikat i przesłać go po połączeniu albo z kolei
    >> odczytać komunikat zakończony np. CR-LF, niekoniecznie takie szczegóły
    >> implementacyjne są interesujące.
    >
    > Są interesujące, jeśli nie chce aby użytkownik przy jego programie ćwiczył
    > swoją cierpliwość - gdy akurat przywiesiło się połączenie.

    No więc z punktu widzenia sensowności organizacji kodu (i co za tym
    idzie niezawodności, maintainability itd.) to mieszanie obsługi
    przywieszonego połączenia z logiką obsługi tego, o czym program jest
    informowany albo o czym informuje za pomocą tego połączenia to tragedia.

    > Albo załóżmy, że mamy prosty protokół, gdzie każda ze stron, na przemian
    > wysyła po jednej lub więcej linii tekstu. Za pomocą interfejsów istream tego
    > się nie odbierze, bo nie wiadomo ile linii zostało przysłanych.

    Sensowne protokoły mają zwykle jakiś sposób zaznaczania końca komunikatu.

    >> Sensowniejsze o tyle, że masz rodzieloną logikę mówiącą jak na jakieś
    >> zdarzenie trzeba reagować z samą obsługą i rozstrzyganiem tego, na co
    >> jak trzeba zareagować. W związku z tym komuś dodającemu nowy typ
    >> zdarzenia do obsługi trudniej będzie zepsuć jakiś aspekt istniejącej
    >> logiki, niż jeśli modyfikuje dużą pętlę z 'jeśli sygnał to tamto,
    >> jeśli coś na sockecie to śmamto, jeśli minęło tyle czasu to owamto".
    >
    > Wszystko zależy od przypadku. Czasem lepiej widać co się dzieje, gdy
    > wszystkie te zdarzenia obsłużone są w jednym miejscu.

    Być może, ale to "czasami" według mnie w większości odnosi się do
    niewielkich programów.

    >> W rzeczywistości wątków się używa bo to wydajny i elastyczny sposób na
    >> zrównoleglenie aplikacji. W przypadku stosowania oddzielnych procesów
    >> samo kszta związane z narzutem na ich odpalanie, IPC itd. często
    >> zabijają wszelkie korzyści ze zrównoleglenia.
    >
    > Pamięci dzielonej da się używać także między procesami. Jedyne ograniczenie:
    > nie można między jednym a drugim przekazywać wprost wskaźników. Czy tak
    > często jest to problemem... nie wiem.

    Bardzo wiele struktur danych zawiera w sobie wskaźniki. Można oczywiście
    zrobić ich odpowiedniki bez wskaźników, ale to jest dodatkowa
    komplikacja, gorsza wydajność i im więcej tego robisz, tym więcej ci
    wraca problemów, które masz z wątkami.

    Pracowałem z takimi systemami, gdzie zamiast wątków robiło się wiele
    procesów operujących na pamięci dzielonej działającej jako prosta baza
    danych, i skalowanie tego było bardzo problematyczne.

    > Narzut odpalania występuje także dla wątków.

    Znacznie mniejsze.

    > Nieprzypadkowo istnieją thread-pool, więc mogą i process-pool.

    Można, ale masz dodatkową komplikację opisu każdego zadania i każdego
    rodzaju danych który chcesz przekazać. Na wątkach można po prostu
    przekazać jakiegoś dowolnego funktora.

    >> Owszem, standard się rozwija, ale zachowanie wsteczniej
    >> kompatybilności z latami 70-tymi jest ważniejsze niż tworzenie
    >> lepszych abstrakcji. Raczej bym powiedział, że rozwój koncentruje się
    >> na dostarczaniu nowej funkcjonalności, słusznie zakładając, że
    >> potrzeba abstrakcji będzie zaspokojona przez biblioteki opakowujące.
    >
    > W samym Linuksie dodawane są też wywołania systemowe, które nowej
    > funkcjonalności tak na prawdę nie wprowadzają, tylko zapewniają inny
    > interfejs do funkcjonalności już istniejących. Np. timerfd_create, signalfd.
    > Dla frameworka to bez większej różnicy, natomiast jest różnica dla programów
    > operujących bezpośrednio na tym API.
    > [Wymienione przeze mnie przykłady są Linux-specific, ale w końcu to też jest
    > uniksowego API].

    Drugi problem, o którym miałem napisać, ale zapomniałem, to że te
    interfejsy systemowe są zazwyczaj w C, a to język wyjątkowo kiepsko
    nadający się do wyrażania jakichkolwiek abstrakcji.

strony : 1 ... 10 ... 16 . [ 17 ] . 18


Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: