<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Archiwa learning log | To co najważniejsze</title>
	<atom:link href="https://www.danuta-cybulska.com/tag/learning-log/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.danuta-cybulska.com/tag/learning-log/</link>
	<description>Blog o wszystkim tym co jest dla mnie najważniejsze w życiu.</description>
	<lastBuildDate>Sat, 26 Sep 2026 08:55:26 +0000</lastBuildDate>
	<language>pl-PL</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.1</generator>

<image>
	<url>https://www.danuta-cybulska.com/wp-content/uploads/2025/06/3-150x150.png</url>
	<title>Archiwa learning log | To co najważniejsze</title>
	<link>https://www.danuta-cybulska.com/tag/learning-log/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Learning Log #8: Asynchroniczność w JavaScript &#8211; promises i async/await</title>
		<link>https://www.danuta-cybulska.com/asynchronicznosc-javascript-promises-async-await-learning-log-8/</link>
					<comments>https://www.danuta-cybulska.com/asynchronicznosc-javascript-promises-async-await-learning-log-8/#respond</comments>
		
		<dc:creator><![CDATA[Danuta]]></dc:creator>
		<pubDate>Wed, 14 Oct 2026 16:00:00 +0000</pubDate>
				<category><![CDATA[LearningLog]]></category>
		<category><![CDATA[Programowanie i Rozwój]]></category>
		<category><![CDATA[async await]]></category>
		<category><![CDATA[asynchroniczność]]></category>
		<category><![CDATA[callbacks]]></category>
		<category><![CDATA[event loop]]></category>
		<category><![CDATA[fetch API]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[learning log]]></category>
		<category><![CDATA[nauka JavaScript]]></category>
		<category><![CDATA[obietnice JavaScript]]></category>
		<category><![CDATA[piekło wywołań zwrotnych]]></category>
		<category><![CDATA[programowanie]]></category>
		<category><![CDATA[promises]]></category>
		<guid isPermaLink="false">https://www.danuta-cybulska.com/?p=6030</guid>

					<description><![CDATA[<p>Środa, 21:50. Ten sam fragment kodu wyświetla się już trzeci wieczór z rzędu. Konsola pokazuje undefined tam, gdzie powinny być dane.</p>
<p>Asynchroniczność w JavaScript to temat, o którym każdy mówił to samo: "To ten moment, kiedy JavaScript przestaje mieć sens, a potem nagle zaczyna mieć sens zupełnie inny niż myślałaś."</p>
<p>Po tygodniach walki, w końcu rozumiem promises i async/await na tyle, żeby o tym napisać.</p>
<p>W tym Learning Logu pokazuję:</p>
<p>- Dlaczego kod w JavaScript nie zawsze wykonuje się w kolejności, w jakiej go piszemy (i dlaczego to konieczne)<br />
- Wywołania zwrotne (callbacks) i "piekło wywołań zwrotnych" - problem, który trzeba było rozwiązać<br />
- Obietnice (Promises) - eleganckie rozwiązanie z łańcuchowaniem operacji<br />
- Async/await - składnia sprawiająca, że kod asynchroniczny wygląda jak zwykły, sekwencyjny kod<br />
- Praktyczny projekt: wyszukiwarka pogody korzystająca z prawdziwego API<br />
- Cztery typowe błędy początkujących (zapominanie o await, operacje sekwencyjne zamiast równoległych, brak obsługi błędów)</p>
<p>Plus: dlaczego warto poznać wszystkie trzy podejścia po kolei, zamiast od razu skakać do najnowszej składni.</p>
<p>Trzy tygodnie frustracji, diagramy na kartce papieru, wieczory gapienia się w undefined w konsoli. Ale kiedy w końcu kliknęło - satysfakcja jakiej nie dała żadna łatwiejsza lekcja.</p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/asynchronicznosc-javascript-promises-async-await-learning-log-8/">Learning Log #8: Asynchroniczność w JavaScript &#8211; promises i async/await</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Środa, 21:50. Ten sam fragment kodu wyświetla się na ekranie już trzeci wieczór z rzędu. Konsola pokazuje <code>undefined</code> tam, gdzie powinny być dane. Zamykam laptopa, otwieram notatnik, zaczynam rysować diagram strzałkami &#8211; próbuję zrozumieć, <strong>w jakiej kolejności właściwie wykonuje się mój kod</strong>.</p>



<p class="wp-block-paragraph"><strong>Asynchroniczność w JavaScript</strong> to temat, o którym każdy, kogo pytałam, mówił to samo: &#8222;To jest ten moment, kiedy JavaScript przestaje mieć sens, a potem nagle zaczyna mieć sens zupełnie inny niż myślałaś.&#8221;</p>



<p class="wp-block-paragraph">Mieli rację w obu częściach tego zdania.</p>



<p class="wp-block-paragraph">Po tygodniach walki z tym tematem &#8211; dosłownie tygodniach, nie dniach, jak przy poprzednich Learning Logach &#8211; w końcu czuję, że rozumiem <strong>obietnice (promises) i składnię async/await</strong> na tyle, żeby napisać o tym w sposób, który mógłby zaoszczędzić komuś innemu część tej frustracji.</p>



<p class="wp-block-paragraph">Dziś w <strong>Learning Log #8</strong> pokażę Wam, dlaczego kod w JavaScript nie zawsze wykonuje się w kolejności, w jakiej go piszemy, jak wyglądała ewolucja rozwiązywania tego problemu (od wywołań zwrotnych, przez obietnice, po async/await), i jakie konkretne błędy sprawiły, że ten temat kosztował mnie więcej godzin niż cała reszta JavaScriptu razem wzięta.</p>



<h3 class="wp-block-heading" style="font-size:22px">Dlaczego ten temat jest tak trudny &#8211; problem u podstaw</h3>



<h4 class="wp-block-heading" style="font-size:20px">Założenie, które trzeba porzucić</h4>



<p class="wp-block-paragraph">Ucząc się Javy, a potem podstaw JavaScriptu, przyzwyczaiłam się do jednej fundamentalnej zasady: <strong>kod wykonuje się linijka po linijce, od góry do dołu, w kolejności, w jakiej go napisałam.</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>console.log('Pierwsze');
console.log('Drugie');
console.log('Trzecie');
</code></pre>



<p class="wp-block-paragraph">Wynik jest oczywisty: &#8222;Pierwsze&#8221;, potem &#8222;Drugie&#8221;, potem &#8222;Trzecie&#8221;. Zawsze w tej kolejności.</p>



<p class="wp-block-paragraph"><strong>Problem zaczyna się, kiedy JavaScript musi na coś poczekać</strong> &#8211; na odpowiedź z serwera, na wczytanie pliku, na upłynięcie określonego czasu. I tu okazuje się, że JavaScript <strong>nie czeka grzecznie w miejscu</strong>, tylko leci dalej do kolejnej linijki kodu, zanim operacja oczekująca się zakończy.</p>



<p class="wp-block-paragraph"><strong>Prosty przykład, który pokazuje ten problem:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>console.log('Pierwsze');

setTimeout(function() {
    console.log('Drugie (opóźnione)');
}, 2000);

console.log('Trzecie');
</code></pre>



<p class="wp-block-paragraph"><strong>Intuicyjne oczekiwanie:</strong> Pierwsze, Drugie (po 2 sekundach), Trzecie</p>



<p class="wp-block-paragraph"><strong>Rzeczywisty wynik:</strong> Pierwsze, Trzecie, Drugie (po 2 sekundach)</p>



<p class="wp-block-paragraph"><strong>WTF moment #1, ten fundamentalny:</strong> &#8222;Dlaczego 'Trzecie&#8217; pojawia się PRZED 'Drugie&#8217;, skoro w kodzie jest napisane po nim?!&#8221;</p>



<h4 class="wp-block-heading" style="font-size:20px">Dlaczego JavaScript działa w ten sposób</h4>



<p class="wp-block-paragraph">JavaScript jest <strong>jednowątkowy</strong> (single-threaded) &#8211; w danym momencie może robić tylko jedną rzecz. Gdyby przy każdym oczekiwaniu (na serwer, na timer, na dowolną operację trwającą jakiś czas) zatrzymywał się i czekał bezczynnie, cała strona internetowa by &#8222;zamarzała&#8221; &#8211; nie dałoby się kliknąć przycisku, przewinąć strony, nic.</p>



<p class="wp-block-paragraph"><strong>Rozwiązaniem jest model asynchroniczny</strong> &#8211; JavaScript &#8222;odkłada na bok&#8221; operacje, które wymagają czekania, kontynuuje wykonywanie reszty kodu, a kiedy odłożona operacja się zakończy, wraca do niej i wykonuje jej dalszą część.</p>



<p class="wp-block-paragraph"><strong>Analogia, która w końcu do mnie dotarła:</strong></p>



<p class="wp-block-paragraph">Wyobraź sobie, że gotujesz obiad. Wkładasz ziemniaki do gotowania (to potrwa 20 minut). Nie stoisz bezczynnie przy garnku przez 20 minut &#8211; zajmujesz się w tym czasie krojeniem warzyw, przygotowaniem mięsa. Kiedy timer przypomni, że ziemniaki są gotowe, wracasz do nich.</p>



<p class="wp-block-paragraph"><strong>JavaScript robi dokładnie to samo z kodem</strong> &#8211; &#8222;wkłada ziemniaki do gotowania&#8221; (operację asynchroniczną), leci dalej do następnych linijek, a kiedy operacja się zakończy, wraca i wykonuje to, co miało się stać po jej zakończeniu.</p>



<h3 class="wp-block-heading" style="font-size:22px">Wywołania zwrotne (callbacks) &#8211; pierwsze rozwiązanie problemu</h3>



<h4 class="wp-block-heading" style="font-size:20px">Jak to działało, zanim poznałam coś lepszego</h4>



<p class="wp-block-paragraph">Zanim poznałam obietnice (promise), JavaScript rozwiązywał asynchroniczność za pomocą <strong>funkcji zwrotnych (callback functions)</strong> &#8211; funkcji przekazywanych jako argument, która wykonuje się dopiero po zakończeniu operacji asynchronicznej.</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>function pobierzDaneUzytkownika(id, funkcjaZwrotna) {
    setTimeout(function() {
        const uzytkownik = { id: id, imie: 'Anna' };
        funkcjaZwrotna(uzytkownik);
    }, 1000);
}

pobierzDaneUzytkownika(1, function(uzytkownik) {
    console.log('Otrzymano użytkownika:', uzytkownik);
});
</code></pre>



<p class="wp-block-paragraph"><strong>To rozwiązywało podstawowy problem</strong> &#8211; kod wewnątrz funkcji zwrotnej wykonuje się dopiero, kiedy dane faktycznie są gotowe, nie wcześniej.</p>



<h4 class="wp-block-heading" style="font-size:20px">Problem, który pojawiał się przy złożonych operacjach &#8211; &#8222;piekło wywołań zwrotnych&#8221;</h4>



<p class="wp-block-paragraph">Kiedy trzeba było wykonać kilka operacji asynchronicznych jedna po drugiej (na przykład: pobierz użytkownika, potem na podstawie jego ID pobierz jego zamówienia, potem na podstawie zamówień pobierz szczegóły produktów), kod zaczynał wyglądać tak:</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>pobierzUzytkownika(1, function(uzytkownik) {
    pobierzZamowienia(uzytkownik.id, function(zamowienia) {
        pobierzSzczegolyProduktu(zamowienia&#91;0].produktId, function(produkt) {
            pobierzOpinieOProdukcie(produkt.id, function(opinie) {
                console.log('Wreszcie mam wszystkie dane:', opinie);
// im głębiej, tym trudniej czytać
            });
        });
    });
});
</code></pre>



<p class="wp-block-paragraph"><strong>To zjawisko ma nawet swoją nazwę &#8211; &#8222;callback hell&#8221; (piekło wywołań zwrotnych)</strong>, ze względu na charakterystyczny kształt kodu przypominający schody prowadzące coraz głębiej w prawo.</p>



<p class="wp-block-paragraph"><strong>WTF moment #2:</strong> &#8222;Jak ktokolwiek czyta i debuguje kod, który wygląda jak trójkąt?!&#8221;</p>



<p class="wp-block-paragraph">Zrozumienie tego problemu było dla mnie kluczowe, żeby docenić, <strong>dlaczego</strong> wprowadzono obietnice &#8211; to nie była zmiana &#8222;dla mody&#8221;, tylko realna odpowiedź na realny problem czytelności i zarządzania kodem.</p>



<h3 class="wp-block-heading" style="font-size:22px">Obietnice (Promises) &#8211; eleganckie rozwiązanie</h3>



<h4 class="wp-block-heading" style="font-size:20px">Czym jest obietnica</h4>



<p class="wp-block-paragraph" style="padding-top:var(--wp--preset--spacing--30)"><strong>Obietnica (Promise)</strong> to obiekt reprezentujący ostateczny wynik operacji asynchronicznej &#8211; może zostać <strong>spełniona</strong> (fulfilled, operacja się powiodła) albo <strong>odrzucona</strong> (rejected, operacja się nie powiodła).</p>



<p class="wp-block-paragraph"><strong>Analogia, która pomogła mi to zrozumieć:</strong></p>



<p class="wp-block-paragraph">Obietnica to jak numerek w McDonald&#8217;s. Zamawiasz jedzenie (rozpoczynasz operację asynchroniczną), dostajesz numerek (obietnicę) &#8211; jeszcze nie masz jedzenia, ale masz <strong>coś</strong>, co reprezentuje przyszłe jedzenie. Kiedy jedzenie jest gotowe (obietnica spełniona), możesz je odebrać. Jeśli restauracja ma problem i nie może zrealizować zamówienia (obietnica odrzucona), dostajesz inną informację.</p>



<h4 class="wp-block-heading" style="font-size:20px">Podstawowa składnia</h4>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>function pobierzDaneUzytkownika(id) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            if (id &gt; 0) {
                resolve({ id: id, imie: 'Anna' });
            } else {
                reject('Nieprawidłowe ID użytkownika');
            }
        }, 1000);
    });
}

pobierzDaneUzytkownika(1)
    .then(function(uzytkownik) {
        console.log('Sukces:', uzytkownik);
    })
    .catch(function(blad) {
        console.log('Błąd:', blad);
    });
</code></pre>



<p class="wp-block-paragraph"><strong>Kluczowe elementy:</strong></p>



<ul class="wp-block-list">
<li><code>resolve()</code> &#8211; wywoływane, kiedy operacja się powiodła</li>



<li><code>reject()</code> &#8211; wywoływane, kiedy operacja się nie powiodła</li>



<li><code>.then()</code> &#8211; kod wykonujący się po pomyślnym zakończeniu</li>



<li><code>.catch()</code> &#8211; kod wykonujący się w przypadku błędu</li>
</ul>



<h4 class="wp-block-heading" style="font-size:20px">Łańcuchowanie obietnic &#8211; rozwiązanie problemu &#8222;piekła wywołań zwrotnych&#8221;</h4>



<p class="wp-block-paragraph" style="padding-top:var(--wp--preset--spacing--30)">To był dla mnie moment przełomowy &#8211; zamiast zagnieżdżania funkcji w funkcjach w funkcjach, obietnice można <strong>łańcuchować</strong>:</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>pobierzUzytkownika(1)
    .then(function(uzytkownik) {
        return pobierzZamowienia(uzytkownik.id);
    })
    .then(function(zamowienia) {
        return pobierzSzczegolyProduktu(zamowienia&#91;0].produktId);
    })
    .then(function(produkt) {
        return pobierzOpinieOProdukcie(produkt.id);
    })
    .then(function(opinie) {
        console.log('Wreszcie mam wszystkie dane:', opinie);
    })
    .catch(function(blad) {
        console.log('Coś poszło nie tak w którymkolwiek kroku:', blad);
    });
</code></pre>



<p class="wp-block-paragraph"><strong>Różnica wizualna jest ogromna</strong> &#8211; kod płynie w dół, nie w prawo. I co szczególnie doceniłam: <strong>jeden <code>.catch()</code> na końcu łapie błąd z DOWOLNEGO miejsca w łańcuchu</strong>, zamiast konieczności obsługi błędu osobno w każdej zagnieżdżonej funkcji zwrotnej.</p>



<p class="wp-block-paragraph"><strong>WTF moment #3, ale w dobrym sensie:</strong> &#8222;Czekaj, to jedna linijka <code>.catch()</code> obsługuje błędy z czterech różnych operacji naraz?!&#8221;</p>



<h3 class="wp-block-heading" style="font-size:22px">Async/Await &#8211; składnia, która wszystko zmieniła</h3>



<h4 class="wp-block-heading" style="font-size:20px">Dlaczego to było moje &#8222;aha!&#8221;</h4>



<p class="wp-block-paragraph">Po tygodniu oswajania się z <code>.then()</code> i <code>.catch()</code>, natrafiłam na składnię <code>async/await</code>, która &#8211; jak się okazało &#8211; to po prostu <strong>wygodniejszy sposób pisania tego samego, co robią obietnice</strong>, ale wyglądający jak zwykły, sekwencyjny kod.</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>async function pobierzWszystkieDane() {
    try {
        const uzytkownik = await pobierzUzytkownika(1);
        const zamowienia = await pobierzZamowienia(uzytkownik.id);
        const produkt = await pobierzSzczegolyProduktu(zamowienia&#91;0].produktId);
        const opinie = await pobierzOpinieOProdukcie(produkt.id);

        console.log('Wreszcie mam wszystkie dane:', opinie);
    } catch (blad) {
        console.log('Coś poszło nie tak:', blad);
    }
}

pobierzWszystkieDane();
</code></pre>



<p class="wp-block-paragraph"><strong>To wygląda niemal identycznie jak zwykły, synchroniczny kod!</strong> Żadnych <code>.then()</code>, żadnego zagnieżdżania &#8211; po prostu linijka po linijce, jakby wszystko działo się w kolejności (mimo że pod spodem dalej jest to asynchroniczne).</p>



<h4 class="wp-block-heading" style="font-size:20px">Kluczowe elementy składni</h4>



<ul class="wp-block-list">
<li><strong><code>async</code></strong> &#8211; słowo kluczowe umieszczane przed definicją funkcji, oznaczające, że funkcja będzie zawierała operacje asynchroniczne i automatycznie zwraca obietnicę.</li>



<li><strong><code>await</code></strong> &#8211; słowo kluczowe używane WEWNĄTRZ funkcji async, &#8222;wstrzymujące&#8221; wykonanie tej konkretnej funkcji (nie całego programu!) do momentu, aż obietnica się rozstrzygnie.</li>



<li><strong><code>try/catch</code></strong> &#8211; standardowy mechanizm obsługi błędów w JavaScript, który przy async/await zastępuje <code>.catch()</code> z obietnic.</li>
</ul>



<h4 class="wp-block-heading" style="font-size:20px">Moment, w którym w końcu zrozumiałam różnicę między &#8222;wstrzymaniem funkcji&#8221; a &#8222;zamrożeniem programu&#8221;</h4>



<p class="wp-block-paragraph">To była kluczowa rzecz, którą myliłam przez dobry tydzień. <code>await</code> <strong>nie zamraża całej strony internetowej</strong> &#8211; zamraża tylko wykonanie tej jednej konkretnej funkcji, w której się znajduje. Reszta programu (obsługa kliknięć, inne funkcje) działa dalej normalnie.</p>



<p class="wp-block-paragraph"><strong>Przykład, który to zilustrował:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>async function wolnaOperacja() {
    console.log('Zaczynam wolną operację');
    await new Promise(resolve =&gt; setTimeout(resolve, 3000));
    console.log('Wolna operacja zakończona');
}

wolnaOperacja();
console.log('Ten tekst pojawi się NATYCHMIAST, nie czeka na wolnaOperacja()');
</code></pre>



<p class="wp-block-paragraph"><strong>Kolejność wykonania:</strong></p>



<ol class="wp-block-list">
<li>&#8222;Zaczynam wolną operację&#8221;</li>



<li>&#8222;Ten tekst pojawi się NATYCHMIAST&#8230;&#8221; (bo <code>wolnaOperacja()</code> nie blokuje reszty kodu)</li>



<li>Po 3 sekundach: &#8222;Wolna operacja zakończona&#8221;</li>
</ol>



<h3 class="wp-block-heading" style="font-size:22px">Praktyczny projekt &#8211; pobieranie danych z prawdziwego API</h3>



<p class="wp-block-paragraph">Po opanowaniu teorii, zbudowałam mój pierwszy projekt wykorzystujący asynchroniczność w praktyce &#8211; <strong>prostą wyszukiwarkę informacji o miastach</strong> korzystającą z darmowego, publicznego API pogodowego.</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>async function pobierzPogodeDlaMiasta(nazwaMiasta) {
    const kluczApi = 'TWOJ_KLUCZ_API';
    const url = `https://api.przykladowaPogoda.com/dane?miasto=${nazwaMiasta}&amp;key=${kluczApi}`;

    try {
        pokazLadowanie(true);

        const odpowiedz = await fetch(url);

        if (!odpowiedz.ok) {
            throw new Error(`Błąd serwera:${odpowiedz.status}`);
        }

        const dane = await odpowiedz.json();

        wyswietlPogode(dane);

    } catch (blad) {
        wyswietlKomunikatBledu('Nie udało się pobrać danych pogodowych: ' + blad.message);
    } finally {
        pokazLadowanie(false);
    }
}

function wyswietlPogode(dane) {
    const kontener = document.getElementById('wynikPogody');
    kontener.innerHTML = `
        &lt;h3&gt;${dane.miasto}&lt;/h3&gt;
        &lt;p&gt;Temperatura:${dane.temperatura}°C&lt;/p&gt;
        &lt;p&gt;Warunki:${dane.opis}&lt;/p&gt;
    `;
}

function wyswietlKomunikatBledu(wiadomosc) {
    const kontener = document.getElementById('wynikPogody');
    kontener.innerHTML = `&lt;p class="blad"&gt;${wiadomosc}&lt;/p&gt;`;
}

function pokazLadowanie(czyPokazac) {
    const spinner = document.getElementById('ladowanie');
    spinner.style.display = czyPokazac ? 'block' : 'none';
}

// Podpięcie do przycisku
document.getElementById('przyciskSzukaj').addEventListener('click', function() {
    const miasto = document.getElementById('inputMiasto').value;
    pobierzPogodeDlaMiasta(miasto);
});
</code></pre>



<p class="wp-block-paragraph"><strong>Co się nauczyłam budując ten projekt:</strong></p>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><code>fetch()</code></strong> &#8211; wbudowana funkcja JavaScript do pobierania danych z zewnętrznych źródeł, zwracająca obietnicę</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><code>response.json()</code></strong> &#8211; konwersja odpowiedzi serwera na obiekt JavaScript, sama w sobie też asynchroniczna (stąd drugi <code>await</code>)</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><code>try/catch/finally</code></strong> &#8211; blok <code>finally</code> wykonuje się zawsze, niezależnie od tego, czy operacja się powiodła czy nie (idealne miejsce na ukrycie animacji ładowania)</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Obsługa różnych typów błędów</strong> &#8211; błąd sieci (serwer nie odpowiada) versus błąd logiczny (serwer odpowiedział, ale z kodem błędu)</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Łączenie manipulacji DOM (o czym pisałam w poprzednim Learning Logu) z operacjami asynchronicznymi</strong></li>
</ul>



<p class="wp-block-paragraph"><strong>Czas realizacji:</strong> 5 godzin, rozłożone na cztery dni &#8211; znacznie dłużej niż poprzednie mini-projekty, ale też znacznie więcej się nauczyłam.</p>



<h3 class="wp-block-heading" style="font-size:22px">Typowe błędy, które popełniłam &#8211; i jak je naprawiłam</h3>



<h4 class="wp-block-heading" style="font-size:20px">Błąd 1: Zapominanie o <code>await</code></h4>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>// ŹLE
async function pobierzDane() {
    const wynik = fetch('&lt;https://przykladowe-api.com/dane&gt;');
    console.log(wynik); // Promise { &lt;pending&gt; } - nie dane, tylko sama obietnica!
}

// DOBRZE
async function pobierzDane() {
    const wynik = await fetch('&lt;https://przykladowe-api.com/dane&gt;');
    console.log(wynik); // teraz faktyczna odpowiedź
}
</code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Bez <code>await</code>, dostajesz samą obietnicę (obiekt &#8222;w trakcie realizacji&#8221;), nie faktyczny wynik operacji. To był mój najczęstszy błąd przez pierwsze dwa tygodnie &#8211; kod &#8222;działał&#8221; bez błędu, ale wyświetlał kompletnie bezużyteczne dane.</p>



<h4 class="wp-block-heading" style="font-size:20px">Błąd 2: Używanie <code>await</code> poza funkcją <code>async</code></h4>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>// ŹLE - błąd składni
function pobierzDane() {
    const wynik = await fetch('&lt;https://przykladowe-api.com/dane&gt;');
}

// DOBRZE
async function pobierzDane() {
    const wynik = await fetch('&lt;https://przykladowe-api.com/dane&gt;');
}
</code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> <code>await</code> działa TYLKO wewnątrz funkcji oznaczonej jako <code>async</code>. To była prosta zasada, ale zapominałam o niej regularnie, szczególnie przy pisaniu krótkich funkcji pomocniczych.</p>



<h4 class="wp-block-heading" style="font-size:20px">Błąd 3: Sekwencyjne wykonywanie operacji, które mogły działać równolegle</h4>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>// NIEOPTYMALNIE - operacje wykonują się jedna po drugiej, mimo że nie muszą
async function pobierzWszystko() {
    const uzytkownik = await pobierzUzytkownika(1); // czeka 1 sekundę
    const produkty = await pobierzProdukty(); // czeka kolejną sekundę
// razem: 2 sekundy, mimo że te operacje nie zależą od siebie!
}

// LEPIEJ - operacje wykonują się jednocześnie
async function pobierzWszystko() {
    const &#91;uzytkownik, produkty] = await Promise.all(&#91;
        pobierzUzytkownika(1),
        pobierzProdukty()
    ]);
// razem: tylko 1 sekunda, bo obie operacje leciały równolegle!
}
</code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> <code>Promise.all()</code> pozwala uruchomić kilka niezależnych operacji asynchronicznych <strong>jednocześnie</strong>, zamiast czekać na jedną, żeby zacząć następną. To był koncept, który zrozumiałam dopiero po przeanalizowaniu, dlaczego mój projekt z pogodą dla kilku miast naraz działał wolniej niż powinien.</p>



<h4 class="wp-block-heading" style="font-size:20px">Błąd 4: Brak obsługi błędów</h4>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>// RYZYKOWNIE - brak try/catch
async function pobierzDane() {
    const odpowiedz = await fetch(url); // co jeśli serwer nie odpowiada?
    const dane = await odpowiedz.json();
    return dane;
}

// BEZPIECZNIE
async function pobierzDane() {
    try {
        const odpowiedz = await fetch(url);
        const dane = await odpowiedz.json();
        return dane;
    } catch (blad) {
        console.error('Nie udało się pobrać danych:', blad);
        return null;
    }
}
</code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Bez bloku <code>try/catch</code>, błąd w operacji asynchronicznej powoduje niewyjaśniony &#8222;cichy&#8221; upadek funkcji, bez żadnej informacji dla użytkownika, co poszło nie tak. To szczególnie problematyczne przy pracy z zewnętrznymi API, które mogą nie odpowiadać z wielu różnych powodów (brak internetu, przeciążony serwer, nieprawidłowe zapytanie).</p>



<h3 class="wp-block-heading" style="font-size:22px">Dlaczego warto było poznać wywołania zwrotne, zanim poznałam obietnice</h3>



<p class="wp-block-paragraph">Zastanawiałam się, czy nie lepiej było od razu uczyć się async/await, pomijając wywołania zwrotne i obietnice jako &#8222;przestarzałe&#8221;. Po przejściu przez wszystkie trzy etapy jestem przekonana, że <strong>ta kolejność miała sens</strong>.</p>



<p class="wp-block-paragraph"><strong>Zrozumienie wywołań zwrotnych</strong> pokazało mi <strong>PROBLEM</strong>, który asynchroniczność w ogóle stwarza.</p>



<p class="wp-block-paragraph"><strong>Poznanie obietnic</strong> pokazało mi, <strong>JAK</strong> ten problem został rozwiązany na poziomie koncepcyjnym.</p>



<p class="wp-block-paragraph"><strong>Zrozumienie async/await</strong> pokazało mi wygodniejszy <strong>SPOSÓB ZAPISU</strong> tego samego rozwiązania.</p>



<p class="wp-block-paragraph">Gdybym zaczęła od razu od async/await, prawdopodobnie umiałabym pisać kod, który działa, ale bez zrozumienia, <strong>co dokładnie dzieje się pod spodem</strong> &#8211; co utrudniałoby debugowanie w momencie, gdy coś pójdzie nie tak w bardziej złożonym scenariuszu.</p>



<h3 class="wp-block-heading" style="font-size:22px">Zasoby, które pomogły mi zrozumieć asynchroniczność</h3>



