21 sie 2023 POIT #208: Narzędzia programisty: Iteracje i timeboxing
Witam w dwieście ósmym odcinku podcastu „Porozmawiajmy o IT”. Tematem dzisiejszej rozmowy w serii podcastów o narzędziach programisty są iteracje i timeboxing.
Dziś moim gościem jest Łukasz Drynkowski, z którym mam przyjemność współtworzyć portal z ofertami pracy dla branży IT o nazwie SOLID.Jobs.
Główne myśli o iteracjach i timeboxingu z tego odcinka to:
- iterujcie, bo z każdą kolejną iteracją produkt staje się lepszy,
- podziel zadanie na dwa sprinty, ale po pierwszym miej gotowy produkt,
- iteracja = nauka i feedback,
- timeboxing jako forma zarządzania czasem.
Subskrypcja podcastu:
- zasubskrybuj w Apple Podcasts, Google Podcasts, Spreaker, Sticher, Spotify, przez RSS, lub Twoją ulubioną aplikację do podcastów na smartphonie (wyszukaj frazę „Porozmawiajmy o IT”)
- ściągnij odcinek w mp3
- poproszę Cię też o polubienie fanpage na Facebooku
Linki:
- Profil SOLID.Jobs na LinkedIn – https://www.linkedin.com/showcase/solid.jobs/
- SOLID.Jobs – https://solid.jobs/
Wsparcie na Patronite:
Wierzę, że dobro wraca i że zawsze znajdą się osoby w bliższym lub dalszym gronie, którym przydaje się to co robię i które zechcą mnie wesprzeć w misji poszerzania horyzontów ludzi z branży IT.
Patronite to tak platforma, na której możesz wspierać twórców internetowych w ich działalności. Mnie możesz wesprzeć kwotą już od 5 zł miesięcznie. Chciałbym oddelegować kilka rzeczy, które wykonuję przy każdym podcaście a zaoszczędzony czas wykorzystać na przygotowanie jeszcze lepszych treści dla Ciebie. Sam jestem patronem kilku twórców internetowych i widzę, że taka pomoc daje dużą satysfakcję obu stronom.
👉Mój profil znajdziesz pod adresem: patronite.pl/porozmawiajmyoit
Pozostańmy w kontakcie:
- 📧 Jeśli masz jakieś pytania lub komentarze, pisz do mnie śmiało na krzysztof@porozmawiajmyoit.pl
- 📩 Zapisz się na newsletter, aby nie przegapić kolejnych ciekawych odcinków
- 🎙 Subskrybuj podcast w lub
Muzyka użyta w podcaście: „Endless Inspiration” Alex Stoner (posłuchaj)
Transkrypcja podcastu
To jest 208. odcinek podcastu „Porozmawiajmy o IT”, w którym w cyklu rozmów z Łukaszem Drynkowskim z portalu z ogłoszeniami pracy IT o nazwie SOLID.Jobs, który mam przyjemność współtworzyć, dyskutujemy o narzędziach programisty. Zapraszamy do słuchania i komentowania. A teraz życzymy Ci miłego słuchania. Odpalamy.
Cześć, Łukasz!
Cześć, Krzysztof!
To kolejne nasze spotkanie w ramach serii o narzędziach programisty. Do tej pory mówiliśmy o różnych narzędziach, które pomagają wytwarzać kod, dbać o jego jakość, jak code review, jak pair programming, jak spike, natomiast oprócz tego, w jaki sposób wytwarzamy ten kod, za pomocą jakich narzędzi, istotny jest też cały flow, proces wytwarzania oprogramowania, czyli na przykład dzielenie sobie zadań na mniejsze rzeczy i ich parkowanie w czasie. Dzisiaj na ten temat będziemy rozmawiać, czyli poruszymy temat iteracji i time boxingu. Iteracja to jest taki trochę buzzword, o którym dużo się mówi, który występuje w różnych kontekstach. Łukasz, jak to u Ciebie wygląda, jak Ty rozumiesz iterację?
Myślę, że fajnie by iterację wytłumaczyć w kontraście do innego słowa, które często występuje razem z iteracją, czyli przyrost. Przyrost to ja rozumiem tak, że po przyroście dostajemy trochę więcej, coś nowego. Natomiast iteracja to jest coś, po czym dostajemy to samo, co już mieliśmy, ale lepsze i poprawione, też wiemy coś więcej. Zawsze to występuje jedno z drugim, bo chcemy i dostać trochę więcej, i chcemy dostać trochę lepiej. Więc iteracja i przyrosty są nierozłączne.
Myślę, że iteracje zostały spopularyzowane poprzez w szczególności scrum, w ogólności podejście agilowe.
Tak, ale iteracje to nie tylko sprinty, nie tylko scrum, przecież iteracje mamy w codziennym naszym programistycznym życiu. Takie choćby TDD, to jest ciąg małych iteracji, pisze testy, pisze kod i na zmianę iteruje.
Iteracja to nie musi być tylko dostarczanie nowej funkcjonalności, nowego wzbogaconego ficzera do klienta po sprincie. To może się tyczyć codziennej małej, drobnej pracy. Wiadomo, że praca programistyczna nie polega na tym, że siadamy i piszemy od początku do zera już gotowe i takie w pełni zdefiniowane rozwiązanie. Zazwyczaj robimy to w takich małych iteracjach i nawet, jeśli tylko my jako programiści wiemy o tych iteracjach, to tak, śmiem twierdzić, w większości przypadków na tym polega programowanie, że powoli wzbogacamy to nasze rozwiązanie, dokładamy coś do niego. To może polegać na tym, jak tutaj chociażby zaznaczyłeś, że TDD jest tego rodzaju podejściem. Piszemy sobie powiedzmy test, później dopisujemy do tego rozwiązanie, wzbogacamy to rozwiązanie po to, żeby doprowadzić do sytuacji, kiedy te napisane testy będą już zielone, a nie tylko na czerwono się świeciły.
Tak, ale też możemy w ramach tego TDD dostać przyrost, czyli trochę czegoś nowego, a możemy dostać nową jakość, trochę poprawiony kod, refaktoryzacja, coś nie zhardcodowane, tylko teraz już działa tak, jak powinno.
Dobrze zdefiniowane pure request, jeśli się skupimy na tym, jak ten kod ma być dokładany do głównego repozytorium, składają się z różnych czy też z wielu commitów i te commity pokazują, w jaki sposób programista dokładał, usprawniał ten kod, w jaki sposób pojawiały się tam małe iteracje, tak przynajmniej powinno być. Oczywiście nieraz zdarza się tak, że to jest jeden duży commit, który nam zamyka temat, ale jeśli jesteśmy w stanie, robiąc code review, i tutaj odwołujemy się do naszego pierwszego odcinka o narzędziach programistów, jeśli jesteśmy w stanie na podstawie tych commitów zobaczyć, jaki był sposób myślenia i poszczególne te etapy rozwijania iteracyjnego rozwiązania, to znacznie łatwiej nam zrozumieć, w jaki sposób programista myślał i co tutaj poeta miał na myśli.
Tak, dla mnie też iteracja to jest core agile, czyli w agilu chcemy dostawać jak najlepszy produkt i coraz lepszy, coraz bardziej udoskonalony, z większą liczbą funkcji, ale też z coraz bardziej dopracowanymi funkcjami.
Taką zaletą, o których tutaj mówisz, oprócz tego, że jesteśmy w stanie powoli, sukcesywnie rozwijać produkt, kod, jest też to, że dosyć szybko zdobywamy wiedzę czy też feedback z szeroko rozumianego rynku. Niezależnie, czy tym rynkiem będą inni programiści w firmie, czy nasz klient zewnętrzny, to ten feedback jesteśmy w stanie uzyskać szybciej i na podstawie tego feedbacku tą łodzią rozwoju naszego programu jesteśmy w stanie kierować w odpowiednim kierunku.
Tak, i te pętle feedbacku mogą mieć różne zakresy. Najmniejszy zakres na przykład TDD, sam z sobą przeprowadzam ten feedback, potem może być trochę większa pętla, gdzie ja z drugim programistą w postaci code review przeprowadzam taką iterację. Dostanę feedback po przejrzeniu kodu, coś poprawiam. Potem jeszcze większa pętla, czyli ta zmiana idzie na przykład do testera i teraz tester patrzy, co tam się dzieje, daje nam feedback, ja tutaj jeszcze coś poprawiam albo oby nie. Potem jeszcze większa pętla i teraz idzie na przykład do tego odbiorcy, klienta naszego, nazwijmy to tak, analityka, czyli taki test na przykład akceptacyjny, i ktoś tutaj patrzy, czy mu się ten kolor buttona podoba. Funkcja już działa, ale teraz patrzymy na takie bardziej wysokopoziomowe aspekty, jakieś UIX-owe na przykład sprawy. Dostaję z powrotem tę funkcję, poprawiam i tak to leci.
Dokładnie tak, można by dołożyć jeszcze jedną pewnie bardziej nawet tutaj szerszą pętlę, mianowicie rynek, cały rynek, kiedy jesteśmy start-upem, kiedy jakąś funkcjonalność gdzieś upowszechniamy, to zbieramy właśnie informacje na temat tego, co działa, co nie działa, co się klika i tej pętli też możemy tutaj użyć.
Tak. Wtedy przykładem takiej formy iteracji będzie MVP, czyli tworzymy minimum viable product, czyli jak najmniejszym kosztem tworzymy coś, co daje już wartość, i chodzi o to, żeby zebrać ten feedback i żeby potem na podstawie tego, co powiedzą użytkownicy, dalej budować produkt, a nie na podstawie tego, co my sobie sami wymyśliliśmy. Innym przykładem tutaj mogłyby być testy AB, czyli na przykład tworzymy funkcję w dwóch różnych wersjach. Dajemy części użytkowników wersję A, innej części wersję B i czekamy na feedback, badamy dane, co się lepiej klika i na podstawie takiej iteracji podejmujemy kolejne decyzje.
Każda z tych pętli iteracyjnych jest wartościowa, każda coś wnosi, ale generalnie jest pewnie taka zasada, że im krótsza pętla, tym lepiej. Wyobraźmy sobie programistę, który tworzy pewną funkcjonalność. Jeśli jest w stanie sam iterować, sam przewidzieć jakieś problemy i je naprawić u źródła, na tym etapie powstawania kodu, oczywiście zajmie to mniej czasu dla niego, dla całej organizacji, tym będzie miało mniejszy impact na innych. Jeśli to będzie musiał wychwycić tester na etapie testów, to oczywiście ta pętla już jest dłuższa, czas na naprawę jest dłuższy, ten balast emocjonalny jest większy, generalnie więcej zachodu potrzeba, żeby naprawić zepsutą albo nie do końca dopracowaną funkcjonalność.
To tutaj się zgodzę z Tobą chyba tylko częściowo, bo zgadzam się, że im krócej do tego uzyskania feedbacku, to tym lepiej. Natomiast nie jestem przekonany, czy im krótsza iteracja, to tym lepiej. Bo tak jak tutaj wcześniej powiedzieliśmy, czy ta iteracja, gdzie dostaję szybko feedback od kolegi programisty, jest lepsza od tego, że coś wpuścimy na rynek i dostaniemy po jakimś czasie ten feedback od klientów, to zależy od tego, co chcemy od tej iteracji osiągnąć w ramach niej.
Dokładnie, tak myślę, że po raz kolejny sprawdzi się to, co chyba powtarzamy w każdym odcinku naszej serii, czyli użyjcie tego narzędzia do swojego zastosowania, w swoim przypadku. Nie ma tutaj takich rozwiązań, które działają zawsze w każdym możliwym przypadku.
Myślę, że tutaj trochę powiedzieliśmy o iteracjach, przejdźmy może jeszcze do tematu time boxingu. Jak tutaj, Krzysztofie, rozumiesz time boxing, czym on w ogóle jest?
Time boxing w takim najbardziej klasycznym ujęciu to jest zamknięcie w jakieś ramy czasowe czegoś. To może być wykonanie zadania, to może być spotkanie, to może być sprint, czyli wszystko, co gdzieś się zaczyna i ma określony czas trwania. W różnoraki sposób możemy to aplikować do wytwarzania kodu, zarówno na etapie samego pisania, testowania, sprintów, planowania. Myślę, że możemy sobie o tym porozmawiać, ale, Łukasz, dlaczego w ogóle o tym time boxingu rozmawiamy, jakie to ma zalety?
To zanim opowiemy o zaletach time boxingu, to jeszcze się odniosę do tego scruma i do sprintów. Taki sprint to jest przykład time boxowania. Mamy sprint, który trwa na przykład tydzień, dwa tygodnie, miesiąc i w tym czasie musimy zrobić to, co było do zrobienia, i nie przekraczamy tego czasu. Jest ustalony jakiś proces, jakiś schemat działania. Druga fajna rzecz, o której wspomniałeś, to że taki timeboxing, to nie jest tylko ograniczenie na jakieś zadanie na przykład programistyczne, możemy time boxować różne rzeczy na przykład spotkania. Jaka jest zaleta tego? Zaleta jest taka, że pozwala nam się skupić na meritum i nie odpływać na jakieś poboczne tematy. Wtedy, jeśli jakiś poboczny temat się pojawi, możemy go na przykład zanotować i oddzielnie do niego podejść, czy to będzie kolejne spotkanie, czy to będzie kolejny osobny ticket na poboczne issue, które się pojawiło w trakcie naszej pracy. Oczywiście time boxing dzięki temu, że ogranicza ten czas, to zmniejsza ryzyko przekroczenia terminów, bo skoro mówimy sobie, że tyle i basta, to tyle i basta. Nie udało się zrobić, to teraz pytanie „co dalej, jak się czegoś nie uda zrobić”. Ale ten czas, który poświęciliśmy, to myślę, że maksymalnie skupiliśmy się na tej jednej rzeczy, maksymalnie zwiększyliśmy dzięki temu produktywność.
O time boxingu można mówić w takim rozumieniu, jak to jest w przypadku ceremonii w scrumie, kiedy faktycznie one mają co do minuty wręcz narzuconą długość i to ma służyć zespołowi, to ma służyć temu, żebyśmy nie rozgadywali się i niepotrzebnie tracili czas. To jest może zasadne, ma sens w przypadku, jeśli wiemy, co chcemy osiągnąć, wiemy, że coś jest powtarzalne, wiemy, że będzie miało podobny przebieg. Natomiast często w programowaniu, wytwarzaniu oprogramowania musimy się mierzyć z przypadkami, kiedy pracujemy z większą liczbą osób, kiedy podchodzimy do realizacji czegoś po raz pierwszy, wówczas nie mamy wystarczającej wiedzy, wystarczającego doświadczenia, żeby ten time boxing sensownie wyznaczyć. Wówczas możemy mówić o takim time boxowaniu trochę w wersji soft, kiedy dajemy sobie jeszcze możliwość na ewentualne rozszerzenie. Oczywiście też jakąś określoną, to nie jest tak, że to w nieskończoność może iść, ale bierzemy tu bufor zapasowy na to, żeby ewentualnie ten time boxing rozszerzyć.
Tak, oczywiście podejścia mogą być różne, dostosujmy podejście do naszej konkretnej sytuacji.
Mówiłeś tutaj, Łukasz, o zaletach time boxingu, o tym, że to może być zwiększenie produktywności, że jesteśmy się w stanie wówczas bardziej skupić na tym jednym zadaniu, ale z drugiej strony myślę, że też tego nie raz doświadczyłeś, wprowadzenie sztywnych ram, sztywnych limitów może być pewnym obciążeniem. Możemy się tym zwyczajnie stresować. Czy myślisz, że to jest nieodzowny element time boxingu, czy to po prostu tak musi być?
Myślę, że to bardzo zależy od osoby. Dla jednych ludzi ten time boxing może być czymś, co pomoże i zwiększy tę produktywność, a tak jak powiedziałeś, mogą być osoby, które się zestresują, że ten czas się zaraz kończy i że trzeba to wykonać w tym konkretnym odcinku czasu, i będą miały paraliż decyzyjny.
Tak, ten stres będzie destrukcyjny.
Tak, albo stres będzie zbyt destrukcyjny, nie jest to coś, co jest dla każdego na pewno, ale myślę, że warto spróbować, warto to też ćwiczyć jako taką formę zarządzania czasem.
Dokładnie tak, w ostatnim odcinku o estymacjach, jak wspomnieliśmy o prawie Parkinsona, który mówi o tym, że praca rozszerza się tak bardzo, na ile pozwala to czas i jest oczywiście to, tak jak powiedziałeś, możliwość zarządzania swoim czasem, czyli to określenie pewnego time boxingu zazwyczaj powoduje, że jesteśmy w stanie w jakiś sposób się zmieścić w tym czasie. Jeśli byśmy tych ram nie mieli, to wszyscy dobrze wiemy, że prokrastynacja potrafi nas złapać w ciągu dnia i wtedy odwlekamy to zadanie, nie mamy tego limitu, uznajemy, że mamy jeszcze jakiś tam czas na realizację ficzera, na dowiezienie danej funkcjonalności. Jeśli te ramy występują, zazwyczaj większość osób, i to tutaj podkreślę, bo to nie znaczy, że każdy tak musi działać, ale znakomita większość osób będzie wiedziała, jak ma sobie dzień zaplanować, żeby faktycznie ten czas wypełnić pracą.
Ale tutaj na przykład możemy też fajnie połączyć iterowanie z time boxingiem i możemy takie zadanie sobie podzielić, nawet niekoniecznie formalnie gdzieś w JIRA w innym narzędziu, tylko u nas w głowie. Dzielimy sobie zadanie na dwa przyrosty, dzisiaj wykonam połowę pracy, jutro drugą połowę, dzisiaj się nie będę aż tak stresował, bo wiem, że jeszcze mam jutro ten zapas czasu. W ten sposób powstaje moim zdaniem coś lepszego, bo mamy ten okres, gdzie chwilę odpoczęliśmy od tego zadania, przemyśleliśmy to na nowo, może nas po drodze oświeciło. Mnie się wydaje, że takie iterowanie jest czymś, co zawsze powoduje, że ta funkcja będzie trochę lepsza. Za pierwszym razem nigdy nic nie wychodzi idealnie, więc jeśli jesteśmy w stanie coś podzielić, nawet na pół, i dwa razy podejść do tego samego zadania, to za drugim razem to wyjdzie lepiej.
Te techniki iteracji i time boxingu dosyć fajnie ze sobą współdziałają. Weźmy chociażby Technikę Pomodoro, która jest najczęściej chyba stosowanym ujęciem tych dwóch rzeczy. Polega ona na tym, że dzielimy sobie czas pracy na iteracje trwające 25 minut, ale to oczywiście można sobie ustawić, ile kto chce minut, i później 5 minut przerwy. I tak powtarzamy kilka razy, później ta przerwa jest dłuższa. Mówiliśmy o tym, że iteracje mogą działać na różnych poziomach. Mogą być małe i duże, taką dużą iteracją może być dowiezienie przyrostu w ramach sprintu, a taką najmniejszą może być ten jeden pomidor, jedna tutaj sesja pomodoro, gdzie przez te 25 minut, już tutaj mówimy o time boxingu, będziemy się starali zrealizować mały przyrost, małą iterację i w ten sposób dowieźć też tą większą.
Tak. Taki sposób pracy też wspiera rozbijanie zadań na mniejsze, takie bardziej ogarnialne części, cząstki może wręcz. Też to są wtedy takie mniejsze części, łatwiej do nich podejść, łatwiej je zrozumieć, łatwiej je na przykład wyestymować.
Czy myślisz, że warto jest ten jeden temat, to skupienie, o którym mówimy, pastwić się nad nim, aż nie zrealizujemy finalnego efektu? Czy to ma sens? Chodzi mi tutaj, żeby nieraz odłożyć zadanie, obudzić się na drugi dzień ze świeżą głową i wtedy się pomysły pojawiają.
Bardzo ciekawe pytanie. Tutaj opowiem o takiej technice, którą stosuję. Lubię, jak zadanie zostanie podzielone na dwa sprinty i nie robimy na przykład takiego zadania programistycznego w jednym sprincie i koniec, tylko w jednym sprincie robimy część tego zadania albo takie MVP, nazwijmy, na koniec mamy tę zaletę, że jest feedback od, nazwijmy to, klienta końcowego czy też tego zlecającego nam dane zadanie i w drugim sprincie możemy podejść do tego jeszcze raz, żeby to doszlifować, wizualnie poprawić UIX-owo, i wtedy ten produkt wychodzi lepszy. Tylko żebyśmy tutaj nie popełnili takiego błędu, że w jednym sprincie robimy połowę zadania, w drugim sprincie drugą połowę. To nie o to chodzi, to jest zupełnie coś innego. Chodzi o to, żeby zrobić pierwszą działającą wersję w pierwszym sprincie i wtedy na drugi sprint poświęcamy może już trochę mniej czasu, to nie musi być wtedy oczywiście tyle samo czasu, ale żeby część tego czasu wydzielić jeszcze na kolejny przyrost czy też kolejną iterację i w ramach tej kolejnej iteracji możemy dopracować ten produkt.
Czy to się według Ciebie też łączy z tematem, który już poruszyliśmy, mianowicie ze spikiem? Można jakoś połączyć to, o czym powiedziałeś, w dwóch sprintach?
Tak, to jest bardzo dobry przykład. W pierwszym sprincie zrobimy spike’a technologicznego, w drugim sprincie zrobimy właściwą funkcję. Tutaj oczywiście jest kwestia jeszcze tego, że spike’a robimy z myślą o tym, żeby to wyrzucić i napisać od nowa. Pytanie, czy chcemy rzeczywiście tę funkcję, to, co zrobiliśmy, wyrzucić, miałem tu na myśli raczej trochę inne podejście, właśnie takie MVP i potem poprawienia, ale oczywiście podejście spikowe też tutaj ma sens.
Ten temat iteracji, time boxingu też przecina się bardzo mocno z biznesem czy też produktem, w sensie uzupełnia się. Dużą rolę ma oczywiście planowanie, o którym powiedzieliśmy, czyli te iteracje powinny faktycznie mieć jakiś sens, żeby nie tylko dowozić wartość dla klienta końcowego, ale żeby też pod względem implementacyjnym miało to sens. Planowanie to oczywiście też jest w jakiś sposób zagospodarowanie potrzebnego, wymaganego i niezbędnego czasu. To też się dosyć dobrze łączy z time boxingiem, ale to przecięcie z biznesem wymaga świadomości ze strony PM, bez którego bardzo trudno będzie programistom realizować cokolwiek w iteracji i szybko wrócimy do takiego waterfallowego podejścia, którego pewnie chcielibyśmy niestety uniknąć. Scrum to jest oczywiście tylko jeden z frameworków, jeden z możliwych wariantów, wariacji do zastosowania. Myślę, że każdy zespół musi znaleźć właściwą dla siebie metodę. Dobrze, Łukasz, myślę, że całkiem dużo już o iteracjach dzisiaj i time boxingu w znaczeniu produktowym, w znaczeniu wpływu na zespół, jak i indywidualną osobę kontrybuującą powiedzieliśmy. Chciałbyś może podsumować?
Jasne, tak że podsumowując, przede wszystkim iterujcie, bo z każdą kolejną iteracją produkt staje się lepszy, albo miejmy nadzieję, że tak jest. Iteracja to oczywiście nauka, iteracja to feedback, tak że jak najbardziej zachęcamy do tworzenia tych pętli iteracji w ramach jednego sprintu i pomiędzy sprintami. Polecam taką technikę, żeby jedno zadanie nie kończyć od początku do końca w jednym sprincie, tylko żeby zawsze zaplanować sobie na kolejny sprint jeszcze taki czas, gdzie trochę dopracujemy to, co nam jeszcze przyjdzie w feedbacku, żebyśmy mieli szansę poprawić. Oczywiście, jeśli nam to służy, to starajmy się time boxować przede wszystkim spotkania, ale także naszą pracę. Zobaczmy, czy to nam służy. Jeśli rzeczywiście pomaga nam to się skupić, zwiększyć produktywność, to time boxujmy zadania nawet dla siebie. Tylko dla siebie. W ten sposób zmniejszajmy ryzyko przekroczenia terminu.
Do tej pory w odcinkach rozmawialiśmy głównie o narzędziach związanych z wytwarzaniem kodu, ze współpracą z innymi, jeśli chodzi o dowożenie całych funkcjonalności, ale myślę, że narzędzia programisty to też są narzędzia usprawniające jego pracę i rozwijające skill programistyczny. Co Ty na to, Łukasz, żebyśmy w tym duchu porozmawiali w następnym odcinku?
Tak, myślę, że nawet mam bardzo fajny pomysł. Porozmawiamy o code kata, czyli czymś, co łączy w sobie te iteracje i jest kolejnym narzędziem, które pozwala nam na naukę i na feedback samemu ze sobą, ale mimo wszystko na stawaniu się coraz lepszym programistą.
Brzmi ciekawie. Już teraz na ten odcinek zapraszamy. Za dzisiaj bardzo dziękujemy. Zapraszamy do odsłuchania wcześniejszych odcinków, już całkiem spora ich ilość jest dostępna. Zapraszamy do odwiedzenia SOLID.Jobs, gdzie możecie znaleźć ciekawe oferty pracy, zawsze z widokami wynagrodzeń. Zapraszamy też do wystawiania ogłoszeń na tym portalu, a ja dzisiaj, Łukasz, Tobie bardzo dziękuję i do usłyszenia.
Dzięki, Krzysztof, cześć!
Cześć!