tag:blogger.com,1999:blog-5047632037494901372.comments2024-02-25T13:55:59.887+01:00Paweł Włodarski - ludzka twarz ITPaweł Włodarskihttp://www.blogger.com/profile/04891037231290616803noreply@blogger.comBlogger234125tag:blogger.com,1999:blog-5047632037494901372.post-50667949125962410662017-11-09T12:45:00.853+01:002017-11-09T12:45:00.853+01:00Fajne zdjęcie ;)Fajne zdjęcie ;)Marek Strejczekhttps://www.blogger.com/profile/14600756435317999188noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-35514756085413120282017-07-29T17:02:40.697+02:002017-07-29T17:02:40.697+02:00Genialne pocieszenie na końcu ;) Śmiechłem z tego ...Genialne pocieszenie na końcu ;) Śmiechłem z tego bardzo :D lolciohttps://www.blogger.com/profile/01192114591476603144noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-18736521953578256302017-07-21T10:42:54.210+02:002017-07-21T10:42:54.210+02:00Zgadza się. W tym przykładzie użyłem Option jedyni...Zgadza się. W tym przykładzie użyłem Option jedynie dla uproszczenia przekazu edukacyjnego.Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-43618021745076760422017-07-21T09:04:46.801+02:002017-07-21T09:04:46.801+02:00W praktyce często zamiast Option bardziej przydaje...W praktyce często zamiast Option bardziej przydaje się Try albo Either. Mają tę zaletę, że pozwalają ci przekazać _co_ jest źle, a nie tylko że jest źle.<br /><br />Czasem różnica między "system leży", "zły format" a "brak uprawnień" ma znaczenie. Na niższym poziomie też się przydaje, żeby powiedzieć np. w którym dokładnie miejscu ten JSON się nie waliduje.Konrad Garushttps://www.blogger.com/profile/07215510981447527548noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-16789347241173176782017-07-01T13:09:45.714+02:002017-07-01T13:09:45.714+02:00Dodatkowo Rafał to się, może przydać jeśli chcesz ...Dodatkowo Rafał to się, może przydać jeśli chcesz "wpuścić" dane do systemu ale niekoniecznie od razu chcesz rozpoczynać konwersje i obliczenia. Coś takiego może wydarzyć się gdy to nie jest prosty request-response ale w momencie otrzymania sygnału/danych wejściowych przygotowujesz taki wstępny szablon do operacji, która zostanie wykonana później i w ramach tej operacji będziesz maił na przykład więcej informacji z runtime, które pozwolą ci lepiej wykonać konwersję. <br /><br />Przykład bardziej realny acz bardzo trywialny. Dostajesz na wejście inta z protokołem tekstowym. Wstępnie możesz sprawdzić czy to legalny int ale nie możesz stwierdzić, że to prawidłowe UserId bo może wcale takiego UserId nie ma.Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-56347952493277305872017-06-30T21:45:54.902+02:002017-06-30T21:45:54.902+02:00plus jeszcze w temacie bezpieczeństwa i poprawnośc...plus jeszcze w temacie bezpieczeństwa i poprawności typów może to będzie dla Ciebie ciekawe : http://pawelwlodarski.blogspot.com/2016/11/bezpieczny-numerek.html chociaż tam użyty jest dosyć egzotyczny język jako przykład.Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-62181078504472253612017-06-30T21:44:28.392+02:002017-06-30T21:44:28.392+02:00"Mam takie wrażenie, że niepotrzebnie komplik..."Mam takie wrażenie, że niepotrzebnie komplikujesz temat (albo ja źle zrozumiałem do czego to prowadzi). Jeżeli mamy funkcję, np. pierwiastek, to ona jest określona dla jakiejś dziedziny. Np. dla rzeczywistych >= 0 daje jakieś wyniki rzeczywiste."<br /><br />W swoim przykładzie ograniczyłeś cały system do prostej funkcji. Mi chodziło o samo wejście do systemu by upewnić się, że w samym systemie posługujesz się prawidłowymi typami. Co jeśli dostaniesz dane do systemu i częścią ich odbioru będzie kontakt z innym serwisem który zwróci ci złożony typ Future[Option[ValidationResult]] i teraz komponowanie tego z wyjątkami zacznie generować coraz większą złożoność kodu. Ja użyłem prostego przykładu i Ty użyłeś prostego przykładu ale musimy pamietać, ze systemy nie są proste jakoś do wyobrażeń trzeba dodać efekt skali. Jeśli trzymając się metafory będziemy mieli złożony system ksiegowy gdzie liczenie pierwiastków jest jedną z miliona funkcji i źle obsłużymy wyjątek co ogólnie da nam wynik z poprawnej dziedziny ale ze złą wartością to jeśli np. wywaliła się procedura licząca vat to może się to skończyć nie rzucaniem kartki w kąt a więzieniem :) <br /><br />Dlaczego operacje na poprawnych typach powinny pomóc nam się przed tym ustrzec? odpowiedź - kompilator. No i na pewno trudno będzie takie podejście obronić w prostych CRUDach bo tam ludzie od lat walą wyjątkami i jakoś to działa bo filozofii wielkiej nie ma. Jak już pojawią się bardziej wymagające obliczenia wtedy poprawność typów nabiera moim zdaniem znaczenia. Mam nadzieję, że ta odpowiedź pomogła.Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-61377957992372273232017-06-30T18:04:33.417+02:002017-06-30T18:04:33.417+02:00Mam takie wrażenie, że niepotrzebnie komplikujesz ...Mam takie wrażenie, że niepotrzebnie komplikujesz temat (albo ja źle zrozumiałem do czego to prowadzi). Jeżeli mamy funkcję, np. pierwiastek, to ona jest określona dla jakiejś dziedziny. Np. dla rzeczywistych >= 0 daje jakieś wyniki rzeczywiste. Jeżeli chcemy rozszerzyć dziedzinę na ujemne liczby, to musimy zwracać wyniki zespolone (czyli zmienił się typ zwracanej wartości, ale również część "obliczeniowa" funkcji). Jeżeli na wejściu podamy coś spoza dziedziny, to w przypadku obliczeń na papierze po prostu się zatrzymamy i zaczniemy odwijać stos, żeby sprawdzić gdzie się pomyliliśmy, czyli rzucamy wyjątek. A dalej to już tylko podejście do obsługi wyjątek, jeden rzuci kartkę w kąt (wyświetli durny komunikat użytkownikowi), inny znajdzie winnego (pomyłkę w obliczeniach, wzorach, kodzie) a użytkownik zobaczy tylko komunikat: "Twoje obliczenia się nie udały, ale nasi najlepsi ludzie pracują nad rozwiązaniem problemu."Anonymoushttps://www.blogger.com/profile/04284181857740933698noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-66504587525745630002017-06-30T15:30:55.054+02:002017-06-30T15:30:55.054+02:00W skali większego systemu możesz czasem chcieć odd...W skali większego systemu możesz czasem chcieć oddzielić walidacje od samej konwersji i niekoniecznie muszą to być te same operacje (np. isNonEmpty może ograniczyć deomenę list do niepustych tak, że .head nie jebnie).No i jak masz optionala w innym miejscu to też mozesz komponować funkcje na innym poziomie. W tym artykule głównym celem było pokazanie, że masz taka możliwość i masz narzędzie więc gdy kiedyś napotkasz sytuację gdy nie możesz ruszyć sygnatury funkcji to możesz spróbować tego podejścia. A być może i samo teoretyczne rozważanie, że tak można zrobić przyniesie wartość edukacyjnąPaweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-1708991027889859372017-06-30T14:26:05.968+02:002017-06-30T14:26:05.968+02:00"Ale co gdy mimo wszystko chcemy zachować fun..."Ale co gdy mimo wszystko chcemy zachować funkcję String => Hex ?"<br />w przykładzie nie udało nam się zachować tej funkcji, bo teraz mamy "SafeHexString => Hex" :(<br /><br />Co da nam rozbicie tego na "validate" i "convert"? tak czy inaczej zostajemy z tym Optionalem, trochę w innym miejscu, ale jednak. <br /><br />Czy np. gdybyśmy konwertowali JSONa do obiektu domenowego to musielibyśmy wykonać operacje przetwarzania dwa razy? Raz przy weryfikacji i raz przy konwersji?Anonymoushttps://www.blogger.com/profile/07887729074376494957noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-18827528177462584982017-04-21T18:05:08.728+02:002017-04-21T18:05:08.728+02:00Nie nagrywam. Trzeba być na miejscu.Nie nagrywam. Trzeba być na miejscu.Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-44757607873582047452017-04-21T15:37:17.280+02:002017-04-21T15:37:17.280+02:00Grzmi interesująco! Bedzie nagranie?Grzmi interesująco! Bedzie nagranie?Anonymoushttps://www.blogger.com/profile/17938886516274513852noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-25350678855611225792017-01-30T09:40:28.982+01:002017-01-30T09:40:28.982+01:00Tyle pytań rekrutacyjnych o PECS... I wszystko jak...Tyle pytań rekrutacyjnych o PECS... I wszystko jak krew w piach ;)damianhttps://www.blogger.com/profile/08008143991404257946noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-58808384122346671692016-11-22T06:55:07.307+01:002016-11-22T06:55:07.307+01:00Jeszcze nie weim czy możesz sobie okreslić "n...Jeszcze nie weim czy możesz sobie okreslić "nie większe" ale na pewno możesz dynamicznie określić typ <br />wektora.<br /><br />fill : a -> (x: Nat) -> Vect x a<br />fill a Z = []<br />fill a (S k) = a :: fill a k<br /><br />Ale pamiętaj, że to był tylko przykład większej idei. List w Idrisie w ogóle nie ma drugiego typu, Vect ma, i technicznie jest stworzenie nawet i samemu czegoś takiego "CustomArray a range"Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-35092759825728998062016-11-22T02:13:42.726+01:002016-11-22T02:13:42.726+01:00Za każdym razem, kiedy widzę tablicę o z góry okre...Za każdym razem, kiedy widzę tablicę o z góry określonej długości, to zastanawiam się, czy nie powinna tam być struktura z jawnie nazwanymi polami, bo inaczej to jest takie Scheme-style (zobacz dowolną strukturę danych w SICP).<br /><br />Interesowałaby mnie inna możliwość - rozwinięcie przykładu ze zwróceniem tablicy n+1 - czy można zadeklarować np. "ta funkcja zawsze zwróci niepustą tablicę" albo "ta funkcja zwróci tablicę nie dłuższą niż x elementów"?Artur Czajkahttps://www.blogger.com/profile/12615215426836980675noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-12061043785768651762016-11-21T21:24:05.578+01:002016-11-21T21:24:05.578+01:00Gdyby ktoś jednak uważał, że artykuł jest jednak n...Gdyby ktoś jednak uważał, że artykuł jest jednak niedorobiony bo nie ma przedstawionego w pełni zabezpieczonego typami rozwiązania to być może nie najsprytniejszym - ale zawsze - rozwiązaniem będzie stworzenie wektora miesięcy o określonej długości<br /><br />months : Vect 3 Month<br />months = [January,February,March] <br /><br />i wtedy mamy gotowa funkcję Fin n -> Month : <br />Data.Vect.index : Fin n -> Vect n a -> a<br /><br />Jednakże ten przykład z "dziurą" w typach, która wykrył sam język jest moim zdaniem tak silnym przykładem, że zostawiłem to w końcowej wersji.<br /><br />Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-55063877619587134042016-11-02T23:01:20.719+01:002016-11-02T23:01:20.719+01:00Można się tylko zastanawiać, czy nadmierna abstrak...Można się tylko zastanawiać, czy nadmierna abstrakcja i hofy-wszędzie-hofy czasem nie prowadzą do tego samego, co kiedyś wyciskanie wszędzie wzorców z GoF albo innych strategii. :-)<br /><br />Zresztą hof to w sumie są strategie, tyle że jak kolega zauważył dużo bardziej uniwersalne i czytelne. Byle nie przesadzać z przedwczesną abstrakcyjnością.Konrad Garushttps://www.blogger.com/profile/07215510981447527548noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-59228198229355117682016-10-08T21:26:49.707+02:002016-10-08T21:26:49.707+02:00Nauka tego języka to process długi i iteracyjny al...Nauka tego języka to process długi i iteracyjny ale nie zerojedynkowy. Czyli wracasz cyklicznie do tych samych zagadnień i za każdym razem uczysz się czegoś nowego.I to się opłaca. Bo w "Nauce Scali" tak samo ważne jest słowo "Scala" co "Nauka". Masz okazję zetknąć się z wieloma sposobami rozwiązywania problemów, których za cholere nie spotkasz w Javie. Także jeśli nawet nie użyjesz jej w praktyce to sam fakt podejścia do nauki zrobi z ciebie lepszego programistę. A co do samego języka to twórcy mieli kilkanaście lat na wyciągnięcie wniosków i wyciągają pomału odchładzając język z mechanizmów o małej przydatności.<br /><br />pzdr,Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-49777340682410357622016-10-03T22:36:16.578+02:002016-10-03T22:36:16.578+02:00No właśnie… Scala…
Subiektywnie o Scali mogę powie...No właśnie… Scala…<br />Subiektywnie o Scali mogę powiedzieć tyle, że po pierwszym "ŁAŁ" zaobserwowałem coś, co najlepiej opisał Bruce Eckel. Różnica jest tylko taka, że ja o Scali tylko czytałem, ale nie kodowałem nic poważnego, a autor książki "Atomic Scala" poświęcił się tematowi znacznie bardziej.<br /><br />Bruce Eckel, źródło: http://bruceeckel.github.io/2015/08/29/what-i-do/<br />I’ve spent a couple of years immersed in Scala (longer in calendar time, but safe to say two years of full immersion) and feel like I have only a surface understanding of that language. I like to think I understand what’s in Atomic Scala, but even then I am unsurprised when someone points out some feature that turns out to have far greater complexity than I thought.<br />[…]<br />One of the issues I had with Scala is the constant feeling of being unable to detect whether I just wasn’t “getting” a particular aspect, or if the language was too complex. […]Anonymoushttps://www.blogger.com/profile/15733944404690570660noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-57082099087556981062016-07-29T21:51:49.183+02:002016-07-29T21:51:49.183+02:00Mi natomiast na myśl przychodzi taka książka (pl. ...Mi natomiast na myśl przychodzi taka książka (pl. Głowa do liczb) oraz kurs na courserze Learning how to learn. Dużo o efektywnym uczeniu w tym o wychodzeniu/unikaniu efektu einstellungMateuszhttps://www.blogger.com/profile/06972517311096265059noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-62625966950816581262016-07-08T14:24:13.162+02:002016-07-08T14:24:13.162+02:00Nie wiem jak wygląda ten coderetreat, ale z opisu ...Nie wiem jak wygląda ten coderetreat, ale z opisu przywodzi na myśl następujący Ted talk:<br />https://www.ted.com/talks/tim_harford_how_messy_problems_can_inspire_creativityAnonymoushttps://www.blogger.com/profile/08884910859459459442noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-18615509075154729712016-04-26T22:49:55.718+02:002016-04-26T22:49:55.718+02:00Zgadzam się z tobą i niestety ubolewam nad faktem ...Zgadzam się z tobą i niestety ubolewam nad faktem że takie myślenie jest utopią. IT to komercha i w korpo (a tam niestety pracuje większość z nas) nagradzane jest posłuszeństwo i liczba Controllerów, Encji, Serwajsów, Tasków i Managero-helperów jake potrafisz naklepać. I tutaj raczej nie zanosi się na zmianę, oczywiście są chwalebne wyjątki, firmy perełki gdzie oprócz "co robimy" zwraca się jeszcze uwagę na "jak to robimy". Jednak większość firm preferuje podejście "encja na twarz i pchasz" bo z tego są po prostu hajsy. A docelowy klient i tak często ma to w szerokim poważaniu. Działa to działa. damianhttps://www.blogger.com/profile/08008143991404257946noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-85018495753905979852016-04-05T12:51:11.332+02:002016-04-05T12:51:11.332+02:00A, czyli ty byś myślał używać Readera tak bardziej...A, czyli ty byś myślał używać Readera tak bardziej "lokalnie". Jasne, można, i przy bardziej skomplikowanych przekształceniach danych (gdzie składasz pare funkcji) pewnie ma spory sens :)<br /><br />Mam jednak wrażenie że przez "funkcyjnych" DI jest często odrzucane "bo tak", i właśnie Reader wskazuja jako zastępstwo - dlatego cały czas szukam jakiegos dobrego przykładu aplikacji która byłaby w tym stylu zrobionaAdam Warskihttps://www.blogger.com/profile/04535036247623614805noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-11086054327208510962016-04-05T10:16:58.742+02:002016-04-05T10:16:58.742+02:00Serwis cały czas może ukrywać istnienie repo bo mo...Serwis cały czas może ukrywać istnienie repo bo możesz mieć zwykły interfejs finsUser(userId):User<br /><br />a ta forma Repository=>User może być zbudowana wewnątrz serwisu i użyta tylko do wewnętrznych przekształceń. Zaleta jest taka, że jak robisz częściowe wywołanie to raczej nic się nie wywali i ten "Serwis" martwi się tylko jak określić relację pomiędzy userId i Repository i później może wysłać ten przepis do egzekucji w innym komponencie/serwisie/klasie gdzie potencjalne zjebki mogą być obsłużone.<br /><br />I teraz to co jest dla mnie dużym plusem to że np. ten przepis Repository=>User jest ten sam i w testach i na produkcji bo dopiero przy Repository pojawi się różnica Mock/Produkcyjne. Przy normalnym wstrzykiwaniu przez konstruktor różnica pojawia się jakby "od razu". <br /><br />No i to co dla mnie jest bardzo wartościowe, to że można to Repository=>User przekształcać przy pomocy funkcji User=>A , które w ogóle istnienia Repozytorium są nieświadome . Oczywiście można tych funkcji używać i tka jak repo jest wstrzyknięte przez konstruktor ale wtedy mam takie odczucie, że kompozycja jest mniej elastyczna bo już z góry narzucony kontekst w którym wywołasz te funkcje jak masz <br />"operacjaNaRepo andThen prostaFunkcja" to operacjaNaRepo jest niezależnym klockiem , jeśli repo jest wstzrknięte konstruktorem to operacjaNaRepo jest "tu i teraz" - to jest tak konsekwencja, która starałem sie pokazać w akapicie "Klasycznie"<br /><br />Co do większej ilości zależności to można wykorzystać fakt, że jak mamy "Repository=>A" to "A" może być "Notification=>B" a "B" może być OtherService=>C. Czyli tak jak jest Funkctor Aplikatywny w validacji w scalaz talk tutaj mógłby być teoretycznie "Reader aplikatywny" ale tu już trzeba samemu zdecydować czy taka rzeźba ma uzasadnienie.<br /><br />Generalnie użyłem koncepcji "Reader" w artykule bo mam odczucie, że programistom Javy prościej operuje się rzeczownikami ale osobiście polecam bardzo aby spróbować wyrzucić pojęcie Reader i patrzeć na to jako zestaw dwóch prostych mechanizmów "curried function" i "lazy evaluation". Moją intuicję zajebiście rozbudował rozdział z "Functional programming in scala" o lazy evaluation gdzie własnie te ziomy co pisały książkę totalnie odseparowały opis programu od momentu wykonania gdzie opisali, która cześć ma być wykonana równolegle i na ilu watkach.<br /><br />pzdr,<br />Paweł Włodarskihttps://www.blogger.com/profile/04891037231290616803noreply@blogger.comtag:blogger.com,1999:blog-5047632037494901372.post-54930848819117785722016-04-05T09:16:36.314+02:002016-04-05T09:16:36.314+02:00Ale chyba jak wołasz ten Serwis.find(userId), to w...Ale chyba jak wołasz ten Serwis.find(userId), to w typie zwracanym gdzieś to Repository siedzi, nie? Albo wprost jako funkcja albo opakowane jeszcze w Reader[]. I oczywiście chodzi mi tutaj o wieksza liczbę zależności - przy jednej to problem jest dosyć prosty ;) Tak więc choćby patrząc na bytecode klienta, jednak ta wiedza że Serwis potrzebuje w jakimś-tam wywołaniu Repository jest. Przy "zwykłym" DI tej zależności nie masz. <br /><br />Może to i dobrze - nie wiem, chociaż wydawało mi się zawsze fajne że mogę takie szczegóły ukryć.<br /><br />Zgoda że Reader to może być dodatkowy tool używany "obok" DI, ale jednak ciężko się oprzeć pokusie chęci znalezienia jakiejś ogólnieszej reguły kiedy co użyć. Np. - choćby te Repository/DAO w aplikacji CRUDowej - wstrzykiwać? Czy przez Readera? A może aplikacje CRUDową robić w PHP? ;) Jeden pomysł jaki na razie mam - który ułatwia testowanie, to do readera wyrzucać te zalezności które są potrzebne dla jednej/dwóch metod z klasy - tak żeby do testowania pozostałych nie trzeba było robić "pustych" mocków.<br /><br />Btw. tego Readera to już od dawna próbuje rozgryźć, patrz http://stackoverflow.com/questions/29174500/reader-monad-for-dependency-injection-multiple-dependencies-nested-calls ;)Adam Warskihttps://www.blogger.com/profile/04535036247623614805noreply@blogger.com