<h4 class="wp-block-heading" style="margin-top:var(--wp--preset--spacing--40);font-size:20px">1. &#8222;JavaScript Visualized: Promises&#8221; &#8211; Lydia Hallie (★★★★★)</h4>



<p class="wp-block-paragraph">Wizualne, animowane wyjaśnienie, jak dokładnie obietnice działają &#8222;pod maską&#8221;. To był zasób, który sprawił, że nagle wszystko &#8222;kliknęło&#8221; po tygodniu czytania czysto tekstowych wyjaśnień.</p>



<h4 class="wp-block-heading" style="font-size:20px">2. <a href="http://JavaScript.info">JavaScript.info</a> &#8211; rozdziały o Promise i Async/await (★★★★★)</h4>



<p class="wp-block-paragraph">Jak zawsze przy tym źródle &#8211; szczegółowe, dokładne wyjaśnienia z licznymi przykładami. Wracałam do konkretnych fragmentów wielokrotnie.</p>



<h4 class="wp-block-heading" style="font-size:20px">3. &#8222;What the heck is the event loop anyway?&#8221; &#8211; Philip Roberts (★★★★★)</h4>



<p class="wp-block-paragraph">Prezentacja konferencyjna (dostępna na YouTube) wyjaśniająca <strong>pętlę zdarzeń (event loop)</strong> &#8211; mechanizm, dzięki któremu JavaScript w ogóle może obsługiwać operacje asynchroniczne, mimo że jest jednowątkowy. To wyjaśnienie dało mi zrozumienie &#8222;dlaczego&#8221; na poziomie znacznie głębszym niż samo &#8222;jak pisać kod&#8221;.</p>



<h4 class="wp-block-heading" style="font-size:20px">4. Praktyka &#8211; budowanie własnych mini-projektów z prawdziwymi API</h4>



<p class="wp-block-paragraph">Żadne wyjaśnienie teoretyczne nie zastąpiło realnego zderzenia się z błędami przy pracy z prawdziwym, zewnętrznym API, które czasem nie odpowiada, zwraca nieoczekiwane dane, albo działa wolniej niż się spodziewałam.</p>



<h3 class="wp-block-heading" style="font-size:22px">Plany na listopad &#8211; co dalej</h3>



<p class="wp-block-paragraph" style="padding-top:var(--wp--preset--spacing--30)"><strong>Tydzień 1-2 października (kontynuacja):</strong></p>



<ul class="wp-block-list">
<li>Utrwalenie async/await przez kolejne mniejsze projekty</li>



<li>Praca z kilkoma różnymi publicznymi API dla praktyki</li>
</ul>



<p class="wp-block-paragraph"><strong>Listopad:</strong></p>



<ul class="wp-block-list">
<li>Pierwszy kontakt z React &#8211; framework, który intensywnie wykorzystuje te same koncepty asynchroniczności, tylko w innym kontekście</li>



<li>Może pierwsza integracja JavaScript z projektami WordPress dla praktycznego zastosowania</li>
</ul>



<p class="wp-block-paragraph"><strong>Cel realistyczny:</strong> Czuć się na tyle pewnie z asynchronicznością, żeby móc czytać i rozumieć kod innych osób wykorzystujący te koncepty, nawet jeśli sama jeszcze nie piszę wszystkiego od razu bezbłędnie.</p>



<h3 class="wp-block-heading" style="font-size:22px">FAQ &#8211; asynchroniczność w JavaScript</h3>



<h4 class="wp-block-heading" style="font-size:20px">Czy muszę rozumieć wywołania zwrotne, jeśli i tak będę używać tylko async/await?</h4>



<p class="wp-block-paragraph">Nie jest to absolutnie konieczne, ale mocno polecam przynajmniej podstawowe zrozumienie problemu, który wywołania zwrotne rozwiązywały. Ułatwia to zrozumienie, DLACZEGO async/await wygląda tak, jak wygląda, zamiast traktowania tej składni jako magicznej formułki do zapamiętania.</p>



<h4 class="wp-block-heading" style="font-size:20px">Ile czasu zajęła Ci nauka tego tematu?</h4>



<p class="wp-block-paragraph">Znacznie więcej niż poprzednich tematów &#8211; około trzech tygodni intensywniejszej nauki, w porównaniu do jednego-dwóch tygodni przy wcześniejszych Learning Logach. To zdecydowanie najtrudniejszy temat JavaScriptu, z jakim się do tej pory zmierzyłam.</p>



<h4 class="wp-block-heading" style="font-size:20px">Czy asynchroniczność jest unikalna dla JavaScriptu?</h4>



<p class="wp-block-paragraph">Nie &#8211; większość nowoczesnych języków programowania ma jakąś formę obsługi operacji asynchronicznych, w tym Java (którą poznałam wcześniej), choć mechanizmy i składnia różnią się znacząco. Koncepcja &#8222;czekania na coś bez blokowania całego programu&#8221; jest uniwersalna w programowaniu.</p>



<h4 class="wp-block-heading" style="font-size:20px">Co było najtrudniejsze w tym temacie?</h4>



<p class="wp-block-paragraph">Zdecydowanie <strong>zrozumienie, dlaczego kod nie wykonuje się w kolejności, w jakiej go napisałam</strong> &#8211; to fundamentalnie łamało moje dotychczasowe intuicje wyniesione z Javy. Dopiero po zrozumieniu pętli zdarzeń (event loop) na poziomie koncepcyjnym, reszta zaczęła mieć sens.</p>



<h4 class="wp-block-heading" style="font-size:20px">Czy warto uczyć się wszystkich trzech podejść (wywołania zwrotne, obietnice, async/await), czy tylko najnowszego?</h4>



<p class="wp-block-paragraph">Polecam przynajmniej podstawowe zrozumienie wszystkich trzech, nawet jeśli w praktyce będziesz pisać kod głównie z użyciem async/await. Duża część istniejącego kodu (w bibliotekach, starszych projektach, dokumentacji) nadal korzysta z obietnic bezpośrednio, a zrozumienie wywołań zwrotnych pomaga docenić, dlaczego w ogóle powstały nowsze rozwiązania.</p>



<h3 class="wp-block-heading" style="font-size:22px">Podsumowanie &#8211; Learning Log #8</h3>



<p class="wp-block-paragraph"><strong>Asynchroniczność w JavaScript</strong> okazała się najtrudniejszym tematem, z jakim zmierzyłam się do tej pory w mojej nauce programowania &#8211; trudniejszym niż podstawy Javy, trudniejszym niż manipulacja DOM, trudniejszym niż cokolwiek wcześniej.</p>



<p class="wp-block-paragraph"><strong>Co osiągnęłam:</strong></p>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Rozumiem, dlaczego JavaScript nie wykonuje kodu zawsze w kolejności zapisu</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Znam historię rozwiązań tego problemu &#8211; od wywołań zwrotnych, przez obietnice, po async/await</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Potrafię pisać funkcje asynchroniczne z poprawną obsługą błędów</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Rozumiem różnicę między operacjami sekwencyjnymi a równoległymi (<code>Promise.all()</code>)</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Zbudowałam działający projekt pobierający dane z prawdziwego, zewnętrznego API</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Znam cztery najczęstsze błędy początkujących i wiem, jak ich unikać</li>
</ul>



<p class="wp-block-paragraph"><strong>Najważniejsza lekcja tego etapu:</strong></p>



<p class="wp-block-paragraph"><strong>Niektóre tematy w programowaniu wymagają nie tylko więcej czasu, ale wręcz zmiany sposobu myślenia.</strong> Asynchroniczność nie jest po prostu &#8222;trudniejszą składnią&#8221; &#8211; wymaga porzucenia fundamentalnego założenia o tym, jak w ogóle działa wykonywanie kodu.</p>



<p class="wp-block-paragraph">Trzy tygodnie frustracji, diagramy strzałkami na kartce papieru, i wieczory gapienia się w konsolę pokazującą <code>undefined</code> &#8211; to była cena zrozumienia tego tematu. Ale teraz, kiedy w końcu &#8222;kliknęło&#8221;, czuję satysfakcję, jakiej nie dała mi żadna łatwiejsza lekcja.</p>



<p class="wp-block-paragraph">Czasem najtrudniejsze tematy dają najwięcej, kiedy się w końcu poddadzą.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><em>PS: Pamiętasz swój moment zrozumienia asynchroniczności? Albo może dopiero się z nią zmagasz i chcesz się podzielić frustracją? Zostaw komentarz &#8211; obiecuję, że rozumiem tę walkę lepiej niż większość rzeczy, o których pisałam do tej pory!</em></p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/asynchronicznosc-javascript-promises-async-await-learning-log-8/">Learning Log #8: Asynchroniczność w JavaScript &#8211; promises i async/await</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.danuta-cybulska.com/asynchronicznosc-javascript-promises-async-await-learning-log-8/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Learning Log #7: JavaScript &#8211; manipulacja DOM, zdarzenia i pierwsza prawdziwa interaktywność</title>
		<link>https://www.danuta-cybulska.com/learning-log-7-javascript-dom-zdarzenia-interaktywnosc/</link>
					<comments>https://www.danuta-cybulska.com/learning-log-7-javascript-dom-zdarzenia-interaktywnosc/#respond</comments>
		
		<dc:creator><![CDATA[Danuta]]></dc:creator>
		<pubDate>Wed, 02 Sep 2026 16:00:00 +0000</pubDate>
				<category><![CDATA[LearningLog]]></category>
		<category><![CDATA[Programowanie i Rozwój]]></category>
		<category><![CDATA[delegacja zdarzeń]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[event bubbling]]></category>
		<category><![CDATA[event listener]]></category>
		<category><![CDATA[frontend]]></category>
		<category><![CDATA[interaktywność]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[learning log]]></category>
		<category><![CDATA[manipulacja DOM]]></category>
		<category><![CDATA[nasłuchiwacze zdarzeń]]></category>
		<category><![CDATA[nauka JavaScript]]></category>
		<category><![CDATA[projekt JavaScript]]></category>
		<category><![CDATA[web development]]></category>
		<guid isPermaLink="false">https://www.danuta-cybulska.com/?p=6009</guid>

					<description><![CDATA[<p>Poniedziałek, 2 września, 21:40. Szkoła wróciła do normalnego rytmu dziś rano. Dom w końcu cichy. A ja siedzę i patrzę na przycisk na ekranie, który właśnie zmienił kolor po kliknięciu. Brzmi banalnie, prawda? Przycisk zmienia kolor. Wielka rzecz. Ale to JA to zrobiłam. Napisałam kod, który sprawił, że strona internetowa reaguje na to, co robi...</p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-7-javascript-dom-zdarzenia-interaktywnosc/">Learning Log #7: JavaScript &#8211; manipulacja DOM, zdarzenia i pierwsza prawdziwa interaktywność</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Poniedziałek, 2 września, 21:40. Szkoła wróciła do normalnego rytmu dziś rano. Dom w końcu cichy. A ja siedzę i patrzę na przycisk na ekranie, który właśnie <strong>zmienił kolor po kliknięciu</strong>.</p>



<p class="wp-block-paragraph">Brzmi banalnie, prawda? Przycisk zmienia kolor. Wielka rzecz.</p>



<p class="wp-block-paragraph">Ale to JA to zrobiłam. Napisałam kod, który sprawił, że strona internetowa <strong>reaguje na to, co robi użytkownik</strong>. Nie odświeżam strony. Nie klikam linku. Element na ekranie po prostu&#8230; reaguje. Na żywo.</p>



<p class="wp-block-paragraph">Po dwóch miesiącach mikroedukacji w wakacje (<a href="https://www.danuta-cybulska.com/learning-log-6-java-vs-javascript-drugi-jezyk/">o czym pisałam w poprzednim wpisie</a>) i powrocie do pełnego tempa we wrześniu, wreszcie dotarłam do tematu, na który czekałam najbardziej: <strong>manipulacja DOM i zdarzenia w JavaScript</strong>. To jest moment, w którym JavaScript przestaje być &#8222;kolejnym językiem do nauki&#8221; i staje się narzędziem, które <strong>tchnie życie w strony internetowe</strong>.</p>



<p class="wp-block-paragraph">Dziś w <strong>Learning Log #7</strong> pokażę Wam czym jest DOM, jak JavaScript nim manipuluje, czym są nasłuchiwacze zdarzeń, i opiszę te momenty &#8222;wow&#8221;, kiedy pierwszy raz zobaczyłam własny kod reagujący na kliknięcie myszką.</p>



<h3 class="wp-block-heading" style="font-size:22px">Czym jest DOM &#8211; wyjaśnienie które w końcu do mnie dotarło</h3>



<h4 class="wp-block-heading" style="font-size:20px">Problem: rozumiałam składnię, ale nie rozumiałam koncepcji</h4>



<p class="wp-block-paragraph">Przez pierwsze tygodnie nauki JavaScript umiałam pisać pętle, funkcje, warunki &#8211; ale nie rozumiałam, <strong>jak to wszystko łączy się ze stroną internetową, którą widzę w przeglądarce</strong>.</p>



<p class="wp-block-paragraph">To była luka, która blokowała mnie od tworzenia czegokolwiek realnego.</p>



<h4 class="wp-block-heading" style="font-size:20px">Wyjaśnienie które zadziałało &#8211; analogia z domem</h4>



<p class="wp-block-paragraph"><strong>DOM</strong> (Document Object Model, po polsku: obiektowy model dokumentu) to sposób, w jaki przeglądarka &#8222;widzi&#8221; stronę internetową &#8211; nie jako tekst HTML, ale jako <strong>strukturę drzewa obiektów</strong>, którymi można manipulować.</p>



<p class="wp-block-paragraph"><strong>Analogia która mi pomogła:</strong></p>



<p class="wp-block-paragraph">Wyobraź sobie dom (budynek, nie stronę). HTML to plan architektoniczny domu &#8211; papierowy dokument opisujący, gdzie są ściany, drzwi, okna.</p>



<p class="wp-block-paragraph"><strong>DOM to sam dom, zbudowany na podstawie tego planu</strong> &#8211; fizyczna struktura, którą można otworzyć, zamknąć, przemalować, przestawić meble.</p>



<p class="wp-block-paragraph"><strong>HTML (plan):</strong></p>



<p class="wp-block-paragraph">html</p>



<pre class="wp-block-code"><code>&lt;div id="salon"&gt;
    &lt;button id="przycisk"&gt;Kliknij mnie&lt;/button&gt;
    &lt;p id="tekst"&gt;Witaj!&lt;/p&gt;
&lt;/div&gt;
</code></pre>



<p class="wp-block-paragraph"><strong>DOM (dom zbudowany z planu):</strong> Przeglądarka tworzy strukturę drzewa:</p>



<pre class="wp-block-code"><code>document
  └── div#salon
        ├── button#przycisk
        └── p#tekst
</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript może wejść do tego &#8222;domu&#8221; i:</strong></p>



<ul class="wp-block-list">
<li>Otworzyć drzwi (znaleźć element)</li>



<li>Przemalować ścianę (zmienić styl)</li>



<li>Przestawić meble (zmienić strukturę)</li>



<li>Zainstalować dzwonek reagujący na naciśnięcie (dodać nasłuchiwacz zdarzenia)</li>
</ul>



<h4 class="wp-block-heading" style="font-size:20px">Pierwsza manipulacja DOM &#8211; znajdowanie elementów</h4>



<p class="wp-block-paragraph"><strong>Podstawowe metody wyszukiwania elementów:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>// Po ID (najczęściej używane)
const przycisk = document.getElementById('przycisk');

// Po klasie (może zwrócić wiele elementów)
const wszystkieKarty = document.getElementsByClassName('karta');

// Po selektorze CSS (najbardziej elastyczne)
const pierwszyPrzycisk = document.querySelector('.przycisk');
const wszystkiePrzyciski = document.querySelectorAll('.przycisk');
</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #1:</strong> &#8222;Czekaj, mogę wyszukiwać elementy DOKŁADNIE tak samo jak w CSS?!&#8221;</p>



<p class="wp-block-paragraph">To była pierwsza rzecz, która sprawiła, że JavaScript nagle &#8222;kliknął&#8221; (nie mylić z tym przyciskiem, o którym za chwilę). Znałam już selektory CSS z pracy z WordPressem. Nagle mogłam użyć tej samej wiedzy do wyszukiwania elementów w JavaScript.</p>



<h3 class="wp-block-heading" style="font-size:22px">Manipulacja DOM &#8211; zmienianie tego, co widać na ekranie</h3>



<h4 class="wp-block-heading" style="font-size:20px">Zmiana tekstu</h4>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>const naglowek = document.getElementById('naglowek');
naglowek.textContent = 'Nowy tekst!';
</code></pre>



<p class="wp-block-paragraph"><strong>Pierwsza rzecz, którą zrobiłam:</strong> Zmiana powitania na stronie w zależności od pory dnia.</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>const godzina = new Date().getHours();
const powitanie = document.getElementById('powitanie');

if (godzina &lt; 12) {
    powitanie.textContent = 'Dzień dobry!';
} else if (godzina &lt; 18) {
    powitanie.textContent = 'Dzień dobry (popołudniu)!';
} else {
    powitanie.textContent = 'Dobry wieczór!';
}
</code></pre>



<p class="wp-block-paragraph"><strong>Efekt na ekranie:</strong> Odświeżam stronę &#8211; tekst się zmienia w zależności od tego, o której godzinie to robię. Proste, ale to był mój <strong>pierwszy prawdziwy moment &#8222;wow&#8221;</strong>.</p>



<h4 class="wp-block-heading" style="font-size:20px">Zmiana stylu (CSS przez JavaScript)</h4>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>const przycisk = document.getElementById('przycisk');
przycisk.style.backgroundColor = 'niebieski';
przycisk.style.color = 'biały';
przycisk.style.padding = '10px 20px';
</code></pre>



<p class="wp-block-paragraph"><strong>Zmiana klasy (lepsza praktyka niż zmiana pojedynczych stylów):</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>const karta = document.querySelector('.karta');
karta.classList.add('podswietlona');
karta.classList.remove('nieaktywna');
karta.classList.toggle('rozwiniety'); // dodaje jeśli nie ma, usuwa jeśli jest
</code></pre>



<p class="wp-block-paragraph"><strong>Dlaczego <code>classList</code> jest lepsze niż bezpośrednie zmienianie <code>style</code>:</strong></p>



<p class="wp-block-paragraph">Bezpośrednia zmiana stylu (<code>element.style.color = 'red'</code>) miesza logikę JavaScript ze stylowaniem CSS. Lepsza praktyka to przygotowanie klas CSS wcześniej (np. <code>.aktywny { color: red; }</code>) i dodawanie/usuwanie tych klas przez JavaScript.</p>



<h4 class="wp-block-heading" style="font-size:20px">Tworzenie nowych elementów dynamicznie</h4>



<p class="wp-block-paragraph">To była kolejna rzecz, która mnie zachwyciła &#8211; możliwość <strong>tworzenia całkowicie nowych elementów HTML</strong> za pomocą kodu, bez wcześniejszego pisania ich w pliku HTML.</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>function dodajZadanie(tresc) {
// Tworzę nowy element
    const nowyElement = document.createElement('li');
    nowyElement.textContent = tresc;
    nowyElement.classList.add('zadanie');

// Dodaję go do listy na stronie
    const lista = document.getElementById('listaZadan');
    lista.appendChild(nowyElement);
}

dodajZadanie('Nauczyć się manipulacji DOM');
dodajZadanie('Zbudować listę zadań');
</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #2:</strong> &#8222;Mogę tworzyć elementy które nigdy nie istniały w oryginalnym HTML?!&#8221;</p>



<p class="wp-block-paragraph">To otworzyło mi drzwi do zrozumienia, jak działają aplikacje typu lista zadań, komentarze dodawane na żywo, czy dynamiczne galerie zdjęć.</p>



<h3 class="wp-block-heading" style="font-size:22px">Zdarzenia (events) &#8211; jak strona reaguje na użytkownika</h3>



<h4 class="wp-block-heading" style="font-size:20px">Czym są zdarzenia</h4>



<p class="wp-block-paragraph"><strong>Zdarzenie</strong> to sygnał, że coś się wydarzyło na stronie &#8211; kliknięcie, najechanie myszką, wpisanie tekstu, przewinięcie strony, załadowanie się dokumentu.</p>



<p class="wp-block-paragraph"><strong>Nasłuchiwacz zdarzenia</strong> (event listener) to fragment kodu, który &#8222;czeka&#8221; na konkretne zdarzenie i uruchamia się, kiedy ono nastąpi.</p>



<h4 class="wp-block-heading" style="font-size:20px">Pierwszy nasłuchiwacz zdarzenia &#8211; moment przełomowy</h4>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>const przycisk = document.getElementById('przycisk');

przycisk.addEventListener('click', function() {
    console.log('Kliknięto przycisk!');
});
</code></pre>



<p class="wp-block-paragraph"><strong>To był moment, o którym pisałam na początku posta.</strong> Kliknęłam przycisk w przeglądarce, i w konsoli pojawił się mój tekst. Coś, co napisałam, zareagowało na moje działanie w czasie rzeczywistym.</p>



<p class="wp-block-paragraph"><strong>Rozwinięcie do praktycznego przykładu &#8211; zmiana koloru po kliknięciu:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>const przycisk = document.getElementById('przycisk');
let jestAktywny = false;

przycisk.addEventListener('click', function() {
    jestAktywny = !jestAktywny; // odwrócenie wartości logicznej

    if (jestAktywny) {
        przycisk.style.backgroundColor = 'zielony';
        przycisk.textContent = 'Aktywne!';
    } else {
        przycisk.style.backgroundColor = 'szary';
        przycisk.textContent = 'Kliknij mnie';
    }
});
</code></pre>



<h4 class="wp-block-heading" style="font-size:20px">Rodzaje zdarzeń które poznałam</h4>



<p class="wp-block-paragraph"><strong>Zdarzenia myszy:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>element.addEventListener('click', funkcja);        // kliknięcie
element.addEventListener('mouseover', funkcja);     // najechanie myszką
element.addEventListener('mouseout', funkcja);      // zjechanie myszką
element.addEventListener('dblclick', funkcja);      // podwójne kliknięcie
</code></pre>



<p class="wp-block-paragraph"><strong>Zdarzenia klawiatury:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>element.addEventListener('keydown', funkcja);       // naciśnięcie klawisza
element.addEventListener('keyup', funkcja);          // puszczenie klawisza
</code></pre>



<p class="wp-block-paragraph"><strong>Zdarzenia formularzy:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>formularz.addEventListener('submit', funkcja);       // wysłanie formularza
input.addEventListener('input', funkcja);             // zmiana wartości podczas pisania
input.addEventListener('change', funkcja);            // zmiana wartości (po opuszczeniu pola)
</code></pre>



<p class="wp-block-paragraph"><strong>Zdarzenia strony:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>window.addEventListener('load', funkcja);             // strona się załadowała
window.addEventListener('scroll', funkcja);            // przewinięcie strony
window.addEventListener('resize', funkcja);            // zmiana rozmiaru okna
</code></pre>



<h3 class="wp-block-heading" style="font-size:22px">Obiekt zdarzenia &#8211; dodatkowe informacje o tym, co się stało</h3>



<p class="wp-block-paragraph">Kiedy funkcja obsługująca zdarzenie się uruchamia, automatycznie dostaje dostęp do <strong>obiektu zdarzenia</strong> &#8211; zawierającego szczegółowe informacje o tym, co dokładnie się wydarzyło.</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>przycisk.addEventListener('click', function(zdarzenie) {
    console.log(zdarzenie.target);        // który element został kliknięty
    console.log(zdarzenie.clientX);       // pozycja X kursora
    console.log(zdarzenie.clientY);       // pozycja Y kursora
});
</code></pre>



<p class="wp-block-paragraph"><strong>Praktyczne zastosowanie &#8211; walidacja formularza podczas pisania:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>const inputEmail = document.getElementById('email');
const komunikat = document.getElementById('komunikatEmail');

inputEmail.addEventListener('input', function(zdarzenie) {
    const wartosc = zdarzenie.target.value;

    if (wartosc.includes('@')) {
        komunikat.textContent = 'Wygląda dobrze!';
        komunikat.style.color = 'zielony';
    } else {
        komunikat.textContent = 'Brakuje znaku @';
        komunikat.style.color = 'czerwony';
    }
});
</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #3:</strong> &#8222;Mogę sprawdzać co użytkownik pisze W CZASIE RZECZYWISTYM, bez klikania jakiegokolwiek przycisku 'sprawdź&#8217;?!&#8221;</p>



<p class="wp-block-paragraph">To był moment, który uświadomił mi, dlaczego nowoczesne formularze internetowe pokazują błędy na bieżąco, zamiast dopiero po wysłaniu.</p>



<h3 class="wp-block-heading" style="font-size:22px">Mój pierwszy prawdziwy projekt interaktywny &#8211; lista zadań</h3>



<p class="wp-block-paragraph">Po dwóch tygodniach nauki manipulacji DOM i zdarzeń, zbudowałam mój pierwszy w pełni interaktywny projekt &#8211; <strong>prostą listę zadań (to-do list)</strong>.</p>



<p class="wp-block-paragraph"><strong>HTML:</strong></p>



<p class="wp-block-paragraph">html</p>



<pre class="wp-block-code"><code>&lt;div class="kontener"&gt;
    &lt;h1&gt;Moja Lista Zadań&lt;/h1&gt;
    &lt;div class="formularz"&gt;
        &lt;input type="text" id="noweZadanie" placeholder="Wpisz zadanie..."&gt;
        &lt;button id="dodajPrzycisk"&gt;Dodaj&lt;/button&gt;
    &lt;/div&gt;
    &lt;ul id="listaZadan"&gt;&lt;/ul&gt;
&lt;/div&gt;
</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>const input = document.getElementById('noweZadanie');
const przyciskDodaj = document.getElementById('dodajPrzycisk');
const lista = document.getElementById('listaZadan');

function dodajZadanie() {
    const tresc = input.value.trim();

// Walidacja - nie dodawaj pustych zadań
    if (tresc === '') {
        alert('Wpisz treść zadania!');
        return;
    }

// Tworzenie nowego elementu listy
    const nowyElement = document.createElement('li');
    nowyElement.classList.add('zadanie');

// Tekst zadania
    const tekstZadania = document.createElement('span');
    tekstZadania.textContent = tresc;

// Przycisk oznaczenia jako wykonane
    const przyciskWykonaj = document.createElement('button');
    przyciskWykonaj.textContent = '✓';
    przyciskWykonaj.classList.add('przycisk-wykonaj');

    przyciskWykonaj.addEventListener('click', function() {
        tekstZadania.classList.toggle('wykonane');
    });

// Przycisk usunięcia
    const przyciskUsun = document.createElement('button');
    przyciskUsun.textContent = '✗';
    przyciskUsun.classList.add('przycisk-usun');

    przyciskUsun.addEventListener('click', function() {
        nowyElement.remove();
    });

// Składanie wszystkiego razem
    nowyElement.appendChild(tekstZadania);
    nowyElement.appendChild(przyciskWykonaj);
    nowyElement.appendChild(przyciskUsun);
    lista.appendChild(nowyElement);

// Czyszczenie inputu po dodaniu
    input.value = '';
    input.focus();
}

// Dodawanie przez kliknięcie przycisku
przyciskDodaj.addEventListener('click', dodajZadanie);

// Dodawanie przez naciśnięcie Enter
input.addEventListener('keydown', function(zdarzenie) {
    if (zdarzenie.key === 'Enter') {
        dodajZadanie();
    }
});
</code></pre>



<p class="wp-block-paragraph"><strong>Co się nauczyłam budując ten projekt:</strong></p>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Łączenie manipulacji DOM z obsługą zdarzeń</strong> &#8211; to nie są osobne tematy, tylko dwa elementy tej samej całości</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Tworzenie zagnieżdżonych elementów dynamicznie</strong> (element wewnątrz elementu wewnątrz elementu)</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Wielokrotne nasłuchiwacze zdarzeń</strong> na różnych elementach jednocześnie</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><code>trim()</code></strong> &#8211; usuwanie białych znaków z początku/końca tekstu (zapobiega dodawaniu &#8222;pustych&#8221; zadań ze spacjami)</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong><code>zdarzenie.key</code></strong> &#8211; sprawdzanie, który konkretnie klawisz został naciśnięty</li>
</ul>



<p class="wp-block-paragraph"><strong>Czas realizacji:</strong> 3 godziny (rozłożone na trzy dni po godzinie)</p>



<p class="wp-block-paragraph"><strong>Porównanie:</strong> Pierwszy mini-projekt w lipcu (kalkulator) zajął mi 2 godziny, ale był statyczny w tym sensie, że nie tworzył nowych elementów. Lista zadań to pierwszy raz, kiedy strona <strong>rozrasta się i zmienia strukturę</strong> w odpowiedzi na to, co robi użytkownik.</p>



<h3 class="wp-block-heading" style="font-size:22px">Wyzwania techniczne &#8211; co sprawiało najwięcej trudności</h3>



<h4 class="wp-block-heading" style="font-size:20px">1. Zrozumienie <code>this</code> wewnątrz nasłuchiwaczy zdarzeń</h4>



<p class="wp-block-paragraph"><strong>Problem:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>przycisk.addEventListener('click', function() {
    console.log(this); // co to jest "this"?
});
</code></pre>



<p class="wp-block-paragraph">W kontekście nasłuchiwacza zdarzenia, <code>this</code> odnosi się do elementu, na którym zdarzenie zostało zarejestrowane (czyli do samego przycisku).</p>



<p class="wp-block-paragraph"><strong>Ale przy funkcji strzałkowej (arrow function) <code>this</code> zachowuje się inaczej:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>przycisk.addEventListener('click', () =&gt; {
    console.log(this); // to NIE jest przycisk, tylko kontekst zewnętrzny
});
</code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Przy pracy z DOM i zdarzeniami, zwykłe funkcje (<code>function() {}</code>) i funkcje strzałkowe (<code>() =&gt; {}</code>) zachowują się różnie względem <code>this</code>. To był mylący temat przez dobry tydzień.</p>



<h4 class="wp-block-heading" style="font-size:20px">2. Event bubbling &#8211; &#8222;wypływanie&#8221; zdarzeń</h4>



<p class="wp-block-paragraph"><strong>Problem:</strong> Kliknięcie na przycisk wewnątrz elementu <code>&lt;li&gt;</code> uruchamiało nasłuchiwacz zarejestrowany na samym <code>&lt;li&gt;</code>, mimo że kliknęłam tylko przycisk.</p>



<p class="wp-block-paragraph"><strong>Wyjaśnienie:</strong> Zdarzenia w DOM &#8222;wypływają&#8221; od elementu, na którym się wydarzyły, w górę przez wszystkich rodziców w strukturze drzewa.</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>lista.addEventListener('click', function(zdarzenie) {
    console.log(zdarzenie.target); // dokładny element, który został kliknięty
    console.log(zdarzenie.currentTarget); // element, na którym zarejestrowano nasłuchiwacz
});
</code></pre>



<p class="wp-block-paragraph"><strong>Praktyczne zastosowanie &#8211; delegacja zdarzeń (event delegation):</strong></p>



<p class="wp-block-paragraph">Zamiast dodawać osobny nasłuchiwacz do każdego elementu listy (co jest nieefektywne przy dynamicznie dodawanych elementach), dodaje się JEDEN nasłuchiwacz do rodzica i sprawdza, co dokładnie zostało kliknięte:</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>lista.addEventListener('click', function(zdarzenie) {
    if (zdarzenie.target.classList.contains('przycisk-usun')) {
        zdarzenie.target.closest('.zadanie').remove();
    }
});
</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #4, ale w dobrym sensie:</strong> Ta technika rozwiązała problem, z którym walczyłam tydzień wcześniej, próbując dodawać nasłuchiwacze do elementów tworzonych dynamicznie.</p>



<h4 class="wp-block-heading" style="font-size:20px">3. Zapobieganie domyślnemu zachowaniu przeglądarki</h4>



<p class="wp-block-paragraph"><strong>Problem:</strong> Formularz po wysłaniu odświeżał całą stronę, co usuwało wszystkie wprowadzone dane.</p>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>formularz.addEventListener('submit', function(zdarzenie) {
    zdarzenie.preventDefault(); // blokuje domyślne odświeżenie strony
// reszta logiki obsługi formularza
});
</code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Wiele elementów HTML ma wbudowane &#8222;domyślne zachowanie&#8221; (formularz wysyła i odświeża stronę, link przenosi na inną stronę). <code>preventDefault()</code> pozwala przejąć kontrolę i zdecydować, co ma się stać zamiast tego.</p>



<h3 class="wp-block-heading" style="font-size:22px">Momenty &#8222;wow&#8221; &#8211; lista moich ulubionych</h3>



<p class="wp-block-paragraph">Podsumowując te dwa tygodnie nauki, oto konkretne momenty, które sprawiły, że poczułam prawdziwą radość z programowania:</p>



<p class="wp-block-paragraph"><strong>1. Pierwszy klik konsoli</strong> &#8211; kiedy <code>console.log('Kliknięto!')</code> faktycznie się pojawił po kliknięciu przycisku</p>



<p class="wp-block-paragraph"><strong>2. Zmiana koloru w czasie rzeczywistym</strong> &#8211; przycisk zmieniający kolor tła po kliknięciu, bez odświeżania strony</p>



<p class="wp-block-paragraph"><strong>3. Tworzenie elementów, których nigdy nie było w HTML</strong> &#8211; dodanie nowego zadania do listy, które fizycznie nie istniało w pliku HTML</p>



<p class="wp-block-paragraph"><strong>4. Walidacja na żywo</strong> &#8211; komunikat błędu pojawiający się i znikający, kiedy piszę w polu formularza, bez klikania czegokolwiek</p>



<p class="wp-block-paragraph"><strong>5. Delegacja zdarzeń działająca poprawnie</strong> &#8211; moment, kiedy zrozumiałam, dlaczego mój kod przestał działać po dodaniu nowych elementów, i jak to naprawić jednym uniwersalnym nasłuchiwaczem</p>



<p class="wp-block-paragraph"><strong>6. Ukończona lista zadań</strong> &#8211; moment, kiedy mogłam dodać zadanie, oznaczyć je jako wykonane, i usunąć &#8211; wszystko bez odświeżania strony ani jednej linijki PHP</p>



<h3 class="wp-block-heading" style="font-size:22px">Zasoby, które pomogły mi zrozumieć DOM i zdarzenia</h3>



<h4 class="wp-block-heading" style="font-size:20px">1. <a href="http://JavaScript.info">JavaScript.info</a> &#8211; rozdział &#8222;Document&#8221; (★★★★★)</h4>



<p class="wp-block-paragraph">Najbardziej szczegółowe i zrozumiałe wyjaśnienie manipulacji DOM, jakie znalazłam. Wracałam do niego wielokrotnie.</p>



<h4 class="wp-block-heading" style="font-size:20px">2. MDN Web Docs &#8211; dokumentacja Event (★★★★★)</h4>



<p class="wp-block-paragraph">Kiedy potrzebowałam sprawdzić, jakie właściwości ma dany typ zdarzenia (np. co dokładnie zawiera obiekt zdarzenia przy <code>keydown</code>), dokumentacja MDN była niezastąpiona.</p>



<h4 class="wp-block-heading" style="font-size:20px">3. Traversy Media &#8211; &#8222;JavaScript DOM Crash Course&#8221; (★★★★★)</h4>



<p class="wp-block-paragraph">Godzinny film, który pokazuje budowanie kilku małych projektów interaktywnych na żywo. Zobaczenie procesu myślowego kogoś doświadczonego bardzo pomogło mi zrozumieć, jak łączyć poszczególne koncepty.</p>



<h4 class="wp-block-heading" style="font-size:20px">4. FreeCodeCamp &#8211; sekcja &#8222;DOM Manipulation&#8221; (★★★★☆)</h4>



<p class="wp-block-paragraph">Ćwiczenia praktyczne z natychmiastową weryfikacją. Trochę oderwane od kontekstu (pojedyncze zadania, nie cały projekt), ale świetne do utrwalenia składni.</p>



<h3 class="wp-block-heading" style="font-size:22px">Plany na wrzesień-październik &#8211; co dalej</h3>



<p class="wp-block-paragraph"><strong>Tydzień 1-2 września:</strong></p>



<ul class="wp-block-list">
<li>Dokończenie tematu zdarzeń (event delegation, custom events)</li>



<li>Rozbudowa listy zadań o zapisywanie w localStorage</li>
</ul>



<p class="wp-block-paragraph"><strong>Tydzień 3-4 września:</strong></p>



<ul class="wp-block-list">
<li>Fetch API &#8211; pobieranie danych z zewnętrznych źródeł</li>



<li>Praca z JSON w JavaScript</li>
</ul>



<p class="wp-block-paragraph"><strong>Październik:</strong></p>



<ul class="wp-block-list">
<li>Pierwsze starcie z asynchronicznością (promises, async/await)</li>



<li>Może pierwszy kontakt z React, jeśli poczuję się gotowa</li>
</ul>



<p class="wp-block-paragraph"><strong>Cel realistyczny:</strong> Do końca września chcę umieć budować w pełni funkcjonalne, interaktywne komponenty dla stron klientów &#8211; formularze z walidacją, proste kalkulatory, dynamiczne galerie.</p>



<h3 class="wp-block-heading" style="font-size:22px">FAQ &#8211; manipulacja DOM i zdarzenia w JavaScript</h3>



<h4 class="wp-block-heading" style="font-size:20px">Czy manipulacja DOM to to samo co React/Vue?</h4>



<p class="wp-block-paragraph">Nie, ale jest fundamentem, na którym te frameworki się opierają. React i Vue &#8222;pod maską&#8221; też manipulują DOM, tylko robią to bardziej efektywnie i za pomocą swojej własnej, uproszczonej składni. Zrozumienie czystego (vanilla) DOM znacznie ułatwia późniejszą naukę frameworków.</p>



<h4 class="wp-block-heading" style="font-size:20px">Czy potrzebuję znać jQuery, żeby manipulować DOM?</h4>



<p class="wp-block-paragraph">Nie. jQuery było popularne, kiedy natywne API JavaScript do manipulacji DOM było bardziej niewygodne. Dzisiaj nowoczesny JavaScript (metody jak <code>querySelector</code>, <code>classList</code>, <code>addEventListener</code>) jest wystarczająco przyjazny, że jQuery stało się w dużej mierze zbędne dla nowych projektów.</p>



<h4 class="wp-block-heading" style="font-size:20px">Ile czasu zajęła Ci nauka tego tematu?</h4>



<p class="wp-block-paragraph">Około dwóch tygodni intensywniejszej nauki (po powrocie do pełnego tempa po wakacjach) &#8211; łącznie może 12-15 godzin, plus dodatkowy czas na budowę projektu listy zadań.</p>



<h4 class="wp-block-heading" style="font-size:20px">Co było najtrudniejsze w tym temacie?</h4>



<p class="wp-block-paragraph">Zdecydowanie zrozumienie <strong>event bubbling i delegacji zdarzeń</strong>. To jest koncept, który na papierze brzmi prosto, ale dopóki nie napotkałam realnego problemu (nasłuchiwacz nie działający na dynamicznie dodanych elementach), nie rozumiałam, po co to jest potrzebne.</p>



<h4 class="wp-block-heading" style="font-size:20px">Czy manipulacja DOM jest przydatna, jeśli pracuję głównie z WordPressem?</h4>



<p class="wp-block-paragraph">Zdecydowanie tak. Nawet przy pracy z gotowym CMS-em, umiejętność dodania własnego, lekkiego JavaScript do konkretnych interakcji (zamiast instalowania kolejnej wtyczki) to ogromna przewaga &#8211; i pod względem wydajności strony, i pod względem tego, co możesz zaoferować klientom.</p>



<h3 class="wp-block-heading" style="font-size:22px">Podsumowanie &#8211; Learning Log #7</h3>



<p class="wp-block-paragraph"><strong>Manipulacja DOM i zdarzenia w JavaScript</strong> to temat, który zmienił moje rozumienie tego, czym w ogóle jest programowanie frontendowe. Wcześniej JavaScript był dla mnie &#8222;kolejnym językiem ze składnią podobną do Javy&#8221;. Teraz jest <strong>narzędziem, które sprawia, że strony internetowe żyją</strong>.</p>



<p class="wp-block-paragraph"><strong>Co osiągnęłam:</strong></p>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Rozumiem czym jest DOM i jak przeglądarka go tworzy</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Potrafię wyszukiwać, tworzyć i modyfikować elementy dynamicznie</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Rozumiem nasłuchiwacze zdarzeń i obiekt zdarzenia</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Znam delegację zdarzeń i wiem, kiedy jej używać</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Zbudowałam pierwszy w pełni interaktywny projekt (lista zadań)</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Widzę bezpośrednie zastosowanie w pracy freelance</li>
</ul>



<p class="wp-block-paragraph"><strong>Najważniejsza lekcja tego etapu:</strong></p>



<p class="wp-block-paragraph"><strong>Programowanie frontendowe to nie pisanie kodu, który &#8222;coś robi&#8221;. To pisanie kodu, który reaguje.</strong></p>



<p class="wp-block-paragraph">Ten przycisk, który zmienia kolor po kliknięciu &#8211; to nie jest wielka rzecz techniczna. Ale to jest moment, w którym zrozumiałam, dlaczego ludzie kochają programowanie frontendu: <strong>piszesz coś, i to coś odpowiada Ci na żywo</strong>.</p>



<p class="wp-block-paragraph">Po wakacyjnej przerwie i strategii mikroedukacji, wrzesień przywrócił mi pełne tempo &#8211; i przyniósł jeden z najbardziej satysfakcjonujących etapów nauki do tej pory.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><em>PS: Pamiętasz swój pierwszy moment &#8222;wow&#8221; w programowaniu? Co to było? A jeśli dopiero zaczynasz naukę DOM i zdarzeń &#8211; z czym masz największe trudności? Zostaw komentarz, chętnie pomogę albo po prostu poczuję się mniej samotna w tym zachwycie nad zmieniającym kolor przyciskiem!</em></p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-7-javascript-dom-zdarzenia-interaktywnosc/">Learning Log #7: JavaScript &#8211; manipulacja DOM, zdarzenia i pierwsza prawdziwa interaktywność</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.danuta-cybulska.com/learning-log-7-javascript-dom-zdarzenia-interaktywnosc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Learning Log #6: Java vs JavaScript &#8211; zaczynam drugi język programowania</title>
		<link>https://www.danuta-cybulska.com/learning-log-6-java-vs-javascript-drugi-jezyk/</link>
					<comments>https://www.danuta-cybulska.com/learning-log-6-java-vs-javascript-drugi-jezyk/#comments</comments>
		
		<dc:creator><![CDATA[Danuta]]></dc:creator>
		<pubDate>Wed, 22 Jul 2026 08:00:00 +0000</pubDate>
				<category><![CDATA[LearningLog]]></category>
		<category><![CDATA[Programowanie i Rozwój]]></category>
		<category><![CDATA[drugi język programowania]]></category>
		<category><![CDATA[freeCodeCamp]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java vs JavaScript]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[learning log]]></category>
		<category><![CDATA[nauka JavaScript]]></category>
		<category><![CDATA[nauka programowania]]></category>
		<category><![CDATA[programowanie]]></category>
		<category><![CDATA[różnice Java JavaScript]]></category>
		<category><![CDATA[vanilla JavaScript]]></category>
		<category><![CDATA[web development]]></category>
		<guid isPermaLink="false">https://www.danuta-cybulska.com/?p=5978</guid>

					<description><![CDATA[<p>Poniedziałek, 1 lipca 2026. Otwieram nowy projekt w VS Code. Nie IntelliJ (Java IDE). VS Code. Tworzę plik: index.html. Potem script.js. Nie .java. Zaczynam naukę JavaScript. Po 6 miesiącach z Javą (styczeń-czerwiec 2026) postanowiłam dodać drugi język. Dlaczego JavaScript? Dlaczego teraz? Czy Java mi pomoże czy przeszkodzi? Trzy tygodnie później (dziś) mogę powiedzieć: nauka drugiego...</p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-6-java-vs-javascript-drugi-jezyk/">Learning Log #6: Java vs JavaScript &#8211; zaczynam drugi język programowania</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Poniedziałek, 1 lipca 2026. Otwieram nowy projekt w VS Code. Nie IntelliJ (Java IDE). VS Code.</p>



<p class="wp-block-paragraph">Tworzę plik: <code>index.html</code>. Potem <code>script.js</code>. Nie <code>.java</code>.</p>



<p class="wp-block-paragraph"><strong>Zaczynam naukę JavaScript.</strong></p>



<p class="wp-block-paragraph">Po 6 miesiącach z Javą (styczeń-czerwiec 2026) postanowiłam dodać drugi język. Dlaczego JavaScript? Dlaczego teraz? Czy Java mi pomoże czy przeszkodzi?</p>



<p class="wp-block-paragraph">Trzy tygodnie później (dziś) mogę powiedzieć: <strong>nauka drugiego języka programowania jest ZUPEŁNIE inna</strong> niż nauki pierwszego. Masz fundamenty (zmienne, pętle, funkcje), ale szczegóły są diametralnie różne. To jak uczyć się francuskiego po hiszpańskim &#8211; podobne, ale gwarantowany chaos w głowie.</p>



<p class="wp-block-paragraph">Dziś w <strong>Learning Log #6</strong> opowiem Wam dlaczego wybrałam JavaScript, jak zaczynałam, co jest podobne do Javy (więcej niż myślałam!), co kompletnie inne (WTF momenty!), i jakie zasoby do nauki wykorzystuję.</p>



<h2 class="wp-block-heading" style="font-size:22px">Dlaczego JavaScript? Decyzja strategiczna</h2>



<h3 class="wp-block-heading" style="font-size:20px">Opcje, które rozważałam po zakończeniu podstaw Java:</h3>



<p class="wp-block-paragraph"><strong> 1: Spring Framework (kontynuacja Java)</strong></p>



<ul class="wp-block-list">
<li><strong>Zalety:</strong> Naturalna progresja, rozwój zaplecza, rynek pracy</li>



<li><strong>Wady:</strong> Ciężkie przy dzieciach, wymaga dużo czasu</li>
</ul>



<p class="wp-block-paragraph"><strong> 2: Python</strong></p>



<ul class="wp-block-list">
<li><strong>Zalety:</strong> Łatwy, wszechstronny, data science, automatyzacja</li>



<li><strong>Wady:</strong> Zero synergii z WordPressem</li>
</ul>



<p class="wp-block-paragraph"><strong>3: JavaScript</strong></p>



<ul class="wp-block-list">
<li><strong>Zalety:</strong> OGROMNA synergia z WordPress, umiejętności front-endowe, natychmiastowe wykorzystanie, lżejszy niż Spring</li>



<li><strong>Wady:</strong> &#8222;Dziwny język&#8221; (słyszałam), może mylące po Javie</li>
</ul>



<p class="wp-block-paragraph"><strong>Wybrałam JavaScript. Dlaczego:</strong></p>



<h3 class="wp-block-heading" style="font-size:20px">1. Synergia z WordPressem</h3>



<p class="wp-block-paragraph"><strong>Aktualnie:</strong> Robię strony WordPress z page builderami (Elementor)</p>



<ul class="wp-block-list">
<li>Mało custom kodu</li>



<li>Ograniczone możliwości</li>



<li>Nie mogę zrobić custom funkcjonalności, które bym chciała</li>
</ul>



<p class="wp-block-paragraph"><strong>Z JavaScriptem:</strong> Mogę dodawać:</p>



<ul class="wp-block-list">
<li>Niestandardowe interakcje (animacje, efekty)</li>



<li>Formularze zaawansowane (walidacja, multi-step)</li>



<li>Kalkulatory (cenniki dynamiczne)</li>



<li>Niestandardowa funkcjonalność (cokolwiek wymyślę)</li>
</ul>



<h3 class="wp-block-heading" style="font-size:22px">2. Natychmiastowe praktyczne zastosowanie</h3>



<p class="wp-block-paragraph"><strong>Java projekt:</strong> Therapy Manager &#8211; używam tylko ja<br><strong>JavaScript:</strong> Mogę użyć w KAŻDYM projekcie dla każdego od jutra</p>



<p class="wp-block-paragraph"><strong>Motywacja:</strong> Widzę natychmiastowy rezultat = łatwiej się uczyć</p>



<h3 class="wp-block-heading" style="font-size:20px">3. Łatwiejszy balans życie/nauka niż Spring</h3>



<p class="wp-block-paragraph"><strong>Spring:</strong> Wymaga 20-30h tygodniowo, żeby ogarnąć (backend, bazy danych, API, deployment)<br><strong>JavaScript:</strong> Mogę uczyć się 1h dziennie i widzieć progres</p>



<p class="wp-block-paragraph"><strong>Z dziećmi:</strong> JavaScript = realistyczne, Spring = przytłaczający</p>



<h3 class="wp-block-heading" style="font-size:20px">4. Umiejętności frontendowe można sprzedać</h3>



<p class="wp-block-paragraph"><strong>Backend (Java/Spring):</strong> Duża konkurencja, wymaga doświadczenia<br><strong>Frontend (JS/React):</strong> Też konkurencja, ale łatwiej pokazać portfolio (strony działają w przeglądarce)</p>



<p class="wp-block-paragraph"><strong>Perspektywa freelancera:</strong> Frontend łatwiej &#8222;sprzedać&#8221; klientom (widzą efekt natychmiast)</p>



<h2 class="wp-block-heading" style="font-size:22px">Pierwsze kroki &#8211; od czego zaczęłam</h2>



<h3 class="wp-block-heading" style="font-size:20px">Tydzień 1 (1-7 lipca): Setup i podstawy składni</h3>



<p class="wp-block-paragraph"><strong>Narzędzia, które zainstalowałam:</strong></p>



<p class="wp-block-paragraph"><strong>1. VS Code</strong> (zamiast IntelliJ)</p>



<ul class="wp-block-list">
<li>Lekki, szybki</li>



<li><strong>Rozszerzenia: </strong>ESLint, Prettier, Live Server</li>



<li><strong>Czas setup:</strong> 30 minut</li>
</ul>



<p class="wp-block-paragraph"><strong>2. Node.js</strong></p>



<ul class="wp-block-list">
<li>Do uruchamiania JS poza przeglądarką</li>



<li>Package manager (npm) &#8211; jak Maven dla Javy</li>



<li><strong>Instalacja:</strong> 10 minut</li>
</ul>



<p class="wp-block-paragraph"><strong>3. Chrome DevTools</strong></p>



<ul class="wp-block-list">
<li>Już miałam (przeglądarka)</li>



<li>Konsola do testowania kodu</li>



<li>Debugger</li>
</ul>



<p class="wp-block-paragraph"><strong>Total setup:</strong> 1 godzina (vs Java było 3 godziny &#8211; IntelliJ, JDK, Maven)</p>



<p class="wp-block-paragraph"><strong>Pierwszy program &#8211; Hello World:</strong></p>



<p class="wp-block-paragraph"><strong>Java (dla porównania):</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`public class HelloWorld {
    public static void main(String&#91;] args) {
        System.out.println("Hello World");
    }
}`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code><code>console.log("Hello World");</code></code></pre>



<p class="wp-block-paragraph"><strong>Reakcja:</strong> &#8222;WAIT, to wszystko?! Gdzie klasa? Gdzie main?&#8221;</p>



<p class="wp-block-paragraph"><strong>Welcome to JavaScript &#8211; język bez szablonów.</strong></p>



<h3 class="wp-block-heading" style="font-size:20px">Mój plan nauki JavaScript:</h3>



<p class="wp-block-paragraph"><strong>1. Fundamenty (lipiec):</strong></p>



<ul class="wp-block-list">
<li>Składnia (zmienne, typy, operatory)</li>



<li>Funkcje i scope</li>



<li>Tablice i obiekty</li>



<li>DOM manipulation (zmiana HTML/CSS przez JS)</li>
</ul>



<p class="wp-block-paragraph"><strong>2. Średniozaawansowany (sierpień):</strong></p>



<ul class="wp-block-list">
<li>ES6+ funkcje (funkcje strzałkowe, destrukturyzacja, promises)</li>



<li>Asynchroniczność (async/await, fetch API)</li>



<li>Events i event handling</li>
</ul>



<p class="wp-block-paragraph"><strong>3. Framework (wrzesień &#8211; może):</strong></p>



<ul class="wp-block-list">
<li>React basics</li>



<li>Albo zostać przy vanilla JS (czystym JS) i opanować dobrze</li>
</ul>



<p class="wp-block-paragraph"><strong>Źródła nauki:</strong></p>



<ul class="wp-block-list">
<li><strong>FreeCodeCamp</strong> (darmowy kurs online) &#8211; główne</li>



<li><strong><a href="http://JavaScript.info">JavaScript.info</a></strong> (dokumentacja) &#8211; odniesienie</li>



<li><strong>YouTube:</strong> Traversy Media, Web Dev Simplified</li>



<li><strong>Praktyka:</strong> Projekty WordPress</li>
</ul>



<p class="wp-block-paragraph"><strong>Czas:</strong> 1h dziennie (vs Java było 1.5h) = lżejsze podejście</p>



<h2 class="wp-block-heading" style="font-size:22px">Co jest PODOBNE do Javy &#8211; zaskakujący!</h2>



<h3 class="wp-block-heading" style="font-size:20px">1. Fundamenty programowania (koncepcje)</h3>



<p class="wp-block-paragraph"><strong>Zmienne:</strong></p>



<p class="wp-block-paragraph"><strong>Java:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code><code>int age = 30; </code>
<code>String name = "Anna"; </code>
<code>boolean isActive = true;</code></code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code><code>let age = 30; </code>
<code>let name = "Anna"; </code>
<code>let isActive = true;</code></code></pre>



<p class="wp-block-paragraph"><strong>Podobne:</strong> Koncept zmiennej, przechowywanie wartości<br><strong>Różne:</strong> <code>let</code> zamiast typu (<code>int</code>, <code>String</code>), JS = dynamicznie typowane</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Pętle:</strong></p>



<p class="wp-block-paragraph"><strong>Java:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`for (int i = 0; i &lt; 5; i++) {
    System.out.println(i);
}`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`for (let i = 0; i &lt; 5; i++) {
    console.log(i);
}`</code></pre>



<p class="wp-block-paragraph"><strong>Identyczne!</strong> (prawie &#8211; <code>let</code> zamiast <code>int</code>)</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Warunki:</strong></p>



<p class="wp-block-paragraph"><strong>Java:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`if (age > 18) {
    System.out.println("Adult");
} else {
    System.out.println("Minor");
}`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`if (age > 18) {
    console.log("Adult");
} else {
    console.log("Minor");
}`</code></pre>



<p class="wp-block-paragraph"><strong>Identyczne!</strong> (prawie &#8211; <code>console.log</code> zamiast <code>System.out.println</code>)</p>



<p class="wp-block-paragraph"><strong>Spostrzeżenia:</strong> Fundamenty są takie same. Java nauczyła mnie myślenia programistycznego &#8211; to przenosi się 1:1 do JS.</p>



<h3 class="wp-block-heading" style="font-size:20px">2. Funkcje (podobne, ale&#8230;)</h3>



<p class="wp-block-paragraph"><strong>Java (metoda):</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`public int add(int a, int b) {
    return a + b;
}`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript (funkcja):</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`function add(a, b) {
    return a + b;
}`</code></pre>



<p class="wp-block-paragraph"><strong>Podobne:</strong></p>



<ul class="wp-block-list">
<li>Słowo kluczowe <code>function</code> (vs <code>public int</code> w Javie)</li>



<li>Instrukcja: Return</li>



<li>Parametry</li>
</ul>



<p class="wp-block-paragraph"><strong>Różne:</strong></p>



<ul class="wp-block-list">
<li>Brak typów (a, b &#8211; nie wiesz czy int, string, object)</li>



<li>Brak modyfikatory dostępu (public, private)</li>
</ul>



<h3 class="wp-block-heading" style="font-size:20px">3. Tablice (arrays)</h3>



<p class="wp-block-paragraph"><strong>Java:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`int&#91;] numbers = {1, 2, 3, 4, 5};
System.out.println(numbers&#91;0]); // 1`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`let numbers = &#91;1, 2, 3, 4, 5];
console.log(numbers&#91;0]); // 1`</code></pre>



<p class="wp-block-paragraph"><strong>Prawie identyczne!</strong></p>



<p class="wp-block-paragraph"><strong>Różnica:</strong> JS arrays są bardziej elastyczne (możesz mix typów)</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`let mixed = &#91;1, "two", true, {name: "Anna"}]; // OK w JS
// W Javie: BŁĄD (tablica musi mieć jeden typ)`</code></pre>



<h3 class="wp-block-heading" style="font-size:20px">4. Obiekty vs Klasy</h3>



<p class="wp-block-paragraph"><strong>Java (klasa):</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`public class Person {<br>private String name;<br>private int age;<br><br>public Person(String name, int age) {<br>    this.name = name;<br>    this.age = age;<br>}<br><br>public String getName() {<br>    return name;<br>}<br><br>}<br><br>Person person = new Person("Anna", 30);`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript (obiekt):</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`const person = {
    name: "Anna",
    age: 30,
    getName: function() {
        return this.name;
    }
};`</code></pre>



<p class="wp-block-paragraph"><strong>Podobne:</strong> Koncept &#8222;obiektu&#8221; (dane + metody)<br><strong>Różne:</strong> JS nie wymaga klasy! (można tworzyć obiekty dosłownie)</p>



<p class="wp-block-paragraph"><strong>JavaScript ma też klasy (ES6):</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`class Person {<br>constructor(name, age) {<br><a href="http://this.name">this.name</a> = name;<br>this.age = age;<br>}<br><br>getName() {<br>    return this.name;<br>}<br><br>}<br><br>const person = new Person("Anna", 30);`</code></pre>



<p class="wp-block-paragraph"><strong>To wygląda prawie jak Java!</strong> Ale pod spodem JS działa inaczej (prototypy, nie prawdziwe klasy).</p>



<h2 class="wp-block-heading" style="font-size:22px">Co jest KOMPLETNIE RÓŻNE &#8211; WTF momenty</h2>



<h3 class="wp-block-heading" style="font-size:20px">1. Typy dynamiczne (loosely typed)</h3>



<p class="wp-block-paragraph"><strong>Java:</strong> Statycznie typowane</p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`int number = 5;
number = "Hello"; // BŁĄD kompilacji!`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong> Dynamicznie typowane</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`let number = 5;
number = "Hello"; // OK! &#x1f631;
console.log(number); // "Hello"`</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #1:</strong> &#8222;Czekaj, mogę zmienić typ zmiennej w trakcie?!&#8221;</p>



<p class="wp-block-paragraph"><strong>Plusy</strong> Elastyczność, mniej kodu<br><strong>Minusy:</strong> Błędy runtime (nie kompilacji), trudniejszy debugging</p>



<p class="wp-block-paragraph"><strong>Moja reakcja:</strong> Początkowo mylące. Teraz doceniam elastyczność, ale brakuje bezpieczeństwa typu Java.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" style="font-size:20px">2. <code>==</code> vs <code>===</code> (porównywanie)</h3>



<p class="wp-block-paragraph"><strong>Java:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`int a = 5;
int b = 5;
if (a == b) { } // true`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`let a = 5;<br>let b = "5";<br><br>console.log(a == b); // true &#x1f631; (porównuje wartość, konwertuje typy)<br>console.log(a === b); // false (porównuje wartość I typ)`</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #2:</strong> &#8222;Czemu jest DWA operatory porównania?!&#8221;</p>



<p class="wp-block-paragraph"><strong>Zasada:</strong> W JS ZAWSZE używaj <code>===</code> (ścisła równość), nigdy <code>==</code> (luźna równość)</p>



<p class="wp-block-paragraph"><strong>Przykład dlaczego:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`console.log(0 == false);  // true &#x1f631;
console.log(0 === false); // false (poprawnie!)`</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" style="font-size:20px">3. <code>var</code> vs <code>let</code> vs <code>const</code> (szaleństwo zakresów)</h3>



<p class="wp-block-paragraph"><strong>Java:</strong> Wszystko ma zakres bloku</p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`{
    int x = 5;
}
System.out.println(x); // BŁĄD - x nie istnieje poza blokiem`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong> <code>var</code> ma zakres funkcji (WTF), <code>let</code>/<code>const</code> mają zakres bloku</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`// VAR (stary sposób - unikaj!)<br>function test() {<br>if (true) {<br>var x = 5;<br>}<br>console.log(x); // 5 &#x1f631; (x istnieje poza if!)<br>}<br><br>// LET (nowy sposób - używaj!)<br>function test() {<br>if (true) {<br>let y = 5;<br>}<br>console.log(y); // ERROR (jak w Javie - dobrze!)<br>}`</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #3:</strong> &#8222;Czemu <code>var</code> działa inaczej niż w normalnym języku?!&#8221;</p>



<p class="wp-block-paragraph"><strong>Zasada:</strong> Nigdy nie używaj <code>var</code>. Zawsze <code>let</code> (zmienne) lub <code>const</code> (stałe).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" style="font-size:20px">4. Hoisting (podnoszenie deklaracji)</h3>



<p class="wp-block-paragraph"><strong>Java:</strong> Musisz zadeklarować zmienną PRZED użyciem</p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`System.out.println(x); // BŁĄD - x nie istnieje
int x = 5;`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong> Deklaracje są &#8222;podnoszone&#8221; na górę</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`console.log(x); // undefined (nie błąd!) &#x1f631;
var x = 5;`</code></pre>



<p class="wp-block-paragraph">Co się dzieje:</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`// JS interpretuje to jako:
var x; // deklaracja "podniesiona"
console.log(x); // undefined
x = 5; // przypisanie`</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #4:</strong> &#8222;Jak to możliwe, że kod działa, ale źle?!&#8221;</p>



<p class="wp-block-paragraph"><strong>Z <code>let</code> jest lepiej:</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code><code>console.log(y); // ERROR (jak w Javie) </code>
<code>let y = 5;</code></code></pre>



<p class="wp-block-paragraph"><strong>Zasada:</strong> Używaj <code>let</code>/<code>const</code>, unikaj <code>var</code> = unikasz problemy z podnoszeniem.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" style="font-size:20px">5. Funkcje są &#8222;first-class citizens&#8221; (obiekty pierwszej klasy)</h3>



<p class="wp-block-paragraph"><strong>Java:</strong> Funkcje (metody) należą do klas. Nie możesz przekazać metody jak zmienną.</p>



<p class="wp-block-paragraph"><strong>JavaScript:</strong> Funkcje można przypisać do zmiennej, przekazać jako argument, zwrócić z funkcji</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`// Funkcja w zmiennej<br>const sayHello = function() {<br>console.log("Hello");<br>};<br><br>// Przekazanie funkcji jako argument<br>function greet(name, callback) {<br>console.log("Hi " + name);<br>callback();<br>}<br><br>greet("Anna", sayHello);<br>// Output:<br>// Hi Anna<br>// Hello`</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #5:</strong> &#8222;Funkcja w zmiennej?! Funkcja jako parametr?!&#8221;</p>



<p class="wp-block-paragraph"><strong>Java odpowiednik (rodzaj):</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>`// Java 8+ lambda
Runnable sayHello = () -> System.out.println("Hello");
sayHello.run();`</code></pre>



<p class="wp-block-paragraph"><strong>Podobne:</strong> Java lambdy, ale w JS to jest główna funkcja, w Javie dodane później.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" style="font-size:20px">6. <code>undefined</code> vs <code>null</code> (dwa &#8222;nic&#8221;)</h3>



<p class="wp-block-paragraph"><strong>Java:</strong> <code>null</code> (tylko jeden &#8222;brak wartości&#8221;)</p>



<p class="wp-block-paragraph"><strong>JavaScript:</strong> <code>undefined</code> I <code>null</code> (dwa różne &#8222;nic&#8221;)</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`let a; // zadeklarowana, nie przypisana<br>console.log(a); // undefined<br><br>let b = null; // explicite "brak wartości"<br>console.log(b); // null<br><br>console.log(typeof a); // "undefined"<br>console.log(typeof b); // "object" &#x1f631; (JS bug od początku języka)`</code></pre>



<p class="wp-block-paragraph"><strong>WTF moment #6:</strong> &#8222;Czemu DWA rodzaje 'nic&#8217;?! I czemu typeof null to 'object&#8217;?!&#8221;</p>



<p class="wp-block-paragraph"><strong>Zasada:</strong></p>



<ul class="wp-block-list">
<li><code>undefined</code> = JS default (zmienna istnieje, nie ma wartości)</li>



<li><code>null</code> = programista wyraźnie mówi &#8222;tutaj jest nic&#8221;</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" style="font-size:20px">7. Brak TypeScript (ale mogę użyć później)</h3>



<p class="wp-block-paragraph"><strong>Java:</strong> Kompilator sprawdza typy PRZED uruchomieniem</p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code><code>int x = "Hello"; // BŁĄD kompilacji</code></code></pre>



<p class="wp-block-paragraph"><strong>JavaScript:</strong> Błędy widoczne DOPIERO w runtime</p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code><code>let x = 5; </code>
<code>x.toUpperCase(); // ERROR runtime! (number nie ma toUpperCase)</code></code></pre>



<p class="wp-block-paragraph"><strong>Problem:</strong> Łatwo zrobić błąd, który widzisz dopiero, gdy uruchamiasz.</p>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong> TypeScript (JavaScript + typy)</p>



<p class="wp-block-paragraph">typescript</p>



<pre class="wp-block-code"><code><code>let x: number = 5; </code>
<code>x = "Hello"; // BŁĄD kompilacji (jak Java!)</code></code></pre>



<p class="wp-block-paragraph"><strong>Mój plan:</strong> Najpierw opanuję vanilla JS, potem może TypeScript (wrzesień-październik).</p>



<h2 class="wp-block-heading" style="font-size:22px">Pierwszy mini-projekt w JavaScript &#8211; Kalkulator interaktywny</h2>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"><strong>Po tygodniu nauki</strong> (7.07) zrobiłam pierwszy mini-projekt.</p>



<p class="wp-block-paragraph"><strong>Co:</strong> Kalkulator terapii &#8211; użytkownik wpisuje liczbę sesji i koszt, dostaje podsumowanie</p>



<p class="wp-block-paragraph"><strong>Technologie:</strong></p>



<ul class="wp-block-list">
<li>HTML (struktura)</li>



<li>CSS (wygląd)</li>



<li>JavaScript (logika)</li>
</ul>



<p class="wp-block-paragraph"><strong>HTML:</strong></p>



<p class="wp-block-paragraph">html</p>



<pre class="wp-block-code"><code>`&lt;!DOCTYPE html><br>&lt;html><br>&lt;head><br>&lt;title>Therapy Cost Calculator&lt;/title><br>&lt;link rel="stylesheet" href="style.css"><br>&lt;/head><br>&lt;body><br>&lt;div class="calculator"><br>&lt;h1>Kalkulator Kosztów Terapii&lt;/h1><br><br>    &lt;label>Liczba sesji miesięcznie:&lt;/label><br>    &lt;input type="number" id="sessions" placeholder="np. 8"><br>    <br>    &lt;label>Koszt jednej sesji (zł):&lt;/label><br>    &lt;input type="number" id="costPerSession" placeholder="np. 75"><br>    <br>    &lt;button onclick="calculateTotal()">Oblicz&lt;/button><br>    <br>    &lt;div id="result">&lt;/div><br>&lt;/div><br><br>&lt;script src="script.js">&lt;/script><br><br>&lt;/body><br>&lt;/html>`</code></pre>



<p class="wp-block-paragraph"><strong>JavaScript (script.js):</strong></p>



<p class="wp-block-paragraph">javascript</p>



<pre class="wp-block-code"><code>`function calculateTotal() {
// Pobierz wartości z inputów
const sessions = document.getElementById('sessions').value;
const costPerSession = document.getElementById('costPerSession').value;

// Walidacja
if (!sessions || !costPerSession) {
    alert('Wypełnij oba pola!');
    return;
}

if (sessions &lt;= 0 || costPerSession &lt;= 0) {
    alert('Liczby muszą być większe od zera!');
    return;
}

// Kalkulacja
const total = sessions * costPerSession;

// Wyświetl wynik
const resultDiv = document.getElementById('result');
resultDiv.innerHTML = `
    &lt;h2>Wynik:&lt;/h2>
    &lt;p>&lt;strong>Sesji:&lt;/strong> ${sessions}&lt;/p>
    &lt;p>&lt;strong>Koszt sesji:&lt;/strong> ${costPerSession} zł&lt;/p>
    &lt;p class="total">&lt;strong>TOTAL:&lt;/strong> ${total} zł/miesiąc&lt;/p>
`;
}</code></pre>



<p class="wp-block-paragraph"><br>Co się nauczyłam:<br><br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /><strong> Manipulacja DOM</strong> &#8211; `document.getElementById()`<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Obsługa zdarzeń</strong> &#8211; `onclick=&#8221;calculateTotal()&#8221;`<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /><strong>Walidacja danych wejściowych</strong> &#8211; sprawdzanie czy pola wypełnione<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Szablony literałów</strong> &#8211; &#8222; `${variable}` &#8222; (lepsze niż konkatenacja)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /><strong> Debugging</strong> &#8211; Chrome DevTools console<br><br><strong>Czas:</strong> 2 godziny od zera do działającego projektu<br><br><strong>Porównanie z Javą:</strong><br>&#8211; Java projekt (Therapy Manager): 55 godzin<br>&#8211; JS projekt (Kalkulator): 2 godziny<br><br><strong>Różnica:</strong> JS =natychmiastowa gratyfikacja (widzisz w przeglądarce od razu), Java = długi proces, ale solidniejszy fundament.</p>



<h2 class="wp-block-heading" style="font-size:22px">Zasoby nauki JavaScript &#8211; co NAPRAWDĘ używam</h2>



<h4 class="wp-block-heading" style="font-size:18px"> 1. FreeCodeCamp (★★★★★)</h4>



<pre class="wp-block-code"><code><strong>Link:</strong> <a href="https://freecodecamp.org">freecodecamp.org</a>

<strong>Co:</strong> Darmowy kurs "JavaScript Algorithms and Data Structures"

<strong>Format: </strong>
- Krótkie lekcje (5-10 min)
- Wyzwania (zadania do rozwiązania)
- Projekty na końcu sekcji

<strong>Dlaczego działa:</strong>
- Interaktywny (piszesz kod w przeglądarce)
- Natychmiastowa informacja zwrotna(widzisz czy poprawnie)
- Darmowe (100%)

<strong>Mój progres:</strong> 30% kursu (3 tygodnie)

<strong>Czas:</strong> 1h dziennie</code></pre>



<h4 class="wp-block-heading" style="font-size:18px">2. JavaScript.info (★★★★★)</h4>



<pre class="wp-block-code"><code><strong>Link:</strong> <a href="https://javascript.info">javascript.info</a>

<strong>Co: </strong>Dokumentacja/tutorial JavaScript - od podstaw do zaawansowanych
<strong>
Format:</strong>
- Artykuły (szczegółowe wyjaśnienia)
- Przykłady kodu
- Zadania na końcu rozdziałów

<strong>Dlaczego używam:</strong>
- Wyczerpujący (wszystko w jednym miejscu)
- Dobrze wyjaśnia "dlaczego", nie tylko "jak"
- Darmowe

<strong>Jak używam:</strong> Odniesienie, gdy czegoś nie rozumiem z FreeCodeCamp</code></pre>



<h4 class="wp-block-heading" style="font-size:18px">3. YouTube &#8211; Traversy Media (★★★★☆)</h4>



<pre class="wp-block-code"><code><strong>Kanał:</strong> <a href="https://www.youtube.com/@TraversyMedia">Traversy Media</a>

<strong>Co:</strong> Tutoriale JavaScript, projekty, web development

<strong>Format:</strong> Video tutorials (30-60 min)

<strong>Ulubione video:</strong>
- "JavaScript Crash Course For Beginners" - 1h 40min
- "Build a Calculator with JavaScript" - projekt
- "DOM Crash Course" - manipulation HTML/CSS

<strong>Dlaczego: </strong>Widzę jak ktoś pisze kod (łatwiej zapamiętać)

<strong>Jak używam: </strong>Wieczory (21:00-22:00,) gdy dzieci śpią</code></pre>



<h4 class="wp-block-heading" style="font-size:18px"> 4. MDN Web Docs (★★★★☆)<br></h4>



<pre class="wp-block-code"><code><strong>Link:</strong> <a href="https://developer.mozilla.org">developer.mozilla.org</a>

<strong>Co:</strong> Oficjalna dokumentacja webowe technologie(HTML, CSS, JS)

<strong>Format:</strong> Dokumentacja referencyjna

<strong>Jak używam:</strong> 
- Gdy potrzebuję szczegółów konkretnej funkcji/metody
- "JavaScript Array methods" - pełna lista
- Przykłady użycia

<strong>Nie dla początkujących:</strong> Sucha dokumentacja, lepsze jako odniesienie niż zasób edukacyjny.
</code></pre>



<h4 class="wp-block-heading" style="font-size:18px">5. ChatGPT (★★★★★)</h4>



<pre class="wp-block-code"><code><strong>Jak używam:</strong>

Wyjaśnianie pojęć:

Ja: "Wyjaśnij mi hoisting w JavaScript jak dla 5-latka"
ChatGPT: &#91;proste wyjaśnienie z przykładami]


Debugging:

Ja: "Czemu ten kod nie działa? &#91;wklejam kod]"
ChatGPT: "Błąd w linii 5 - używasz var zamiast let, to powoduje..."


Code review:

Ja: "Czy ten kod jest OK? Jak mogę go ulepszyć?"
ChatGPT: &#91;sugestie, najlepsze praktyki]

<strong>Zalety:</strong> Natychmiastowe odpowiedzi, nieograniczone pytania, dostępne 24/7
<strong>Wady:</strong> Czasem się myli, trzeba weryfikować</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" style="font-size:22px">Java vs JavaScript &#8211; podsumowanie pierwszych 3 tygodni</h2>



<h3 class="wp-block-heading" style="font-size:20px">Co jest ŁATWIEJSZE w JS niż w Javie:</h3>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Setup</strong> &#8211; 1h vs 3h (Java)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Szablon</strong> &#8211; prawie zero (vs dużo w Javie)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Natychmiastowa informacja zwrotna</strong> &#8211; odświeżenie przeglądarki vs kompilacja<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Krzywa uczenia się</strong> &#8211; szybszy start (widzisz efekty od razu)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Projekty</strong> &#8211; 2h mini-projekt vs 55h w Javie</p>



<h3 class="wp-block-heading" style="font-size:20px">Co jest TRUDNIEJSZE w JS niż w Javie:</h3>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Typ bezpieczeństwa</strong> &#8211; brak (łatwo zrobić błąd)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dziwactwa języka</strong> &#8211; <code>==</code> vs <code>===</code>, podnoszenie, <code>var</code> zakres<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Debugging</strong> &#8211; błędy run-time (nie czas kompilacji)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Konsekwencja</strong> &#8211; wiele sposobów na to samo (mylące!)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Asynchroniczność</strong> &#8211; callbacks, promises, async/await (jeszcze przed mną, ale słyszałam że trudne)</p>



<h3 class="wp-block-heading" style="font-size:20px">Co się przenosi z Javy 1:1:</h3>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Pętle (for, while)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Warunki (if/else, switch)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Funkcje (koncept)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Tablice (koncept, podobna składnia)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Obiekty/klasy (trochę inne, ale koncept ten sam)<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Myślenie programistyczne</strong> &#8211; algorytmy, rozwiązywanie problemów</p>



<h3 class="wp-block-heading" style="font-size:20px">Czy Java pomogła w nauce JS?</h3>



<p class="wp-block-paragraph"><strong>TAK, ogromnie.</strong></p>



<p class="wp-block-paragraph"><strong>Bez Javy:</strong></p>



<ul class="wp-block-list">
<li>Musiałabym uczyć się fundamentów (pętle, warunki, funkcje) od zera</li>



<li>Nie rozumiałabym OOP</li>



<li>Nie wiedziałabym jak projektować kod</li>
</ul>



<p class="wp-block-paragraph"><strong>Z Javą:</strong></p>



<ul class="wp-block-list">
<li>Fundamenty mam (przeskoczyłam 50% kursu JS)</li>



<li>Rozumiem klasy w JS (bo znam z Javy)</li>



<li>Myślę algorytmicznie (transfer skill)</li>
</ul>



<p class="wp-block-paragraph"><strong>Ale:</strong></p>



<ul class="wp-block-list">
<li>Java-owe nawyki czasem przeszkadzają (próbuję deklarować typy, których JS nie ma)</li>



<li>Muszę &#8222;oduczyć się&#8221; od Java ścisłość</li>
</ul>



<p class="wp-block-paragraph"><strong>Werdykt:</strong> Java była świetnym pierwszym językiem. JavaScript jako drugi = łatwiejszy, niż gdyby był pierwszy.</p>



<h2 class="wp-block-heading" style="font-size:22px">Plany na sierpień &#8211; co dalej z JS</h2>



<p class="wp-block-paragraph"><strong>Tydzień 1-2 sierpnia:</strong></p>



<ul class="wp-block-list">
<li>Dokończenie FreeCodeCamp &#8222;Basic JavaScript&#8221; (50% pozostało)</li>



<li>Praktyka: 3-4 mini-projekty (todo list, quiz, countdown timer)</li>
</ul>



<p class="wp-block-paragraph"><strong>Tydzień 3-4 sierpnia:</strong></p>



<ul class="wp-block-list">
<li>ES6 funkcje (arrow functions, destructuring, spread operator)</li>



<li>Zaawansowana manipulacja DOM</li>



<li>Pierwszy projekt dla klienta WordPress (walidacja formularza niestandardowego)</li>
</ul>



<p class="wp-block-paragraph"><strong>Wrzesień:</strong></p>



<ul class="wp-block-list">
<li>Asynchronous JS (promises, async/await, fetch API)</li>



<li>Może React basics (jeśli czuję się ready)</li>



<li>Większy projekt (może blog z fetch API)</li>
</ul>



<p class="wp-block-paragraph"><strong>Cel:</strong> Do końca sierpnia czuć się komfortowo z vanilla JavaScript.</p>



<p class="wp-block-paragraph"><strong>Realistycznie:</strong> Nie zostanę ekspertem w miesiąc. Ale będę mogła używać JS w projektach klientów.</p>



<h2 class="wp-block-heading" style="font-size:22px">FAQ &#8211; nauka drugiego języka programowania</h2>



<h3 class="wp-block-heading" style="font-size:20px">Czy powinnam kończyć Java całkowicie przed JS?</h3>



<p class="wp-block-paragraph"><strong>NIE.</strong></p>



<p class="wp-block-paragraph">Nie musisz być ekspertem Javy, żeby zacząć JS.</p>



<p class="wp-block-paragraph"><strong>Wystarczy:</strong></p>



<ul class="wp-block-list">
<li>Rozumieć podstawy (zmienne, pętle, funkcje, obiekty)</li>



<li>Zbudować 1-2 projekty</li>
</ul>



<p class="wp-block-paragraph"><strong>Reszta:</strong> Nauczysz się w trakcie lub później.</p>



<h3 class="wp-block-heading" style="font-size:20px">Jak nie pomieszać Java i JS w głowie?</h3>



<p class="wp-block-paragraph"><strong>Początkowo:</strong> Mieszam. Piszę <code>System.out.println</code> zamiast <code>console.log</code>.</p>



<p class="wp-block-paragraph"><strong>Pomaga:</strong></p>



<ul class="wp-block-list">
<li>Używanie różnych IDE (IntelliJ dla Java, VS Code dla JS)</li>



<li>Projekty w jednym języku naraz (nie przełączać co godzinę)</li>



<li>Praktyka (mózg się przyzwyczaja)</li>
</ul>



<p class="wp-block-paragraph"><strong>Po 3 tygodniach:</strong> Już rzadziej mieszam.</p>



<h3 class="wp-block-heading" style="font-size:20px">Czy TypeScript zamiast JavaScriptu?</h3>



<p class="wp-block-paragraph"><strong>TypeScript</strong> = JavaScript + typy (jak Java)</p>



<p class="wp-block-paragraph"><strong>Argument ZA:</strong> Jeśli znasz Javę, TypeScript będzie bardziej podobny</p>



<p class="wp-block-paragraph"><strong>Argument PRZECIW:</strong> Nauka TypeScriptu = nauka JS + nauka TypeScript w działaniu (więcej naraz)</p>



<p class="wp-block-paragraph"><strong>Moja decyzja:</strong> Vanilla JS najpierw. TypeScript może później (wrzesień-październik).</p>



<h3 class="wp-block-heading" style="font-size:20px">Ile czasu dziennie poświęcam?</h3>



<p class="wp-block-paragraph"><strong>JavaScript:</strong> 1h dziennie (vs Java było 1.5h)</p>



<p class="wp-block-paragraph"><strong>Rozłożenie:</strong></p>



<ul class="wp-block-list">
<li>Rano: 30 min (FreeCodeCamp wyzwania)</li>



<li>Wieczór: 30 min (projekt/praktyka)</li>
</ul>



<p class="wp-block-paragraph"><strong>Weekendy:</strong> 2-3h (większe projekty)</p>



<p class="wp-block-paragraph"><strong>Dlaczego mniej niż Java:</strong> Wakacje, dzieci, jestem zmęczona. 1h = zrównoważony.</p>



<h3 class="wp-block-heading" style="font-size:20px">Czy warto uczyć się wielu języków naraz?</h3>



<p class="wp-block-paragraph"><strong>Moim zdaniem: NIE.</strong></p>



<p class="wp-block-paragraph">1 język na raz. Opanuj podstawy, potem dodaj drugi.</p>



<p class="wp-block-paragraph"><strong>Dlaczego:</strong></p>



<ul class="wp-block-list">
<li>Mylące (mieszasz składnie)</li>



<li>Przytłaczający (dwa razy więcej nauki)</li>



<li>Powolny postęp (rozmywasz czas)</li>
</ul>



<p class="wp-block-paragraph"><strong>Lepiej:</strong></p>



<ul class="wp-block-list">
<li>6 miesięcy Java (solidnie)</li>



<li>Potem JavaScript (z fundamentami z Javy)</li>
</ul>



<h2 class="wp-block-heading" style="font-size:22px">Podsumowanie &#8211; Learning Log #6</h2>



<p class="wp-block-paragraph"><strong>Nauka drugiego języka programowania:</strong></p>



<ul class="wp-block-list">
<li><strong>Łatwiejsza</strong> niż pierwszego (fundamenty mam)</li>



<li><strong>Trudniejsza</strong> niż myślałam (dziwactwa, różnice, mieszanie)</li>



<li><strong>Wartościowe</strong> &#8211; widzę konkretny benefit (projekty WordPress)</li>
</ul>



<p class="wp-block-paragraph"><strong>Java vs JavaScript:</strong></p>



<ul class="wp-block-list">
<li><strong>Podobne:</strong> Fundamenty (pętle, warunki, funkcje)</li>



<li><strong>Różne:</strong> Typy, scope, dziwactwa, filozofia języka</li>



<li><strong>Werdykt:</strong> Java pomogła ogromnie, ale JS wymaga &#8222;oduczyć się&#8221; od ścisłość</li>
</ul>



<p class="wp-block-paragraph"><strong>Progres po 3 tygodniach:</strong></p>



<ul class="wp-block-list">
<li>30% FreeCodeCamp kursu</li>



<li>1 mini-projekt (calculator)</li>



<li>Rozumiem podstawy</li>



<li>Czuję się komfortowo z kodem</li>
</ul>



<p class="wp-block-paragraph"><strong>Cel sierpień:</strong></p>



<ul class="wp-block-list">
<li>80% FreeCodeCamp</li>



<li>5-7 mini-projektów</li>



<li>Pierwszy większy projekt  (custom JS w WordPress)</li>
</ul>



<p class="wp-block-paragraph"><strong>Najważniejsza lekcja:</strong></p>



<p class="wp-block-paragraph"><strong>&#8222;Drugi język ≠ zaczynać od zera. Masz fundamenty. Użyj ich.&#8221;</strong></p>



<p class="wp-block-paragraph">Java nauczyła mnie programowania. JavaScript uczy mnie praktyczności i elastyczności.</p>



<p class="wp-block-paragraph">Oba są potrzebne. Oba mają miejsce w moim portfolio.</p>



<p class="wp-block-paragraph"><strong>Od osoby, która się uczy do osoby, która buduje &#8211; teraz w DWÓCH językach.</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><em>PS: Też uczysz się drugiego języka programowania? Z czego na co przeszłaś/przeszedłeś? Co było najtrudniejsze? Zostaw komentarz &#8211; ciekawa jestem Waszych doświadczeń!</em></p>



<p class="wp-block-paragraph"></p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-6-java-vs-javascript-drugi-jezyk/">Learning Log #6: Java vs JavaScript &#8211; zaczynam drugi język programowania</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.danuta-cybulska.com/learning-log-6-java-vs-javascript-drugi-jezyk/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Learning Log #5: Pierwszy większy projekt w Java &#8211; od pomysłu do działającej aplikacji</title>
		<link>https://www.danuta-cybulska.com/learning-log-5-pierwszy-projekt-java-therapy-manager/</link>
					<comments>https://www.danuta-cybulska.com/learning-log-5-pierwszy-projekt-java-therapy-manager/#respond</comments>
		
		<dc:creator><![CDATA[Danuta]]></dc:creator>
		<pubDate>Wed, 10 Jun 2026 16:00:00 +0000</pubDate>
				<category><![CDATA[LearningLog]]></category>
		<category><![CDATA[Programowanie i Rozwój]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java application]]></category>
		<category><![CDATA[learning log]]></category>
		<category><![CDATA[nauka Java]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[pierwszy projekt]]></category>
		<category><![CDATA[portfolio programming]]></category>
		<category><![CDATA[programowanie obiektowe]]></category>
		<category><![CDATA[projekt dla początkujących]]></category>
		<category><![CDATA[projekt w Java]]></category>
		<category><![CDATA[Therapy Manager]]></category>
		<guid isPermaLink="false">https://www.danuta-cybulska.com/?p=5795</guid>

					<description><![CDATA[<p>Wtorek, 3 czerwca, 22:47. Ostatni test przechodzi. Zielone checkmarki w konsoli. Aplikacja działa. Mój pierwszy większy projekt w Java jest GOTOWY. Patrzę na ekran i czuję&#8230; dumę? Ulgę? Niedowierzanie? Wszystko naraz. 5 tygodni temu to był tylko pomysł w Notion: &#8222;Zbuduj coś prawdziwego, nie tylko ćwiczenia z kursu.&#8221; Dzisiaj mam 47 klas, 2847 linii kodu...</p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-5-pierwszy-projekt-java-therapy-manager/">Learning Log #5: Pierwszy większy projekt w Java &#8211; od pomysłu do działającej aplikacji</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim" style="background-color:#286ec6"></span><img fetchpriority="high" decoding="async" width="620" height="410" src="https://www.danuta-cybulska.com/wp-content/uploads/2026/03/pierwszy-projekt-w-Java.png" class="wp-block-cover__image-background wp-post-image" alt="pierwszy projekt w Java" data-object-fit="cover" data-object-position="51% 36%" style="object-position:51% 36%;" srcset="https://www.danuta-cybulska.com/wp-content/uploads/2026/03/pierwszy-projekt-w-Java.png 620w, https://www.danuta-cybulska.com/wp-content/uploads/2026/03/pierwszy-projekt-w-Java-300x198.png 300w, https://www.danuta-cybulska.com/wp-content/uploads/2026/03/pierwszy-projekt-w-Java-370x245.png 370w" sizes="(max-width: 620px) 100vw, 620px" /><div class="wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained"><h2 style="background-color:#abb7c26e" class="has-text-align-center has-link-color wp-elements-1 wp-block-post-title has-text-color has-white-color has-background has-x-large-font-size">Learning Log #5: Pierwszy większy projekt w Java &#8211; od pomysłu do działającej aplikacji</h2></div></div>



<p class="wp-block-paragraph">Wtorek, 3 czerwca, 22:47. Ostatni test przechodzi. Zielone checkmarki w konsoli. Aplikacja działa.</p>



<p class="wp-block-paragraph"><strong>Mój pierwszy większy projekt w Java jest GOTOWY.</strong></p>



<p class="wp-block-paragraph">Patrzę na ekran i czuję&#8230; dumę? Ulgę? Niedowierzanie? Wszystko naraz.</p>



<p class="wp-block-paragraph">5 tygodni temu to był tylko pomysł w Notion: &#8222;Zbuduj coś prawdziwego, nie tylko ćwiczenia z kursu.&#8221; Dzisiaj mam 47 klas, 2847 linii kodu i działającą aplikację do zarządzania terapiami mojego dziecka.</p>



<p class="wp-block-paragraph"><strong>Pierwszy projekt w Java</strong> to przełom. To moment, gdy przestajesz być &#8222;osobą, która się uczy&#8221; i stajesz się &#8222;osobą, która buduje&#8221;. To jest ogromna różnica.</p>



<p class="wp-block-paragraph">Dziś opowiem Wam całą historię &#8211; od pomysłu, przez architekturę, wyzwania techniczne, do finału. I najważniejsze: co czułam kończąc pierwszy prawdziwy projekt jako programistka.</p>



<h2 class="wp-block-heading">Skąd pomysł &#8211; dlaczego akurat aplikacja do terapii?</h2>



<h3 class="wp-block-heading">Problem, który widziałam codziennie</h3>



<p class="wp-block-paragraph"><strong>Moja rzeczywistość:</strong></p>



<ul class="wp-block-list">
<li>8-9 godzin terapii tygodniowo (SI, logopedia, pedagogika, TUS)</li>



<li>3 różne ośrodki</li>



<li>5 terapeutów</li>



<li>Niekończące się faktury, zestawienia kosztów, raporty dla NFZ</li>



<li>Excel, który się sypie co miesiąc</li>
</ul>



<p class="wp-block-paragraph"><strong>Próbowałam gotowych rozwiązań:</strong></p>



<ul class="wp-block-list">
<li>Kalendarz Google &#8211; za prosty (tylko daty, bez kosztów)</li>



<li>Excel &#8211; chaotyczny, gubię dane</li>



<li>Aplikacje do zarządzania zdrowiem &#8211; zbyt ogólne, nie dla terapii</li>
</ul>



<p class="wp-block-paragraph"><strong>Pomyślałam:</strong> &#8222;Co jeśli zbuduję własną aplikację?&#8221;</p>



<h3 class="wp-block-heading">Punkt zwrotny &#8211; rozmowa z instruktorem kursu</h3>



<p class="wp-block-paragraph"><strong>Napisałam na Discord Zajavka:</strong></p>



<p class="wp-block-paragraph">&#8222;Skończyłam podstawy kursu. Co dalej? Spring? JavaScript?&#8221;</p>



<p class="wp-block-paragraph"><strong>Instruktor odpowiedział:</strong></p>



<p class="wp-block-paragraph">&#8222;Przed Springiem zbuduj JEDEN solidny projekt w czystej Javie. Coś co rozwiązuje prawdziwy problem. Pokaże Ci jak projektować aplikacje, nie tylko pisać kod.&#8221;</p>



<p class="wp-block-paragraph"><strong>I kliknęło.</strong></p>



<h2 class="wp-block-heading">Pierwszy projekt w Java &#8211; planowanie</h2>



<h3 class="wp-block-heading">Tydzień 1: Research i wymyślanie funkcjonalności</h3>



<p class="wp-block-paragraph"><strong>Pytania, które sobie zadałam:</strong></p>



<ol class="wp-block-list">
<li><strong>Co aplikacja MUSI umieć?</strong> (MVP &#8211; Minimum Viable Product)
<ul class="wp-block-list">
<li>Dodawanie sesji terapii</li>



<li>Przechowywanie informacji o terapeutach i ośrodkach</li>



<li>Kalkulacja kosztów miesięcznych</li>



<li>Generowanie raportów</li>
</ul>
</li>



<li><strong>Co byłoby FAJNE, ale nie konieczne?</strong> (v2.0)
<ul class="wp-block-list">
<li>Przypomnienia o sesjach</li>



<li>Statystyki roczne</li>



<li>Export do PDF</li>



<li>Integracja z kalendarzem</li>
</ul>
</li>



<li><strong>Czego NIE potrzebuję?</strong> (scope control)
<ul class="wp-block-list">
<li>GUI (graficzny interfejs) &#8211; na razie konsola wystarczy</li>



<li>Baza danych &#8211; na razie pliki tekstowe</li>



<li>Multi-user &#8211; tylko ja używam</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph"><strong>Decyzja:</strong> Buduję wersję konsolową z podstawowymi funkcjami. GUI później.</p>



<h3 class="wp-block-heading">Tydzień 2: Architektura &#8211; najpierw plan, potem kod</h3>



<p class="wp-block-paragraph"><strong>Błąd początkujących:</strong> Otwieram IDE i zaczynam pisać kod bez planu.</p>



<p class="wp-block-paragraph"><strong>Lepsze podejście:</strong> Planuję strukturę na papierze.</p>



<p class="wp-block-paragraph"><strong>Moja architektura &#8211; diagram klas:</strong></p>



<pre class="wp-block-code"><code>MAIN ENTITIES (główne encje):

TherapySession (Sesja terapii)
├── sessionId: String
├── therapyType: TherapyType (enum)
├── therapist: Therapist
├── dateTime: LocalDateTime
├── duration: int (minuty)
├── cost: BigDecimal
├── paid: boolean
├── notes: String

Therapist (Terapeuta)
├── therapistId: String
├── name: String
├── specialization: String
├── phone: String
├── email: String
├── hourlyRate: BigDecimal

TherapyCenter (Ośrodek terapeutyczny)
├── centerId: String
├── name: String
├── address: Address
├── phone: String
├── therapists: List&lt;Therapist>

TherapyType (Typ terapii - ENUM)
├── SI (Integracja sensoryczna)
├── SPEECH (Logopedia)
├── PEDAGOGY (Pedagogika)
├── EARLY_INTERVENTION (Wczesne wspomaganie)</code></pre>



<p class="wp-block-paragraph"><strong>SERVICES (serwisy &#8211; logika biznesowa):</strong></p>



<pre class="wp-block-code"><code>TherapySessionService
├── addSession()
├── updateSession()
├── deleteSession()
├── findSessionById()
├── getAllSessions()
├── getSessionsByMonth()
├── getSessionsByTherapist()

ReportService
├── generateMonthlyReport()
├── calculateTotalCost()
├── calculateCostByType()
├── generateYearlyStatistics()

PaymentService
├── markAsPaid()
├── getUnpaidSessions()
├── getTotalUnpaid()</code></pre>



<p class="wp-block-paragraph"><strong>REPOSITORIES (dostęp do danych):</strong></p>



<pre class="wp-block-code"><code>FileRepository&lt;T>
├── save(T entity)
├── findById(String id)
├── findAll()
├── delete(String id)
├── update(T entity)</code></pre>



<p class="wp-block-paragraph"><strong>UTILITIES (narzędzia pomocnicze):</strong></p>



<pre class="wp-block-code"><code>DateUtils - formatowanie dat
ValidationUtils - walidacja danych
FileUtils - operacje na plikach</code></pre>



<h3 class="wp-block-heading">Dlaczego taka struktura?</h3>



<p class="wp-block-paragraph"><strong>Podział odpowiedzialności:</strong></p>



<ul class="wp-block-list">
<li><strong>Entities</strong> = Dane (co przechowujemy)</li>



<li><strong>Services</strong> = Logika (co robimy z danymi)</li>



<li><strong>Repositories</strong> = Dostęp (jak zapisujemy/odczytujemy)</li>



<li><strong>UI</strong> = Interfejs (jak użytkownik widzi)</li>
</ul>



<p class="wp-block-paragraph"><strong>Efekt:</strong> Jeśli zmienię sposób zapisywania (z plików na bazę danych) &#8211; zmieniam tylko Repository. Services i Entities pozostają bez zmian.</p>



<h2 class="wp-block-heading">Tydzień 3-4: Implementacja &#8211; pierwszy kod</h2>



<h3 class="wp-block-heading">Zaczynanie od Entity</h3>



<p class="wp-block-paragraph"><strong>TherapySession.java &#8211; pierwsza klasa:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>public class TherapySession {
    private String sessionId;
    private TherapyType therapyType;
    private Therapist therapist;
    private LocalDateTime dateTime;
    private int durationMinutes;
    private BigDecimal cost;
    private boolean paid;
    private String notes;
    
    // Constructor
    public TherapySession(String sessionId, TherapyType therapyType, 
                         Therapist therapist, LocalDateTime dateTime,
                         int durationMinutes, BigDecimal cost) {
        this.sessionId = sessionId;
        this.therapyType = therapyType;
        this.therapist = therapist;
        this.dateTime = dateTime;
        this.durationMinutes = durationMinutes;
        this.cost = cost;
        this.paid = false; // domyślnie nieopłacone
    }
    
    // Getters and setters
    public String getSessionId() { return sessionId; }
    public TherapyType getTherapyType() { return therapyType; }
    // ... itd
    
    // Business methods
    public void markAsPaid() {
        this.paid = true;
    }
    
    public boolean isInMonth(int year, int month) {
        return dateTime.getYear() == year 
            &amp;&amp; dateTime.getMonthValue() == month;
    }
    
    @Override
    public String toString() {
        return String.format("%s | %s | %s | %.2f zł | %s",
            dateTime.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm")),
            therapyType,
            therapist.getName(),
            cost,
            paid ? "OPŁACONE" : "DO ZAPŁATY"
        );
    }
}</code></pre>



<p class="wp-block-paragraph"><strong>Co się nauczyłam:</strong></p>



<ul class="wp-block-list">
<li>BigDecimal dla pieniędzy (nie double! &#8211; problemy z precyzją)</li>



<li>LocalDateTime dla dat (lepsze niż Date)</li>



<li>Enum dla typów terapii (type-safe, nie String)</li>



<li>Business methods w encji (markAsPaid, isInMonth)</li>
</ul>



<h3 class="wp-block-heading">Wzorzec repozytorium &#8211; pierwsza abstrakcja</h3>



<p class="wp-block-paragraph"><strong>Problem:</strong> Jak zapisywać dane?</p>



<p class="wp-block-paragraph"><strong>Opcje:</strong></p>



<ol class="wp-block-list">
<li>Baza danych (za trudne na start)</li>



<li>Pliki tekstowe (proste, ale jak czytać/zapisywać?)</li>
</ol>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong> Wzorzec repozytorium z plikami JSON</p>



<p class="wp-block-paragraph"><strong>FileRepository.java &#8211; generyczny repozytorium:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>public class FileRepository&lt;T> {
    private final String filePath;
    private final Class&lt;T> entityClass;
    private final ObjectMapper objectMapper; // Jackson dla JSON
    
    public FileRepository(String filePath, Class&lt;T> entityClass) {
        this.filePath = filePath;
        this.entityClass = entityClass;
        this.objectMapper = new ObjectMapper()
            .registerModule(new JavaTimeModule()); // dla LocalDateTime
    }
    
    public void save(T entity) throws IOException {
        List&lt;T> entities = findAll();
        entities.add(entity);
        writeToFile(entities);
    }
    
    public List&lt;T> findAll() throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            return new ArrayList&lt;>();
        }
        
        return objectMapper.readValue(file, 
            objectMapper.getTypeFactory()
                .constructCollectionType(List.class, entityClass)
        );
    }
    
    public Optional&lt;T> findById(String id) throws IOException {
        return findAll().stream()
            .filter(e -> getId(e).equals(id))
            .findFirst();
    }
    
    public void update(T entity) throws IOException {
        List&lt;T> entities = findAll();
        String id = getId(entity);
        
        entities.removeIf(e -> getId(e).equals(id));
        entities.add(entity);
        writeToFile(entities);
    }
    
    public void delete(String id) throws IOException {
        List&lt;T> entities = findAll();
        entities.removeIf(e -> getId(e).equals(id));
        writeToFile(entities);
    }
    
    private void writeToFile(List&lt;T> entities) throws IOException {
        objectMapper.writerWithDefaultPrettyPrinter()
            .writeValue(new File(filePath), entities);
    }
    
    // Reflection do wyciągnięcia ID
    private String getId(T entity) {
        try {
            Method method = entity.getClass().getMethod("getSessionId");
            return (String) method.invoke(entity);
        } catch (Exception e) {
            throw new RuntimeException("Entity must have getSessionId method", e);
        }
    }
}</code></pre>



<p class="wp-block-paragraph"><strong>Co się nauczyłam:</strong></p>



<ul class="wp-block-list">
<li>Generics (<code>&lt;T></code>) &#8211; jeden magazyn dla różnych encji</li>



<li>Jackson ObjectMapper &#8211; serialization (proces przekształcania obiektów, tj. instancji określonych klas) do JSON</li>



<li>Reflection (mechanizm, który umożliwia na odczyt i modyfikację informacji o klasach) &#8211; wyciąganie ID dynamicznie</li>



<li>Exception handling (Obsługa wyjątków )- IOException musi być obsłużone</li>
</ul>



<h3 class="wp-block-heading">Service layer &#8211; logika biznesowa</h3>



<p class="wp-block-paragraph"><strong>TherapySessionService.java:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>public class TherapySessionService {
    private final FileRepository&lt;TherapySession> repository;
    
    public TherapySessionService() {
        this.repository = new FileRepository&lt;>(
            "data/therapy_sessions.json", 
            TherapySession.class
        );
    }
    
    public void addSession(TherapySession session) {
        try {
            // Walidacja
            if (session.getCost().compareTo(BigDecimal.ZERO) &lt;= 0) {
                throw new IllegalArgumentException("Koszt musi być > 0");
            }
            if (session.getDateTime().isAfter(LocalDateTime.now())) {
                System.out.println("UWAGA: Sesja w przyszłości");
            }
            
            repository.save(session);
            System.out.println("✓ Dodano sesję: " + session);
            
        } catch (IOException e) {
            System.err.println("Błąd zapisu: " + e.getMessage());
        }
    }
    
    public List&lt;TherapySession> getSessionsByMonth(int year, int month) {
        try {
            return repository.findAll().stream()
                .filter(s -> s.isInMonth(year, month))
                .sorted(Comparator.comparing(TherapySession::getDateTime))
                .toList();
        } catch (IOException e) {
            System.err.println("Błąd odczytu: " + e.getMessage());
            return new ArrayList&lt;>();
        }
    }
    
    public void markSessionAsPaid(String sessionId) {
        try {
            Optional&lt;TherapySession> session = repository.findById(sessionId);
            if (session.isPresent()) {
                session.get().markAsPaid();
                repository.update(session.get());
                System.out.println("✓ Oznaczono jako opłacone");
            } else {
                System.out.println("✗ Nie znaleziono sesji");
            }
        } catch (IOException e) {
            System.err.println("Błąd: " + e.getMessage());
        }
    }
}</code></pre>



<p class="wp-block-paragraph"><strong>Co się nauczyłam:</strong></p>



<ul class="wp-block-list">
<li>Walidacja danych (sprawdzanie przed zapisem)</li>



<li>User feedback (komunikaty co się dzieje)</li>



<li>Error handling (try-catch, komunikaty błędów)</li>



<li>Stream API dla filtrowania i sortowania</li>
</ul>



<h3 class="wp-block-heading">Report Service &#8211; generowanie raportów</h3>



<p class="wp-block-paragraph"><strong>To była najtrudniejsza część.</strong></p>



<p class="wp-block-paragraph"><strong>ReportService.java:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>public class ReportService {
    private final TherapySessionService sessionService;
    
    public void generateMonthlyReport(int year, int month) {
        List&lt;TherapySession> sessions = 
            sessionService.getSessionsByMonth(year, month);
        
        if (sessions.isEmpty()) {
            System.out.println("Brak sesji w tym miesiącu");
            return;
        }
        
        System.out.println("=".repeat(80));
        System.out.println("RAPORT MIESIĘCZNY: " + month + "/" + year);
        System.out.println("=".repeat(80));
        
        // Grupowanie po typie terapii
        Map&lt;TherapyType, List&lt;TherapySession>> byType = sessions.stream()
            .collect(Collectors.groupingBy(TherapySession::getTherapyType));
        
        // Podsumowanie per typ
        byType.forEach((type, typeSessions) -> {
            int count = typeSessions.size();
            int totalMinutes = typeSessions.stream()
                .mapToInt(TherapySession::getDurationMinutes)
                .sum();
            BigDecimal totalCost = typeSessions.stream()
                .map(TherapySession::getCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            long paidCount = typeSessions.stream()
                .filter(TherapySession::isPaid)
                .count();
            
            System.out.printf("\n%s:\n", type);
            System.out.printf("  Liczba sesji: %d\n", count);
            System.out.printf("  Całkowity czas: %dh %dmin\n", 
                totalMinutes / 60, totalMinutes % 60);
            System.out.printf("  Całkowity koszt: %.2f zł\n", totalCost);
            System.out.printf("  Opłacone: %d/%d\n", paidCount, count);
        });
        
        // Suma totalna
        BigDecimal grandTotal = sessions.stream()
            .map(TherapySession::getCost)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        BigDecimal unpaid = sessions.stream()
            .filter(s -> !s.isPaid())
            .map(TherapySession::getCost)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        System.out.println("\n" + "=".repeat(80));
        System.out.printf("SUMA CAŁKOWITA: %.2f zł\n", grandTotal);
        System.out.printf("DO ZAPŁATY: %.2f zł\n", unpaid);
        System.out.println("=".repeat(80));
    }
}
```

**Output przykładowy:**
```
================================================================================
RAPORT MIESIĘCZNY: 5/2026
================================================================================

SI:
  Liczba sesji: 8
  Całkowity czas: 8h 0min
  Całkowity koszt: 600.00 zł
  Opłacone: 8/8

SPEECH:
  Liczba sesji: 8
  Całkowity czas: 6h 0min
  Całkowity koszt: 520.00 zł
  Opłacone: 6/8

PEDAGOGY:
  Liczba sesji: 4
  Całkowity czas: 4h 0min
  Całkowity koszt: 240.00 zł
  Opłacone: 4/4

================================================================================
SUMA CAŁKOWITA: 1360.00 zł
DO ZAPŁATY: 130.00 zł
================================================================================</code></pre>



<p class="wp-block-paragraph"><strong>Co się nauczyłam:</strong></p>



<ul class="wp-block-list">
<li>Collectors.groupingBy() &#8211; grupowanie strumieni</li>



<li>Reduce dla sumowania BigDecimal</li>



<li>String formatting (printf)</li>



<li>Prezentacja danych (czytelny output)</li>
</ul>



<h2 class="wp-block-heading">Tydzień 5: UI i finiszowanie</h2>



<h3 class="wp-block-heading">Interfejs konsolowy &#8211; prosty, ale funkcjonalny</h3>



<p class="wp-block-paragraph"><strong>MainMenu.java:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>public class MainMenu {
    private final Scanner scanner;
    private final TherapySessionService sessionService;
    private final ReportService reportService;
    
    public void run() {
        while (true) {
            displayMenu();
            int choice = getChoice();
            
            switch (choice) {
                case 1 -> addSession();
                case 2 -> listSessions();
                case 3 -> markAsPaid();
                case 4 -> generateReport();
                case 5 -> {
                    System.out.println("Do widzenia!");
                    return;
                }
                default -> System.out.println("Nieprawidłowy wybór");
            }
        }
    }
    
    private void displayMenu() {
        System.out.println("\n" + "=".repeat(50));
        System.out.println("SYSTEM ZARZĄDZANIA TERAPIAMI");
        System.out.println("=".repeat(50));
        System.out.println("1. Dodaj sesję terapii");
        System.out.println("2. Pokaż sesje (obecny miesiąc)");
        System.out.println("3. Oznacz jako opłacone");
        System.out.println("4. Generuj raport miesięczny");
        System.out.println("5. Wyjście");
        System.out.print("\nWybór: ");
    }
    
    private void addSession() {
        System.out.println("\n=== NOWA SESJA ===");
        
        // Wybór typu terapii
        System.out.println("Typ terapii:");
        TherapyType&#91;] types = TherapyType.values();
        for (int i = 0; i &lt; types.length; i++) {
            System.out.printf("%d. %s\n", i + 1, types&#91;i]);
        }
        int typeChoice = scanner.nextInt() - 1;
        TherapyType type = types&#91;typeChoice];
        
        // Wybór terapeuty (z listy wcześniej dodanych)
        Therapist therapist = selectTherapist();
        
        // Data i czas
        System.out.print("Data (dd.MM.yyyy): ");
        String dateStr = scanner.next();
        System.out.print("Godzina (HH:mm): ");
        String timeStr = scanner.next();
        LocalDateTime dateTime = parseDateTime(dateStr, timeStr);
        
        // Czas trwania
        System.out.print("Czas trwania (minuty): ");
        int duration = scanner.nextInt();
        
        // Koszt
        System.out.print("Koszt (zł): ");
        BigDecimal cost = scanner.nextBigDecimal();
        
        // Utworzenie sesji
        TherapySession session = new TherapySession(
            UUID.randomUUID().toString(),
            type,
            therapist,
            dateTime,
            duration,
            cost
        );
        
        sessionService.addSession(session);
    }
}</code></pre>



<p class="wp-block-paragraph"><strong>Co się nauczyłam:</strong></p>



<ul class="wp-block-list">
<li>Scanner dla input użytkownika</li>



<li>Menu loop (while true + switch)</li>



<li>UUID dla unikalnych ID</li>



<li>User experience (komunikaty, formatowanie)</li>
</ul>



<h2 class="wp-block-heading">Wyzwania techniczne &#8211; co było najtrudniejsze</h2>



<h3 class="wp-block-heading">1. Serializacja LocalDateTime do JSON</h3>



<p class="wp-block-paragraph"><strong>Problem:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code><code>Exception: Cannot serialize LocalDateTime</code></code></pre>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>ObjectMapper mapper = new ObjectMapper()
    .registerModule(new JavaTimeModule())
    .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);</code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Jackson potrzebuje dodatkowych modułów dla Java 8 Date/Time API.</p>



<h3 class="wp-block-heading">2. BigDecimal arytmetyka</h3>



<p class="wp-block-paragraph"><strong>Problem:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code><code>BigDecimal total = cost1 + cost2; // BŁĄD! Nie można + dla BigDecimal</code></code></pre>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code><code>BigDecimal total = cost1.add(cost2);</code></code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> BigDecimal to immutable (niemodyfikowalny), używaj metod (.add, .subtract, .multiply)</p>



<h3 class="wp-block-heading">3. File I/O exceptions</h3>



<p class="wp-block-paragraph"><strong>Problem:</strong> Aplikacja crashuje gdy plik nie istnieje.</p>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>public List&lt;T> findAll() throws IOException {
    File file = new File(filePath);
    if (!file.exists()) {
        // Utwórz pusty plik
        file.getParentFile().mkdirs();
        file.createNewFile();
        writeToFile(new ArrayList&lt;>());
        return new ArrayList&lt;>();
    }
    return objectMapper.readValue(file, ...);
}</code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Zawsze sprawdzaj czy plik/folder istnieje przed czytaniem.</p>



<h3 class="wp-block-heading">4. Null handling w Optional</h3>



<p class="wp-block-paragraph"><strong>Problem:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-2"><code>TherapySession session = repository.findById(id); // może null
session.markAsPaid(); // NullPointerException!</code></pre>



<p class="wp-block-paragraph"><strong>Rozwiązanie:</strong></p>



<p class="wp-block-paragraph">java</p>



<pre class="wp-block-code"><code>Optional&lt;TherapySession> sessionOpt = repository.findById(id);
if (sessionOpt.isPresent()) {
    sessionOpt.get().markAsPaid();
} else {
    System.out.println("Nie znaleziono");
}

// Lub functional style:
sessionOpt.ifPresent(TherapySession::markAsPaid);
```

**Lekcja:** Optional to explicite "może być null", obsługuj zawsze.

## Statystyki projektu - liczby

**Czas pracy:** 5 tygodni (kwiecień-maj 2026)
- Tydzień 1: Planowanie (10h)
- Tydzień 2: Architektura (8h)
- Tydzień 3-4: Implementacja (25h)
- Tydzień 5: UI + testy (12h)
- **Total: ~55 godzin**

**Kod:**
- **47 klas** (entities, services, repositories, utils, UI)
- **2847 linii kodu** (bez komentarzy)
- **89 metod** (średnio 32 linie/klasa)
- **23 pliki testowe** (JUnit tests)

**Biblioteki użyte:**
- Jackson (JSON serialization)
- JUnit 5 (testy jednostkowe)
- SLF4J + Logback (logging)

**Struktura folderów:**
```
therapy-manager/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   ├── com.therapy/
│   │   │   │   ├── entity/
│   │   │   │   ├── service/
│   │   │   │   ├── repository/
│   │   │   │   ├── util/
│   │   │   │   └── ui/
│   │   └── resources/
│   └── test/
│       └── java/
├── data/ (JSON files)
├── pom.xml (Maven dependencies)
└── README.md</code></pre>



<h2 class="wp-block-heading">Co czułam finiszując projekt</h2>



<h3 class="wp-block-heading">3 czerwca, 22:47 &#8211; ostatni test przechodzi</h3>



<p class="wp-block-paragraph"><strong>Uczucia w tym momencie:</strong></p>



<p class="wp-block-paragraph"><strong>1. Niedowierzanie</strong> &#8222;To naprawdę działa? Ja to zbudowałam?&#8221;</p>



<p class="wp-block-paragraph">5 miesięcy temu nie znałam Javy. Dzisiaj mam działającą aplikację z 47 klasami.</p>



<p class="wp-block-paragraph"><strong>2. Duma</strong> Pokazałam partnerowi: &#8222;Patrz, to dodaje sesję, to generuje raport&#8230;&#8221;</p>



<p class="wp-block-paragraph">On: &#8222;Zrobiłaś TO?! To jest niesamowite!&#8221;</p>



<p class="wp-block-paragraph">Ja: <em>wzruszenie</em> (szczęśliwe łzy)</p>



<p class="wp-block-paragraph"><strong>3. Ulga</strong> Mogłam odpuścić 100 razy. &#8222;Za trudne&#8221;, &#8222;Nie dam rady&#8221;, &#8222;Może później&#8221;.</p>



<p class="wp-block-paragraph">Ale nie odpuściłam. I skończyłam.</p>



<p class="wp-block-paragraph"><strong>4. Więcej</strong>&#8230; To był tylko początek. Już myślałam: &#8222;Co dalej? GUI? Baza danych? Spring?&#8221;</p>



<h3 class="wp-block-heading">Perspektywa &#8211; co projekt zmienił</h3>



<p class="wp-block-paragraph"><strong>Przed projektem:</strong></p>



<ul class="wp-block-list">
<li>&#8222;Programowanie to nauka składni i algorytmów&#8221;</li>



<li>&#8222;Projekty to coś dla ekspertów&#8221;</li>



<li>&#8222;Ja tylko uczę się z tutoriali&#8221;</li>
</ul>



<p class="wp-block-paragraph"><strong>Po projekcie:</strong></p>



<ul class="wp-block-list">
<li>&#8222;Programowanie to rozwiązywanie problemów&#8221;</li>



<li>&#8222;Projekty to jedyny sposób, żeby naprawdę się nauczyć&#8221;</li>



<li>&#8222;Ja BUDUJĘ, nie tylko uczę się&#8221;</li>
</ul>



<p class="wp-block-paragraph"><strong>Mentalna zmiana:</strong> Od &#8222;osoby która się uczy&#8221; do &#8222;programistki&#8221;.</p>



<h2 class="wp-block-heading">Co bym zrobiła inaczej</h2>



<h3 class="wp-block-heading">1. Testy od początku, nie na końcu</h3>



<p class="wp-block-paragraph"><strong>Zrobiłam:</strong> Napisałam kod, potem testy.</p>



<p class="wp-block-paragraph"><strong>Lepiej:</strong> TDD (Test-Driven Development) &#8211; testy najpierw, kod potem.</p>



<p class="wp-block-paragraph"><strong>Dlaczego:</strong> Łatwiej refaktorować, gdy masz testy.</p>



<h3 class="wp-block-heading">2. Mniejsze commity do Git</h3>



<p class="wp-block-paragraph"><strong>Zrobiłam:</strong> Wielkie commity &#8222;Added 10 classes&#8221;</p>



<p class="wp-block-paragraph"><strong>Lepiej:</strong> Małe, atomowe commity &#8222;Add TherapySession entity&#8221;, &#8222;Add FileRepository&#8221;</p>



<p class="wp-block-paragraph"><strong>Dlaczego:</strong> Łatwiej wrócić do poprzedniej wersji.</p>



<h3 class="wp-block-heading">3. Więcej loggingu</h3>



<p class="wp-block-paragraph"><strong>Zrobiłam:</strong> System.out.println() wszędzie</p>



<p class="wp-block-paragraph"><strong>Lepiej:</strong> SLF4J logger z poziomami (DEBUG, INFO, ERROR)</p>



<p class="wp-block-paragraph"><strong>Dlaczego:</strong> Łatwiejszy debugging na produkcji.</p>



<h3 class="wp-block-heading">4. Dokumentacja w trakcie, nie po</h3>



<p class="wp-block-paragraph"><strong>Zrobiłam:</strong> Dokumentacja README na końcu (zapomniałam połowę decyzji)</p>



<p class="wp-block-paragraph"><strong>Lepiej:</strong> Notatki w Notion podczas budowania</p>



<p class="wp-block-paragraph"><strong>Dlaczego:</strong> Świeża pamięć = lepsza dokumentacja.</p>



<h2 class="wp-block-heading">Co dalej &#8211; plany na projekt</h2>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /><strong>Wersja 1.0 (zrobione):</strong> </p>



<ul class="wp-block-list">
<li>Konsolowy interface</li>



<li>JSON file storage</li>



<li>Podstawowe raporty</li>
</ul>



<p class="wp-block-paragraph"><strong>Wersja 2.0 (czerwiec-lipiec):</strong></p>



<ul class="wp-block-list">
<li>GUI (JavaFX) &#8211; graficzny interfejs</li>



<li>Eksport raportów do PDF</li>



<li>Charts (wykresy kosztów)</li>
</ul>



<p class="wp-block-paragraph"><strong>Wersja 3.0 (sierpień-wrzesień):</strong></p>



<ul class="wp-block-list">
<li>Baza danych (PostgreSQL zamiast JSON)</li>



<li>Multi-user (mąż też może dodawać sesje)</li>



<li>Web interface (może Spring Boot?)</li>
</ul>



<p class="wp-block-paragraph"><strong>Ale najpierw:</strong> Przerwa. Odpoczynek. Perspektywa.</p>



<h2 class="wp-block-heading">Nauki z pierwszego projektu w Java</h2>



<h3 class="wp-block-heading">Techniczne:</h3>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>OOP design</strong> &#8211; jak projektować klasy i relacje <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Wzorce projektowe</strong> – repozytorium, warstwa usług, wstrzykiwanie zależności<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>File I/O</strong> &#8211; czytanie/zapis plików, JSON serializacja<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Kolekcje i strumienie</strong> – filtrowanie, grupowanie, redukcja<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Obsługa wyjątków</strong> &#8211; try-catch, niestandardowe wyjątki<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Testing</strong> &#8211; JUnit, pokrycie testowe</p>



<h3 class="wp-block-heading">Nietechniczne (ważniejsze!):</h3>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Ukończenie > Perfekcja</strong> &#8211; lepiej skończony prosty projekt niż nie skończony perfekcyjny <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Małe kroki</strong> &#8211; 1h dziennie przez 5 tygodni > 10h przez 1 dzień <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Realne problemy</strong> &#8211; budowanie czegoś co rozwiązuje własny problem = motywacja <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Liczy się pęd</strong> &#8211; 1 dzień przerwy OK, 3 dni = trudno wrócić <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Świętuj zwycięstwa</strong> &#8211; skończony projekt = osiągnięcie, świętuj to!</p>



<h2 class="wp-block-heading">FAQ &#8211; pierwszy projekt w Java</h2>



<h3 class="wp-block-heading">Czy potrzebuję skończyć cały kurs przed projektem?</h3>



<p class="wp-block-paragraph"><strong>NIE.</strong> Ja zaczęłam projekt po:</p>



<ul class="wp-block-list">
<li>Podstawach składni (zmienne, pętle, warunki)</li>



<li>OOP (klasy, obiekty, dziedziczenie)</li>



<li>Collections (List, Map, Set)</li>



<li>Podstawach Streams</li>
</ul>



<p class="wp-block-paragraph"><strong>Reszta nauczyłam się w trakcie projektu</strong> (JSON, File I/O, design patterns).</p>



<h3 class="wp-block-heading">Ile czasu dziennie pracowałaś?</h3>



<p class="wp-block-paragraph"><strong>Średnio:</strong> 1.5h dziennie (10-15h tygodniowo)</p>



<p class="wp-block-paragraph"><strong>Rozłożenie:</strong></p>



<ul class="wp-block-list">
<li>Popołudnia: 1h (14:00-15:00)</li>



<li>Wieczory: 30 min (21:30-22:00) &#8211; gdy energia była</li>
</ul>



<p class="wp-block-paragraph"><strong>Weekendy:</strong> 3-4h (sobota rano, partner z dziećmi)</p>



<h3 class="wp-block-heading">Jak wybrać dobry projekt dla początkujących?</h3>



<p class="wp-block-paragraph"><strong>3 kryteria:</strong></p>



<ol class="wp-block-list">
<li><strong>Rozwiązuje TWÓJ problem</strong> &#8211; motywacja wewnętrzna</li>



<li><strong>Zakres realistyczny</strong> &#8211; zrobisz w 4-6 tygodni</li>



<li><strong>Trochę za trudny</strong> &#8211; uczysz się nowego, ale nie przytłaczający</li>
</ol>



<p class="wp-block-paragraph"><strong>Przykłady dobrych pierwszych projektów:</strong></p>



<ul class="wp-block-list">
<li>Todo list manager (klasyk, ale działa)</li>



<li>Expense tracker (śledzenie wydatków)</li>



<li>Library manager (zarządzanie książkami)</li>



<li>Habit tracker (śledzenie nawyków)</li>



<li>Recipe organizer (przepisy kulinarne)</li>
</ul>



<p class="wp-block-paragraph"><strong>Zły projekt:</strong> &#8222;Zbuduję Facebooka&#8221; (gwarantowane rozszerzenie zakresu)</p>



<h3 class="wp-block-heading">Co jeśli utknę i nie wiem jak coś zrobić?</h3>



<p class="wp-block-paragraph"><strong>Moja strategia:</strong></p>



<p class="wp-block-paragraph"><strong>1. Google (15 min)</strong> &#8211; &#8222;How to serialize LocalDateTime to JSON Java&#8221; <br><strong>2. Stack Overflow (15 min)</strong> &#8211; czytam różne rozwiązania <br><strong>3. ChatGPT (10 min)</strong> &#8211; pytam o konkretny problem <br><strong>4. Discord/forum kursu (24h)</strong> &#8211; pytam instruktora <br><strong>5. Następnego dnia świeży umysł</strong>&#8211; czasem sen rozwiązuje</p>



<p class="wp-block-paragraph"><strong>Zasada:</strong> Max 1h szukania rozwiązania. Potem przerwa/pomoc.</p>



<h3 class="wp-block-heading">Czy pokazać projekt w portfolio?</h3>



<p class="wp-block-paragraph"><strong>TAK!</strong> Nawet prosty projekt pokazuje:</p>



<ul class="wp-block-list">
<li>Umiesz skończyć, co zaczynasz</li>



<li>Rozumiesz OOP i design patterns</li>



<li>Piszesz czysty kod</li>



<li>Rozwiązujesz problemy</li>
</ul>



<p class="wp-block-paragraph"><strong>Lepiej:</strong> 1 skończony prosty projekt niż 10 nie skończonych &#8222;ambitnych&#8221;.</p>



<h2 class="wp-block-heading">Podsumowanie &#8211; mój pierwszy prawdziwy projekt</h2>



<p class="wp-block-paragraph"><strong>Therapy Manager v1.0:</strong></p>



<ul class="wp-block-list">
<li>47 klas</li>



<li>2847 linii kodu</li>



<li>55 godzin pracy</li>



<li>5 tygodni od pomysłu do finiszu</li>



<li>Aplikacja która rozwiązuje mój realny problem</li>
</ul>



<p class="wp-block-paragraph"><strong>Co zyskałam:</strong></p>



<ul class="wp-block-list">
<li>Umiejętność projektowania aplikacji</li>



<li>Pewność siebie jako programistka</li>



<li>Element portfolio (pokazuję na GitHubie)</li>



<li>Praktyczne narzędzie (używam codziennie!)</li>
</ul>



<p class="wp-block-paragraph"><strong>Najważniejsza lekcja:</strong></p>



<p class="wp-block-paragraph"><strong>&#8222;Programowania nie uczy się przez czytanie poradników. Uczy się przez BUDOWANIE.&#8221;</strong></p>



<p class="wp-block-paragraph">Możesz przeczytać 100 tutoriali o Javie. Ale dopiero gdy zbudujesz projekt &#8211; rozumiesz jak to wszystko się łączy.</p>



<p class="wp-block-paragraph"><strong>Pierwszy projekt w Java to przełom.</strong> Od &#8222;osoby która się uczy&#8221; do &#8222;osoby która buduje&#8221;.</p>



<p class="wp-block-paragraph">I jeśli ja mogłam &#8211; z godzinę dziennie, z dziećmi w terapiach, między freelancingiem &#8211; to Ty też możesz.</p>



<p class="wp-block-paragraph"><strong>Zbuduj coś. Zakończ to. Świętuj.</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><em>PS: Też budujesz swój pierwszy projekt? Utknąłeś gdzieś? Napisz w komentarzu &#8211; chętnie pomogę! A jeśli skończyłeś projekt &#8211; podziel się, co zbudowałeś? Ciekawa jestem!</em></p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-5-pierwszy-projekt-java-therapy-manager/">Learning Log #5: Pierwszy większy projekt w Java &#8211; od pomysłu do działającej aplikacji</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.danuta-cybulska.com/learning-log-5-pierwszy-projekt-java-therapy-manager/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Learning Log #4: Strumienie, lambdy i funkcyjne programowanie w Java</title>
		<link>https://www.danuta-cybulska.com/programowanie-funkcyjne-java/</link>
					<comments>https://www.danuta-cybulska.com/programowanie-funkcyjne-java/#respond</comments>
		
		<dc:creator><![CDATA[Danuta]]></dc:creator>
		<pubDate>Wed, 29 Apr 2026 16:00:00 +0000</pubDate>
				<category><![CDATA[LearningLog]]></category>
		<category><![CDATA[Programowanie i Rozwój]]></category>
		<category><![CDATA[functional programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[lambda Java]]></category>
		<category><![CDATA[learning log]]></category>
		<category><![CDATA[method references]]></category>
		<category><![CDATA[nauka programowania]]></category>
		<category><![CDATA[Optional]]></category>
		<category><![CDATA[programowanie funkcyjne]]></category>
		<category><![CDATA[streams API]]></category>
		<category><![CDATA[Zajavka]]></category>
		<guid isPermaLink="false">https://www.danuta-cybulska.com/?p=5781</guid>

					<description><![CDATA[<p>Kawa trzecia dzisiaj. Kod na ekranie wygląda&#8230; dziwnie. Zamiast pętli for mam Zamiast: Mam: Witajcie w świecie programowania funkcyjnego w Java. Tydzień 13-14 mojej nauki (po oficjalnym zakończeniu podstaw Zajavka) poświęciłam na zaawansowane tematy: strumienie (Streams API), wyrażenia lambda i Optional. Tematy, które na początku wyglądały jak hieroglify, a teraz&#8230; no cóż, nadal są trudne,...</p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/programowanie-funkcyjne-java/">Learning Log #4: Strumienie, lambdy i funkcyjne programowanie w Java</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim" style="background-color:#c7cacb"></span><img decoding="async" width="620" height="410" src="https://www.danuta-cybulska.com/wp-content/uploads/2026/02/17.png" class="wp-block-cover__image-background wp-post-image" alt="programowanie funkcyjne Java" data-object-fit="cover" data-object-position="51% 36%" style="object-position:51% 36%;" srcset="https://www.danuta-cybulska.com/wp-content/uploads/2026/02/17.png 620w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/17-300x198.png 300w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/17-340x226.png 340w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/17-370x245.png 370w" sizes="(max-width: 620px) 100vw, 620px" /><div class="wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained"><h2 style="background-color:#abb7c26e" class="has-text-align-center has-link-color wp-elements-3 wp-block-post-title has-text-color has-white-color has-background has-x-large-font-size">Learning Log #4: Strumienie, lambdy i funkcyjne programowanie w Java</h2></div></div>



<p class="wp-block-paragraph">Kawa trzecia dzisiaj. Kod na ekranie wygląda&#8230; dziwnie. Zamiast pętli <code>for</code> mam </p>



<pre class="wp-block-code"><code><code>.stream().filter().map().collect()</code></code></pre>



<p class="wp-block-paragraph">Zamiast:</p>



<pre class="wp-block-code"><code>java<br><br><code>for (int i = 0; i &lt; list.size(); i++) { ... }</code></code></pre>



<p class="wp-block-paragraph">Mam:</p>



<pre class="wp-block-code"><code>java<br><br><code>list.stream().forEach(item -> ...)</code></code></pre>



<p class="wp-block-paragraph"><strong>Witajcie w świecie programowania funkcyjnego w Java.</strong></p>



<p class="wp-block-paragraph">Tydzień 13-14 mojej nauki (po oficjalnym zakończeniu podstaw Zajavka) poświęciłam na zaawansowane tematy: <strong>strumienie (Streams API), wyrażenia lambda i Optional</strong>. Tematy, które na początku wyglądały jak hieroglify, a teraz&#8230; no cóż, nadal są trudne, ale już rozumiem PO CO.</p>



<h2 class="wp-block-heading">Czym są wyrażenia lambda w Java?</h2>



<h3 class="wp-block-heading">Najprostsza definicja:</h3>



<p class="wp-block-paragraph"><strong>Lambda to funkcja bez nazwy, którą można przekazać jako argument.</strong></p>



<p class="wp-block-paragraph">Zamiast pisać:</p>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-4"><code>java

public interface Greeting { 
    void sayHello(String name); 
}

public class PolishGreeting implements Greeting { 
     @Override 
     public void sayHello(String name) { 
         System.out.println("Cześć " + name); 
     } 
}

// Użycie: 
Greeting greeting = new PolishGreeting(); 
greeting.sayHello("Anna");</code></pre>



<p class="wp-block-paragraph">Możesz napisać:</p>



<pre class="wp-block-code"><code>java

<code>Greeting greeting = (name) -> System.out.println("Cześć " + name); </code>
<code>greeting.sayHello("Anna");</code></code></pre>



<p class="wp-block-paragraph"><strong>10 linii → 1 linia. To jest moc lambd.</strong></p>



<h3 class="wp-block-heading">Składnia lambda &#8211; od długiej do krótkiej:</h3>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-5"><code>java

// Wersja pełna (typ parametru + nawias + return) 
(String name) -> { return "Cześć " + name; }

// Bez typu (Java infers - wywnioskuje) 
(name) -> { return "Cześć " + name; }

// Bez return (single expression) 
(name) -> "Cześć " + name

// Jeden parametr = bez nawiasu 
name -> "Cześć " + name</code></pre>



<p class="wp-block-paragraph"><strong>Wszystkie 4 wersje robią TO SAMO.</strong></p>



<h3 class="wp-block-heading">Mój przykład &#8211; filtrowanie terapii:</h3>



<p class="wp-block-paragraph"><strong>Przed lambdą:</strong></p>



<pre class="wp-block-code"><code>java

<code>public class ExpensiveTherapyFilter { </code>   <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">public List&lt;Therapy> filter(List&lt;Therapy> therapies) { </span>
          <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">List&lt;Therapy> result = new ArrayList&lt;>(); </span>
          <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">for (Therapy therapy : therapies) {</span>
              <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;"> if (therapy.getCost() > 70) {</span>
                  <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;"> result.add(therapy);</span>
               <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">} </span>
          <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">} </span>
          <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">return result; </span>
   <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">}</span>
<span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">}</span></code></pre>



<p class="wp-block-paragraph"><strong>Z lambdą:</strong></p>



<pre class="wp-block-code"><code>java

<code>List&lt;Therapy> expensive = therapies.stream()</code>    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;"> .filter(t -> t.getCost() > 70) </span>
     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.collect(Collectors.toList());</span></code></pre>



<p class="wp-block-paragraph"><strong>15 linii → 3 linie. Czytelniejsze. Mniej szablonowe.</strong></p>



<h2 class="wp-block-heading">Streams API &#8211; pipeline przetwarzania danych</h2>



<h3 class="wp-block-heading">Czym jest strumień (stream)?</h3>



<p class="wp-block-paragraph"><strong>Strumień to sekwencja elementów</strong> które możesz przetwarzać w pipeline (rurociąg).</p>



<p class="wp-block-paragraph"><strong>Analogia &#8211; taśma produkcyjna:</strong></p>



<p class="wp-block-paragraph">Wyobraź sobie fabrykę:</p>



<ol class="wp-block-list">
<li><strong>Źródło:</strong> Surowce wchodzą na taśmę</li>



<li><strong>Operacje pośrednie:</strong> Czyszczenie → Cięcie → Malowanie</li>



<li><strong>Operacja końcowa:</strong> Pakowanie do pudełka</li>
</ol>



<p class="wp-block-paragraph">W Javie:</p>



<ol class="wp-block-list">
<li><strong>Źródło:</strong> <code>list.stream()</code></li>



<li><strong>Operacje pośrednie:</strong> <code>.filter()</code> → <code>.map()</code> → <code>.sorted()</code></li>



<li><strong>Operacja końcowa:</strong> <code>.collect()</code> lub <code>.forEach()</code></li>
</ol>



<h3 class="wp-block-heading">Podstawowe operacje:</h3>



<p class="wp-block-paragraph"><strong>filter() &#8211; filtrowanie</strong></p>



<pre class="wp-block-code"><code>java

<code>// Tylko terapie droższe niż 70 zł </code>
<code>List&lt;Therapy> expensive = therapies.stream() </code>     .<span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">filter(t -> t.getCost() > 70) </span>
     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.collect(Collectors.toList());</span></code></pre>



<p class="wp-block-paragraph"><strong>map() &#8211; transformacja</strong></p>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-6"><code>java

// Lista kosztów (z Therapy robi Double) 
   List&lt;Double> costs = therapies.stream() 
        .map(t -> t.getCost()) 
        .collect(Collectors.toList());

// Skrócona wersja (method reference): 
   List&lt;Double> costs = therapies.stream() 
       .map(Therapy::getCost) 
       .collect(Collectors.toList());</code></pre>



<p class="wp-block-paragraph"><strong>sorted() &#8211; sortowanie</strong></p>



<pre class="wp-block-code"><code>java

<code>// Posortowane po cenie (rosnąco) </code>
<code>List&lt;Therapy> sorted = therapies.stream() <span style="background-color: initial; font-family: inherit; font-size: inherit; text-align: initial; color: rgb(102, 102, 102);"> </span>   </code>    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.sorted(Comparator.comparing(Therapy::getCost)) </span>
    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.collect(Collectors.toList());</span></code></pre>



<p class="wp-block-paragraph"><strong>forEach() &#8211; akcja na każdym</strong></p>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-7"><code>java

// Wypisz każdą terapię 
   therapies.stream() 
       .forEach(t -> System.out.println(t.getName()));

// Lub krócej: 
   therapies.stream() 
       .forEach(System.out::println);`</code></pre>



<h3 class="wp-block-heading">Łańcuchowanie operacji (chaining):</h3>



<pre class="wp-block-code"><code>java

<code>// Znajdź 3 najdroższe terapie typu "SI" i wypisz ich nazwy </code>
<code>therapies.stream()</code>    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.filter(t -> t.getType().equals("SI")) // tylko SI </span>
<span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">    .sorted(Comparator.comparing(Therapy::getCost).reversed()) // od najdroższych </span>
    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.limit(3) // tylko 3 </span>
    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.map(Therapy::getName) // same nazwy </span>
    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.forEach(System.out::println); // wypisz</span></code></pre>



<p class="wp-block-paragraph"><strong>Piękno:</strong> Czytasz to jak zdanie po polsku &#8211; &#8222;weź terapie, odfiltruj SI, posortuj po cenie malejąco, weź 3, wyciągnij nazwy, wypisz&#8221;</p>



<h2 class="wp-block-heading">Mój projekt &#8211; analiza kosztów terapii z Streams</h2>



<p class="wp-block-paragraph">Zbudowałam system analizy moich wydatków na terapie używając Streams API.</p>



<pre class="wp-block-code"><code>java

public class TherapyAnalyzer { private List&lt;TherapySession> sessions;

public TherapyAnalyzer(List&lt;TherapySession> sessions) {
    this.sessions = sessions;
}

// 1. Całkowity koszt wszystkich terapii
public double getTotalCost() {
    return sessions.stream()
        .mapToDouble(TherapySession::getCost)
        .sum();
}

// 2. Średni koszt terapii
public double getAverageCost() {
    return sessions.stream()
        .mapToDouble(TherapySession::getCost)
        .average()
        .orElse(0.0);
}

// 3. Najdroższa terapia
public Optional&lt;TherapySession> getMostExpensive() {
    return sessions.stream()
        .max(Comparator.comparing(TherapySession::getCost));
}

// 4. Grupowanie po typie terapii
public Map&lt;String, List&lt;TherapySession>> groupByType() {
    return sessions.stream()
        .collect(Collectors.groupingBy(TherapySession::getType));
}

// 5. Suma kosztów per typ terapii
public Map&lt;String, Double> getCostByType() {
    return sessions.stream()
        .collect(Collectors.groupingBy(
            TherapySession::getType,
            Collectors.summingDouble(TherapySession::getCost)
        ));
}

// 6. Liczba sesji per typ
public Map&lt;String, Long> getCountByType() {
    return sessions.stream()
        .collect(Collectors.groupingBy(
            TherapySession::getType,
            Collectors.counting()
        ));
}

// 7. Terapie w danym miesiącu
public List&lt;TherapySession> getSessionsInMonth(int year, int month) {
    return sessions.stream()
        .filter(s -> s.getDate().getYear() == year)
        .filter(s -> s.getDate().getMonthValue() == month)
        .sorted(Comparator.comparing(TherapySession::getDate))
        .collect(Collectors.toList());
}

// 8. Top 5 najdroższych sesji
public List&lt;TherapySession> getTop5MostExpensive() {
    return sessions.stream()
        .sorted(Comparator.comparing(TherapySession::getCost).reversed())
        .limit(5)
        .collect(Collectors.toList());
}

// 9. Czy są nieopłacone terapie?
public boolean hasUnpaidSessions() {
    return sessions.stream()
        .anyMatch(s -> !s.isPaid());
}

// 10. Wszystkie opłacone?
public boolean allPaid() {
    return sessions.stream()
        .allMatch(TherapySession::isPaid);
}

}</code></pre>



<h3 class="wp-block-heading">Użycie:</h3>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-8"><code>java

// Przykładowe dane 
   List&lt;TherapySession> sessions = List.of( 
        new TherapySession("SI", LocalDate.of(2026, 4, 1), 75.0, true), 
        new TherapySession("Logopeda", LocalDate.of(2026, 4, 3), 65.0, true), 
        new TherapySession("SI", LocalDate.of(2026, 4, 8), 75.0, false), 
        new TherapySession("Pedagog", LocalDate.of(2026, 4, 10), 60.0, true), 
        new TherapySession("Logopeda", LocalDate.of(2026, 4, 15), 65.0, false) 
   );

TherapyAnalyzer analyzer = new TherapyAnalyzer(sessions);

// Analiza 
   System.out.println("Total: " + analyzer.getTotalCost() + " zł"); 
// Output: Total: 340.0 zł

   System.out.println("Average: " + analyzer.getAverageCost() + " zł"); 
// Output: Average: 68.0 zł

   Map&lt;String, Double> costByType = analyzer.getCostByType(); 
   System.out.println("SI: " + costByType.get("SI") + " zł"); 
// Output: SI: 150.0 zł

   System.out.println("Has unpaid: " + analyzer.hasUnpaidSessions()); 
// Output: Has unpaid: true`</code></pre>



<p class="wp-block-paragraph"><strong>Realny użytek:</strong> Teraz mogę w sekundę wygenerować raport miesięczny dla księgowej!</p>



<h2 class="wp-block-heading">Optional &#8211; koniec z NullPointerException?</h2>



<h3 class="wp-block-heading">Problem z null:</h3>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-9"><code>java

public Therapy getMostExpensiveTherapy(List&lt;Therapy> therapies) { 
       Therapy result = null; for (Therapy t : therapies) {
               if (result == null || t.getCost() > result.getCost()) { 
               result = t; 
               } 
       } return result; 
// Co jeśli lista pusta? → null 
}

// Użycie: 
Therapy expensive = getMostExpensiveTherapy(therapies); System.out.println(expensive.getName());   // BOOM! NullPointerException jeśli lista pusta`</code></pre>



<h3 class="wp-block-heading">Rozwiązanie &#8211; Optional:</h3>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-10"><code>java

public Optional&lt;Therapy> getMostExpensiveTherapy(List&lt;Therapy> therapies) {
       return therapies.stream() 
       .max(Comparator.comparing(Therapy::getCost)); 
}

// Użycie - wersja 1 (sprawdź czy jest) 
Optional&lt;Therapy> expensive = getMostExpensiveTherapy(therapies); 
if (expensive.isPresent()) { 
    System.out.println(expensive.get().getName());
} else { 
    System.out.println("No therapies"); 
}

// Użycie - wersja 2 
(functional style) getMostExpensiveTherapy(therapies) 
     .ifPresent(t -> System.out.println(t.getName()));

// Użycie - wersja 3 (default value) 
String name = getMostExpensiveTherapy(therapies) 
       .map(Therapy::getName) 
       .orElse("No therapies");</code></pre>



<p class="wp-block-paragraph"><strong>Optional mówi wyraźnie:</strong> &#8222;Ta metoda może NIE zwrócić wartości&#8221;</p>



<h3 class="wp-block-heading">Kiedy używać Optional:</h3>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>TAK:</strong></p>



<ul class="wp-block-list">
<li>Zwracane wartości metod które mogą być puste</li>



<li>Rezultat wyszukiwania</li>



<li><code>stream().findFirst()</code>, <code>.max()</code>, <code>.min()</code></li>
</ul>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>NIE:</strong></p>



<ul class="wp-block-list">
<li>Pola w klasach (ciężkie, memory overhead)</li>



<li>Parametry metod (null-check prostszy)</li>



<li>Collections (używaj pustej listy zamiast Optional&lt;List&gt;)</li>
</ul>



<h2 class="wp-block-heading">Method references &#8211; skróty lambd</h2>



<p class="wp-block-paragraph">Czasem lambda to tylko przekazanie do innej metody:</p>



<pre class="wp-block-code has-pinnacle-primary-color has-text-color has-link-color wp-elements-11"><code>java

// Lambda 
list.forEach(item -> System.out.println(item));

// Method reference 
list.forEach(System.out::println);`</code></pre>



<h3 class="wp-block-heading">Typy method references:</h3>



<p class="wp-block-paragraph"><strong>1. Static method</strong></p>



<pre class="wp-block-code"><code>java

<code>// Lambda </code>
<code>list.stream().map(s -> Integer.parseInt(s))</code>
<code>// Method reference </code>
<code>list.stream().map(Integer::parseInt)</code></code></pre>



<p class="wp-block-paragraph"><strong>2. Instance method</strong></p>



<pre class="wp-block-code"><code>java

<code>// Lambda </code>
<code>therapies.stream().map(t -> t.getName()) </code>
<code>// Method reference </code>
<code>therapies.stream().map(Therapy::getName)</code></code></pre>



<p class="wp-block-paragraph"><strong>3. Constructor</strong></p>



<pre class="wp-block-code"><code>java

<code>// Lambda </code>
<code>list.stream().map(name -> new Therapy(name))</code>
<code>// Method reference </code>
<code>list.stream().map(Therapy::new)</code></code></pre>



<h2 class="wp-block-heading">Typowe błędy które popełniłam</h2>



<h3 class="wp-block-heading">1. Modyfikowanie źródła w stream</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>java

<code>List&lt;Therapy> therapies = new ArrayList&lt;>(originalList);</code> <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">therapies.stream() </span>
      <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.forEach(t -> therapies.add(new Therapy("Copy"))); // ConcurrentModificationException!</span></code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Streams NIE mogą modyfikować kolekcji źródłowej.</p>



<h3 class="wp-block-heading">2. Używanie side effects w lambda</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>java

<code>int&#91;] counter = {0}; // <span style="background-color: initial; font-family: inherit; font-size: inherit; text-align: initial; color: rgb(102, 102, 102);">zmienna</span><span style="background-color: initial; font-family: inherit; font-size: 0.875rem; text-align: initial;"> zewnętrzna zmienna </span><span style="background-color: initial; font-family: inherit; font-size: inherit; text-align: initial; color: rgb(102, 102, 102);"> </span><span style="background-color: initial; font-family: inherit; font-size: 0.875rem; text-align: initial;">therapies.stream() </span></code>      <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.forEach(t -> counter&#91;0]++); // </span>ŹLE! Efekt uboczny</code></pre>



<p class="wp-block-paragraph"><strong>Lepiej:</strong></p>



<pre class="wp-block-code"><code>java

<code>long count = therapies.stream().count(); // <span style="background-color: initial; font-family: inherit; font-size: inherit; text-align: initial; color: rgb(102, 102, 102);">Sposób funkcjonalny</span></code></code></pre>



<h3 class="wp-block-heading">3. Zapomnienie .collect()</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>java

<code>therapies.stream() </code>     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.filter(t -> t.getCost() > 70) </span>
     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.map(Therapy::getName); // To NIE zwraca List! To Stream!</span></code></pre>



<p class="wp-block-paragraph"><strong>Poprawka:</strong></p>



<pre class="wp-block-code"><code>java

<code>List&lt;String> names = therapies.stream() </code>     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.filter(t -> t.getCost() > 70) </span>
     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.map(Therapy::getName) .collect(Collectors.toList()); // Teraz tak!</span></code></pre>



<h3 class="wp-block-heading">4. Używanie Optional.get() bez sprawdzenia</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>java

<code>Optional&lt;Therapy> therapy = findTherapy();System.out.println(therapy.get().getName()); // NoSuchElementException jeśli empty!</code></code></pre>



<p class="wp-block-paragraph"><strong>Lepiej:</strong></p>



<pre class="wp-block-code"><code>java

<code>therapy.ifPresent(t -> System.out.println(t.getName())); </code>
<code>// Lub </code>
<code>String name = therapy.map(Therapy::getName).orElse("Unknown");</code></code></pre>



<h2 class="wp-block-heading">Kiedy używać programowania funkcyjnego, a kiedy imperatywnego?</h2>



<h3 class="wp-block-heading">Użyj functional (streams, lambda):</h3>



<p class="wp-block-paragraph"> <strong>Transformacja danych:</strong></p>



<pre class="wp-block-code"><code>java

<code>List&lt;String> names = therapies.stream() </code>    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.map(Therapy::getName) </span>
    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.collect(Collectors.toList());</span></code></pre>



<p class="wp-block-paragraph"> <strong>Filtrowanie:</strong></p>



<pre class="wp-block-code"><code>java

<code>List&lt;Therapy> expensive = therapies.stream() </code>    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.filter(t -> t.getCost() > 70) </span>
    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.collect(Collectors.toList());</span></code></pre>



<p class="wp-block-paragraph"><strong>Agregacja:</strong></p>



<pre class="wp-block-code"><code>java

<code>double total = therapies.stream() </code>    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.mapToDouble(Therapy::getCost) </span>
    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.sum();</span></code></pre>



<h3 class="wp-block-heading">Użyj imperative (pętla for):</h3>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Wczesne wyjście (early exit):</strong></p>



<pre class="wp-block-code"><code>java

<code>for (Therapy t : therapies) { </code>     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">if (t.getName().equals("SI")) { </span>
         <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">return t; // Znalazłem, wychodzę </span>
     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">}</span>
<span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">}</span></code></pre>



<p class="wp-block-paragraph">(Stream też może: <code>.filter().findFirst()</code> ale pętla czytelniejsza)</p>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Modyfikacja elementów in-place:</strong></p>



<pre class="wp-block-code"><code>java

<code>for (Therapy t : therapies) {</code>    <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;"> t.markAsPaid(); // Zmieniam obiekt </span>
 <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">}</span></code></pre>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Proste iteracje:</strong></p>



<pre class="wp-block-code"><code>java

<code>for (int i = 0; i &lt; 10; i++) { </code>     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">System.out.println(i); </span>
 <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">}</span></code></pre>



<p class="wp-block-paragraph">(Stream: <code>IntStream.range(0, 10).forEach(System.out::println)</code> &#8211; przesada)</p>



<h2 class="wp-block-heading">Wydajność &#8211; czy streams są szybkie?</h2>



<h3 class="wp-block-heading">Benchmark test (100,000 elementów):</h3>



<p class="wp-block-paragraph"><strong>Pętla FOR:</strong></p>



<pre class="wp-block-code"><code>java

<code>// Czas: ~15ms </code>
<code>List&lt;Integer> result = new ArrayList&lt;>(); for (Integer num : numbers) {</code>       <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;"> if (num % 2 == 0) { </span>
           <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">result.add(num * 2); </span>
        <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">}</span>
  <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">}</span></code></pre>



<p class="wp-block-paragraph"><strong>Stream:</strong></p>



<pre class="wp-block-code"><code>java

<code>// Czas: ~25ms </code>
<code>List&lt;Integer> result = numbers.stream() </code>     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.filter(n -> n % 2 == 0) </span>
     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.map(n -> n * 2) </span>
     <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.collect(Collectors.toList());</span></code></pre>



<p class="wp-block-paragraph"><strong>Parallel stream:</strong></p>



<pre class="wp-block-code"><code>java

<code>// Czas: ~10ms (na multi-core!) </code>
<code>List&lt;Integer> result = numbers.parallelStream() </code>      <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.filter(n -> n % 2 == 0) </span>
      <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.map(n -> n * 2) </span>
      <span style="background-color: initial; color: rgb(240, 80, 110); font-family: inherit; font-size: 0.875rem; text-align: initial;">.collect(Collectors.toList());</span></code></pre>



<p class="wp-block-paragraph"><strong>Wnioski:</strong></p>



<ul class="wp-block-list">
<li>For pętla najszybsza dla prostych operacji</li>



<li>Stream ~30-50% wolniejszy (ogólnie)</li>



<li>Parallel stream może być najszybszy (jeśli CPU ma wiele rdzeni)</li>
</ul>



<p class="wp-block-paragraph"><strong>Ale:</strong> Różnica 10ms vs 25ms? W 99% aplikacji nieistotna. <strong>Czytelność &gt; Performance</strong> (chyba że przetwarzasz miliony rekordów).</p>



<h2 class="wp-block-heading">Co dalej &#8211; moja droga nauki</h2>



<p class="wp-block-paragraph">Po 17 tygodniach z Java (podstawy Zajavka + zaawansowane tematy):</p>



<p class="wp-block-paragraph"><strong>Decydowałam się:</strong> <strong>JavaScript!</strong></p>



<p class="wp-block-paragraph"><strong>Dlaczego nie Spring/zaawansowana Java:</strong></p>



<ul class="wp-block-list">
<li>Za ciężkie przy dzieciach i freelancingu</li>



<li>Potrzebuję czegoś bardziej natychmiast przydatnego</li>
</ul>



<p class="wp-block-paragraph"><strong>Dlaczego JavaScript:</strong></p>



<ul class="wp-block-list">
<li>Synergia z WordPress (mogę od razu stosować!)</li>



<li>Frontend umiejętności są rynkowe</li>



<li>Łatwiejszy balans życie/nauka</li>
</ul>



<p class="wp-block-paragraph"><strong>Ale Java była nieoceniona:</strong></p>



<ul class="wp-block-list">
<li>Nauczyła mnie OOP solidnie</li>



<li>Pokazała, że mogę uczyć się programowania</li>



<li>Dała fundamenty które pomogą w JS</li>
</ul>



<p class="wp-block-paragraph"><strong>Next:</strong> Learning Log #5 będzie o&#8230; JavaScript! Od Javy do JS &#8211; co jest podobne, co inne, pierwsze wrażenia.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Podsumowanie &#8211; tydzień 13-14</h2>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Nauczyłam się:</strong> Lambdy, Streams API, Optional, method references <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Napisałam:</strong> TherapyAnalyzer &#8211; realny użytek streams <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Zrozumiałam:</strong> Kiedy programowanie funkcyjne, kiedy imperative <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Odkryłam:</strong> Parallel streams (game changer dla dużych zbiorów!) <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Czas nauki:</strong> 12h w ciągu 2 tygodni (poprawiła się regularność!)</p>



<p class="wp-block-paragraph"><strong>Programowanie funkcyjne w Java początkowo:</strong> Hieroglify <br><strong>Programowanie funkcyjne w Java teraz:</strong> Potężne narzędzie które skraca kod 3x</p>



<p class="wp-block-paragraph"><strong>Czy było warto?</strong> Absolutnie. Stream API to must-know dla każdego Java developera.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><em>PS: Też uczysz się Java? Streams wydają Ci się trudne czy intuicyjne? A może przechodzisz z Javy na inny język? Zostaw komentarz &#8211; ciekawa jestem Waszych doświadczeń!</em></p>



<p class="wp-block-paragraph"></p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/programowanie-funkcyjne-java/">Learning Log #4: Strumienie, lambdy i funkcyjne programowanie w Java</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.danuta-cybulska.com/programowanie-funkcyjne-java/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Learning Log #3: Tydzień 12 Zajavka &#8211; interfejsy, klasy abstrakcyjne i koniec podstaw Java</title>
		<link>https://www.danuta-cybulska.com/learning-log-3-interfejsy-java-zajavka-koniec-podstaw/</link>
					<comments>https://www.danuta-cybulska.com/learning-log-3-interfejsy-java-zajavka-koniec-podstaw/#respond</comments>
		
		<dc:creator><![CDATA[Danuta]]></dc:creator>
		<pubDate>Wed, 18 Mar 2026 17:00:00 +0000</pubDate>
				<category><![CDATA[LearningLog]]></category>
		<category><![CDATA[Programowanie i Rozwój]]></category>
		<category><![CDATA[co dalej]]></category>
		<category><![CDATA[functional interface]]></category>
		<category><![CDATA[interfejsy Java]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[klasy abstrakcyjne Java]]></category>
		<category><![CDATA[koniec kursu]]></category>
		<category><![CDATA[learning log]]></category>
		<category><![CDATA[mama programuje]]></category>
		<category><![CDATA[multiple implementation]]></category>
		<category><![CDATA[nauka programowania]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Zajavka]]></category>
		<guid isPermaLink="false">https://www.danuta-cybulska.com/?p=5770</guid>

					<description><![CDATA[<p>Siedemnasty tydzień od startu z kursem Zajavka. Oficjalnie tydzień 12 &#8211; ostatni tydzień podstawowej części kursu. Kawa się parowała. Słuchawki na uszach. Dziecko spokojne. I ja, patrząc na ekran z napisem &#8222;Gratulacje! Udało Ci się ukończyć kurs podstawowy!&#8221; czułam&#8230; ulgę. I dumę. I lekki strach &#8222;co dalej?&#8221;. Interfejsy w Java brzmiały dla mnie przez długi...</p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-3-interfejsy-java-zajavka-koniec-podstaw/">Learning Log #3: Tydzień 12 Zajavka &#8211; interfejsy, klasy abstrakcyjne i koniec podstaw Java</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim" style="background-color:#9c8d60"></span><img decoding="async" width="2560" height="1708" src="https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-scaled.jpg" class="wp-block-cover__image-background wp-post-image" alt="interfejsy Java." data-object-fit="cover" data-object-position="51% 36%" style="object-position:51% 36%;" srcset="https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-scaled.jpg 2560w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-300x200.jpg 300w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-1024x683.jpg 1024w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-767x512.jpg 767w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-1536x1025.jpg 1536w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-2048x1366.jpg 2048w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-scaled-340x226.jpg 340w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-scaled-1696x1132.jpg 1696w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-scaled-848x566.jpg 848w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-scaled-740x494.jpg 740w, https://www.danuta-cybulska.com/wp-content/uploads/2026/02/a-minimalist-desktop-setup-featuring-a-laptop-keyboard-and-a-small-green-plant-on-a-vibrant-background.-16770262-scaled-370x247.jpg 370w" sizes="(max-width: 2560px) 100vw, 2560px" /><div class="wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained"><h2 style="background-color:#abb7c26e" class="has-text-align-center has-link-color wp-elements-12 wp-block-post-title has-text-color has-white-color has-background has-x-large-font-size">Learning Log #3: Tydzień 12 Zajavka &#8211; interfejsy, klasy abstrakcyjne i koniec podstaw Java</h2></div></div>



<p class="wp-block-paragraph">Siedemnasty tydzień od startu z kursem Zajavka. Oficjalnie tydzień 12 &#8211; ostatni tydzień podstawowej części kursu.</p>



<p class="wp-block-paragraph">Kawa się parowała. Słuchawki na uszach. Dziecko spokojne. I ja, patrząc na ekran z napisem &#8222;Gratulacje! Udało Ci się ukończyć kurs podstawowy!&#8221; czułam&#8230; ulgę. I dumę. I lekki strach &#8222;co dalej?&#8221;.</p>



<p class="wp-block-paragraph"><strong>Interfejsy w Java</strong> brzmiały dla mnie przez długi czas jak jakaś magiczna zaawansowana rzecz. Dziś wiem, że to jeden z najpotężniejszych narzędzi w OOP. I pokażę Wam dlaczego.</p>



<h2 class="wp-block-heading">Gdzie jestem w kursie Java?</h2>



<p class="wp-block-paragraph"><strong>Oficjalnie:</strong> Tydzień 12/12 kursu &#8222;Java w 12 tygodni Zajavka&#8221; &#8211; koniec podstaw ✓</p>



<p class="wp-block-paragraph"><strong>Realnie:</strong> 17 tygodni od startu (czyli ~4 miesiące kalendarzowe)</p>



<p class="wp-block-paragraph"><strong>Co dalej:</strong> Zajavka ma część zaawansowaną &#8211; Spring, bazy danych, REST API. Decyduję czy kontynuować czy przejść na JavaScript.</p>



<p class="wp-block-paragraph"><strong>Czas nauki w tym tygodniu:</strong> 10 godzin (wracam do formy!)</p>



<h2 class="wp-block-heading">Czym są interfejsy w Java? (w końcu rozumiem!)</h2>



<h3 class="wp-block-heading">Analogia która mi pomogła &#8211; umowa o pracę:</h3>



<p class="wp-block-paragraph">Wyobraź sobie że zatrudniasz pracownika. Nie obchodzi Cię:</p>



<ul class="wp-block-list">
<li>Jak dokładnie wykonuje pracę</li>



<li>Jakie narzędzia używa</li>



<li>Jaki ma proces myślowy</li>
</ul>



<p class="wp-block-paragraph">Obchodzi Cię tylko: <strong>czy potrafi zrobić to co potrzebujesz</strong>.</p>



<p class="wp-block-paragraph">Interfejs w Java to właśnie taka &#8222;umowa&#8221; &#8211; deklaracja &#8222;potrafię to i to&#8221; bez szczegółów &#8222;jak&#8221;.</p>



<h3 class="wp-block-heading">Przykład z życia &#8211; Payment:</h3>



<pre class="wp-block-code"><code>java<br><br>`// INTERFEJS = umowa public interface Payment { boolean processPayment(double amount); String getPaymentStatus(); }<br><br>// IMPLEMENTACJA 1 - Karta kredytowa public class CreditCardPayment implements Payment { private String cardNumber;<br><br>public CreditCardPayment(String cardNumber) {<br>    this.cardNumber = cardNumber;<br>}<br><br>@Override<br>public boolean processPayment(double amount) {<br>    System.out.println("Processing " + amount + " PLN via credit card");<br>    // Tutaj logika połączenia z operatorem kart<br>    return true;<br>}<br><br>@Override<br>public String getPaymentStatus() {<br>    return "Credit card payment successful";<br>}<br><br>}</code></pre>



<pre class="wp-block-code"><code>// IMPLEMENTACJA 2 - BLIK public class BlikPayment implements Payment { private String phoneNumber;<br><br>public BlikPayment(String phoneNumber) {<br>    this.phoneNumber = phoneNumber;<br>}<br><br>@Override<br>public boolean processPayment(double amount) {<br>    System.out.println("Processing " + amount + " PLN via BLIK");<br>    // Tutaj logika BLIK<br>    return true;<br>}<br><br>@Override<br>public String getPaymentStatus() {<br>    return "BLIK payment successful";<br>}<br><br>}<br><br>// UŻYCIE - najważniejsze! public class PaymentProcessor {<br><br>public void executePayment(Payment payment, double amount) {<br>    // Nie wiem CZY to karta, BLIK czy coś innego<br>    // Wiem tylko że payment POTRAFI processPayment()<br>    if (payment.processPayment(amount)) {<br>        System.out.println(payment.getPaymentStatus());<br>    }<br>}<br><br><br>}<br><br>// W praktyce: PaymentProcessor processor = new PaymentProcessor();<br><br>Payment creditCard = new CreditCardPayment("1234-5678"); Payment blik = new BlikPayment("123456789");<br><br>processor.executePayment(creditCard, 100.50); processor.executePayment(blik, 200.00);`</code></pre>



<h3 class="wp-block-heading">Co mnie zaskoczyło?</h3>



<p class="wp-block-paragraph"><strong>PaymentProcessor nie wie,</strong> czy dostaje kartę czy BLIK. Wie tylko że dostaje coś co implementuje <code>Payment</code>. I to wystarczy!</p>



<p class="wp-block-paragraph">To jest <strong>cała magia interfejsów</strong> &#8211; loose coupling, flexibility, extensibility.</p>



<h2 class="wp-block-heading">Dlaczego interfejsy są lepsze niż klasy abstrakcyjne?</h2>



<p class="wp-block-paragraph">To było moje największe &#8222;aha!&#8221; tego tygodnia.</p>



<h3 class="wp-block-heading">Klasa abstrakcyjna:</h3>



<pre class="wp-block-code"><code>java<br><br>`public abstract class Animal { protected String name;<br><br>public Animal(String name) {<br>    this.name = name;<br>}<br><br>public abstract void makeSound();<br><br>public void sleep() {  // Konkretna implementacja<br>    System.out.println(name + " is sleeping");<br>}<br><br><br>}<br><br>public class Dog extends Animal { public Dog(String name) { super(name); }<br><br>@Override<br>public void makeSound() {<br>    System.out.println("Woof!");<br>}<br><br><br>}`</code></pre>



<p class="wp-block-paragraph"><strong>Problem:</strong> Dog może dziedziczyć tylko z JEDNEJ klasy. Co jeśli Dog ma być też <code>Trainable</code>? Nie można.</p>



<h3 class="wp-block-heading">Interfejsy &#8211; <strong>wiele implementacji</strong>!</h3>



<pre class="wp-block-code"><code>java<br><br>`public interface Animal { void makeSound(); }<br><br>public interface Trainable { void train(String command); boolean isTraned(); }<br><br>public interface Playful { void play(); }<br><br>// Jedna klasa, WIELE interfejsów! public class Dog implements Animal, Trainable, Playful { private String name; private boolean trained = false;<br><br>@Override<br>public void makeSound() {<br>    System.out.println("Woof!");<br>}<br><br>@Override<br>public void train(String command) {<br>    System.out.println("Training: " + command);<br>    trained = true;<br>}<br><br>@Override<br>public boolean isTrained() {<br>    return trained;<br>}<br><br>@Override<br>public void play() {<br>    System.out.println("Playing fetch!");<br>}<br><br>}`</code></pre>



<p class="wp-block-paragraph"><strong>Java nie ma multiple inheritance (dziedziczenia wielokrotnego) ale ma multiple implementation (implementacji wielokrotnych)!</strong></p>



<p class="wp-block-paragraph">To rozwiązuje problem &#8222;co jeśli potrzebuję cech z wielu źródeł&#8221;.</p>



<h2 class="wp-block-heading">Kiedy używać czego? (moja ściąga)</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th class="has-text-align-left" data-align="left">Użyj INTERFEJSU gdy&#8230;</th><th class="has-text-align-left" data-align="left">Użyj KLASY ABSTRAKCYJNEJ gdy&#8230;</th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left">Określasz &#8222;co klasa potrafi&#8221;</td><td class="has-text-align-left" data-align="left">Definiujesz &#8222;czym klasa jest&#8221;</td></tr><tr><td class="has-text-align-left" data-align="left">Potrzebujesz wielu źródeł zachowań</td><td class="has-text-align-left" data-align="left">Masz wspólny kod do współdzielenia</td></tr><tr><td class="has-text-align-left" data-align="left">Chcesz loose coupling</td><td class="has-text-align-left" data-align="left">Masz silną relację hierarchiczną</td></tr><tr><td class="has-text-align-left" data-align="left">Przykład: Flyable, Swimmable, Payable</td><td class="has-text-align-left" data-align="left">Przykład: Animal, Vehicle, Shape</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Praktyczna zasada:</strong> Domyślnie używaj interfejsów. Klasy abstrakcyjne tylko, gdy naprawdę potrzebujesz współdzielić implementację.</p>



<h2 class="wp-block-heading">Mój projekt &#8211; Therapy Management System</h2>



<p class="wp-block-paragraph">Postanowiłam stworzyć coś użytecznego &#8211; system zarządzania terapiami mojego dziecka.</p>



<h3 class="wp-block-heading">Design z interfejsami:</h3>



<pre class="wp-block-code"><code>java<br><br>`// INTERFEJSY - umowy public interface Schedulable { LocalDateTime getDateTime(); int getDuration(); boolean reschedule(LocalDateTime newTime); }<br><br>public interface Billable { double getCost(); boolean isPaid(); void markAsPaid(); }<br><br>public interface Reportable { String generateReport(); Map&lt;String, Object> getStatistics(); }<br><br>// IMPLEMENTACJA - terapia ma wszystkie 3 cechy public class TherapySession implements Schedulable, Billable, Reportable { private String therapyType; // "SI", "Logopeda", "Pedagog" private LocalDateTime dateTime; private int durationMinutes; private double cost; private boolean paid; private String notes;<br><br>public TherapySession(String type, LocalDateTime dateTime, <br>                     int duration, double cost) {<br>    this.therapyType = type;<br>    this.dateTime = dateTime;<br>    this.durationMinutes = duration;<br>    this.cost = cost;<br>    this.paid = false;<br>}<br><br>// Schedulable methods<br>@Override<br>public LocalDateTime getDateTime() {<br>    return dateTime;<br>}<br><br>@Override<br>public int getDuration() {<br>    return durationMinutes;<br>}<br><br>@Override<br>public boolean reschedule(LocalDateTime newTime) {<br>    this.dateTime = newTime;<br>    System.out.println("Rescheduled to: " + newTime);<br>    return true;<br>}<br><br>// Billable methods<br>@Override<br>public double getCost() {<br>    return cost;<br>}<br><br>@Override<br>public boolean isPaid() {<br>    return paid;<br>}<br><br>@Override<br>public void markAsPaid() {<br>    this.paid = true;<br>    System.out.println("Marked as paid: " + cost + " PLN");<br>}<br><br>// Reportable methods<br>@Override<br>public String generateReport() {<br>    return String.format("Therapy: %s | Date: %s | Duration: %d min | Cost: %.2f PLN | Paid: %s",<br>        therapyType, dateTime, durationMinutes, cost, paid ? "Yes" : "No");<br>}<br><br>@Override<br>public Map&lt;String, Object> getStatistics() {<br>    Map&lt;String, Object> stats = new HashMap&lt;>();<br>    stats.put("type", therapyType);<br>    stats.put("duration", durationMinutes);<br>    stats.put("cost", cost);<br>    stats.put("paid", paid);<br>    return stats;<br>}<br><br>}<br><br>// MANAGEMENT CLASSES - pracują z interfejsami! public class BillingManager {<br><br>public double calculateTotalUnpaid(List&lt;Billable> items) {<br>    return items.stream()<br>        .filter(item -> !item.isPaid())<br>        .mapToDouble(Billable::getCost)<br>        .sum();<br>}<br><br>public void processPayments(List&lt;Billable> items) {<br>    items.stream()<br>        .filter(item -> !item.isPaid())<br>        .forEach(item -> {<br>            item.markAsPaid();<br>        });<br>}<br><br>}<br><br>public class ScheduleManager {<br><br>public List&lt;Schedulable> getUpcoming(List&lt;Schedulable> items) {<br>    LocalDateTime now = LocalDateTime.now();<br>    return items.stream()<br>        .filter(item -> item.getDateTime().isAfter(now))<br>        .sorted(Comparator.comparing(Schedulable::getDateTime))<br>        .toList();<br>}<br><br>}<br><br>public class ReportGenerator {<br><br>public void generateMonthlyReport(List&lt;Reportable> items) {<br>    System.out.println("=== MONTHLY REPORT ===");<br>    items.forEach(item -> {<br>        System.out.println(item.generateReport());<br>    });<br>}<br><br>}`</code></pre>



<h3 class="wp-block-heading">Użycie w praktyce:</h3>



<pre class="wp-block-code"><code>java<br><br>`public class Main { public static void main(String&#91;] args) { // Tworzę sesje terapii List&lt;TherapySession> sessions = new ArrayList&lt;>();<br><br>    sessions.add(new TherapySession("SI", <br>        LocalDateTime.of(2026, 3, 20, 14, 0), 60, 75.00));<br>    sessions.add(new TherapySession("Logopeda", <br>        LocalDateTime.of(2026, 3, 22, 10, 0), 45, 65.00));<br>    sessions.add(new TherapySession("Pedagog", <br>        LocalDateTime.of(2026, 3, 25, 15, 0), 60, 60.00));<br>    <br>    // Billing - obsługuje Billable<br>    BillingManager billing = new BillingManager();<br>    double unpaid = billing.calculateTotalUnpaid(<br>        new ArrayList&lt;>(sessions));  // TherapySession implements Billable!<br>    System.out.println("Total unpaid: " + unpaid + " PLN");<br>    <br>    // Schedule - obsługuje Schedulable<br>    ScheduleManager schedule = new ScheduleManager();<br>    List&lt;Schedulable> upcoming = schedule.getUpcoming(<br>        new ArrayList&lt;>(sessions));  // TherapySession implements Schedulable!<br>    System.out.println("Upcoming sessions: " + upcoming.size());<br>    <br>    // Reports - obsługuje Reportable<br>    ReportGenerator reports = new ReportGenerator();<br>    reports.generateMonthlyReport(<br>        new ArrayList&lt;>(sessions));  // TherapySession implements Reportable!<br>}<br><br>}<br><br><br>**Output:**<br><br>Total unpaid: 200.00 PLN Upcoming sessions: 3 === MONTHLY REPORT === Therapy: SI | Date: 2026-03-20T14:00 | Duration: 60 min | Cost: 75.00 PLN | Paid: No Therapy: Logopeda | Date: 2026-03-22T10:00 | Duration: 45 min | Cost: 65.00 PLN | Paid: No Therapy: Pedagog | Date: 2026-03-25T15:00 | Duration: 60 min | Cost: 60.00 PLN | Paid: No`</code></pre>



<h3 class="wp-block-heading">Dlaczego to jest piękne?</h3>



<p class="wp-block-paragraph"><code>BillingManager</code> nie wie, że pracuje z <code>TherapySession</code>. Wie tylko, że dostaje <code>Billable</code>.</p>



<p class="wp-block-paragraph">Jutro mogę dodać <code>DoctorVisit implements Billable</code> i <code>BillingManager</code> będzie działać BEZ ZMIAN!</p>



<p class="wp-block-paragraph"><strong>To jest siła interfejsów &#8211; rozszerzalność bez modyfikacji istniejącego kodu.</strong></p>



<h2 class="wp-block-heading">Default methods w interfejsach (Java 8+)</h2>



<p class="wp-block-paragraph">To mnie totalnie zaskoczyło &#8211; interfejsy mogą mieć implementację!</p>



<pre class="wp-block-code"><code>java<br><br>`public interface Reportable { String generateReport();<br><br>// DEFAULT METHOD - konkretna implementacja!<br>default void printReport() {<br>    System.out.println("=== REPORT ===");<br>    System.out.println(generateReport());<br>    System.out.println("==============");<br>}<br><br>default String getShortSummary() {<br>    String full = generateReport();<br>    return full.substring(0, Math.min(50, full.length())) + "...";<br>}<br><br>}`</code></pre>



<p class="wp-block-paragraph">Teraz każda klasa implementująca <code>Reportable</code> automatycznie dostaje <code>printReport()</code> i <code>getShortSummary()</code>!</p>



<p class="wp-block-paragraph"><strong>Kiedy używać:</strong></p>



<ul class="wp-block-list">
<li>Gdy większość implementacji będzie miała tą samą logikę</li>



<li>Gdy chcesz dodać metodę do interfejsu bez łamania istniejącego kodu</li>
</ul>



<h2 class="wp-block-heading">Typowe błędy które popełniłam</h2>



<h3 class="wp-block-heading">1. Zbyt duże interfejsy (<strong>zanieczyszczenie interfejsów</strong>)</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>java<br><br><code>public interface TherapyManagement { void schedule(); void reschedule(); void cancel(); double getCost(); void markAsPaid(); String generateReport(); void sendReminder(); void exportToCalendar(); // ... 20 metod później }</code></code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> To narusza ISP (Interface Segregation Principle &#8211; Zasada Segregacji Interfejsów ). Lepiej wiele małych interfejsów niż jeden wielki.</p>



<p class="wp-block-paragraph"><strong>Poprawka:</strong> Rozdziel na <code>Schedulable</code>, <code>Billable</code>, <code>Reportable</code>, <code>Notifiable</code>.</p>



<h3 class="wp-block-heading">2. Interfejs z jedną metodą bez sensu</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>java<br><br><code>public interface CanExist { boolean exists(); }</code></code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Nie każda metoda potrzebuje interfejsu. Czasem po prostu metoda w klasie wystarczy.</p>



<h3 class="wp-block-heading">3. Mieszanie abstrakcji</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>java<br><br><code>public interface Payment { boolean processPayment(double amount); void setCardNumber(String card); // Co jeśli to BLIK? Nie ma karty! }</code></code></pre>



<p class="wp-block-paragraph"><strong>Lekcja:</strong> Interfejs powinien opisywać zachowanie wspólne dla WSZYSTKICH implementacji.</p>



<h2 class="wp-block-heading">Functional Interfaces &#8211; bonus</h2>



<p class="wp-block-paragraph">Odkryłam że interfejs z JEDNĄ metodą abstrakcyjną to &#8222;functional interface&#8221; i może być użyty z lambda!</p>



<pre class="wp-block-code"><code>java<br><br>`@FunctionalInterface public interface TherapyCostCalculator { double calculate(int sessions, double pricePerSession); }<br><br>// Użycie z lambdą: TherapyCostCalculator standard = (sessions, price) -> sessions * price; TherapyCostCalculator withDiscount = (sessions, price) -> sessions * price * 0.9; // 10% discount<br><br>System.out.println("Standard: " + standard.calculate(8, 75)); // 600.0 System.out.println("Discount: " + withDiscount.calculate(8, 75)); // 540.0`</code></pre>



<p class="wp-block-paragraph">To otwiera drogę do <strong>programowania funkcyjnego</strong> w Java!</p>



<h2 class="wp-block-heading">Koniec podstaw Zajavka &#8211; co dalej?</h2>



<p class="wp-block-paragraph"><strong>Tydzień 12 = koniec fundamentów</strong>. Przeszłam przez:</p>



<ul class="wp-block-list">
<li>Podstawy składni Java</li>



<li>OOP (klasy, obiekty, dziedziczenie)</li>



<li>Agregacja i kompozycja</li>



<li><strong>Interfejsy i klasy abstrakcyjne</strong> ✓</li>
</ul>



<p class="wp-block-paragraph"><strong>Co dalej &#8211; moje opcje:</strong></p>



<h3 class="wp-block-heading">Opcja 1: Zajavka &#8211; poziom zaawansowany</h3>



<ul class="wp-block-list">
<li>Spring Framework</li>



<li>Hibernate / JPA</li>



<li>REST APIs</li>



<li>Microservices</li>
</ul>



<p class="wp-block-paragraph"><strong>Plusy:</strong> Kontynuacja, naturalny postęp, solidna backend-dev ścieżka <strong>Minusy:</strong> Jeszcze więcej Java, może za ciężkie przy dzieciach</p>



<h3 class="wp-block-heading">Opcja 2: JavaScript</h3>



<ul class="wp-block-list">
<li>Naturalny krok dla freelancerki WordPress</li>



<li>Synergia z moją pracą</li>



<li>Frontend interaktywność</li>
</ul>



<p class="wp-block-paragraph"><strong>Plusy:</strong> Praktyczne dla mojej kariery, lżejsze od Springa, już mam podstawy JS <strong>Minusy:</strong> Restart w kolejnym języku, powtarzanie podstaw</p>



<h3 class="wp-block-heading">Opcja 3: Konsolidacja + Budowa</h3>



<ul class="wp-block-list">
<li>Zatrzymać się na podstawach Java</li>



<li>Zbudować 2-3 solidne projekty</li>



<li>Pokazać portfolio</li>
</ul>



<p class="wp-block-paragraph"><strong>Plusy:</strong> Solidne fundamenty, działający kod <strong>Minusy:</strong> Może za mało dla ryneku pracy</p>



<p class="wp-block-paragraph"><strong>Moja decyzja:</strong> Myślę, że&#8230; <strong>JavaScript</strong>. Powody:</p>



<ol class="wp-block-list">
<li>Synergia z WordPress (mogę od razu używać w pracy!)</li>



<li>Łatwiejszy balans z dziećmi (dużo mniej ciężki niż Spring)</li>



<li>Frontend umiejętności są wartościowe</li>



<li>Zawsze mogę wrócić do Java później</li>
</ol>



<h2 class="wp-block-heading">Podsumowanie nauki Java &#8211; 17 tygodni</h2>



<p class="wp-block-paragraph"><strong>Co osiągnęłam:</strong> <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Podstawy składni Java &#8211; solidnie <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> OOP &#8211; rozumiem i używam <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Agregacja/kompozycja &#8211; odhaczone <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Interfejsy &#8211; w końcu rozumiem! <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 2 projekty robocze (Family system, Therapy Management)</p>



<p class="wp-block-paragraph"><strong>Statystyki:</strong></p>



<ul class="wp-block-list">
<li>17 tygodni (zamiast 12)</li>



<li>~120 godzin nauki całościowo</li>



<li>~7h tygodniowo średnio</li>



<li>2 pełne projekty</li>



<li>Setki linii kodu</li>
</ul>



<p class="wp-block-paragraph"><strong>Czy było warto? TAK.</strong> Java nauczyła mnie:</p>



<ul class="wp-block-list">
<li>Myślenia obiektowo</li>



<li>Projektowania systemów</li>



<li>Że mogę uczyć się programowania przy dzieciach</li>



<li>Że 1h dziennie wystarczy</li>
</ul>



<p class="wp-block-paragraph"><strong>Następny krok:</strong> Learning Log #4 będzie o&#8230; JavaScript albo <em>o PHP</em> (?!) ! Czekać na dalsze informacje.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><em>PS: Też kończycie kurs/etap nauki? Co dalej planujesz? Zostaw komentarz &#8211; ciekawa jestem Waszych ścieżek. A jeśli macie pytania o interfejsy w Java &#8211; pytajcie, teraz gdy w końcu rozumiem chętnie pomogę!</em></p>



<p class="wp-block-paragraph"></p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-3-interfejsy-java-zajavka-koniec-podstaw/">Learning Log #3: Tydzień 12 Zajavka &#8211; interfejsy, klasy abstrakcyjne i koniec podstaw Java</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.danuta-cybulska.com/learning-log-3-interfejsy-java-zajavka-koniec-podstaw/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Learning Log #2: Tydzień 10-11 Zajavka &#8211; agregacja, kompozycja i kiedy klasy się przyjaźnią</title>
		<link>https://www.danuta-cybulska.com/learning-log-2-agregacja-kompozycja-java-zajavka/</link>
					<comments>https://www.danuta-cybulska.com/learning-log-2-agregacja-kompozycja-java-zajavka/#respond</comments>
		
		<dc:creator><![CDATA[Danuta]]></dc:creator>
		<pubDate>Wed, 18 Feb 2026 17:00:00 +0000</pubDate>
				<category><![CDATA[LearningLog]]></category>
		<category><![CDATA[Programowanie i Rozwój]]></category>
		<category><![CDATA[agregacja Java]]></category>
		<category><![CDATA[has-a vs is-a]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[kompozycja Java]]></category>
		<category><![CDATA[kurs Java]]></category>
		<category><![CDATA[learning log]]></category>
		<category><![CDATA[mama programuje]]></category>
		<category><![CDATA[nauka Java]]></category>
		<category><![CDATA[OOP Java]]></category>
		<category><![CDATA[planowanie]]></category>
		<category><![CDATA[programowanie z dziećmi]]></category>
		<category><![CDATA[ProgramowanieJava]]></category>
		<category><![CDATA[relacje między klasami]]></category>
		<category><![CDATA[Zajavka]]></category>
		<guid isPermaLink="false">https://www.danuta-cybulska.com/?p=5759</guid>

					<description><![CDATA[<p>Kubek kawy numer trzy dzisiaj. Słuchawki na uszach. Dzieci w końcu się uspokoiły i bawią się same. Mam może godzinę. Tydzień 10 i 11 kursu Zajavka był&#8230; intensywny. Dwa tygodnie zajęło mi przebrnięcie przez materiał, który teoretycznie powinien zająć jeden. Ale wiesz co? I tak jestem z siebie dumna. Dziś o tym jak klasy współpracują...</p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-2-agregacja-kompozycja-java-zajavka/">Learning Log #2: Tydzień 10-11 Zajavka &#8211; agregacja, kompozycja i kiedy klasy się przyjaźnią</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-background-dim" style="background-color:#999d9e"></span><img loading="lazy" decoding="async" width="620" height="410" src="https://www.danuta-cybulska.com/wp-content/uploads/2026/01/12.png" class="wp-block-cover__image-background wp-post-image" alt="Zajavka" data-object-fit="cover" data-object-position="51% 36%" style="object-position:51% 36%;" srcset="https://www.danuta-cybulska.com/wp-content/uploads/2026/01/12.png 620w, https://www.danuta-cybulska.com/wp-content/uploads/2026/01/12-300x198.png 300w, https://www.danuta-cybulska.com/wp-content/uploads/2026/01/12-340x226.png 340w, https://www.danuta-cybulska.com/wp-content/uploads/2026/01/12-370x245.png 370w" sizes="(max-width: 620px) 100vw, 620px" /><div class="wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained"><h2 style="background-color:#abb7c26e" class="has-text-align-center has-link-color wp-elements-13 wp-block-post-title has-text-color has-white-color has-background has-x-large-font-size">Learning Log #2: Tydzień 10-11 Zajavka &#8211; agregacja, kompozycja i kiedy klasy się przyjaźnią</h2></div></div>



<p class="wp-block-paragraph">Kubek kawy numer trzy dzisiaj. Słuchawki na uszach. Dzieci w końcu się uspokoiły i bawią się same. Mam może godzinę.</p>



<p class="wp-block-paragraph"><strong>Tydzień 10 i 11 kursu Zajavka</strong> był&#8230; intensywny. Dwa tygodnie zajęło mi przebrnięcie przez materiał, który teoretycznie powinien zająć jeden. Ale wiesz co? I tak jestem z siebie dumna.</p>



<p class="wp-block-paragraph">Dziś o tym jak <strong>klasy współpracują ze sobą w Java</strong> &#8211; o agregacji, kompozycji i relacjach które sprawiają że kod przestaje być zbiorem przypadkowych kawałków, a zaczyna być&#8230; systemem.</p>



<h2 class="wp-block-heading">Gdzie jestem w kursie Java?</h2>



<p class="wp-block-paragraph"><strong>Oficjalnie:</strong> Tydzień 10-11 z kursu &#8222;Java w 12 tygodni Zajavka&#8221;</p>



<p class="wp-block-paragraph"><strong>Realnie:</strong> Gdzieś na 13-14 tygodniu od startu (pamiętajcie &#8211; życie z dziećmi ma swoje tempo)</p>



<p class="wp-block-paragraph"><strong>Postęp:</strong> ~65% kursu. Podstawy mam solidne, teraz wchodzę w zaawansowane OOP.</p>



<p class="wp-block-paragraph"><strong>Czas nauki:</strong> ~8 godzin w ostatnich dwóch tygodniach (mniej niż zwykle &#8211; dzieci były częściej wymagające)</p>



<h2 class="wp-block-heading">Co to jest agregacja i kompozycja?</h2>



<p class="wp-block-paragraph">Przez pierwszy dzień myślałam, że to jakaś magiczna zaawansowana rzecz. Potem zrozumiałam: to po prostu <strong>jak klasy trzymają inne klasy w sobie</strong>.</p>



<h3 class="wp-block-heading">Najprostsza analogia &#8211; mój dom:</h3>



<p class="wp-block-paragraph"><strong>Agregacja</strong> = Mebli w domu</p>



<ul class="wp-block-list">
<li>Dom MA meble</li>



<li>Meble mogą istnieć bez domu (można je przenieść)</li>



<li>Dom przestaje istnieć → meble dalej są</li>
</ul>



<p class="wp-block-paragraph"><strong>Kompozycja</strong> = Pokoje w domu</p>



<ul class="wp-block-list">
<li>Dom SKŁADA SIĘ Z pokoi</li>



<li>Pokoje nie mogą istnieć bez domu</li>



<li>Dom przestaje istnieć → pokoje też przestają</li>
</ul>



<h3 class="wp-block-heading">W kodzie Java:</h3>



<pre class="wp-block-code"><code>// AGREGACJA - słabszy związek
public class House {
    private List&lt;Furniture> furniture;  // meble mogą być w innym domu

    public House(List&lt;Furniture> furniture) {
        this.furniture = furniture;  // dostajemy meble z zewnątrz
    }
}

// KOMPOZYCJA - silny związek
public class House {
    private List&lt;Room> rooms;  // pokoje należą TYLKO do tego domu

    public House() {
        this.rooms = new ArrayList&lt;>();
        rooms.add(new Room("Bedroom"));  // tworzymy pokoje WEWNĄTRZ
        rooms.add(new Room("Kitchen"));
    }
}</code></pre>



<h2 class="wp-block-heading">Mój pierwszy projekt z agregacją &#8211; Family</h2>



<p class="wp-block-paragraph">Postanowiłam zrobić coś bliskiego sercu &#8211; system zarządzania rodziną (bo przecież mam doświadczenie <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f605.png" alt="😅" class="wp-smiley" style="height: 1em; max-height: 1em;" />).</p>



<pre class="wp-block-code"><code>public class Person {
    private String name;
    private int age;
    private String role;  // "parent", "child"

    public Person(String name, int age, String role) {
        this.name = name;
        this.age = age;
        this.role = role;
    }

    public String getName() {
        return name;
    }

    public String getRole() {
        return role;
    }

    @Override
    public String toString() {
        return name + " (" + age + " years, " + role + ")";
    }
}

public class Family {
    private String familyName;
    private List&lt;Person> members;  // AGREGACJA - osoby mogą istnieć poza rodziną

    public Family(String familyName) {
        this.familyName = familyName;
        this.members = new ArrayList&lt;>();
    }

    public void addMember(Person person) {
        members.add(person);
        System.out.println(person.getName() + " joined " + familyName + " family");
    }

    public void removeMember(Person person) {
        members.remove(person);
        System.out.println(person.getName() + " left the family");
    }

    public void showFamily() {
        System.out.println(familyName + " Family:");
        for (Person member : members) {
            System.out.println("  - " + member);
        }
    }

    public List&lt;Person> getParents() {
        return members.stream()
                .filter(p -> p.getRole().equals("parent"))
                .toList();
    }
}

// Użycie:
public class Main {
    public static void main(String&#91;] args) {
        Person mom = new Person("Anna", 32, "parent");
        Person dad = new Person("Marek", 34, "parent");
        Person child1 = new Person("Kasia", 5, "child");
        Person child2 = new Person("Tomek", 3, "child");

        Family smiths = new Family("Smith");
        smiths.addMember(mom);
        smiths.addMember(dad);
        smiths.addMember(child1);
        smiths.addMember(child2);

        smiths.showFamily();
        // Output:
        // Smith Family:
        //   - Anna (32 years, parent)
        //   - Marek (34 years, parent)
        //   - Kasia (5 years, child)
        //   - Tomek (3 years, child)
    }
}
</code></pre>



<h3 class="wp-block-heading">Co mnie zaskoczyło?</h3>



<p class="wp-block-paragraph">To że <strong>osoby (Person) nie wiedzą o rodzinie (Family)</strong>. Mogą istnieć osobno. Mogą być w kilku rodzinach jednocześnie (np. rozszerzona rodzina). To jest cała idea agregacji!</p>



<h2 class="wp-block-heading">Kompozycja &#8211; silniejszy związek</h2>



<p class="wp-block-paragraph">Kompozycja to, gdy obiekt <strong>nie może istnieć bez swojego &#8222;rodzica&#8221;</strong>.</p>



<h3 class="wp-block-heading">Mój przykład &#8211; Therapy Session</h3>



<pre class="wp-block-code"><code>public class TherapySession {
    private String type;  // "SI", "logopeda", "pedagog"
    private LocalDateTime dateTime;
    private int durationMinutes;

    // Konstruktor pakietowy - tylko TherapySchedule może tworzyć sesje
    TherapySession(String type, LocalDateTime dateTime, int durationMinutes) {
        this.type = type;
        this.dateTime = dateTime;
        this.durationMinutes = durationMinutes;
    }

    @Override
    public String toString() {
        return type + " therapy on " + dateTime + " (" + durationMinutes + " min)";
    }
}

public class TherapySchedule {
    private String childName;
    private List&lt;TherapySession> sessions;  // KOMPOZYCJA

    public TherapySchedule(String childName) {
        this.childName = childName;
        this.sessions = new ArrayList&lt;>();  // tworzymy listę TUTAJ
    }

    public void addSession(String type, LocalDateTime dateTime, int duration) {
        // Tworzymy sesję WEWNĄTRZ harmonogramu
        TherapySession session = new TherapySession(type, dateTime, duration);
        sessions.add(session);
        System.out.println("Added: " + session);
    }

    public void showSchedule() {
        System.out.println("Therapy schedule for " + childName + ":");
        sessions.forEach(System.out::println);
    }

    public int getTotalHoursThisMonth() {
        return sessions.stream()
                .mapToInt(s -> s.durationMinutes)
                .sum() / 60;
    }
}

// Użycie:
TherapySchedule schedule = new TherapySchedule("Michaś");
schedule.addSession("SI", LocalDateTime.now().plusDays(1), 60);
schedule.addSession("Logopeda", LocalDateTime.now().plusDays(2), 45);
schedule.addSession("Pedagog", LocalDateTime.now().plusDays(3), 60);

schedule.showSchedule();
// Output:
// Therapy schedule for Michaś:
// SI therapy on 2026-02-19T14:30 (60 min)
// Logopeda therapy on 2026-02-20T10:00 (45 min)
// Pedagog therapy on 2026-02-21T15:00 (60 min)</code></pre>



<h3 class="wp-block-heading">Różnica kluczowa:</h3>



<p class="wp-block-paragraph">W agregacji <code>Person</code> jest tworzony <strong>NA ZEWNĄTRZ</strong> i przekazywany do <code>Family</code>.</p>



<p class="wp-block-paragraph">W kompozycji <code>TherapySession</code> jest tworzony <strong>WEWNĄTRZ</strong> <code>TherapySchedule</code>.</p>



<h2 class="wp-block-heading">Relacje między klasami &#8211; has-a vs is-a</h2>



<p class="wp-block-paragraph">To był dla mnie moment &#8222;aha!&#8221; tego tygodnia.</p>



<h3 class="wp-block-heading">IS-A = dziedziczenie (inheritance)</h3>



<pre class="wp-block-code"><code>public class Animal {
    String name;
}

public class Dog extends Animal {
    // Dog IS-A Animal
}</code></pre>



<h3 class="wp-block-heading">HAS-A = agregacja/kompozycja</h3>



<pre class="wp-block-code"><code>public class Person {
    String name;
}

public class House {
    Person owner;  // House HAS-A Person
}</code></pre>



<p class="wp-block-paragraph"><strong>Kiedy używać czego?</strong></p>



<p class="wp-block-paragraph"><strong>IS-A</strong> gdy mówimy: &#8222;X jest typem Y&#8221;</p>



<ul class="wp-block-list">
<li>Pies jest zwierzęciem</li>



<li>Samochód elektryczny jest samochodem</li>



<li>Student jest osobą</li>
</ul>



<p class="wp-block-paragraph"><strong>HAS-A</strong> gdy mówimy: &#8222;X ma Y&#8221; lub &#8222;X składa się z Y&#8221;</p>



<ul class="wp-block-list">
<li>Osoba ma adres</li>



<li>Samochód ma silnik</li>



<li>Harmonogram ma sesje terapii</li>
</ul>



<h2 class="wp-block-heading">Typowe błędy, które popełniłam</h2>



<h3 class="wp-block-heading">1. Mylenie agregacji z kompozycją</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>public class Family {
    private List&lt;Person> members = new ArrayList&lt;>();

    public void addMember(String name, int age) {
        members.add(new Person(name, age));  // To jest kompozycja!
    }
}</code></pre>



<p class="wp-block-paragraph"><strong>Poprawka:</strong></p>



<pre class="wp-block-code"><code>public class Family {
    private List&lt;Person> members = new ArrayList&lt;>();

    public void addMember(Person person) {  // Agregacja - dostajemy obiekt z zewnątrz
        members.add(person);
    }
}</code></pre>



<h3 class="wp-block-heading">2. Publiczny konstruktor w kompozycji</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>public class TherapySession {
    public TherapySession(...) { }  // Każdy może tworzyć sesje!
}</code></pre>



<p class="wp-block-paragraph"><strong>Poprawka:</strong></p>



<pre class="wp-block-code"><code>public class TherapySession {
    TherapySession(...) { }  // Package-private - tylko TherapySchedule może tworzyć
}</code></pre>



<h3 class="wp-block-heading">3. Zapomnienie o null safety</h3>



<p class="wp-block-paragraph"><strong>Błąd:</strong></p>



<pre class="wp-block-code"><code>public void showFamily() {
    for (Person member : members) {  // Co jeśli members jest null?
        System.out.println(member);
    }
}</code></pre>



<p class="wp-block-paragraph"><strong>Poprawka:</strong></p>



<pre class="wp-block-code"><code>public void showFamily() {
    if (members == null || members.isEmpty()) {
        System.out.println("No family members");
        return;
    }
    members.forEach(System.out::println);
}</code></pre>



<h2 class="wp-block-heading">Praktyczne zastosowanie &#8211; mój mini projekt</h2>



<p class="wp-block-paragraph">Zbudowałam system do <strong>śledzenia kosztów terapii</strong> (bardzo przydatne w moim życiu!).</p>



<p class="wp-block-paragraph"><strong>Klasy:</strong></p>



<ul class="wp-block-list">
<li><code>Therapy</code> &#8211; pojedyncza terapia (typ, koszt jednostkowy)</li>



<li><code>TherapySession</code> &#8211; konkretna sesja (data, czas trwania)</li>



<li><code>Child</code> &#8211; dziecko (ma listę terapii &#8211; <strong>agregacja</strong>)</li>



<li><code>MonthlyReport</code> &#8211; raport miesięczny (tworzy sesje wewnątrz &#8211; <strong>kompozycja</strong>)</li>
</ul>



<pre class="wp-block-code"><code>public class Therapy {
    private String type;
    private double costPerSession;

    public Therapy(String type, double costPerSession) {
        this.type = type;
        this.costPerSession = costPerSession;
    }

    public double getCostPerSession() {
        return costPerSession;
    }

    public String getType() {
        return type;
    }
}

public class Child {
    private String name;
    private List&lt;Therapy> therapies;  // AGREGACJA

    public Child(String name) {
        this.name = name;
        this.therapies = new ArrayList&lt;>();
    }

    public void enrollInTherapy(Therapy therapy) {
        therapies.add(therapy);
    }

    public double calculateMonthlyCost(int sessionsPerTherapy) {
        return therapies.stream()
                .mapToDouble(t -> t.getCostPerSession() * sessionsPerTherapy)
                .sum();
    }
}</code></pre>



<p class="wp-block-paragraph"><strong>Rezultat:</strong> Mam working code, który pokazuje mi że:</p>



<ul class="wp-block-list">
<li>2x terapia SI po 75 zł = 600 zł/mies (8 sesji)</li>



<li>2x logopeda po 65 zł = 520 zł/mies (8 sesji)</li>



<li>1x pedagog po 60 zł = 240 zł/mies (4 sesje)</li>



<li><strong>Total: 1360 zł/mies</strong></li>
</ul>



<p class="wp-block-paragraph">Bonus: Kod, który faktycznie rozwiązuje mój realny problem!</p>



<h2 class="wp-block-heading">Nauka Java z życiem w tle</h2>



<h3 class="wp-block-heading">Jak wyglądały te dwa tygodnie:</h3>



<p class="wp-block-paragraph"><strong>Tydzień 10:</strong></p>



<ul class="wp-block-list">
<li>Dzieci niewymagające wzmożonej uwagi = 6h nauki</li>



<li>4x po godzinie + 2h w weekend</li>



<li>Zbudowałam Family system</li>
</ul>



<p class="wp-block-paragraph"><strong>Tydzień 11:</strong></p>



<ul class="wp-block-list">
<li>Dziecko wymagające uwagi = 2h nauki</li>



<li>Tylko wieczory gdy spało</li>



<li>Dokończyłam Therapy cost tracker</li>
</ul>



<p class="wp-block-paragraph"><strong>Total:</strong> 8h na 2 tygodnie = mniej niż zwykle</p>



<p class="wp-block-paragraph"><strong>Reakcja:</strong> Mogłam się stresować, że &#8222;za wolno&#8221;. Zamiast tego myślę: &#8222;8h to 8h więcej niż zero. Progress!&#8221;</p>



<h3 class="wp-block-heading">Co pomaga, gdy czas jest ograniczony:</h3>



<ol class="wp-block-list">
<li><strong>Małe cele</strong> &#8211; nie &#8222;skończę tydzień 10&#8221;, ale &#8222;zrozumiem agregację dziś&#8221;</li>



<li><strong>Praktyczne projekty</strong> &#8211; Family, Therapy &#8211; rzeczy z mojego życia</li>



<li><strong>Notatki głosowe</strong> &#8211; gdy dziecko się budzi, a ja mam pomysł</li>



<li><strong>Akceptacja</strong> &#8211; niektóre dni = zero nauki. I to OK.</li>
</ol>



<h2 class="wp-block-heading">Plany na tydzień 12</h2>



<p class="wp-block-paragraph">Przede mną:</p>



<ul class="wp-block-list">
<li><strong>Interfejsy</strong> &#8211; co to i dlaczego</li>



<li><strong>Abstrakcyjne klasy</strong> &#8211; kiedy używać</li>



<li><strong>Polimorfizm</strong> &#8211; ostatecznie zrozumieć</li>
</ul>



<p class="wp-block-paragraph"><strong>Kurs Java Zajavka</strong> powoli zbliża się do końca podstawowej części. Czuję że solidne fundamenty są już położone.</p>



<h2 class="wp-block-heading">Dla kogo jest ten learning log?</h2>



<p class="wp-block-paragraph">To nie jest tutorial &#8222;jak programować w Java&#8221;. To jest <strong>real talk o nauce programowania jako mama</strong>.</p>



<p class="wp-block-paragraph">Jeśli:</p>



<ul class="wp-block-list">
<li>Uczysz się przy dzieciach</li>



<li>Masz 5-10h tygodniowo, nie 40h</li>



<li>Czasem tydzień mija bez linii kodu</li>



<li>Zastanawiasz się &#8222;czy to w ogóle ma sens&#8221;</li>
</ul>



<p class="wp-block-paragraph"><strong>To TAK, ma sens.</strong> 8h to 8h. Progress nie musi być liniowy.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Podsumowanie tygodnia 10-11</h2>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Nauczyłam się:</strong> Agregacja, kompozycja, relacje między klasami <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Napisałam:</strong> Family system, Therapy cost tracker (working code!) <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Zrozumiałam:</strong> HAS-A vs IS-A, kiedy używać agregacji a kiedy kompozycji<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Walczę z:</strong> Null safety, poprawne projektowanie relacji <br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Czas nauki:</strong> 8h w ciągu 2 tygodni (mniej przez chorobę dziecka)</p>



<p class="wp-block-paragraph"><strong>Następny Learning Log:</strong> Tydzień 12 &#8211; interfejsy i abstrakcyjne klasy. Zapisz się do newslettera, żeby nie przegapić!</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><em>PS: Też walczysz z nauką przy dzieciach? Też masz tygodnie gdzie zero czasu? Napisz w komentarzu &#8211; przypomnimy sobie nawzajem że nie jesteśmy sami. A jeśli masz pytania o agregację, kompozycję czy Zajavka &#8211; pytaj śmiało!</em></p>



<p class="wp-block-paragraph"></p>
<p>Artykuł <a href="https://www.danuta-cybulska.com/learning-log-2-agregacja-kompozycja-java-zajavka/">Learning Log #2: Tydzień 10-11 Zajavka &#8211; agregacja, kompozycja i kiedy klasy się przyjaźnią</a> pochodzi z serwisu <a href="https://www.danuta-cybulska.com">To co najważniejsze</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.danuta-cybulska.com/learning-log-2-agregacja-kompozycja-java-zajavka/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
