<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Lukasz-zielinski.pl - Blog o programowaniu i karierze w IT</title>
    <link>https://lukasz-zielinski.pl</link>
    <description>Chcesz pisać lepszy kod, nadążać za technologiami i rozwijać karierę w IT? Czytaj o decyzjach, które ułatwiają ci codzienną pracę i zawodowy rozwój.</description>
    <language>pl</language>
    <pubDate>Wed, 11 Nov 2026 17:35:00 +0100</pubDate>
    <lastBuildDate>Wed, 11 Nov 2026 17:35:00 +0100</lastBuildDate>
    <item>
      <title>Polecenia SQL bez tajemnic - DDL, DML, DQL, DCL i TCL</title>
      <link>https://lukasz-zielinski.pl/polecenia-sql-bez-tajemnic-ddl-dml-dql-dcl-i-tcl</link>
      <description>Polecenia SQL w praktyce: poznaj DDL, DML, DQL, DCL i TCL, unikaj zmian bez WHERE i sprawdź różnice między bazami.</description>
      <content:encoded><![CDATA[<head></head><p>Kończysz zapytanie, naciskasz „uruchom” i nagle tabela jest pusta albo zmieniły się wiersze, których nie planujesz ruszać. Polecenia SQL zwykle dzieli się na grupy według ich funkcji, ale ta klasyfikacja nie zawsze jest formalnym podziałem języka ani gwarancją, że każde polecenie zadziała tak samo w każdej bazie.</p>

<p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/28f4b11ce8b77311ea236ea7dcbde7c3/sql-commands-cheat-sheet-ddl-dml-dql-dcl-tcl-diagram.webp" class="image article-image" loading="lazy" alt="Diagram klasyfikuje polecenia SQL: DDL (CREATE, ALTER), DML (SELECT, INSERT), DCL (GRANT) i TCL (COMMIT)."></p>

<div class="short-summary">
  <h2 id="najpierw-ustal-czy-polecenie-czyta-dane-zmienia-je-czy-zmienia-strukture">Najpierw ustal, czy polecenie czyta dane, zmienia je czy zmienia strukturę</h2>
  <ul>
    <li><strong>SELECT</strong> odczytuje dane, a <strong>INSERT</strong>, <strong>UPDATE</strong> i <strong>DELETE</strong> zmieniają wiersze.</li>
    <li><strong>CREATE</strong>, <strong>ALTER</strong> i <strong>DROP</strong> dotyczą obiektów bazy, takich jak tabele.</li>
    <li><strong>WHERE</strong> ogranicza zakres modyfikacji, ale jego brak może oznaczać zmianę lub usunięcie wszystkich wierszy.</li>
    <li><strong>BEGIN</strong>, <strong>COMMIT</strong> i <strong>ROLLBACK</strong> pomagają kontrolować transakcję, choć zachowanie zależy od silnika bazy.</li>
    <li><strong>LIMIT</strong> i niektóre inne elementy składni różnią się między systemami.</li>
  </ul>
</div>

<h2 id="piec-grup-porzadkuje-polecenia-ale-nie-jest-scisla-klasyfikacja-sql">Pięć grup porządkuje polecenia, ale nie jest ścisłą klasyfikacją SQL</h2>
<p>Gdy czytasz zestawienie poleceń, skróty <strong>DDL, DML, DQL, DCL i TCL</strong> pomagają szybko rozpoznać ich rolę. Traktuj je jednak jako praktyczny podział dydaktyczny, a nie uniwersalną taksonomię narzuconą przez standard SQL.</p>
<p>Przykładowo <code>SELECT</code> bywa opisywany jako DQL, czyli język zapytań, choć w części materiałów zalicza się go do szerszej grupy DML. Sama nazwa kategorii mniej pomaga niż odpowiedź na pytanie: <strong>czy polecenie czyta dane, zmienia rekordy, strukturę, uprawnienia czy stan transakcji?</strong></p>
<p>Uważam, że początkującej osobie bardziej przyda się rozpoznawanie skutków komendy niż zapamiętywanie skrótów. W praktyce te skutki są widoczne już w nazwie polecenia i jego klauzulach.</p>

<h2 id="select-insert-update-i-delete-obsluguja-codzienna-prace-z-rekordami">SELECT, INSERT, UPDATE i DELETE obsługują codzienną pracę z rekordami</h2>
<p>Najczęściej zaczynasz od odczytu. <code>SELECT</code> pobiera wskazane kolumny z tabeli, a <code>WHERE</code> zawęża wynik do wierszy spełniających warunek:</p>
<pre><code>SELECT email, status
FROM users
WHERE status = 'active';</code></pre>
<p>Gdy wstawiasz nowe dane, używasz <code>INSERT INTO</code>; gdy zmieniasz istniejące, <code>UPDATE</code>; gdy usuwasz wiersze, <code>DELETE</code>. W tych dwóch ostatnich poleceniach warunek wymaga szczególnej uwagi: bez <code>WHERE</code> aktualizacja lub usunięcie obejmie całą tabelę. Dokumentacja <a href="https://www.postgresql.org/docs/current/dml-delete.html" target="_blank" rel="noopener noreferrer nofollow">PostgreSQL</a> wyraźnie pokazuje, że <code>DELETE FROM products;</code> usuwa wszystkie wiersze.</p>
<pre><code>UPDATE users
SET status = 'inactive'
WHERE last_login &lt; DATE '2024-01-01';

DELETE FROM sessions
WHERE expires_at &lt; CURRENT_TIMESTAMP;</code></pre>
<p>Przed wykonaniem zmiany możesz użyć warunku z polecenia modyfikującego w osobnym <code>SELECT</code>, by zobaczyć, które rekordy pasują. Przy odczycie większych zbiorów ograniczaj też liczbę zwracanych wierszy, ale pamiętaj, że składnia limitu różni się między bazami.</p>

<h2 id="create-alter-i-drop-zmieniaja-strukture-bazy">CREATE, ALTER i DROP zmieniają strukturę bazy</h2>
<a href="https://lukasz-zielinski.pl/alter-table-bez-niespodzianek-jak-bezpiecznie-zmienic-tabele">Dodanie kolumny</a> nie zmienia pojedynczego rekordu, lecz samą tabelę. Polecenia z grupy <strong>DDL</strong> tworzą, modyfikują lub usuwają obiekty bazy, takie jak tabele, widoki i indeksy.
<table>
  <tbody>
    <tr><th>Polecenie</th><th>Skutek</th><th>Przykład</th></tr>
    <tr><td><code>CREATE</code></td><td>Tworzy obiekt</td><td><code>CREATE TABLE tasks (id INTEGER, title VARCHAR(200));</code></td></tr>
    <tr><td><code>ALTER</code></td><td>Zmienia istniejący obiekt</td><td><code>ALTER TABLE tasks ADD COLUMN done BOOLEAN;</code></td></tr>
    <tr><td><code>DROP</code></td><td>Usuwa obiekt</td><td><code>DROP TABLE tasks;</code></td></tr>
    <tr><td><code>TRUNCATE</code></td><td>Opróżnia tabelę</td><td><code>TRUNCATE TABLE tasks;</code></td></tr>
  </tbody>
</table>
<p><code>DROP TABLE</code> usuwa tabelę jako obiekt, a <code>TRUNCATE</code> usuwa jej zawartość, pozostawiając samą tabelę. Nie zakładaj jednak, że <code>TRUNCATE</code> to po prostu szybszy <code>DELETE</code>: może inaczej działać z wyzwalaczami, kluczami obcymi i transakcjami.</p>

<h2 id="commit-nie-zawsze-cofnie-zmiane-w-strukturze-tabeli">COMMIT nie zawsze cofnie zmianę w strukturze tabeli</h2>
<p>Transakcja grupuje operacje, które mają zostać zatwierdzone razem. <code>BEGIN</code> rozpoczyna blok, <code>COMMIT</code> zatwierdza zmiany, a <code>ROLLBACK</code> wycofuje niezakończoną transakcję; dokładne zachowanie zależy jednak od systemu bazy i rodzaju polecenia.</p>
<pre><code>BEGIN;

UPDATE accounts
SET balance = balance - 50
WHERE account_id = 17;

UPDATE accounts
SET balance = balance + 50
WHERE account_id = 42;

COMMIT;</code></pre>
<p>Tu oba przelewy są częścią jednej transakcji, więc nie powinien zostać zatwierdzony tylko jeden z nich. W PostgreSQL bez jawnego bloku każde poprawne polecenie działa domyślnie w osobnej transakcji. Inaczej trzeba myśleć o MySQL: w MySQL 8.4 wiele poleceń DDL, w tym <code>ALTER TABLE</code>, <code>DROP TABLE</code> i <code>TRUNCATE TABLE</code>, powoduje niejawne zatwierdzenie aktywnej transakcji. Opisuje to dokumentacja <a href="https://dev.mysql.com/doc/refman/8.4/en/implicit-commit.html" target="_blank" rel="noopener noreferrer nofollow">MySQL 8.4 Reference Manual</a>.</p>
<p>Wniosek jest praktyczny: przed zmianą struktury nie polegaj na <code>ROLLBACK</code> jako uniwersalnym „cofnij”. Sprawdź zachowanie konkretnego silnika i rodzaju polecenia, zanim wykonasz je na ważnej bazie.</p>

<h2 id="klauzule-i-dialekt-decyduja-o-tym-co-naprawde-wykona-baza">Klauzule i dialekt decydują o tym, co naprawdę wykona baza</h2>
<p>Dwie komendy mogą wyglądać niemal identycznie, a mimo to różnić się składnią albo szczegółami działania. Na przykład do ograniczania liczby wierszy PostgreSQL i MySQL obsługują <code>LIMIT</code>, natomiast w Microsoft SQL Server spotkasz między innymi <code>TOP</code> lub składnię <code>OFFSET ... FETCH</code>. Dokumentacja <a href="https://www.postgresql.org/docs/current/sql-select.html" target="_blank" rel="noopener noreferrer nofollow">polecenia SELECT w PostgreSQL</a> zaznacza, że <code>LIMIT</code> i <code>OFFSET</code> są składnią specyficzną dla PostgreSQL, używaną również przez MySQL.</p>
<p>Równie ważna jest kolejność klauzul. <code>WHERE</code> filtruje wiersze przed grupowaniem, a <code>HAVING</code> pozwala filtrować wyniki grupowania. Jeśli zapytanie zawiera <code>ORDER BY</code> i ograniczenie wyników, sortowanie powinno poprzedzać limit, by wynik nie zależał od przypadkowej kolejności zwróconych rekordów.</p>
<table>
  <tbody>
    <tr><th>Sytuacja</th><th>Możliwy skutek</th><th>Co zrobić</th></tr>
    <tr><td><code>UPDATE</code> lub <code>DELETE</code> bez <code>WHERE</code></td><td>Zmiana albo usunięcie wszystkich wierszy tabeli</td><td>Uruchom najpierw <code>SELECT</code> z planowanym warunkiem</td></tr>
    <tr><td><code>LIMIT</code> odrzucony przez bazę</td><td>Składnia nie pasuje do dialektu</td><td>Sprawdź dokumentację używanego systemu i zastosuj jego składnię limitowania</td></tr>
    <tr><td><code>ROLLBACK</code> po poleceniu DDL w MySQL</td><td>Zmiana mogła już zatwierdzić wcześniejszą transakcję</td><td>Zweryfikuj zasady niejawnego zatwierdzania przed wykonaniem DDL</td></tr>
    <tr><td>Wynik z <code>LIMIT</code> bez stabilnego sortowania</td><td>Przy kolejnych wykonaniach mogą pojawić się inne wiersze</td><td>Dodaj <code>ORDER BY</code> po kolumnie zapewniającej przewidywalną kolejność</td></tr>
  </tbody>
</table>
<p>Jeśli przenosisz zapytanie między bazami, zacznij od sprawdzenia <strong>składni limitowania, obsługi transakcji i poleceń DDL</strong>. To te różnice najłatwiej przeoczyć w kodzie, który na pierwszy rzut oka wygląda przenośnie.</p>

<h2 id="bezpieczny-nawyk-zaczyna-sie-przed-uruchomieniem-komendy">Bezpieczny nawyk zaczyna się przed uruchomieniem komendy</h2>
<p>Przed zmianą danych przeczytaj polecenie od końca: czy warunek wskazuje właściwe rekordy, czy tabela jest poprawna i czy sesja działa w oczekiwanym trybie transakcji. Przy niepewnym <code>UPDATE</code> lub <code>DELETE</code> najpierw uruchom odpowiadający mu <code>SELECT</code>, a przy większej zmianie sprawdź możliwość odtworzenia danych z kopii.</p>
<p><strong>Najpierw rozpoznaj skutek, potem wykonuj.</strong> Gdy wiesz, czy komenda odczytuje rekordy, modyfikuje je, zmienia strukturę czy steruje transakcją, łatwiej przewidzieć zarówno wynik zapytania, jak i moment, w którym zmiany staną się trwałe.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Bazy danych</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/f8c5cb29a495a336391ecd7c40dff7bc/polecenia-sql-bez-tajemnic-ddl-dml-dql-dcl-i-tcl.webp"/>
      <pubDate>Wed, 11 Nov 2026 17:35:00 +0100</pubDate>
    </item>
    <item>
      <title>Confluence w firmie - jak uporządkować wiedzę zespołu?</title>
      <link>https://lukasz-zielinski.pl/confluence-w-firmie-jak-uporzadkowac-wiedze-zespolu</link>
      <description>Confluence porządkuje wiedzę zespołu, ale wymaga dobrej struktury. Sprawdź, jak zacząć, połączyć go z Jira i uniknąć problemów z dostępem.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Na spotkaniu kto&#347; wrzuca decyzj&#281; do czatu, tydzie&#324; p&oacute;&#378;niej nikt nie pami&#281;ta, gdzie jej szuka&#263;. <strong>Confluence to narz&#281;dzie Atlassian do tworzenia i porz&#261;dkowania firmowej wiedzy</strong>, cho&#263; sama platforma nie sprawi, &#380;e dokumentacja b&#281;dzie aktualna ani &#322;atwa do znalezienia.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/2a125eaea9e0d57fd8718e3467ac5905/atlassian-confluence-page-editor-workspace-screenshot-spaces-pages-team-documentation.webp" class="image article-image" loading="lazy" alt="Strona g&#322;&oacute;wna Banc.ly Marketing. Zobacz, co to jest Confluence, poznaj zesp&oacute;&#322; i &#347;led&#378; OKRs."></p><div class="short-summary">
  <h2 id="confluence-porzadkuje-wiedze-zespolu-jesli-wiadomo-co-i-gdzie-zapisywac">Confluence porz&#261;dkuje wiedz&#281; zespo&#322;u, je&#347;li wiadomo, co i gdzie zapisywa&#263;</h2>
  <ul>
    <li><strong>Strony</strong> s&#322;u&#380;&#261; do dokumentacji, notatek, instrukcji i plan&oacute;w.</li>
    <li><strong>Przestrzenie</strong> grupuj&#261; strony wed&#322;ug zespo&#322;u, produktu lub projektu.</li>
    <li><strong>Jira &#347;ledzi prac&#281;</strong>, a Confluence przechowuje jej kontekst i wiedz&#281;.</li>
    <li><strong>Plan Free</strong> nie pozwala konfigurowa&#263; uprawnie&#324; do przestrzeni ani stron.</li>
    <li><strong>Nieaktualne tre&#347;ci</strong> i niejasna struktura potrafi&#261; zmieni&#263; wiki w trudny do przeszukania magazyn.</li>
  </ul>
</div><h2 id="confluence-zamienia-rozproszone-notatki-w-firmowa-baze-wiedzy">Confluence zamienia rozproszone notatki w firmow&#261; baz&#281; wiedzy</h2><p>W praktyce Confluence przypomina firmow&#261; wiki: zesp&oacute;&#322; tworzy strony, &#322;&#261;czy je ze sob&#261; i uk&#322;ada w przestrzeniach. Mo&#380;esz tam opisa&#263; spos&oacute;b uruchomienia projektu, decyzj&#281; architektoniczn&#261; albo instrukcj&#281; wdro&#380;enia nowej osoby. <strong>Informacja ma zosta&#263; po spotkaniu</strong>, a nie znikn&#261;&#263; w historii czatu.</p><p>Strona mo&#380;e mie&#263; histori&#281; zmian, komentarze i za&#322;&#261;czniki. W zale&#380;no&#347;ci od konfiguracji dost&#281;pne s&#261; te&#380; inne typy tre&#347;ci, na przyk&#322;ad tablice do wsp&oacute;lnego szkicowania czy bazy danych do porz&#261;dkowania informacji. Uwa&#380;am, &#380;e dla zespo&#322;u IT najbardziej przydatne s&#261; dobrze utrzymane instrukcje i opisy decyzji, bo pomagaj&#261; odtworzy&#263; nie tylko &bdquo;co robimy&rdquo;, lecz tak&#380;e &bdquo;dlaczego&rdquo;.</p><h2 id="przestrzen-porzadkuje-strony-ale-nie-zastepuje-dobrego-nazewnictwa">Przestrze&#324; porz&#261;dkuje strony, ale nie zast&#281;puje dobrego nazewnictwa</h2><p>Gdy dokumentacja ro&#347;nie, &#322;atwo wpa&#347;&#263; w pu&#322;apk&#281; tworzenia osobnej przestrzeni dla ka&#380;dej drobnej sprawy. Prostszy uk&#322;ad zwykle lepiej znosi zmiany: przestrze&#324; dla produktu lub zespo&#322;u, a w niej strony dotycz&#261;ce wdro&#380;e&#324;, architektury i procedur. <strong>Strona odpowiada za konkretn&#261; tre&#347;&#263;, przestrze&#324; za jej szerszy kontekst</strong>.</p><p>Przyk&#322;adowo, w przestrzeni zespo&#322;u platformowego mo&#380;esz umie&#347;ci&#263; instrukcj&#281; lokalnego uruchomienia us&#322;ugi, decyzj&#281; o wyborze kolejki oraz procedur&#281; obs&#322;ugi incydentu. Ka&#380;dy temat powinien mie&#263; w&#322;asn&#261; stron&#281; z jasnym tytu&#322;em i w&#322;a&#347;cicielem, czyli osob&#261; odpowiedzialn&#261; za jej aktualno&#347;&#263;. Bez tego wyszukiwanie przypomina przegl&#261;danie szuflady z kablami: co&#347; tam jest, ale trudno zgadn&#261;&#263; co.</p><h2 id="jira-pilnuje-zadan-a-confluence-przechowuje-ich-kontekst">Jira pilnuje zada&#324;, a Confluence przechowuje ich kontekst</h2><p>W Jira zesp&oacute;&#322; &#347;ledzi zg&#322;oszenia, statusy i prac&#281; do wykonania. Confluence s&#322;u&#380;y do opisu wiedzy, kt&oacute;ra nie mie&#347;ci si&#281; w samym zadaniu: wymaga&#324;, ustale&#324;, instrukcji czy uzasadnienia decyzji. Atlassian opisuje t&#281; r&oacute;&#380;nic&#281; w dokumentacji integracji: przestrzenie Jira gromadz&#261; elementy pracy, a przestrzenie Confluence strony i inne tre&#347;ci.</p><p>Przyk&#322;ad jest prosty: zg&#322;oszenie w Jira mo&#380;e dotyczy&#263; wdro&#380;enia nowego mechanizmu logowania, a powi&#261;zana strona w Confluence wyja&#347;nia jego za&#322;o&#380;enia i ograniczenia. Je&#347;li zesp&oacute;&#322; ma g&#322;&oacute;wnie zadania do &#347;ledzenia, zacznij od Jira; je&#347;li potrzebuje wsp&oacute;lnego miejsca na dokumentacj&#281; i ustalenia, przyda si&#281; Confluence. <strong>Przy pracy projektowej oba narz&#281;dzia uzupe&#322;niaj&#261; si&#281;</strong>, ale nie musisz wdra&#380;a&#263; ich jednocze&#347;nie.</p><h2 id="plan-free-moze-ujawnic-tresci-osobom-ktorym-nie-chcesz-ich-pokazywac">Plan Free mo&#380;e ujawni&#263; tre&#347;ci osobom, kt&oacute;rym nie chcesz ich pokazywa&#263;</h2><p>Tu &#322;atwo o b&#322;&#281;dne za&#322;o&#380;enie: ma&#322;y zesp&oacute;&#322; mo&#380;e zacz&#261;&#263; bezp&#322;atnie, ale w planie Free uprawnienia do stron i przestrzeni nie s&#261; konfigurowalne. Wed&#322;ug dokumentacji <a href="https://support.atlassian.com/confluence-cloud/docs/learn-about-confluence-cloud-plans/" target="_blank" rel="noopener noreferrer nofollow">Atlassian dotycz&#261;cej plan&oacute;w Confluence Cloud</a>, osoby maj&#261;ce dost&#281;p do instancji Free mog&#261; przegl&#261;da&#263; i edytowa&#263; jej przestrzenie oraz tre&#347;ci.</p><p>Je&#347;li w tej samej instancji maj&#261; znale&#378;&#263; si&#281; materia&#322;y dla ca&#322;ego zespo&#322;u i dokumenty przeznaczone dla w&#261;skiej grupy, sprawd&#378; ustawienia dost&#281;pu przed publikacj&#261;. W planach, kt&oacute;re pozwalaj&#261; zarz&#261;dza&#263; dost&#281;pem, uprawnienia obejmuj&#261; poziom ca&#322;ej witryny, przestrzeni oraz konkretnej tre&#347;ci. <strong>Ograniczenie strony nie daje jej szerszego dost&#281;pu ni&#380; przestrze&#324;, w kt&oacute;rej si&#281; znajduje</strong>, wi&#281;c b&#322;&#281;dny uk&#322;ad na wy&#380;szym poziomie mo&#380;e utrudni&#263; ochron&#281; pojedynczego dokumentu.</p><table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Co mo&#380;e by&#263; przyczyn&#261;</th>
      <th scope="col">Co zrobi&#263;</th>
    </tr>
    <tr>
      <td>Ka&#380;da osoba z dost&#281;pem do instancji mo&#380;e edytowa&#263; tre&#347;ci</td>
      <td>Instancja korzysta z planu Free</td>
      <td>Nie umieszczaj tam materia&#322;&oacute;w wymagaj&#261;cych odr&#281;bnych uprawnie&#324;; sprawd&#378; plan i konfiguracj&#281; dost&#281;pu</td>
    </tr>
    <tr>
      <td>Osoba nadal widzi stron&#281; mimo ograniczenia</td>
      <td>Uprawnienie mo&#380;e wynika&#263; z innej grupy lub poziomu dost&#281;pu</td>
      <td>Sprawd&#378; dost&#281;p do ca&#322;ej witryny, przestrzeni i strony oraz cz&#322;onkostwo w grupach</td>
    </tr>
    <tr>
      <td>Nowa osoba nie mo&#380;e otworzy&#263; dokumentacji zespo&#322;u</td>
      <td>Mo&#380;e nie mie&#263; dost&#281;pu do w&#322;a&#347;ciwej przestrzeni</td>
      <td>Popro&#347; administratora przestrzeni o sprawdzenie uprawnie&#324;</td>
    </tr>
  </tbody>
</table><h2 id="dokumentacja-dziala-gdy-strony-maja-wlascicieli-i-date-przegladu">Dokumentacja dzia&#322;a, gdy strony maj&#261; w&#322;a&#347;cicieli i dat&#281; przegl&#261;du</h2><p>Najcz&#281;stszy problem z firmow&#261; wiki nie wynika z braku funkcji, tylko z tego, &#380;e stare instrukcje zostaj&#261; obok aktualnych, a nikt nie wie, kt&oacute;rej ufa&#263;. Podobne zastrze&#380;enia wracaj&#261; w dyskusjach u&#380;ytkownik&oacute;w: wsp&oacute;&#322;praca jest wygodna, dop&oacute;ki porz&#261;dek i aktualno&#347;&#263; tre&#347;ci nie wymkn&#261; si&#281; zespo&#322;owi spod kontroli. <strong>W&#322;a&#347;ciciel strony oraz termin przegl&#261;du</strong> pomagaj&#261; unikn&#261;&#263; dokumentacji, kt&oacute;ra wygl&#261;da wiarygodnie, ale prowadzi do nieaktualnych krok&oacute;w.</p><p>Przy tworzeniu strony zapisz, do kogo jest skierowana, kto za ni&#261; odpowiada i kiedy nale&#380;y j&#261; sprawdzi&#263; ponownie. Dla instrukcji wdro&#380;eniowej sensownym wyzwalaczem przegl&#261;du mo&#380;e by&#263; zmiana procesu lub narz&#281;dzia, a nie arbitralna data. Dzi&#281;ki temu zesp&oacute;&#322; nie aktualizuje wszystkiego r&oacute;wnie cz&#281;sto, tylko wraca do tre&#347;ci wtedy, gdy zmieniaj&#261; si&#281; warunki jej u&#380;ycia.</p><h2 id="najlepszy-start-to-jedna-przestrzen-i-dokumentacja-codziennej-pracy">Najlepszy start to jedna przestrze&#324; i dokumentacja codziennej pracy</h2><p>Je&#347;li zesp&oacute;&#322; dopiero poznaje Confluence, zacznij od jednej przestrzeni i kilku stron, po kt&oacute;re ludzie rzeczywi&#347;cie si&#281;gaj&#261;: instrukcji uruchomienia projektu, zasad wdra&#380;ania zmian i opisu decyzji technicznych. <strong>Prosty uk&#322;ad &#322;atwiej utrzyma&#263;</strong> ni&#380; rozbudowan&#261; struktur&#281;, kt&oacute;rej nikt nie aktualizuje.</p><p>Wyb&oacute;r narz&#281;dzia sam w sobie nie uporz&#261;dkuje wiedzy. Gdy ka&#380;da strona ma jasny cel, w&#322;a&#347;ciciela i sensowne miejsce, Confluence mo&#380;e ograniczy&#263; powracaj&#261;ce pytania i u&#322;atwi&#263; przekazywanie pracy mi&#281;dzy osobami. Je&#347;li brakuje tych zasad, nawet najlepsza wiki szybko stanie si&#281; kolejnym miejscem do szukania informacji.</p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>Kariera i biznes IT</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/ece45f9372dfa5adf19e074ed4c999c9/confluence-w-firmie-jak-uporzadkowac-wiedze-zespolu.webp"/>
      <pubDate>Wed, 11 Nov 2026 17:19:00 +0100</pubDate>
    </item>
    <item>
      <title>Selektor klasy CSS nie działa? Sprawdź, gdzie jest błąd</title>
      <link>https://lukasz-zielinski.pl/selektor-klasy-css-nie-dziala-sprawdz-gdzie-jest-blad</link>
      <description>Selektor klasy CSS nie działa? Sprawdź nazwy klas, spacje, specyficzność i kaskadę. Poznaj prosty sposób diagnozy problemu.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Przycisk na stronie nie zmienia koloru, cho&#263; regu&#322;a CSS wygl&#261;da poprawnie. Cz&#281;sto winna jest liter&oacute;wka w nazwie klasy albo selektor, kt&oacute;ry przegrywa z inn&#261; regu&#322;&#261;, ale czasem problem le&#380;y w samym HTML-u.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/0278e8b9389be57d27f864eb2bfff3ec/css-class-selector-html-element-example-code-editor.webp" class="image article-image" loading="lazy" alt="Fragment kodu CSS pokazuj&#261;cy, jak selektory (w tym klasy) wp&#322;ywaj&#261; na wygl&#261;d tekstu."></p><div class="short-summary">
  <h2 id="klasy-pozwalaja-stylowac-elementy-bez-wiazania-wygladu-z-nazwa-tagu">Klasy pozwalaj&#261; stylowa&#263; elementy bez wi&#261;zania wygl&#261;du z nazw&#261; tagu</h2>
  <ul>
    <li><strong>Kropka w CSS</strong> wskazuje selektor klasy, na przyk&#322;ad <code>.button</code>.</li>
    <li><strong>Spacje w HTML</strong> rozdzielaj&#261; klasy przypisane do jednego elementu.</li>
    <li><strong>Wielko&#347;&#263; liter</strong> w nazwach klas ma znaczenie: <code>.Card</code> i <code>.card</code> to r&oacute;&#380;ne selektory.</li>
    <li><strong>Prosty selektor</strong> &#322;atwiej nadpisa&#263; ni&#380; rozbudowan&#261; regu&#322;&#281; o wysokiej specyficzno&#347;ci.</li>
  </ul>
</div><h2 id="selektor-klasy-zaczyna-sie-od-kropki-a-atrybut-html-juz-nie">Selektor klasy zaczyna si&#281; od kropki, a atrybut HTML ju&#380; nie</h2><p>W HTML przypisujesz elementowi nazw&#281; przez atrybut <code>class</code>, a w CSS poprzedzasz t&#281; nazw&#281; kropk&#261;. To drobna r&oacute;&#380;nica, ale w&#322;a&#347;nie na niej potykaj&#261; si&#281; osoby, kt&oacute;re pierwszy raz &#322;&#261;cz&#261; oba pliki.</p><pre><code><button class="button button-primary">Zapisz</button>

.button {
  padding: 0.75rem 1rem;
  border: 0;
}

.button-primary {
  background: #174ea6;
  color: white;
}</code></pre><p>Jeden element mo&#380;e mie&#263; kilka klas, rozdzielonych spacjami. W przyk&#322;adzie przycisk dostaje wsp&oacute;lne odst&#281;py z <code>.button</code> oraz kolor z <code>.button-primary</code>. <strong>W HTML nie stawiasz kropek</strong>: zapis <code>class=".button"</code> oznacza&#322;by nazw&#281; klasy zawieraj&#261;c&#261; kropk&#281;, a nie klas&#281; &bdquo;button&rdquo;.</p><p>Selektor <code>.button</code> pasuje do elementu, kt&oacute;rego lista klas zawiera dok&#322;adnie nazw&#281; <code>button</code>. Dlatego <code>.btn</code> nie zadzia&#322;a na elemencie z <code>class="button"</code>, nawet je&#347;li nazwy wydaj&#261; si&#281; podobne. Zasady dopasowania opisuje <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/Class_selectors" target="_blank" rel="noopener noreferrer nofollow">dokumentacja selektor&oacute;w klas MDN</a>.</p><h2 id="sprawdz-nazwe-i-dopasowanie-zanim-zmienisz-deklaracje-css">Sprawd&#378; nazw&#281; i dopasowanie, zanim zmienisz deklaracje CSS</h2><p>Gdy styl nie dzia&#322;a, dok&#322;adanie kolejnych w&#322;a&#347;ciwo&#347;ci zwykle tylko zaciemnia spraw&#281;. Najpierw por&oacute;wnaj nazw&#281; klasy w HTML-u z selektorem, a potem sprawd&#378;, czy regu&#322;a w og&oacute;le pasuje do elementu.</p><table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Mo&#380;liwa przyczyna</th>
      <th scope="col">Co zrobi&#263;</th>
    </tr>
    <tr>
      <td>HTML ma <code>class="card"</code>, CSS ma <code>.cards</code></td>
      <td>Nazwy s&#261; r&oacute;&#380;ne</td>
      <td>Ujednoli&#263; nazw&#281; w HTML-u lub CSS-ie.</td>
    </tr>
    <tr>
      <td>HTML ma <code>class="Card"</code>, CSS ma <code>.card</code></td>
      <td>Inna wielko&#347;&#263; liter</td>
      <td>Popraw zapis tak, aby by&#322; identyczny po obu stronach.</td>
    </tr>
    <tr>
      <td>HTML ma <code>class="card featured"</code>, regu&#322;a to <code>.card.featured</code></td>
      <td>Selektor wymaga obu klas na tym samym elemencie</td>
      <td>Dodaj brakuj&#261;c&#261; klas&#281; albo u&#380;yj samego <code>.card</code>, je&#347;li ma pasowa&#263; do wszystkich kart.</td>
    </tr>
    <tr>
      <td>Regu&#322;a pasuje, lecz kolor si&#281; nie zmienia</td>
      <td>Inna deklaracja wygrywa w kaskadzie</td>
      <td>Sprawd&#378; aktywne regu&#322;y i specyficzno&#347;&#263; w panelu Styles narz&#281;dzi deweloperskich.</td>
    </tr>
    <tr>
      <td>Nazwa klasy zaczyna si&#281; od cyfry albo zawiera znak specjalny</td>
      <td>Selektor mo&#380;e wymaga&#263; ucieczki znaku</td>
      <td>Najpro&#347;ciej zmieni&#263; nazw&#281; na identyfikator zaczynaj&#261;cy si&#281; od litery, np. <code>item-123</code>.</td>
    </tr>
  </tbody>
</table><p>Rozr&oacute;&#380;nij te&#380; dwa zapisy, kt&oacute;re wygl&#261;daj&#261; niemal identycznie. <code>.card.featured</code> wybiera element maj&#261;cy obie klasy, a <code>.card .featured</code> szuka elementu z klas&#261; <code>featured</code> wewn&#261;trz elementu z klas&#261; <code>card</code>. Jedna spacja zmienia cel selektora.</p><h2 id="jedna-klasa-ma-specyficznosc-0-1-0-ale-kontekst-moze-ja-podbic">Jedna klasa ma specyficzno&#347;&#263; 0-1-0, ale kontekst mo&#380;e j&#261; podbi&#263;</h2><p>Gdy dwie regu&#322;y ustawiaj&#261; t&#281; sam&#261; w&#322;a&#347;ciwo&#347;&#263; dla tego samego elementu, przegl&#261;darka rozstrzyga konflikt wed&#322;ug kaskady. Specyficzno&#347;&#263; selektora to jeden z element&oacute;w tego rozstrzygni&#281;cia: <code>.card</code> ma warto&#347;&#263; <strong>0-1-0</strong>, a <code>article.card</code> ma <strong>0-1-1</strong>, bo dochodzi selektor elementu.</p><pre><code>.card {
  color: #222;
}

article.card {
  color: #174ea6;
}</code></pre><p>Je&#347;li element to <code><article class="card"></article></code>, obie regu&#322;y pasuj&#261;, ale druga ma wi&#281;ksz&#261; specyficzno&#347;&#263;. Z kolei <code>#app .card</code> wygrywa z nimi przez selektor ID. Algorytm i przyk&#322;ady opisuje specyfikacja <a href="https://www.w3.org/TR/selectors-4/#specificity-rules" target="_blank" rel="noopener noreferrer nofollow">Selectors Level 4</a>.</p><p><strong>Regu&#322;a praktyczna:</strong> je&#347;li nowa klasa ma zmienia&#263; jeden element niezale&#380;nie od jego otoczenia, zacznij od selektora klasy, na przyk&#322;ad <code>.card-title</code>. Gdy musisz dopisa&#263; kilka poziom&oacute;w zagnie&#380;d&#380;enia albo <code>!important</code>, zanim styl zacznie dzia&#322;a&#263;, najpierw sprawd&#378; istniej&#261;cy konflikt. Uwa&#380;am, &#380;e proste selektory s&#261; &#322;atwiejsze w utrzymaniu, bo kolejna osoba mo&#380;e je nadpisa&#263; bez rozpl&#261;tywania ca&#322;ego &#322;a&#324;cucha.</p><h2 id="nazwy-klas-opisuj-rola-elementu-a-stan-trzymaj-osobno">Nazwy klas opisuj rol&#261; elementu, a stan trzymaj osobno</h2><p>Klasa <code>.red</code> m&oacute;wi, jak co&#347; wygl&#261;da, lecz niewiele m&oacute;wi o tym, czym jest. Je&#347;li projekt zmieni kolor przycisku, nazwa przestanie pasowa&#263; do jego funkcji; <code>.button-danger</code> albo <code>.button-primary</code> lepiej opisuje zastosowanie.</p><p>Popularnym uporz&#261;dkowanym schematem jest BEM. W jego konwencji <code>card__title</code> oznacza element bloku &bdquo;card&rdquo;, a <code>card--featured</code> jego modyfikator. Dokumentacja <a href="https://bem.info/en/methodology/naming-convention/" target="_blank" rel="noopener noreferrer nofollow">konwencji nazewniczej BEM</a> podkre&#347;la, &#380;e nazwa ma wskazywa&#263; blok, element lub modyfikator, nie przypadkowy kolor.</p><p>Przyk&#322;ad w HTML-u mo&#380;e wygl&#261;da&#263; tak: <code><article class="card card--featured"></article></code>. Pierwsza klasa zapewnia bazowy wygl&#261;d komponentu, druga sygnalizuje jego wariant. To czytelniejsze ni&#380; osobny zestaw zupe&#322;nie niezwi&#261;zanych klas dla ka&#380;dej odmiany karty.</p><h2 id="wybierz-konwencje-wedlug-skali-projektu-nie-mody">Wybierz konwencj&#281; wed&#322;ug skali projektu, nie mody</h2><p>W ma&#322;ym &#263;wiczeniu wystarcz&#261; nazwy takie jak <code>.button</code> i <code>.button-primary</code>. Przy kilku wsp&oacute;&#322;dzielonych komponentach pomaga BEM lub inna konsekwentna konwencja; w aplikacji korzystaj&#261;cej z CSS Modules nazwy klas mog&#261; by&#263; lokalne dla pliku, co ogranicza przypadkowe kolizje.</p><p>Je&#347;li budujesz niewielk&#261; stron&#281;, nie wdra&#380;aj rozbudowanej metodologii tylko po to, by nazwy wygl&#261;da&#322;y &bdquo;profesjonalnie&rdquo;. Gdy wiele os&oacute;b rozwija wsp&oacute;lny interfejs, wybierz jedn&#261; zasad&#281; nazewnictwa i trzymaj si&#281; jej w nowych komponentach. Najgorszy uk&#322;ad to mieszanka, w kt&oacute;rej <code>.blue</code> opisuje kolor, <code>.header-item</code> struktur&#281;, a <code>.active</code> stan, bez wsp&oacute;lnego porz&#261;dku.</p><h2 id="najpierw-upewnij-sie-ze-klasa-trafia-w-element">Najpierw upewnij si&#281;, &#380;e klasa trafia w element</h2><p>Przy problemie ze stylem przejd&#378; kr&oacute;tk&#261; &#347;cie&#380;k&#281;: sprawd&#378; zgodno&#347;&#263; nazwy, obecno&#347;&#263; klasy na w&#322;a&#347;ciwym elemencie, spacje w selektorze i regu&#322;y konkuruj&#261;ce o t&#281; sam&#261; w&#322;a&#347;ciwo&#347;&#263;. Dopiero potem zmieniaj specyficzno&#347;&#263;. Taka kolejno&#347;&#263; cz&#281;sto pozwala naprawi&#263; CSS bez dok&#322;adania kolejnych wyj&#261;tk&oacute;w.</p><p>Je&#347;li selektor jest poprawny, ale zmiana wci&#261;&#380; nie dzia&#322;a, panel Styles w DevTools poka&#380;e, kt&oacute;ra deklaracja wygrywa i sk&#261;d pochodzi. <strong>Najpierw napraw dopasowanie albo konflikt</strong>, a dopiero potem zdecyduj, czy nazewnictwo klas potrzebuje wi&#281;kszego porz&#261;dku.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Frontend i UX</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/90d7d37b8a2d20602617feceb4964c02/selektor-klasy-css-nie-dziala-sprawdz-gdzie-jest-blad.webp"/>
      <pubDate>Tue, 10 Nov 2026 11:07:00 +0100</pubDate>
    </item>
    <item>
      <title>Klasy w Pythonie bez pułapek - self, instancje i dataclass</title>
      <link>https://lukasz-zielinski.pl/klasy-w-pythonie-bez-pulapek-self-instancje-i-dataclass</link>
      <description>Klasy w Pythonie: poznaj self, instancje i dataclass, wybierz klasę lub słownik i unikaj współdzielonego stanu. Sprawdź poradnik.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Masz kilka zada&#324; do wykonania, a ka&#380;de ma w&#322;asny status, dane i metod&#281; zmiany stanu. Klasa w <a href="https://lukasz-zielinski.pl/python-print-od-podstaw-sep-end-i-roznica-miedzy-print-a-return">Python</a>ie zwykle dobrze porz&#261;dkuje taki kod, cho&#263; przy jednym prostym rekordzie s&#322;ownik mo&#380;e by&#263; l&#380;ejszym wyborem.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/552680ab2b8228d3e85f84cf81627810/python-class-instance-diagram-self-attributes-methods.webp" class="image article-image" loading="lazy" alt="Schemat ilustruj&#261;cy klas&#281; " human w pythonie z atrybutami age height weight i metodami sleep od kt pochodz obiekty person></p><div class="short-summary">
  <h2 id="klasa-laczy-stan-obiektu-z-operacjami-ktore-na-nim-wykonujesz">Klasa &#322;&#261;czy stan obiektu z operacjami, kt&oacute;re na nim wykonujesz</h2>
  <ul>
    <li><strong>Klasa</strong> opisuje wsp&oacute;ln&#261; struktur&#281; i zachowanie obiekt&oacute;w.</li>
    <li><strong>Instancja</strong> to pojedynczy obiekt utworzony na podstawie klasy.</li>
    <li><strong>self</strong> wskazuje instancj&#281;, na kt&oacute;rej dzia&#322;a metoda.</li>
    <li><strong>Dataclass</strong> ogranicza powtarzalny kod, gdy obiekt g&#322;&oacute;wnie przechowuje dane.</li>
    <li><strong>S&#322;ownik</strong> cz&#281;sto wystarczy, gdy struktura danych jest ma&#322;a lub zmienna.</li>
  </ul>
</div><h2 id="klasa-opisuje-typ-obiektu-a-instancja-przechowuje-wlasny-stan">Klasa opisuje typ obiektu, a instancja przechowuje w&#322;asny stan</h2><p>Wyobra&#378; sobie dwa zadania o tym samym zestawie p&oacute;l: nazwie i statusie. <strong>Klasa</strong> opisuje, jakie dane i operacje maj&#261; by&#263; dost&#281;pne, a ka&#380;da utworzona instancja przechowuje w&#322;asne warto&#347;ci.</p><p>W definicji zapisujesz metody, czyli funkcje zwi&#261;zane z klas&#261;. Gdy wywo&#322;ujesz metod&#281; przez obiekt, Python przekazuje t&#281; instancj&#281; jako pierwszy argument. Dlatego <code>job.finish()</code> mo&#380;na rozumie&#263; jako wywo&#322;anie <code>Job.finish(job)</code>, co opisuje <a href="https://docs.python.org/3/tutorial/classes.html" target="_blank" rel="noopener noreferrer nofollow">oficjalny samouczek Pythona</a>.</p><p>Ten mechanizm sprawia, &#380;e metoda mo&#380;e zmienia&#263; stan w&#322;a&#347;ciwego obiektu. Bez tej wi&#281;zi &#322;atwo sko&#324;czy&#263; z funkcjami, kt&oacute;rym za ka&#380;dym razem trzeba przekazywa&#263; ten sam zestaw powi&#261;zanych danych.</p><h2 id="wystarcza-trzy-elementy-zeby-utworzyc-i-uzyc-obiektu">Wystarcz&#261; trzy elementy, &#380;eby utworzy&#263; i u&#380;y&#263; obiektu</h2><p>Najprostsza klasa potrzebuje nazwy, metody <code>__init__</code> ustawiaj&#261;cej pocz&#261;tkowe dane oraz metody opisuj&#261;cej dzia&#322;anie obiektu. W przyk&#322;adzie zadanie zmienia status z &bdquo;oczekuj&#261;ce&rdquo; na &bdquo;gotowe&rdquo;.</p><pre><code>class Job:
    def __init__(self, name):
        self.name = name
        self.status = "oczekuj&#261;ce"

    def finish(self):
        self.status = "gotowe"

job = Job("Raport")
job.finish()

print(job.name)    # Raport
print(job.status)  # gotowe</code></pre><p><code>self</code> nie jest specjalnym s&#322;owem kluczowym. To powszechnie u&#380;ywana nazwa pierwszego argumentu metody, kt&oacute;r&#261; opisuje <a href="https://docs.python.org/3/faq/programming.html" target="_blank" rel="noopener noreferrer nofollow">FAQ dokumentacji Pythona</a>. Mimo &#380;e technicznie mo&#380;na wybra&#263; inn&#261; nazw&#281;, trzymaj si&#281; <code>self</code>, bo dzi&#281;ki temu kod jest czytelny dla innych os&oacute;b.</p><p>Jest tu te&#380; pu&#322;apka, kt&oacute;ra ujawnia si&#281; dopiero przy kilku obiektach. Je&#347;li lista mia&#322;aby by&#263; atrybutem klasy, a nie instancji, wszystkie obiekty mog&#322;yby wsp&oacute;&#322;dzieli&#263; t&#281; sam&#261; list&#281;:</p><pre><code>class Job:
    tags = []  # wsp&oacute;lna lista dla instancji tej klasy</code></pre><p>Gdy ka&#380;da instancja ma mie&#263; osobne tagi, tw&oacute;rz list&#281; w <code>__init__</code>: <code>self.tags = []</code>. Atrybuty zmienne, takie jak listy i s&#322;owniki, szczeg&oacute;lnie &#322;atwo przypadkiem wsp&oacute;&#322;dzieli&#263;.</p><h2 id="wybierz-klase-wtedy-gdy-dane-i-metody-tworza-jeden-model">Wybierz klas&#281; wtedy, gdy dane i metody tworz&#261; jeden model</h2><p>Je&#347;li masz tylko chwilowy zestaw p&oacute;l, klasa mo&#380;e do&#322;o&#380;y&#263; ceremonii zamiast porz&#261;dku. <strong>Praktyczna granica</strong> jest prosta: u&#380;yj s&#322;ownika dla danych o zmiennym kszta&#322;cie, a klasy wtedy, gdy chcesz po&#322;&#261;czy&#263; ustalone dane z zachowaniem obiektu.</p><table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Co wybra&#263;</th>
      <th scope="col">Dlaczego</th>
    </tr>
    <tr>
      <td>Jednorazowe dane, kt&oacute;rych pola mog&#261; si&#281; zmienia&#263;</td>
      <td><code>dict</code></td>
      <td>Mo&#380;esz dodawa&#263; i usuwa&#263; klucze bez zmieniania definicji typu.</td>
    </tr>
    <tr>
      <td>Sta&#322;y zestaw p&oacute;l, g&#322;&oacute;wnie do przechowywania danych</td>
      <td><code>@dataclass</code></td>
      <td>Dekorator generuje cz&#281;&#347;&#263; powtarzalnych metod, mi&#281;dzy innymi inicjalizacj&#281; i reprezentacj&#281; obiektu.</td>
    </tr>
    <tr>
      <td>Obiekt ma pilnowa&#263; regu&#322; lub wykonywa&#263; operacje na swoim stanie</td>
      <td>Zwyk&#322;a klasa</td>
      <td>Samodzielnie okre&#347;lasz, jak obiekt powstaje i jak wolno zmienia&#263; jego stan.</td>
    </tr>
  </tbody>
</table><p>Wbudowany modu&#322; <code>dataclasses</code> pozwala zapisa&#263; klas&#281; z polami bez r&#281;cznego tworzenia cz&#281;&#347;ci typowych metod. <a href="https://docs.python.org/3/library/dataclasses.html" target="_blank" rel="noopener noreferrer nofollow">Dokumentacja modu&#322;u dataclasses</a> opisuje mi&#281;dzy innymi generowanie inicjalizacji, por&oacute;wnywania i tekstowej reprezentacji. Pami&#281;taj jednak, &#380;e sama adnotacja typu, taka jak <code>name: str</code>, nie zast&#281;puje walidacji danych.</p><p>Przyznam, &#380;e do prostego obiektu przenosz&#261;cego dane wybra&#322;bym dataclass, a do obiektu pilnuj&#261;cego regu&#322;, takiego jak zadanie z dozwolonymi przej&#347;ciami statusu, zwyk&#322;&#261; klas&#281;. S&#322;ownik zostawi&#322;bym dla danych, kt&oacute;rych struktura naprawd&#281; mo&#380;e si&#281; zmienia&#263;.</p><h2 id="gdy-stan-obiektu-nie-zmienia-sie-poprawnie-sprawdz-miejsce-przypisania">Gdy stan obiektu nie zmienia si&#281; poprawnie, sprawd&#378; miejsce przypisania</h2><p>Dwa obiekty zachowuj&#261; si&#281; tak, jakby by&#322;y jednym? Najpierw sprawd&#378;, czy zmienna, kt&oacute;r&#261; zmieniasz, nale&#380;y do instancji, czy zosta&#322;a zdefiniowana na poziomie klasy.</p><table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Prawdopodobna przyczyna</th>
      <th scope="col">Co zrobi&#263;</th>
    </tr>
    <tr>
      <td>Zmiana listy w jednym obiekcie wp&#322;ywa na drugi</td>
      <td>Lista jest atrybutem klasy i jest wsp&oacute;&#322;dzielona.</td>
      <td>Utw&oacute;rz j&#261; w <code>__init__</code> przez przypisanie do <code>self</code>.</td>
    </tr>
    <tr>
      <td>Wywo&#322;anie <code>job.finish()</code> zg&#322;asza b&#322;&#261;d brakuj&#261;cego argumentu</td>
      <td>Metoda mo&#380;e nie przyjmowa&#263; <code>self</code> w definicji.</td>
      <td>Dodaj <code>self</code> jako pierwszy parametr metody instancji.</td>
    </tr>
    <tr>
      <td>Warto&#347;&#263; pola nie pojawia si&#281; po utworzeniu obiektu</td>
      <td>Przypisanie mog&#322;o trafi&#263; do zmiennej lokalnej zamiast do atrybutu instancji.</td>
      <td>W <code>__init__</code> przypisz warto&#347;&#263; do <code>self.nazwa_pola</code>.</td>
    </tr>
  </tbody>
</table><p>Je&#347;li metoda ma dzia&#322;a&#263; bez konkretnej instancji, sprawd&#378;, czy potrzebujesz metody klasowej lub statycznej. Nie dodawaj jednak dekoratora tylko po to, &#380;eby omin&#261;&#263; brak <code>self</code>: najpierw ustal, czy operacja dotyczy stanu obiektu, ca&#322;ej klasy, czy nie potrzebuje &#380;adnego z nich.</p><h2 id="traktuj-klase-jak-narzedzie-nie-obowiazkowy-etap">Traktuj klas&#281; jak narz&#281;dzie, nie obowi&#261;zkowy etap</h2><p>Prosty skrypt nie musi zaczyna&#263; si&#281; od hierarchii klas. Je&#347;li kilka funkcji stale przyjmuje te same dane i razem pilnuj&#261; wsp&oacute;lnego stanu, model obiektowy mo&#380;e je uporz&#261;dkowa&#263;; przy kr&oacute;tkim przetwarzaniu pojedynczego s&#322;ownika funkcja b&#281;dzie zwykle prostsza.</p><p><strong>Dobry test:</strong> je&#347;li potrafisz nazwa&#263; obiekt rzeczownikiem i wskaza&#263;, co mo&#380;e zrobi&#263; albo jak zmienia sw&oacute;j stan, klasa prawdopodobnie ma sens. Je&#347;li potrzebujesz tylko wygodnego pojemnika na sta&#322;e pola, rozwa&#380; <code>@dataclass</code>; gdy pola s&#261; nieprzewidywalne, zacznij od s&#322;ownika.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Programowanie</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/3bdac280709589316c765b59fea4d356/klasy-w-pythonie-bez-pulapek-self-instancje-i-dataclass.webp"/>
      <pubDate>Mon, 09 Nov 2026 11:50:00 +0100</pubDate>
    </item>
    <item>
      <title>Czy SQL BETWEEN obejmuje obie granice? Sprawdź daty i NULL</title>
      <link>https://lukasz-zielinski.pl/czy-sql-between-obejmuje-obie-granice-sprawdz-daty-i-null</link>
      <description>SQL BETWEEN obejmuje granice, ale daty z godziną mogą ucinać koniec dnia. Sprawdź NULL i bezpieczny zapis zakresów.</description>
      <content:encoded><![CDATA[<p>Raport z zamówieniami znów pomija część rekordów z ostatniego dnia miesiąca, choć warunek wygląda poprawnie. Operator <code>BETWEEN</code> obejmuje obie granice zakresu, ale przy kolumnie z godziną górna data może oznaczać dopiero początek tego dnia.</p>

<div class="short-summary">
  <h2 id="between-obejmuje-oba-konce-lecz-typ-kolumny-zmienia-wynik">BETWEEN obejmuje oba końce, lecz typ kolumny zmienia wynik</h2>
  <ul>
    <li><strong>Granice są domknięte:</strong> wartość równa dolnej lub górnej granicy pasuje do zakresu.</li>
    <li><strong>Daty z godziną:</strong> granica zapisana jako data może wykluczyć późniejsze godziny tego samego dnia.</li>
    <li><strong>Przedział otwarty:</strong> dla raportu obejmującego cały dzień końcowy często lepiej użyć warunku „od tej daty włącznie, przed następną”.</li>
    <li><strong>NULL:</strong> rekordy z brakiem wartości nie spełniają warunku zakresu.</li>
  </ul>
</div>

<p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/b8b39b23e8f11eb5aa6ef91e208f0684/sql-between-operator-query-code-example-date-range.webp" class="image article-image" loading="lazy" alt="Porównanie baz danych: widać różnice między tabelami `dev.Dept` i `prod.Dept`, gdzie `sql between` może pomóc znaleźć dane."></p>

<h2 id="granice-between-sa-wlaczone-do-zakresu">Granice BETWEEN są włączone do zakresu</h2>
<p>Wynik leży w przedziale, jeśli jest <strong>większy lub równy dolnej granicy</strong> i jednocześnie mniejszy lub równy górnej. Tę logikę można zapisać krócej przez <code>BETWEEN</code>:</p>
<pre><code>SELECT order_id, total
FROM orders
WHERE total BETWEEN 100 AND 500;</code></pre>
<p>Zapytanie zwróci zamówienia o wartości od 100 do 500, łącznie z obiema kwotami granicznymi. Tak samo można zapisać warunek jako <code>total &gt;= 100 AND total &lt;= 500</code>. Uważam, że przy prostym zakresie liczbowym <code>BETWEEN</code> jest czytelny, o ile pamiętasz, że końce także przechodzą filtr.</p>
<p>Jeśli granice mają być wykluczone, operator nie pasuje. Zapisz wtedy warunek jawnie, na przykład <code>total &gt; 100 AND total &lt; 500</code>. Różnica jednego znaku może zmienić wynik dla rekordów leżących dokładnie na progu.</p>

<h2 id="data-bez-godziny-moze-uciac-rekordy-z-konca-dnia">Data bez godziny może uciąć rekordy z końca dnia</h2>
<p>W tabeli przechowujesz zamówienia jako znaczniki czasu, a raport ma objąć cały marzec. Warunek <code>BETWEEN '2026-03-01' AND '2026-03-31'</code> może wyglądać naturalnie, ale górna granica często odpowiada północy rozpoczynającej 31 marca. Zamówienie zarejestrowane tego dnia po północy wypada wtedy poza zakresem.</p>
<p>Bezpieczniej zdefiniować początek włącznie, a koniec wyłącznie:</p>
<pre><code>WHERE created_at &gt;= '2026-03-01'
  AND created_at &lt;  '2026-04-01'</code></pre>
<p>To podejście obejmuje wszystkie znaczniki czasu w marcu, niezależnie od tego, czy baza przechowuje sekundy, milisekundy czy większą precyzję. <strong>Nie trzeba zgadywać ostatniej chwili dnia</strong> ani dopisywać ułamków sekundy, które mogą nie pasować do typu kolumny.</p>
<p>Przy kolumnie typu `DATE`, która nie przechowuje godziny, górna granica z <code>BETWEEN</code> działa zgodnie z oczekiwaniem. Problem pojawia się przy `DATETIME` lub typie timestamp, dlatego najpierw sprawdź typ kolumny, a dopiero potem dobierz zapis.</p>

<h2 id="null-i-odwrocone-granice-wymagaja-osobnego-sprawdzenia">NULL i odwrócone granice wymagają osobnego sprawdzenia</h2>
<p>Filtr zakresu nie zamienia braku danych w wartość. Gdy badana kolumna albo jedna z granic ma wartość <code>NULL</code>, warunek nie daje wyniku prawdziwego, więc wiersz nie przechodzi przez <code>WHERE</code>. Jeśli brak wartości ma być uwzględniony, dopisz osobny warunek.</p>
<table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Skutek</th>
      <th scope="col">Co zrobić</th>
    </tr>
    <tr>
      <td>Kolumna zawiera <code>NULL</code></td>
      <td>Wiersz nie spełnia warunku zakresu.</td>
      <td>Dodaj <code>OR kolumna IS NULL</code>, jeśli brak wartości ma być częścią wyniku.</td>
    </tr>
    <tr>
      <td>Dolna granica jest większa od górnej</td>
      <td>Zakres nie obejmuje zwykłych wartości.</td>
      <td>Zweryfikuj kolejność parametrów przed wykonaniem zapytania.</td>
    </tr>
    <tr>
      <td>Granice mają różne typy</td>
      <td>Niektóre silniki odrzucą warunek, inne mogą wykonać konwersję.</td>
      <td>Użyj zgodnych typów i sprawdź zasady swojego silnika SQL.</td>
    </tr>
    <tr>
      <td>Porównywane są wartości zmiennoprzecinkowe</td>
      <td>Zaokrąglenia reprezentacji mogą dać zaskakujące wyniki blisko granicy.</td>
      <td>Dla kwot wybierz typ dziesiętny, a dla pomiarów określ akceptowaną tolerancję.</td>
    </tr>
  </tbody>
</table>
<p>Ostatni przypadek jest podstępny, bo zapytanie może wykonać się bez błędu, a mimo to zachować się inaczej, niż sugeruje zapis liczby. Dokumentacja <a href="https://dev.mysql.com/doc/refman/8.4/en/problems-with-float.html" target="_blank" rel="noopener noreferrer nofollow">MySQL</a> opisuje problem przybliżonego przechowywania typów zmiennoprzecinkowych; dla wartości pieniężnych wybór typu danych bywa ważniejszy niż sam operator.</p>

<h2 id="silnik-sql-wplywa-na-szczegoly-nie-na-sens-operatora">Silnik SQL wpływa na szczegóły, nie na sens operatora</h2>
<p>Podstawowa zasada jest wspólna, lecz silniki różnią się w wymaganiach dotyczących typów i w sposobie obsługi wyrażeń. W <a href="https://learn.microsoft.com/en-us/sql/t-sql/language-elements/between-transact-sql" target="_blank" rel="noopener noreferrer nofollow">Transact-SQL dla SQL Server</a> wyrażenie testowane i obie granice muszą mieć zgodne typy danych. Dokumentacja <a href="https://www.postgresql.org/docs/current/functions-comparison.html" target="_blank" rel="noopener noreferrer nofollow">PostgreSQL</a> opisuje zakres jako domknięty, a <a href="https://www.sqlite.org/lang_expr.html" target="_blank" rel="noopener noreferrer nofollow">SQLite</a> zaznacza, że wyrażenie po lewej stronie operatora jest obliczane raz.</p>
<p>W praktyce nie zakładaj, że konwersja tekstu na datę lub liczbę zadziała identycznie w każdym środowisku. Parametry zapytania przekazuj jako wartości właściwego typu, szczególnie gdy aplikacja obsługuje więcej niż jeden silnik bazy.</p>

<h2 id="najpierw-sprawdz-typ-potem-wybierz-granice">Najpierw sprawdź typ, potem wybierz granice</h2>
<p>Przy debugowaniu rozbieżnego raportu najkrótsza droga prowadzi przez trzy pytania: czy granice są włączone, czy kolumna zawiera czas oraz czy w danych występuje <code>NULL</code>. Gdy zakres dotyczy pełnych dni w kolumnie czasu, zapis z końcem wyłącznym zwykle usuwa problem bez sztucznych końcowych sekund.</p>
<p>Jeśli testujesz sam operator, dodaj do danych rekordy dokładnie na dolnej i górnej granicy oraz jeden tuż poza nimi. Taki mały test ujawnia, czy problem tkwi w logice zakresu, typie kolumny czy parametrach przekazanych przez aplikację.</p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>Bazy danych</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/2726d60852162eee635682476f4659f1/czy-sql-between-obejmuje-obie-granice-sprawdz-daty-i-null.webp"/>
      <pubDate>Mon, 09 Nov 2026 09:16:00 +0100</pubDate>
    </item>
    <item>
      <title>Ficzer - co oznacza w IT i backlogu?</title>
      <link>https://lukasz-zielinski.pl/ficzer-co-oznacza-w-it-i-backlogu</link>
      <description>Ficzer to funkcja programu czy większy element backlogu? Sprawdź znaczenie słowa, różnice między błędem a zadaniem oraz rolę feature flag.</description>
      <content:encoded><![CDATA[<p>Na daily pada zdanie: „Dorzucimy jeszcze ten ficzer”, ale w ticketach nie wiadomo, czy chodzi o nową opcję, poprawkę czy cały większy kawałek produktu. <strong>Ficzer</strong> to potoczne określenie funkcji lub możliwości programu, choć w zespole może oznaczać zadanie o różnej skali.</p>

<div class="short-summary">
  <h2 id="ficzer-oznacza-funkcje-produktu-ale-jego-skala-zalezy-od-kontekstu">Ficzer oznacza funkcję produktu, ale jego skala zależy od kontekstu</h2>
  <ul>
    <li><strong>Znaczenie:</strong> ficzer to spolszczone, potoczne angielskie <em>feature</em>, czyli funkcja lub możliwość programu.</li>
    <li><strong>W backlogu:</strong> ficzer może oznaczać większy element produktu, złożony z kilku historyjek, albo po prostu nową funkcję.</li>
    <li><strong>W rozmowie:</strong> samo słowo nie wyznacza zakresu pracy. Doprecyzuj użytkownika, efekt i kryteria akceptacji.</li>
    <li><strong>W kodzie:</strong> ficzer to funkcja produktu, a feature flag to mechanizm, który pozwala ją włączać lub wyłączać.</li>
  </ul>
</div>

<p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/41fc8803c53459eae08369b198e0ea05/programista-i-product-manager-omawiajacy-backlog-funkcji-aplikacji-na-ekranie-laptopa.webp" class="image article-image" loading="lazy" alt="Backlog w projekcie " scrum in space z zadaniami dotycz misji na marsa. landing to nazwa epickiego zadania.></p>

<h2 id="ficzer-to-funkcja-programu-ale-slowo-jest-potoczne">Ficzer to funkcja programu, ale słowo jest potoczne</h2>
<p>Gdy ktoś mówi o ficzerze, zwykle ma na myśli <strong>funkcję, opcję albo możliwość</strong>, którą daje aplikacja. Przykładem może być filtrowanie zamówień, eksport raportu do CSV czy logowanie za pomocą klucza dostępu.</p>

<p>To spolszczona wymowa angielskiego <em>feature</em>. W rozmowie zespołowej brzmi naturalnie, ale w specyfikacji, umowie albo opisie dla klienta lepiej użyć precyzyjniejszego słowa, takiego jak „funkcja” lub „funkcjonalność”.</p>

<p><strong>Uważam, że „ficzer” jest użyteczny w rozmowie, dopóki wszyscy rozumieją, o jakim efekcie dla użytkownika mowa.</strong> Problem zaczyna się wtedy, gdy etykieta zastępuje opis zakresu pracy.</p>

<h2 id="w-backlogu-ficzer-moze-obejmowac-kilka-historyjek">W backlogu ficzer może obejmować kilka historyjek</h2>
<p>W jednym zespole „ficzer” oznacza drobną opcję, w innym większy element planu produktu. W typowej hierarchii Azure DevOps epik dzieli się na ficzery, ficzer na historyjki użytkownika, a historyjka może być rozpisana na zadania. <a href="https://learn.microsoft.com/en-us/devops/plan/scaling-agile" target="_blank" rel="noopener noreferrer nofollow">Microsoft Learn</a> zaznacza zarazem, że nazwy i poziomy takiej taksonomii można dostosować do organizacji.</p>

<p>Wyobraź sobie epik „Ułatwić obsługę płatności”. Jednym z ficzerów może być „Zapamiętywanie metody płatności”, a jego częścią historyjka: „Jako klient chcę wybrać zapisaną kartę, aby szybciej opłacić zamówienie”. Dla programisty konkretna implementacja może rozpaść się jeszcze na zadania dotyczące API, interfejsu i testów.</p>

<p>Skala zależy więc od tego, jak zespół planuje pracę. Według <a href="https://learn.microsoft.com/en-us/azure/devops/boards/backlogs/backlogs-overview?view=azure-devops" target="_blank" rel="noopener noreferrer nofollow">dokumentacji Azure Boards</a> ficzer może grupować powiązane elementy backlogu i opisywać możliwość, którą da się dostarczyć użytkownikom. Nie wynika z tego jednak, że każda firma używa tego słowa dokładnie tak samo.</p>

<h2 id="feature-i-historyjka-uzytkownika-nie-zawsze-znacza-to-samo">Feature i historyjka użytkownika nie zawsze znaczą to samo</h2>
<p>Tu łatwo o nieporozumienie: angielskie <em>feature</em> bywa nazwą większego elementu produktu, ale w innych praktykach może opisywać funkcjonalność z perspektywy użytkownika. <a href="https://cucumber.io/docs/terms/user-story/" target="_blank" rel="noopener noreferrer nofollow">Cucumber</a> opisuje historyjkę jako mały fragment wartościowej funkcjonalności, który powinien dać się zademonstrować i mieć testowalne kryteria akceptacji.</p>

<p>Inny podział znajdziesz w <a href="https://framework.scaledagile.com/features-and-capabilities" target="_blank" rel="noopener noreferrer nofollow">Scaled Agile Framework</a>: tam ficzer ma zwięźle nazywać funkcję i wiązać ją z oczekiwaną korzyścią, a format historyjki użytkownika nie jest zalecany do opisywania każdego ficzera. <strong>Wniosek jest praktyczny: nie zakładaj hierarchii na podstawie samej nazwy</strong>, tylko sprawdź, jak zespół definiuje elementy backlogu.</p>

<p>Podobna pułapka dotyczy plików Gherkin. Słowo <code>Feature</code> na początku takiego pliku jest nagłówkiem opisującym obszar funkcji i grupującym scenariusze testowe. <a href="https://cucumber.io/docs/gherkin/reference/" target="_blank" rel="noopener noreferrer nofollow">Referencja Gherkin</a> pokazuje więc użycie terminu w konkretnym formacie testów, a nie uniwersalny rozmiar zadania w każdym backlogu.</p>

<h2 id="po-opisie-ticketu-poznasz-czy-chodzi-o-ficzer-blad-czy-zadanie">Po opisie ticketu poznasz, czy chodzi o ficzer, błąd czy zadanie</h2>
<p>Sam przymiotnik „nowy” niczego nie rozstrzyga. Jeśli element dostarcza użytkownikowi nową możliwość, zwykle mowa o ficzerze; jeśli naprawia niezgodne z oczekiwaniem działanie, chodzi o błąd; jeśli opisuje pracę techniczną potrzebną do innego elementu, to zadanie.</p>

<table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja w ticketach</th>
      <th scope="col">Co prawdopodobnie oznacza</th>
      <th scope="col">Jak doprecyzować</th>
    </tr>
    <tr>
      <td>Użytkownik może filtrować historię zakupów po dacie</td>
      <td>Nowa funkcja, czyli ficzer</td>
      <td>Opisz, kto jej używa i jaki wynik ma zobaczyć.</td>
    </tr>
    <tr>
      <td>Filtr daty pokazuje zamówienia spoza wybranego zakresu</td>
      <td>Błąd, bo istniejąca funkcja działa nieprawidłowo</td>
      <td>Podaj kroki odtworzenia i oczekiwany wynik.</td>
    </tr>
    <tr>
      <td>Dodanie indeksu do tabeli przyspiesza wyszukiwanie</td>
      <td>Zadanie techniczne, jeśli użytkownik nie dostaje nowej opcji</td>
      <td>Powiąż je z funkcją lub problemem, który ma obsłużyć.</td>
    </tr>
    <tr>
      <td>Zmiana koloru przycisku bez uzasadnienia funkcjonalnego</td>
      <td>Może być poprawką UX albo zadaniem, niekoniecznie ficzerem</td>
      <td>Wyjaśnij, jak zmiana poprawi wykonanie konkretnej czynności.</td>
    </tr>
  </tbody>
</table>

<p>Przy opisie zgłoszenia odpowiedz na trzy pytania: <strong>kto korzysta, co może zrobić i po czym poznać, że działa</strong>. Jeśli odpowiedź wymaga kilku niezależnych efektów, rozbij element na mniejsze historyjki lub zadania, zamiast zostawiać w backlogu hasło „dodać ficzer”.</p>

<h2 id="feature-flag-steruje-dostepnoscia-ficzera">Feature flag steruje dostępnością ficzera</h2>
<p>W rozmowach o wdrożeniu możesz usłyszeć, że nowy ficzer „jest za flagą”. Chodzi o <em>feature flag</em>, czyli mechanizm pozwalający włączać lub wyłączać daną ścieżkę działania bez zmiany samej definicji funkcji. <a href="https://martinfowler.com/articles/feature-toggles.html" target="_blank" rel="noopener noreferrer nofollow">Martin Fowler</a> opisuje tę technikę jako sposób kontrolowania zachowania systemu, na przykład stopniowego udostępniania nowej funkcji.</p>

<p>W przykładzie z eksportem raportu zespół może wdrożyć kod wcześniej, ale udostępnić opcję najpierw tylko pracownikom firmy. <strong>Ficzer jest wtedy funkcją produktu, a flaga narzędziem do zarządzania jej dostępnością.</strong> Pomieszanie tych pojęć utrudnia rozmowę o tym, co faktycznie trzeba zbudować, a co tylko włączyć.</p>

<h2 id="najbezpieczniej-dopisac-do-slowa-ficzer-oczekiwany-efekt">Najbezpieczniej dopisać do słowa „ficzer” oczekiwany efekt</h2>
<p>Jeśli podczas spotkania pada „zróbmy ficzer”, dopytaj, jaką czynność użytkownik ma dzięki niemu wykonać i czy rozmowa dotyczy nowej funkcji, poprawki czy technicznej pracy w tle. Taki krótki dopisek zamienia branżowy skrót w opis, który można zaplanować, przetestować i odebrać.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Kariera i biznes IT</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/7caa2bacfca470bf7617429823aa8f84/ficzer-co-oznacza-w-it-i-backlogu.webp"/>
      <pubDate>Mon, 09 Nov 2026 08:20:00 +0100</pubDate>
    </item>
    <item>
      <title>CSS float w praktyce - opływanie tekstu, clear i flow-root</title>
      <link>https://lukasz-zielinski.pl/css-float-w-praktyce-oplywanie-tekstu-clear-i-flow-root</link>
      <description>Dowiedz się, kiedy użyć CSS float, clear i flow-root oraz dlaczego Flexbox i Grid lepiej sprawdzają się w layoutach.</description>
      <content:encoded><![CDATA[<p>Miniatura artykułu przylega do lewej krawędzi, a tekst układa się obok niej, lecz następny blok wskakuje w to samo miejsce. W takiej sytuacji <strong>float CSS</strong> może być właściwym narzędziem, o ile problemem jest opływanie elementu przez tekst, a nie budowa całego układu strony.</p>

<p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/ac98ca36f0916472f3f3b6aacf5ea13f/css-float-text-wrapping-around-image-diagram-float-left-right-clear-flow-root.webp" class="image article-image" loading="lazy" alt="Ilustracja pokazuje, jak `float:left` i `float:right` wpływają na układ elementów, z `clear:both` resetującym ten efekt."></p>

<div class="short-summary">
  <h2 id="float-sluzy-do-oplywania-tresci-a-nie-do-budowania-calego-layoutu">Float służy do opływania treści, a nie do budowania całego layoutu</h2>
  <ul>
    <li><strong>float: left</strong> i <strong>float: right</strong> ustawiają element przy krawędzi, obok której może płynąć tekst.</li>
    <li><strong>Flexbox</strong> sprawdza się przy układaniu elementów w jednym wymiarze, a <strong>Grid</strong> przy siatce wierszy i kolumn.</li>
    <li><strong>clear</strong> zatrzymuje opływanie przy kolejnym elemencie.</li>
    <li><strong>display: flow-root</strong> pomaga kontenerowi objąć wysokością pływające dzieci.</li>
    <li><strong>float: inline-start</strong> dopasowuje stronę do kierunku pisma.</li>
  </ul>
</div>

<h2 id="float-ustawia-element-z-boku-a-tekst-plynie-obok-niego">Float ustawia element z boku, a tekst płynie obok niego</h2>
<p>Wyobraź sobie zdjęcie w artykule, które ma zajmować lewą część akapitu, podczas gdy tekst opływa je z prawej. Właśnie do takiego efektu służy właściwość <code>float</code>: przesuwa element ku lewej lub prawej krawędzi kontenera, pozwalając treści tekstowej układać się przy jego boku.</p>
<p>Najprostszy przykład wygląda tak:</p>
<pre><code>.article-image {
  float: left;
  width: 12rem;
  margin: 0 1rem 0.75rem 0;
}</code></pre>
<p>Wartość <code>left</code> oznacza lewą stronę, <code>right</code> prawą, a <code>none</code> wyłącza opływanie. Właściwość <code>float</code> nie centruje elementu i nie ustawia go precyzyjnie w dowolnym miejscu; wpływa na to, jak układa się obok niego zawartość. Tak opisuje ją dokumentacja <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/float" target="_blank" rel="noopener noreferrer nofollow">MDN dotycząca właściwości float</a>.</p>
<p>To rozróżnienie oszczędza sporo poprawiania CSS. <strong>Jeśli chcesz, by tekst opływał obraz albo niewielki panel, float pasuje do zadania</strong>; jeśli ustawiasz obok siebie przyciski, karty lub kolumny, wybierz inny model układu.</p>

<h2 id="do-kolumn-wybierz-flexbox-albo-grid-nie-float">Do kolumn wybierz Flexbox albo Grid, nie float</h2>
<p>Układ dwóch kolumn może wyglądać poprawnie przy użyciu float, dopóki nie zmieni się treść, szerokość ekranu albo kolejność elementów. Właśnie wtedy ręczne kontrolowanie szerokości, odstępów i czyszczenia opływania zaczyna przeszkadzać. <strong>Uważam, że float warto zostawić do opływania treści, a strukturę interfejsu budować Flexboksem lub Gridem.</strong></p>
<table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Lepsze narzędzie</th>
      <th scope="col">Powód</th>
    </tr>
    <tr>
      <td>Tekst ma opływać ilustrację w artykule</td>
      <td><code>float</code></td>
      <td>Tekst może układać się przy boku elementu i poniżej niego.</td>
    </tr>
    <tr>
      <td>Elementy mają tworzyć pasek, na przykład przyciski w nagłówku</td>
      <td><code>display: flex</code></td>
      <td>Flexbox porządkuje elementy w jednym wymiarze i pozwala kontrolować odstępy.</td>
    </tr>
    <tr>
      <td>Strona ma mieć wiersze i kolumny kart</td>
      <td><code>display: grid</code></td>
      <td>Grid daje kontrolę nad układem w dwóch wymiarach.</td>
    </tr>
    <tr>
      <td>Kolejny blok ma zaczynać się pod pływającym elementem</td>
      <td><code>clear</code></td>
      <td>Blok przestaje układać się przy elemencie float.</td>
    </tr>
  </tbody>
</table>
<p>Praktyczna decyzja jest prosta: <strong>opływanie tekstu oznacza float; układ komponentów oznacza Flexbox albo Grid</strong>. Materiał edukacyjny <a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Floats" target="_blank" rel="noopener noreferrer nofollow">MDN o float</a> również wskazuje, że ta technika wróciła do pierwotnego zadania, gdy Flexbox i Grid przejęły budowanie typowych layoutów.</p>

<h2 id="clear-konczy-oplywanie-a-flow-root-naprawia-wysokosc-kontenera">clear kończy opływanie, a flow-root naprawia wysokość kontenera</h2>
<p>Najczęstszy zgrzyt pojawia się pod krótkim akapitem: nagłówek, przycisk albo kolejny tekst wsuwa się obok obrazka. Jeśli ten element ma rozpocząć nowy fragment poniżej float, dodaj <code>clear</code>:</p>
<pre><code>.next-section {
  clear: both;
}</code></pre>
<p><code>clear: left</code> zatrzymuje opływanie elementów pływających w lewo, <code>clear: right</code> tych po prawej, a <code>clear: both</code> uwzględnia obie strony. To ustawienie dotyczy wskazanego elementu; samo z siebie nie sprawia, że kontener obejmie wysokością swoje pływające dzieci.</p>
<p>Gdy tło lub obramowanie rodzica kończy się przed pływającym obrazem, użyj <code>display: flow-root</code> na kontenerze:</p>
<pre><code>.article-copy {
  display: flow-root;
}</code></pre>
<p><strong>flow-root tworzy nowy kontekst formatowania blokowego</strong>, dzięki czemu kontener obejmuje pływające elementy bez dodatkowego pseudo-elementu clearfix. To rozwiązanie opisuje <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/clear" target="_blank" rel="noopener noreferrer nofollow">dokumentacja MDN właściwości clear</a>, a szczegóły mechanizmu wyjaśnia materiał o <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Display/Block_formatting_context" target="_blank" rel="noopener noreferrer nofollow">kontekście formatowania blokowego</a>.</p>

<h2 id="float-logiczny-lepiej-znosi-zmiane-kierunku-tekstu">Float logiczny lepiej znosi zmianę kierunku tekstu</h2>
<p>W polskim interfejsie <code>float: left</code> zwykle ustawia element po lewej, ale taki zapis opisuje fizyczną stronę ekranu. Przy obsłudze języków pisanych od prawej do lewej trzeba brać pod uwagę kierunek tekstu, inaczej obraz może zostać po niewłaściwej stronie.</p>
<p>W takim przypadku można użyć wartości logicznych:</p>
<pre><code>.article-image {
  float: inline-start;
  margin-inline-end: 1rem;
}</code></pre>
<p><code>inline-start</code> oznacza początek kierunku pisma, a <code>inline-end</code> jego koniec. Dla tekstu pisanego od lewej do prawej pierwsza wartość wskazuje lewą stronę; przy kierunku od prawej do lewej wskazuje prawą. <strong>To drobna zmiana, która pozwala uniknąć osobnych reguł dla obu kierunków</strong>.</p>

<h2 id="diagnozuj-efekt-po-tym-co-dzieje-sie-z-tekstem-i-rodzicem">Diagnozuj efekt po tym, co dzieje się z tekstem i rodzicem</h2>
<p>Gdy float zachowuje się inaczej, niż zakładasz, najpierw ustal, czy problem dotyczy opływania, kolejnego elementu, czy wysokości kontenera. Te trzy objawy mają różne przyczyny, więc jedna przypadkowa poprawka często przenosi problem zamiast go rozwiązać.</p>
<table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja lub objaw</th>
      <th scope="col">Prawdopodobna przyczyna</th>
      <th scope="col">Co zrobić</th>
    </tr>
    <tr>
      <td>Kolejny nagłówek pojawia się obok obrazka</td>
      <td>Element nagłówka nadal może opływać float.</td>
      <td>Dodaj <code>clear: both</code> do nagłówka lub jego kontenera.</td>
    </tr>
    <tr>
      <td>Tło rodzica nie obejmuje obrazu</td>
      <td>Pływające dziecko nie zwiększa zwykłej wysokości rodzica.</td>
      <td>Ustaw <code>display: flow-root</code> na rodzicu.</td>
    </tr>
    <tr>
      <td>Kilka elementów układa się w nieprzewidywalne kolumny</td>
      <td>Float został użyty do budowy layoutu zamiast do opływania treści.</td>
      <td>Zbuduj układ za pomocą Flexboxa lub Grida.</td>
    </tr>
    <tr>
      <td>Obraz znajduje się po złej stronie w wersji językowej</td>
      <td>Reguła używa fizycznej wartości <code>left</code> lub <code>right</code>.</td>
      <td>Rozważ <code>inline-start</code> albo <code>inline-end</code>.</td>
    </tr>
  </tbody>
</table>
<p>Ta kolejność diagnozy pomaga uniknąć popularnego odruchu, czyli dodawania kolejnych szerokości i marginesów, gdy faktyczny problem leży w przepływie treści. <strong>Najpierw popraw regułę odpowiadającą objawowi</strong>, a dopiero potem dopracuj odstępy.</p>

<h2 id="float-zostaw-tam-gdzie-tekst-naprawde-ma-oplywac-element">Float zostaw tam, gdzie tekst naprawdę ma opływać element</h2>
<p>Jeśli akapit ma płynąć wokół ilustracji, float nadal jest zwięzłym i czytelnym rozwiązaniem. Gdy celem jest rozmieszczenie kart, menu albo kolumn, wybór Flexboxa lub Grida zwykle daje prostsze reguły i mniej niespodzianek przy zmianie treści.</p>
<p>Wróć więc do początkowej sytuacji z miniaturą i kolejnym blokiem: dla samego opływania ustaw float, dla elementu, który ma zejść pod obraz, dodaj clear, a gdy kontener nie obejmuje grafiki, zastosuj flow-root. <strong>Tak rozdzielone zadania sprawiają, że CSS pozostaje czytelny także wtedy, gdy artykuł urośnie.</strong></p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>Frontend i UX</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/0b8c883cd7d3e8e92eb6ce9070cc2ba6/css-float-w-praktyce-oplywanie-tekstu-clear-i-flow-root.webp"/>
      <pubDate>Sun, 08 Nov 2026 17:08:00 +0100</pubDate>
    </item>
    <item>
      <title>HTTP 500 po wdrożeniu? Znajdź źródło błędu</title>
      <link>https://lukasz-zielinski.pl/http-500-po-wdrozeniu-znajdz-zrodlo-bledu</link>
      <description>HTTP 500 nie wskazuje winnej warstwy. Sprawdź logi, trace ID, różnice między kodami 502-504 i bezpieczne retry. Poznaj metody diagnostyki.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Po wdro&#380;eniu nowej wersji endpoint zwraca 500, a komunikat w przegl&#261;darce nie m&oacute;wi, czy winny jest kod, baza czy us&#322;uga po&#347;rednia. <strong>Internal Server Error</strong> oznacza, &#380;e serwer nie obs&#322;u&#380;y&#322; &#380;&#261;dania z powodu nieoczekiwanej sytuacji, ale sam kod odpowiedzi nie wskazuje jeszcze miejsca awarii.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/abd9ccc3561647ee9f0d0fd243cb066f/schemat-diagnostyki-http-500-logi-aplikacji-reverse-proxy-backend.webp" class="image article-image" loading="lazy" alt="Komunikat " internal="" server="" error="" na="" ekranie="" komputera="" wskazuj="" problem="" z="" serwerem.=""></p><div class="short-summary">
  <h2 id="sam-kod-500-nie-wskaze-winnej-warstwy">Sam kod 500 nie wska&#380;e winnej warstwy</h2>
  <ul>
    <li><strong>HTTP 500</strong> to og&oacute;lna odpowied&#378; serwera, a nie diagnoza konkretnego b&#322;&#281;du.</li>
    <li><strong>Zakres awarii</strong> zaw&#281;zisz, sprawdzaj&#261;c, czy problem dotyczy jednego endpointu, regionu, klienta czy wszystkich &#380;&#261;da&#324;.</li>
    <li><strong>Logi i trace ID</strong> po&#322;&#261;cz&#261; odpowied&#378; widoczn&#261; dla klienta ze zdarzeniem w aplikacji lub infrastrukturze.</li>
    <li><strong>Ponowienie &#380;&#261;dania</strong> mo&#380;e pom&oacute;c przy kr&oacute;tkim zak&#322;&oacute;ceniu, ale przy operacji zapisuj&#261;cej dane grozi jej wykonaniem dwa razy.</li>
  </ul>
</div><h2 id="http-500-opisuje-skutek-nie-przyczyne">HTTP 500 opisuje skutek, nie przyczyn&#281;</h2><p>Specyfikacja <a href="https://www.rfc-editor.org/rfc/rfc9110.html" target="_blank" rel="noopener noreferrer nofollow">RFC 9110</a> definiuje ten status jako sygna&#322;, &#380;e serwer napotka&#322; nieoczekiwany warunek i nie m&oacute;g&#322; zrealizowa&#263; &#380;&#261;dania. W praktyce odpowied&#378; mo&#380;e powsta&#263; w aplikacji, serwerze WWW albo warstwie po&#347;rednicz&#261;cej, wi&#281;c tre&#347;&#263; komunikatu sama w sobie nie ujawnia, kt&oacute;ra z nich zawiod&#322;a.</p><p>To rozr&oacute;&#380;nienie chroni przed cz&#281;stym skr&oacute;tem my&#347;lowym: &bdquo;500 oznacza b&#322;&#261;d aplikacji&rdquo;. Uwa&#380;am, &#380;e lepiej traktowa&#263; ten kod jako <strong>punkt wej&#347;cia do diagnostyki</strong>, a nie gotowe rozpoznanie. Szczeg&oacute;lnie &#380;e podobne problemy w infrastrukturze dostaj&#261; inne kody.</p><h2 id="porownaj-500-z-502-503-i-504-zanim-zmienisz-kod">Por&oacute;wnaj 500 z 502, 503 i 504, zanim zmienisz kod</h2><p>R&oacute;&#380;nica mi&#281;dzy tymi odpowiedziami wskazuje, gdzie szuka&#263; pierwszego tropu. <strong>500</strong> m&oacute;wi og&oacute;lnie o nieoczekiwanym b&#322;&#281;dzie po stronie serwera; pozosta&#322;e kody precyzuj&#261; problemy zwi&#261;zane z po&#347;rednikiem, dost&#281;pno&#347;ci&#261; lub czasem odpowiedzi.</p><table>
  <tbody>
    <tr>
      <th>Odpowied&#378;</th>
      <th>Co sygnalizuje</th>
      <th>Pierwszy trop</th>
    </tr>
    <tr>
      <td>500 Internal Server Error</td>
      <td>Serwer napotka&#322; nieoczekiwany warunek.</td>
      <td>Wyj&#261;tek aplikacji, konfiguracja, zale&#380;no&#347;&#263; albo wyczerpany zas&oacute;b.</td>
    </tr>
    <tr>
      <td>502 Bad Gateway</td>
      <td>Serwer dzia&#322;aj&#261;cy jako brama lub proxy dosta&#322; nieprawid&#322;ow&#261; odpowied&#378; od serwera nadrz&#281;dnego.</td>
      <td>Po&#322;&#261;czenie i odpowied&#378; backendu widziane z warstwy proxy.</td>
    </tr>
    <tr>
      <td>503 Service Unavailable</td>
      <td>Us&#322;uga nie mo&#380;e teraz obs&#322;u&#380;y&#263; &#380;&#261;dania.</td>
      <td>Przeci&#261;&#380;enie, niedost&#281;pna instancja lub zaplanowane wy&#322;&#261;czenie.</td>
    </tr>
    <tr>
      <td>504 Gateway Timeout</td>
      <td>Brama nie otrzyma&#322;a odpowiedzi na czas.</td>
      <td>Op&oacute;&#378;niony backend albo zale&#380;no&#347;&#263;, kt&oacute;ra nie odpowiada w limicie.</td>
    </tr>
  </tbody>
</table><p>To wskaz&oacute;wki, nie niepodwa&#380;alne etykiety: aplikacja mo&#380;e zwr&oacute;ci&#263; 500 tak&#380;e wtedy, gdy problem zacz&#261;&#322; si&#281; w zale&#380;no&#347;ci, a konfiguracja proxy mo&#380;e zmieni&#263; widoczny status. Sprawd&#378; wi&#281;c <strong>odpowied&#378; z ka&#380;dej warstwy</strong>, zamiast opiera&#263; diagnoz&#281; wy&#322;&#261;cznie na kodzie widocznym w przegl&#261;darce.</p><h2 id="najpierw-ustal-czy-awaria-jest-lokalna-czy-szeroka">Najpierw ustal, czy awaria jest lokalna, czy szeroka</h2><p>
Jeden <a href="https://lukasz-zielinski.pl/blad-500-po-wdrozeniu-jak-znalezc-przyczyne-awarii">b&#322;&#261;d po wdro&#380;eniu</a> i seria b&#322;&#281;d&oacute;w w ca&#322;ym regionie to dwa r&oacute;&#380;ne scenariusze. Zanim zaczniesz edytowa&#263; konfiguracj&#281;, zestaw czas wyst&#261;pienia odpowiedzi z wdro&#380;eniami, metrykami i logami; taki prosty przekr&oacute;j cz&#281;sto ogranicza liczb&#281; mo&#380;liwych przyczyn.
</p><table>
  <tbody>
    <tr>
      <th>Sytuacja</th>
      <th>Prawdopodobny trop</th>
      <th>Co zrobi&#263;</th>
    </tr>
    <tr>
      <td>500 pojawia si&#281; wy&#322;&#261;cznie na jednym endpointcie.</td>
      <td>B&#322;&#261;d &#347;cie&#380;ki kodu, walidacji danych albo jej zale&#380;no&#347;ci.</td>
      <td>Por&oacute;wnaj logi &#380;&#261;da&#324; z udanymi wywo&#322;aniami tego samego endpointu.</td>
    </tr>
    <tr>
      <td>B&#322;&#281;dy zaczynaj&#261; si&#281; tu&#380; po wdro&#380;eniu.</td>
      <td>Regresja, migracja schematu lub niezgodna konfiguracja.</td>
      <td>Sprawd&#378; r&oacute;&#380;nice mi&#281;dzy wersjami i rozwa&#380; rollback, je&#347;li awaria obejmuje krytyczny przep&#322;yw.</td>
    </tr>
    <tr>
      <td>Wiele endpoint&oacute;w zawodzi jednocze&#347;nie.</td>
      <td>Wsp&oacute;lna zale&#380;no&#347;&#263;, pula po&#322;&#261;cze&#324;, pami&#281;&#263; albo problem infrastruktury.</td>
      <td>Sprawd&#378; metryki zasob&oacute;w i statusy zale&#380;no&#347;ci, zanim zmienisz kod aplikacji.</td>
    </tr>
    <tr>
      <td>B&#322;&#261;d dotyczy tylko cz&#281;&#347;ci &#380;&#261;da&#324; lub jednej instancji.</td>
      <td>Nier&oacute;wny ruch, wadliwy w&#281;ze&#322; albo r&oacute;&#380;nice w konfiguracji.</td>
      <td>Por&oacute;wnaj instancje, strefy i identyfikatory &#380;&#261;da&#324;; sprawd&#378;, czy ruch trafia nier&oacute;wno.</td>
    </tr>
  </tbody>
</table><p>Je&#347;li wpis w logu aplikacji nie odpowiada b&#322;&#281;dowi widocznemu na brzegu systemu, sprawd&#378; logi reverse proxy, load balancera i bramy API. <strong>Brak wyj&#261;tku w aplikacji</strong> nie dowodzi, &#380;e &#380;&#261;danie przesz&#322;o przez ni&#261; bez problemu.</p><h2 id="trace-id-skraca-droge-od-alarmu-do-przyczyny">Trace ID skraca drog&#281; od alarmu do przyczyny</h2><p>Komunikat dla u&#380;ytkownika powinien by&#263; oszcz&#281;dny, ale log wewn&#281;trzny musi zawiera&#263; dane pozwalaj&#261;ce odtworzy&#263; przebieg &#380;&#261;dania. Generuj lub przekazuj <strong>identyfikator korelacyjny</strong> przez kolejne us&#322;ugi, a nast&#281;pnie zapisuj go przy b&#322;&#281;dzie razem z nazw&#261; endpointu, wersj&#261; aplikacji, instancj&#261; i czasem.</p><p>Przyk&#322;adowo: po wdro&#380;eniu ro&#347;nie liczba odpowiedzi 500 na jednym endpointcie, lecz wykres dost&#281;pno&#347;ci ca&#322;ej us&#322;ugi nadal wygl&#261;da dobrze. Filtr po trace ID ujawnia, &#380;e b&#322;&#281;dy dotycz&#261; wywo&#322;a&#324; zale&#380;no&#347;ci, podczas gdy pozosta&#322;e &#347;cie&#380;ki dzia&#322;aj&#261;. W takim przypadku sprawd&#378; limit czasu, obs&#322;ug&#281; wyj&#261;tku i zmian&#281; kontraktu integracji, zamiast restartowa&#263; wszystkie instancje.</p><p>Nie zapisuj w odpowiedzi dla klienta stack trace, sekret&oacute;w ani szczeg&oacute;&#322;&oacute;w infrastruktury. <strong>Pe&#322;ne szczeg&oacute;&#322;y zostaw w zabezpieczonych logach</strong>; na zewn&#261;trz zwr&oacute;&#263; kr&oacute;tki komunikat i identyfikator, kt&oacute;ry mo&#380;na przekaza&#263; zespo&#322;owi wsparcia.</p><h2 id="ponawiaj-bezpiecznie-bo-retry-moze-powielic-zapis">Ponawiaj bezpiecznie, bo retry mo&#380;e powieli&#263; zapis</h2><p>Automatyczna ponowna pr&oacute;ba bywa rozs&#261;dna przy przej&#347;ciowym problemie, ale nie rozwi&#261;&#380;e trwa&#322;ego wyj&#261;tku ani b&#322;&#281;dnej konfiguracji. Dokumentacja <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TroubleshootingInternalServerErrors.html" target="_blank" rel="noopener noreferrer nofollow">Amazon DynamoDB</a> opisuje, &#380;e w tej us&#322;udze b&#322;&#281;dy 500 mog&#261; wynika&#263; mi&#281;dzy innymi z przej&#347;ciowych problem&oacute;w <a href="https://lukasz-zielinski.pl/docker-compose-i-sieci-dlaczego-api-nie-laczy-sie-z-baza">sieci</a>owych lub infrastrukturalnych; to przyk&#322;ad specyficzny dla DynamoDB, a nie obietnica, &#380;e ka&#380;dy b&#322;&#261;d 500 zniknie po ponowieniu.</p><p>Przy &#380;&#261;daniu odczytu ponowienie cz&#281;sto jest bezpieczniejsze. Przy p&#322;atno&#347;ci, utworzeniu zam&oacute;wienia albo innym zapisie klient mo&#380;e nie wiedzie&#263;, czy serwer zd&#261;&#380;y&#322; wykona&#263; operacj&#281; przed b&#322;&#281;dem. Stosuj retry z ograniczon&#261; liczb&#261; pr&oacute;b i narastaj&#261;cym op&oacute;&#378;nieniem, a operacje, kt&oacute;re mog&#261; zosta&#263; powt&oacute;rzone, zabezpieczaj <strong>kluczem idempotencji</strong>, czyli identyfikatorem pozwalaj&#261;cym rozpozna&#263; ponowne wys&#322;anie tej samej operacji.</p><p>Gdy alert dotyczy krytycznego przep&#322;ywu, a b&#322;&#281;dy zacz&#281;&#322;y si&#281; po zmianie, najpierw przywr&oacute;&#263; sprawne dzia&#322;anie, na przyk&#322;ad przez rollback, je&#347;li potwierdzaj&#261; to dane. Potem odtw&oacute;rz zdarzenie na podstawie log&oacute;w i popraw przyczyn&#281;; samo maskowanie 500 kolejn&#261; pr&oacute;b&#261; mo&#380;e zamieni&#263; awari&#281; w seri&#281; duplikat&oacute;w.</p><h2 id="zamien-pojedyncze-500-w-uzyteczny-sygnal">Zamie&#324; pojedyncze 500 w u&#380;yteczny sygna&#322;</h2><p>Pojedynczy status nie wyja&#347;ni awarii, ale dobrze zaprojektowany monitoring mo&#380;e szybko pokaza&#263; jej zasi&#281;g i moment pocz&#261;tku. Alertuj na <strong>odsetek b&#322;&#281;d&oacute;w w danym endpointcie</strong>, nie tylko na surow&#261; liczb&#281; odpowiedzi, i zestawiaj go z op&oacute;&#378;nieniami oraz wersj&#261; wdro&#380;enia.</p><p>Gdy pojawi si&#281; nast&#281;pny 500, zacznij od pytania, gdzie odpowied&#378; powsta&#322;a i kt&oacute;re &#380;&#261;dania obejmuje. To prowadzi do log&oacute;w, trace ID i w&#322;a&#347;ciwej warstwy systemu, zamiast do przypadkowych restart&oacute;w.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>DevOps i infrastruktura</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/e46a7bd9ad53636adffd5c3137a0198e/http-500-po-wdrozeniu-znajdz-zrodlo-bledu.webp"/>
      <pubDate>Sun, 08 Nov 2026 14:46:00 +0100</pubDate>
    </item>
    <item>
      <title>try-catch w praktyce - jak obsługiwać wyjątki bez ukrywania błędów</title>
      <link>https://lukasz-zielinski.pl/try-catch-w-praktyce-jak-obslugiwac-wyjatki-bez-ukrywania-bledow</link>
      <description>Poznaj zasady try-catch: kiedy przechwytywać wyjątki, jak działa await i do czego służy finally. Sprawdź praktyczne przykłady w JavaScript.</description>
      <content:encoded><![CDATA[<p>Żądanie do API kończy się błędem, a aplikacja zamiast wyświetlić użytkownikowi sensowny komunikat nagle przerywa działanie. Blok <strong>try-catch</strong> pozwala przejąć kontrolę nad takim wyjątkiem, o ile kod w <code>catch</code> naprawdę potrafi obsłużyć problem, a nie tylko go ukrywa.</p>

<div class="short-summary">
  <h2 id="obsluguj-wyjatek-tylko-wtedy-gdy-wiesz-co-zrobic-dalej">Obsługuj wyjątek tylko wtedy, gdy wiesz, co zrobić dalej</h2>
  <ul>
    <li><strong>try</strong> obejmuje fragment, w którym może wystąpić wyjątek.</li>
    <li><strong>catch</strong> powinien rozpoznawać błąd i podjąć działanie albo przekazać go dalej.</li>
    <li><strong>finally</strong> służy do sprzątania, a nie do obsługi błędu.</li>
    <li>W JavaScript odrzucona obietnica trafia do <strong>try-catch</strong> tylko wtedy, gdy ją obsłużysz, na przykład przez <code>await</code>.</li>
  </ul>
</div>

<h2 id="blok-catch-ma-sens-tylko-wtedy-gdy-zmienia-dalszy-przebieg-programu">Blok catch ma sens tylko wtedy, gdy zmienia dalszy przebieg programu</h2>

<p>Wyjątek przerywa zwykły przepływ instrukcji i szuka pasującej obsługi. Gdy program ją znajdzie, wykonuje kod <code>catch</code>; jeśli nie, błąd może propagować się wyżej, aż do miejsca, które potrafi zareagować. <strong>Samo złapanie wyjątku nie naprawia problemu.</strong></p>

<p>Przykład w JavaScript pokazuje właściwy cel: zamienić techniczny błąd odczytu danych na kontrolowany rezultat dla aplikacji.</p>

<pre><code>async function pobierzProfil(id) {
  try {
    const odpowiedz = await fetch(`/api/profiles/${id}`);

    if (!odpowiedz.ok) {
      throw new Error(`HTTP ${odpowiedz.status}`);
    }

    return await odpowiedz.json();
  } catch (error) {
    console.error("Nie udało się pobrać profilu:", error);
    return null;
  }
}</code></pre>

<p>W takim wariancie funkcja zwraca <code>null</code>, więc jej kod wywołujący musi umieć obsłużyć brak profilu. Jeśli zwrócenie wartości zastępczej prowadziłoby do błędnych danych albo ukrywało awarię, zamiast tego wyjątek powinien zostać ponownie zgłoszony. <strong>Obsługa jest dobra dopiero wtedy, gdy dalszy stan programu pozostaje zrozumiały.</strong></p>

<h2 id="lap-tylko-bledy-na-ktore-masz-konkretna-reakcje">Łap tylko błędy, na które masz konkretną reakcję</h2>

<p>Najczęstsza pułapka jest kusząco prosta: objąć dużą część funkcji jednym <code>try</code> i przechwycić każdy wyjątek. Wtedy pojedynczy handler może ukryć zarówno spodziewany brak pliku, jak i błąd programistyczny, którego nie powinno się traktować jak zwykłego przypadku.</p>

<p>Przydatna reguła brzmi: <strong>jeśli potrafisz wskazać konkretną reakcję na dany typ błędu, przechwytuj go lokalnie; jeśli nie, pozwól mu dotrzeć do wyższej warstwy</strong>, która może zapisać kontekst i zdecydować o odpowiedzi. Ogólny handler na granicy aplikacji nadal może być potrzebny, ale nie powinien po cichu zamieniać każdej awarii w pozorny sukces.</p>

<table>
  <tbody>
    <tr>
      <th>Sytuacja</th>
      <th>Prawdopodobny skutek</th>
      <th>Co zrobić</th>
    </tr>
    <tr>
      <td>Błąd sieciowy, a ekran ma pokazać komunikat i umożliwić ponowienie</td>
      <td>Użytkownik może dostać czytelną informację zamiast przerwanego widoku</td>
      <td>Przechwyć spodziewany błąd i ustaw stan interfejsu na „nie udało się pobrać danych”</td>
    </tr>
    <tr>
      <td>Pusty blok <code>catch</code> lub samo logowanie bez dalszej decyzji</td>
      <td>Program może działać dalej, choć wynik operacji jest nieznany</td>
      <td>Przywróć bezpieczny stan, zwróć jawny błąd albo przekaż wyjątek wyżej</td>
    </tr>
    <tr>
      <td>W wielu miejscach pojawia się <code>catch (Exception)</code></td>
      <td>Różne błędy trafiają do tej samej, często zbyt ogólnej obsługi</td>
      <td>Zawęź typ wyjątku; szeroki handler zostaw dla granicy procesu lub aplikacji</td>
    </tr>
  </tbody>
</table>

<p>Badanie analizujące ponad <strong>10 tys. bloków obsługi wyjątków</strong> i ponad <strong>77 tys. przepływów wyjątków</strong> w 16 projektach Java i C# wykazało, że pojedynczy blok <code>try</code> może wiązać się nawet z 12 potencjalnie możliwymi wyjątkami, które dalej propagują się w programie. To dobry powód, by sprawdzać dokumentację wywoływanych metod zamiast zakładać, że ryzyko kończy się na widocznej linijce; opis badania znajdziesz w pracy <a href="https://arxiv.org/abs/1708.00817" target="_blank" rel="noopener noreferrer nofollow">Revisiting Exception Handling Practices with Exception Flow Analysis</a>.</p>

<h2 id="w-javascript-brak-await-moze-ominac-catch">W JavaScript brak await może ominąć catch</h2>

<p>Tu łatwo o błąd, który wygląda na działający kod. Blok <code>try-catch</code> przechwytuje synchroniczne wyjątki, ale przy operacjach asynchronicznych musi jeszcze dojść do faktycznego oczekiwania na wynik obietnicy. Dokumentacja <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function" target="_blank" rel="noopener noreferrer nofollow">MDN dotycząca funkcji async</a> wyjaśnia, że <code>await</code> pozwala potraktować odrzucenie obietnicy jak wyjątek w tym bloku.</p>

<pre><code>async function pobierzDane() {
  try {
    const dane = await pobierzZSerwera();
    return dane;
  } catch (error) {
    console.error("Pobieranie nie powiodło się:", error);
    return null;
  }
}</code></pre>

<p>Jeśli usuniesz <code>await</code>, funkcja może zwrócić odrzuconą obietnicę, zanim błąd dotrze do tego <code>catch</code>. Wtedy obsługę trzeba dodać w łańcuchu, na przykład przez <code>.catch(...)</code>, albo poczekać na wynik wewnątrz bloku. <strong>Sprawdź, czy błąd występuje podczas wywołania, czy dopiero po nim</strong> - od tego zależy, gdzie powinien znaleźć się handler.</p>

<p>Podobna ostrożność przydaje się przy wielu równoległych operacjach. Gdy każda ma zostać rozliczona osobno, dobierz sposób zbierania wyników do tego celu; sama lista wyrażeń <code>await</code> nie zawsze podłącza obsługę odrzuceń wszystkich obietnic w tym samym momencie.</p>

<h2 id="finally-sprzata-a-w-roznych-jezykach-robi-to-inaczej">finally sprząta, a w różnych językach robi to inaczej</h2>

<p>W bloku <code>finally</code> umieszcza się czynności, które powinny wykonać się przy opuszczaniu konstrukcji, na przykład zwolnienie zasobu lub zakończenie stanu ładowania. W JavaScript działa on po <code>try</code> i <code>catch</code>, także wtedy, gdy przepływ wychodzi przez <code>return</code>. Uważam, że najczytelniej trzymać tam sprzątanie, a nie decyzje o tym, czy błąd uznać za obsłużony.</p>

<p>Składnia zależy od języka, a drobne różnice wpływają na poprawność kodu. W C# kolejność bloków <code>catch</code> ma znaczenie: środowisko sprawdza je od góry i wykona pierwszy pasujący handler. Z kolei Java oferuje <code>try-with-resources</code>, który automatycznie zamyka zasoby implementujące <code>AutoCloseable</code>; szczegóły opisuje dokumentacja <a href="https://docs.oracle.com/javase/tutorial/essential/exceptions/handling.html" target="_blank" rel="noopener noreferrer nofollow">Oracle Java Tutorials</a>. W C# przykłady kolejności i ponownego zgłaszania wyjątku przedstawia <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/exception-handling-statements" target="_blank" rel="noopener noreferrer nofollow">dokumentacja Microsoft Learn</a>.</p>

<p>Praktycznie oznacza to, że nie przenoś mechanicznie wzorca z jednego języka do drugiego. W Javie dla zasobu, który trzeba zamknąć, rozważ konstrukcję <code>try-with-resources</code>; w C# uporządkuj obsługę typów od bardziej szczegółowych do ogólnych; w JavaScript upewnij się, że odrzucenie obietnicy rzeczywiście trafia do handlera.</p>

<h2 id="przed-dodaniem-try-catch-ustal-jaki-stan-ma-przetrwac-blad">Przed dodaniem try-catch ustal, jaki stan ma przetrwać błąd</h2>

<p>Najpierw odpowiedz sobie na jedno pytanie: <strong>co program ma zrobić, gdy ta operacja się nie powiedzie?</strong> Jeśli odpowiedź brzmi „pokazać komunikat i pozwolić ponowić”, lokalna obsługa może być właściwa. Jeśli nie ma bezpiecznej kontynuacji, przechwycenie wyjątku tylko opóźni moment, w którym problem stanie się widoczny.</p>

<p>Przy projektowaniu handlera nazwij typ błędu, zachowaj informacje przydatne do diagnozy i wybierz jawny rezultat albo ponowne zgłoszenie. Wtedy <code>try-catch</code> przestaje być siatką rozpiętą pod całym kodem, a staje się kontrolowanym punktem decyzji.</p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>Programowanie</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/0a5097d68271a551458f6e6cafd56a92/try-catch-w-praktyce-jak-obslugiwac-wyjatki-bez-ukrywania-bledow.webp"/>
      <pubDate>Sun, 08 Nov 2026 12:02:00 +0100</pubDate>
    </item>
    <item>
      <title>SQL DELETE - jak usuwać dane bezpiecznie</title>
      <link>https://lukasz-zielinski.pl/sql-delete-jak-usuwac-dane-bezpiecznie</link>
      <description>Jak bezpiecznie używać SQL DELETE? Sprawdź, jak testować WHERE, korzystać z transakcji i kontrolować klucze obce przed usunięciem danych.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Masz usun&#261;&#263; testowe konto z bazy, ale jego identyfikator wyst&#281;puje te&#380; w tabeli zam&oacute;wie&#324;. Polecenie <code>DELETE</code> skasuje wskazane wiersze, o ile warunek <code>WHERE</code> trafi dok&#322;adnie w nie, cho&#263; powi&#261;zania mi&#281;dzy tabelami mog&#261; zmieni&#263; wynik albo zablokowa&#263; operacj&#281;.</p><div class="short-summary">
  <h2 id="usun-tylko-te-wiersze-ktore-potrafisz-jednoznacznie-wskazac">Usu&#324; tylko te wiersze, kt&oacute;re potrafisz jednoznacznie wskaza&#263;</h2>
  <ul>
    <li><strong>Bez WHERE</strong> polecenie usuwa wszystkie wiersze z tabeli.</li>
    <li><strong>Przed DELETE</strong> uruchom SELECT z tym samym warunkiem i sprawd&#378; wynik.</li>
    <li><strong>Transakcja</strong> mo&#380;e umo&#380;liwi&#263; cofni&#281;cie zmian, je&#347;li nie zosta&#322;y zatwierdzone i silnik j&#261; obs&#322;uguje.</li>
    <li><strong>Sk&#322;adnia zale&#380;y od bazy</strong>, mi&#281;dzy innymi przy kasowaniu ograniczonej liczby rekord&oacute;w.</li>
  </ul>
</div><h2 id="delete-usuwa-wiersze-a-brak-where-obejmuje-cala-tabele">DELETE usuwa wiersze, a brak WHERE obejmuje ca&#322;&#261; tabel&#281;</h2><p>W codziennej pracy &#322;atwo pomyli&#263; poprawne polecenie z bezpiecznym poleceniem. <code>DELETE FROM users WHERE id = 42;</code> usuwa wiersz spe&#322;niaj&#261;cy warunek; wersja bez <code>WHERE</code> usuwa wszystkie wiersze, pozostawiaj&#261;c tabel&#281;, jej kolumny i indeksy.</p><p>Uwa&#380;am, &#380;e najbezpieczniejszy nawyk to najpierw potraktowa&#263; warunek jak zapytanie diagnostyczne. Ten sam filtr uruchomiony jako <code>SELECT</code> pokazuje, kt&oacute;re rekordy obejmie p&oacute;&#378;niejsze kasowanie.</p><pre><code>SELECT id, email
FROM users
WHERE id = 42;

DELETE FROM users
WHERE id = 42;</code></pre><p>Sprawd&#378;, czy wynik SELECT zawiera w&#322;a&#347;ciwy rekord, a potem upewnij si&#281;, &#380;e w edytorze wykonujesz ca&#322;e polecenie, nie sam&#261; jego pierwsz&#261; lini&#281;. Przy filtrze opartym na dacie, statusie albo fragmencie tekstu jeden warunek mo&#380;e pasowa&#263; do wielu wierszy.</p><h2 id="transakcja-pozwala-zatrzymac-delete-przed-zatwierdzeniem">Transakcja pozwala zatrzyma&#263; DELETE przed zatwierdzeniem</h2><p>Gdy nie masz pewno&#347;ci, czy filtr jest precyzyjny, transakcja daje dodatkowy etap kontroli. W <a href="https://lukasz-zielinski.pl/alter-table-bez-niespodzianek-jak-bezpiecznie-zmienic-tabele">PostgreSQL</a> mo&#380;esz wykona&#263; kasowanie i podejrze&#263; usuni&#281;te dane przez <code>RETURNING</code>, zanim zatwierdzisz transakcj&#281;.</p><pre><code>BEGIN;

DELETE FROM users
WHERE id = 42
RETURNING id, email;

-- Je&#347;li wynik jest poprawny:
COMMIT;

-- Je&#347;li co&#347; si&#281; nie zgadza, zamiast COMMIT:
ROLLBACK;</code></pre><p><code>RETURNING</code> zwraca wiersze obj&#281;te operacj&#261;, wi&#281;c nie trzeba odpytywa&#263; tabeli osobnym zapytaniem po usuni&#281;ciu. T&#281; sk&#322;adni&#281; opisuje dokumentacja <a href="https://www.postgresql.org/docs/current/dml-returning.html" target="_blank" rel="noopener noreferrer nofollow">PostgreSQL</a>. Zanim uruchomisz podobny skrypt w innym systemie, sprawd&#378; jego dokumentacj&#281;, bo dost&#281;pno&#347;&#263; i sk&#322;adnia tej klauzuli zale&#380;&#261; od bazy.</p><p>To zabezpieczenie dzia&#322;a pod warunkiem, &#380;e operacja odbywa si&#281; w transakcji, kt&oacute;r&#261; mo&#380;na wycofa&#263;, a klient nie zatwierdzi zmian automatycznie. Je&#347;li polecenie zosta&#322;o ju&#380; zatwierdzone, zwyk&#322;e <code>ROLLBACK</code> nie przywr&oacute;ci skasowanych rekord&oacute;w. Wtedy pozostaj&#261; mechanizmy odtwarzania, takie jak kopia zapasowa lub odzyskiwanie punktowe, je&#347;li s&#261; skonfigurowane.</p><h2 id="kasowanie-partiami-wymaga-skladni-wlasciwej-dla-silnika">Kasowanie partiami wymaga sk&#322;adni w&#322;a&#347;ciwej dla silnika</h2><p>Przy du&#380;ej tabeli usuwanie wszystkich pasuj&#261;cych rekord&oacute;w naraz mo&#380;e d&#322;ugo trzyma&#263; blokady i obci&#261;&#380;a&#263; baz&#281;. Rozbijanie operacji na partie bywa rozs&#261;dne, ale limit nie zawsze wybiera rekordy w kolejno&#347;ci, kt&oacute;rej oczekujesz.</p><p>W MySQL mo&#380;na po&#322;&#261;czy&#263; pojedynczotabelowe <code>DELETE</code> z <code>ORDER BY</code> i <code>LIMIT</code>. SQL Server obs&#322;uguje <code>TOP</code>, lecz samo <code>DELETE TOP (n)</code> nie gwarantuje kolejno&#347;ci wyboru wierszy. Microsoft zaleca u&#380;ycie podzapytania z <code>ORDER BY</code>, je&#347;li kasowanie ma przebiega&#263; na przyk&#322;ad od najstarszych rekord&oacute;w.</p><pre><code>-- MySQL: usuwaj najstarsze pasuj&#261;ce rekordy w partii
DELETE FROM events
WHERE created_at &lt; '2024-01-01'
ORDER BY created_at
LIMIT 500;</code></pre><p>R&oacute;&#380;nic&#281; mi&#281;dzy sk&#322;adniami opisuj&#261; dokumentacje <a href="https://dev.mysql.com/doc/refman/26.7/en/delete.html" target="_blank" rel="noopener noreferrer nofollow">MySQL</a> i <a href="https://learn.microsoft.com/en-us/sql/t-sql/queries/top-transact-sql?view=sql-server-ver17" target="_blank" rel="noopener noreferrer nofollow">Microsoft Learn dla SQL Server</a>. Nie przeno&#347; przyk&#322;adu z jednego silnika do drugiego bez sprawdzenia sk&#322;adni, a w operacji partiami u&#380;yj stabilnego kryterium, na przyk&#322;ad daty wraz z unikalnym identyfikatorem.</p><h2 id="klucze-obce-moga-zatrzymac-kasowanie-albo-usunac-kolejne-dane">Klucze obce mog&#261; zatrzyma&#263; kasowanie albo usun&#261;&#263; kolejne dane</h2><p>Wiersz mo&#380;e by&#263; powi&#261;zany z innymi tabelami przez klucz obcy. Wtedy baza mo&#380;e odm&oacute;wi&#263; usuni&#281;cia rekordu nadrz&#281;dnego albo skasowa&#263; powi&#261;zane rekordy, je&#347;li relacj&#281; skonfigurowano z akcj&#261; <code>ON DELETE CASCADE</code>.</p><table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Mo&#380;liwa przyczyna lub skutek</th>
      <th scope="col">Co zrobi&#263;</th>
    </tr>
    <tr>
      <td>DELETE zwraca b&#322;&#261;d klucza obcego</td>
      <td>Inne wiersze nadal wskazuj&#261; na rekord przeznaczony do usuni&#281;cia.</td>
      <td>Sprawd&#378; relacje i ustal, czy najpierw trzeba obs&#322;u&#380;y&#263; rekordy zale&#380;ne.</td>
    </tr>
    <tr>
      <td>Po usuni&#281;ciu znikaj&#261; rekordy z kilku tabel</td>
      <td>Relacja mo&#380;e mie&#263; skonfigurowane <code>ON DELETE CASCADE</code>.</td>
      <td>Przed kasowaniem sprawd&#378; definicje kluczy obcych i zakres operacji.</td>
    </tr>
    <tr>
      <td>Usuwa si&#281; wi&#281;cej wierszy ni&#380; zak&#322;adano</td>
      <td>Warunek pasuje do wielu rekord&oacute;w albo obejmuje zbyt szeroki zakres.</td>
      <td>Uruchom SELECT z tym samym filtrem i obejrzyj identyfikatory wynik&oacute;w.</td>
    </tr>
  </tbody>
</table><p>Przyk&#322;ad: konto klienta ma pi&#281;&#263; zam&oacute;wie&#324;. Je&#347;li relacja mi&#281;dzy klientami a zam&oacute;wieniami blokuje kasowanie, samo usuni&#281;cie klienta si&#281; nie powiedzie; przy kaskadzie mog&#261; znikn&#261;&#263; r&oacute;wnie&#380; jego zam&oacute;wienia. Uwa&#380;am, &#380;e przed operacj&#261; na danych produkcyjnych trzeba sprawdzi&#263; nie tylko warunek w <code>DELETE</code>, ale te&#380; zachowanie relacji.</p><h2 id="delete-truncate-i-drop-sluza-do-roznych-zadan">DELETE, TRUNCATE i DROP s&#322;u&#380;&#261; do r&oacute;&#380;nych zada&#324;</h2><p>Podobne nazwy &#322;atwo sprowadzi&#263; do jednego znaczenia: &bdquo;usu&#324; dane&rdquo;. Skutek zale&#380;y jednak od tego, czy chcesz wybra&#263; cz&#281;&#347;&#263; wierszy, opr&oacute;&#380;ni&#263; tabel&#281;, czy usun&#261;&#263; sam obiekt.</p><ul>
  <li><code>DELETE</code> usuwa wiersze wskazane przez warunek. Bez <code>WHERE</code> obejmuje wszystkie wiersze, ale zachowuje tabel&#281;.</li>
  <li><code>TRUNCATE</code> s&#322;u&#380;y do szybkiego opr&oacute;&#380;nienia tabeli, jednak jego dost&#281;pno&#347;&#263;, mo&#380;liwo&#347;&#263; cofni&#281;cia i dzia&#322;anie przy kluczach obcych zale&#380;&#261; od systemu bazodanowego.</li>
  <li><code>DROP TABLE</code> usuwa tabel&#281; jako obiekt, a wi&#281;c tak&#380;e jej struktur&#281;.</li>
</ul><p>Dokumentacja MySQL wskazuje, &#380;e <code>TRUNCATE TABLE</code> mo&#380;e szybciej opr&oacute;&#380;ni&#263; tabel&#281; ni&#380; <code>DELETE</code> bez warunku, ale nie mo&#380;na go u&#380;y&#263; w transakcji. To szczeg&oacute;&#322;, kt&oacute;ry zmienia wyb&oacute;r: je&#347;li potrzebujesz mo&#380;liwo&#347;ci wycofania operacji, sprawd&#378; zachowanie konkretnego silnika, zamiast zast&#281;powa&#263; jedno polecenie drugim.</p><h2 id="przed-wykonaniem-sprawdz-trzy-rzeczy">Przed wykonaniem sprawd&#378; trzy rzeczy</h2><p>Przy kasowaniu liczy si&#281; nie d&#322;ugo&#347;&#263; zapytania, lecz to, czy przewidziano jego rzeczywisty zakres. Przed uruchomieniem skryptu sprawd&#378; <strong>warunek, relacje i mo&#380;liwo&#347;&#263; cofni&#281;cia</strong>.</p><ul>
  <li>Uruchom <code>SELECT</code> z dok&#322;adnie tym samym filtrem.</li>
  <li>Sprawd&#378; klucze obce oraz ewentualne kaskadowe usuwanie.</li>
  <li>Ustal, czy pracujesz w transakcji i czy klient nie zatwierdzi zmian automatycznie.</li>
  <li>Przy du&#380;ej liczbie rekord&oacute;w sprawd&#378; sk&#322;adni&#281; partii dla swojego silnika.</li>
</ul><p>Je&#347;li te punkty s&#261; jasne, <code>DELETE</code> staje si&#281; przewidywalnym narz&#281;dziem, a nie ruchem w ciemno. Najwi&#281;cej ostro&#380;no&#347;ci wymagaj&#261; warunki, kt&oacute;re wygl&#261;daj&#261; precyzyjnie, lecz w bazie pasuj&#261; do wi&#281;kszej liczby danych, ni&#380; zak&#322;adasz.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Bazy danych</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/7da28fcc6139a32fcc5674fd1c0aebd0/sql-delete-jak-usuwac-dane-bezpiecznie.webp"/>
      <pubDate>Sun, 08 Nov 2026 08:34:00 +0100</pubDate>
    </item>
    <item>
      <title>Hackathon - co naprawdę daje udział i jak się przygotować?</title>
      <link>https://lukasz-zielinski.pl/hackathon-co-naprawde-daje-udzial-i-jak-sie-przygotowac</link>
      <description>Hackathon to nie zawsze konkurs. Sprawdź, co daje udział, jak zbudować prototyp i co zweryfikować w regulaminie przed startem.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p><strong>Masz pomys&#322; na aplikacj&#281;, ale zwykle brakuje czasu, zespo&#322;u albo powodu, &#380;eby wreszcie zacz&#261;&#263;?</strong> Hackathon to wydarzenie, podczas kt&oacute;rego uczestnicy pracuj&#261; nad rozwi&#261;zaniem okre&#347;lonego problemu w ograniczonym czasie, cho&#263; nie ka&#380;da edycja ko&#324;czy si&#281; konkursem i wyborem zwyci&#281;zcy. W&#322;a&#347;nie ten szczeg&oacute;&#322; zmienia to, czego mo&#380;esz oczekiwa&#263; od udzia&#322;u.</p><div class="short-summary">
  <h2 id="hackathon-daje-krotki-termin-i-wspolny-cel-ale-efekt-zalezy-od-formatu">Hackathon daje kr&oacute;tki termin i wsp&oacute;lny cel, ale efekt zale&#380;y od formatu</h2>
  <ul>
    <li><strong>Efekt:</strong> najcz&#281;&#347;ciej powstaje <a href="https://lukasz-zielinski.pl/mvp-jak-zbudowac-wersje-ktora-sprawdza-pomysl">prototyp</a> lub demonstracja pomys&#322;u, a nie gotowy, produkcyjny produkt.</li>
    <li><strong>Sk&#322;ad zespo&#322;u:</strong> poza programowaniem przydaj&#261; si&#281; projektowanie UX/UI, wiedza domenowa i umiej&#281;tno&#347;&#263; prezentacji.</li>
    <li><strong>Do&#347;wiadczenie:</strong> pocz&#261;tkuj&#261;cy mog&#261; do&#322;&#261;czy&#263;, je&#347;li zakres zadania i zasady wydarzenia odpowiadaj&#261; ich umiej&#281;tno&#347;ciom.</li>
    <li><strong>Przed zg&#322;oszeniem:</strong> sprawd&#378; regulamin, kryteria oceny, zasady u&#380;ycia gotowego kodu oraz prawa do projektu.</li>
  </ul>
</div><h2 id="hackathon-konczy-sie-prototypem-a-niekoniecznie-dzialajacym-produktem">Hackathon ko&#324;czy si&#281; prototypem, a niekoniecznie dzia&#322;aj&#261;cym produktem</h2><p>Wyobra&#378; sobie, &#380;e w pi&#261;tek wieczorem zesp&oacute;&#322; dostaje problem do rozwi&#261;zania, a w niedziel&#281; ma pokaza&#263; pomys&#322; jury. Taki sprint to sedno hackathonu: pracujesz z innymi nad rozwi&#261;zaniem konkretnego wyzwania, zwykle technicznego, biznesowego lub spo&#322;ecznego. <strong>Hackowanie</strong> oznacza tu eksperymentowanie i szybkie budowanie, nie w&#322;amywanie si&#281; do system&oacute;w.</p><p>Rezultatem bywa klikalny prototyp, fragment aplikacji, wizualizacja danych albo demonstracja koncepcji. Taki efekt mo&#380;e przekona&#263; do dalszego rozwijania projektu, ale sam w sobie nie dowodzi, &#380;e rozwi&#261;zanie jest bezpieczne, skalowalne i gotowe dla klient&oacute;w. Prawd&#281; m&oacute;wi&#261;c, w&#322;a&#347;nie t&#281; r&oacute;&#380;nic&#281; naj&#322;atwiej przeoczy&#263;, gdy prezentacja wygl&#261;da efektownie.</p><h2 id="dobry-zespol-potrzebuje-wiecej-niz-samych-programistow">Dobry zesp&oacute;&#322; potrzebuje wi&#281;cej ni&#380; samych programist&oacute;w</h2><p>Kod nie rozwi&#261;&#380;e problemu, je&#347;li zesp&oacute;&#322; nie ustali, dla kogo buduje i co chce sprawdzi&#263;. Poza osobami programuj&#261;cymi przydaj&#261; si&#281; wi&#281;c kompetencje z UX/UI, analizy danych, dziedziny, kt&oacute;rej dotyczy wyzwanie, oraz prezentowania pomys&#322;&oacute;w. W mniejszej ekipie jedna osoba mo&#380;e &#322;&#261;czy&#263; kilka r&oacute;l.</p><p>Je&#347;li przychodzisz bez gotowego zespo&#322;u, sprawd&#378;, czy organizator przewiduje dobieranie ekip na miejscu. Pocz&#261;tkuj&#261;cy te&#380; mog&#261; wnie&#347;&#263; wk&#322;ad: przygotowa&#263; makiet&#281;, opisa&#263; przypadki u&#380;ycia, przetestowa&#263; przep&#322;yw aplikacji lub zebra&#263; dane. <strong>Nie musisz zna&#263; ca&#322;ego stosu technologicznego</strong>, ale przed wydarzeniem obejrzyj temat i narz&#281;dzia, kt&oacute;rych organizator wymaga.</p><h2 id="regulamin-moze-zmienic-znaczenie-gotowego-kodu-i-samego-finalu">Regulamin mo&#380;e zmieni&#263; znaczenie gotowego kodu i samego fina&#322;u</h2><p>Dwa wydarzenia nazwane hackathonami mog&#261; dzia&#322;a&#263; zupe&#322;nie inaczej. Przyk&#322;adowo opis <a href="https://nahackathon.pl/" target="_blank" rel="noopener noreferrer nofollow">Hackathonu HS3</a> wskazuje format bez rywalizacji i zwyci&#281;zc&oacute;w, podczas gdy w regulaminie konkursowego <a href="https://bip.stat.gov.pl/files/gfx/bip/pl/defaultstronaopisowa/826/1/1/hackathon_kodujsdg_regulamin.pdf" target="_blank" rel="noopener noreferrer nofollow">hackathonu GUS &bdquo;Koduj z GUS&rdquo;</a> zapisano, &#380;e zg&#322;oszony prototyp aplikacji ma powsta&#263; podczas wydarzenia i bazowa&#263; na pracy uczestnik&oacute;w. <strong>Sama nazwa nie m&oacute;wi wi&#281;c, czy liczy si&#281; konkurs, wsp&oacute;&#322;praca czy konkretny rezultat.</strong></p><p>Przed zapisem szukaj w regulaminie odpowiedzi na cztery pytania: co wolno przygotowa&#263; wcze&#347;niej, jakie narz&#281;dzia i biblioteki mo&#380;na wykorzysta&#263;, kto zachowuje prawa do projektu oraz jak jury b&#281;dzie go ocenia&#263;. Je&#347;li nie widzisz jasnych zasad dotycz&#261;cych kodu lub w&#322;asno&#347;ci intelektualnej, popro&#347; organizatora o wyja&#347;nienie przed rozpocz&#281;ciem pracy. Taki detal mo&#380;e przes&#261;dzi&#263;, czy pomys&#322; da si&#281; p&oacute;&#378;niej rozwija&#263; poza wydarzeniem.</p><h2 id="jesli-masz-tylko-pomysl-przez-pierwsze-godziny-ogranicz-jego-zakres">Je&#347;li masz tylko pomys&#322;, przez pierwsze godziny ogranicz jego zakres</h2><p>Za&#322;&oacute;&#380;my, &#380;e zesp&oacute;&#322; chce stworzy&#263; aplikacj&#281;, kt&oacute;ra pomaga mieszka&#324;com zg&#322;asza&#263; problemy w okolicy. Pe&#322;ny produkt wymaga&#322;by kont u&#380;ytkownik&oacute;w, mapy, powiadomie&#324; i panelu dla urz&#281;du. W kr&oacute;tkim sprincie lepiej wybra&#263; jeden przep&#322;yw: zg&#322;oszenie usterki na mapie i podgl&#261;d statusu.</p><p>Takie zaw&#281;&#380;enie pozwala pokaza&#263; dzia&#322;anie rozwi&#261;zania zamiast kilku niedoko&#324;czonych ekran&oacute;w. Pod koniec zesp&oacute;&#322; mo&#380;e zaprezentowa&#263;, jaki problem rozwi&#261;zuje prototyp, jak z niego skorzysta&#263; i czego jeszcze nie obejmuje. <strong>Uwa&#380;am, &#380;e udany projekt hackathonowy to taki, kt&oacute;ry jasno pokazuje jedn&#261; sprawdzaln&#261; hipotez&#281;</strong>, a nie obiecuje kompletnego systemu.</p><table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Co mo&#380;e z niej wynika&#263;</th>
      <th scope="col">Co zrobi&#263;</th>
    </tr>
    <tr>
      <td>Nie masz zespo&#322;u</td>
      <td>Mo&#380;esz nie zd&#261;&#380;y&#263; znale&#378;&#263; os&oacute;b o uzupe&#322;niaj&#261;cych si&#281; kompetencjach.</td>
      <td>Sprawd&#378;, czy organizator prowadzi dobieranie ekip; przygotuj kr&oacute;tkie przedstawienie umiej&#281;tno&#347;ci i pomys&#322;u.</td>
    </tr>
    <tr>
      <td>Masz gotowy fragment aplikacji</td>
      <td>Regulamin mo&#380;e ogranicza&#263; u&#380;ycie kodu sprzed wydarzenia.</td>
      <td>Przeczytaj zasady dotycz&#261;ce pracy w&#322;asnej i materia&#322;&oacute;w zewn&#281;trznych, a w razie w&#261;tpliwo&#347;ci zapytaj organizatora.</td>
    </tr>
    <tr>
      <td>Chcesz p&oacute;&#378;niej rozwija&#263; projekt</td>
      <td>Niejasne zapisy mog&#261; utrudni&#263; ustalenie, kto ma prawa do rozwi&#261;zania.</td>
      <td>Przed zg&#322;oszeniem sprawd&#378; postanowienia o w&#322;asno&#347;ci intelektualnej i licencjach.</td>
    </tr>
    <tr>
      <td>Nie chcesz rywalizowa&#263;</td>
      <td>Wydarzenie mo&#380;e mie&#263; form&#281; wsp&oacute;&#322;pracy bez rankingu albo konkurs z jury.</td>
      <td>Zweryfikuj format, kryteria oceny i to, czy fina&#322; wymaga prezentacji.</td>
    </tr>
  </tbody>
</table><h2 id="udzial-ma-sens-gdy-cel-wydarzenia-pasuje-do-twojego-celu">Udzia&#322; ma sens, gdy cel wydarzenia pasuje do twojego celu</h2><p>Hackathon mo&#380;e pom&oacute;c prze&#263;wiczy&#263; prac&#281; w zespole, sprawdzi&#263; now&#261; technologi&#281; albo pozna&#263; osoby z bran&#380;y. Nie traktowa&#322;bym jednak samego udzia&#322;u jako gwarancji oferty pracy. Projekt mo&#380;e sta&#263; si&#281; dobrym materia&#322;em do portfolio, je&#347;li potrafisz wyja&#347;ni&#263; sw&oacute;j wk&#322;ad, decyzje techniczne i ograniczenia prototypu.</p><p>Je&#347;li zale&#380;y ci na nauce, szukaj wydarzenia z mentorami i zadaniami dopasowanymi do poziomu uczestnik&oacute;w. Gdy chcesz rozwija&#263; pomys&#322; biznesowy, wa&#380;niejsze b&#281;d&#261; dost&#281;p do ekspert&oacute;w domenowych, prawa do rozwi&#261;zania i mo&#380;liwo&#347;&#263; dalszej wsp&oacute;&#322;pracy. <strong>Wyb&oacute;r formatu podporz&#261;dkuj temu, co chcesz wynie&#347;&#263;</strong>, zamiast kierowa&#263; si&#281; sam&#261; nagrod&#261; lub rozpoznawalno&#347;ci&#261; organizatora.</p><h2 id="najlepszy-final-to-projekt-ktory-da-sie-obronic-po-prezentacji">Najlepszy fina&#322; to projekt, kt&oacute;ry da si&#281; obroni&#263; po prezentacji</h2><p>Na scenie &#322;atwo skupi&#263; si&#281; na slajdach i efekcie &bdquo;wow&rdquo;. Po hackathonie bardziej przyda si&#281; umiej&#281;tno&#347;&#263; wskazania, co dzia&#322;a, co pozostaje atrap&#261; i jaki by&#322;by nast&#281;pny krok przed wdro&#380;eniem. To w&#322;a&#347;nie taka uczciwa prezentacja sprawia, &#380;e prototyp mo&#380;e sta&#263; si&#281; pocz&#261;tkiem sensownego projektu, a nie tylko weekendow&#261; demonstracj&#261;.</p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>Kariera i biznes IT</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/e454f421068cfbf2a60c993d3d49266b/hackathon-co-naprawde-daje-udzial-i-jak-sie-przygotowac.webp"/>
      <pubDate>Fri, 06 Nov 2026 14:08:00 +0100</pubDate>
    </item>
    <item>
      <title>Interfejs w telefonie - czym różni się system, nakładka i aplikacja?</title>
      <link>https://lukasz-zielinski.pl/interfejs-w-telefonie-czym-rozni-sie-system-nakladka-i-aplikacja</link>
      <description>Czym jest interfejs w telefonie? Poznaj różnice między systemem, nakładką i aplikacją oraz sprawdź, jak oceniać wygodę obsługi.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>

</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/60e58e696aa22d998d40679d1008d16a/android-smartphone-user-interface-home-screen-settings-panel-app-navigation-ux.webp" class="image article-image" loading="lazy" alt="Widok interfejsu w telefonie z map&#261; San Francisco. Widoczna wyszukiwarka, ikony dom, restauracje, kawa i menu z opcjami: Explore, Go, Saved, Contribute, Updates."></p><p>Odblokowujesz telefon, przesuwasz palcem po ekranie i otwierasz aplikacj&#281; bez zastanawiania si&#281;, gdzie nacisn&#261;&#263;. <strong>Interfejs w telefonie</strong> to warstwa, przez kt&oacute;r&#261; obs&#322;ugujesz urz&#261;dzenie i jego aplikacje, cho&#263; jej wygl&#261;d zale&#380;y od systemu, producenta oraz konkretnego programu.</p><div class="short-summary">
  <h2 id="interfejs-laczy-ekran-z-dzialaniem-telefonu">Interfejs &#322;&#261;czy ekran z dzia&#322;aniem telefonu</h2>
  <ul>
    <li><strong>Interfejs systemu</strong> obejmuje mi&#281;dzy innymi ekran g&#322;&oacute;wny, powiadomienia, ustawienia i nawigacj&#281;.</li>
    <li><strong>Interfejs aplikacji</strong> to przyciski, pola, menu i inne elementy s&#322;u&#380;&#261;ce do wykonania zada&#324; w programie.</li>
    <li><strong>Android i iOS</strong> inaczej organizuj&#261; cz&#281;&#347;&#263; gest&oacute;w i element&oacute;w systemowych.</li>
    <li><strong>Dla tw&oacute;rcy aplikacji</strong> liczy si&#281; czytelno&#347;&#263;, <a href="https://lukasz-zielinski.pl/justowanie-tekstu-kiedy-poprawia-wyglad-a-kiedy-szkodzi">dost&#281;pno&#347;&#263;</a> i poprawne dzia&#322;anie na r&oacute;&#380;nych ekranach.</li>
  </ul>
</div><h2 id="interfejs-to-sposob-w-jaki-telefon-odpowiada-na-twoje-dzialania">Interfejs to spos&oacute;b, w jaki telefon odpowiada na twoje dzia&#322;ania</h2><p>Dotykasz ikony, wpisujesz tekst albo przesuwasz panel powiadomie&#324;. Ka&#380;dy taki ruch jest cz&#281;&#347;ci&#261; interakcji, a elementy widoczne na ekranie podpowiadaj&#261;, co mo&#380;esz zrobi&#263; i co stanie si&#281; po dotkni&#281;ciu. <strong>Interfejs u&#380;ytkownika, czyli UI</strong>, obejmuje te elementy wizualne oraz sposoby sterowania urz&#261;dzeniem.</p><p>W telefonie spotykaj&#261; si&#281; co najmniej dwie warstwy. <strong>Interfejs systemowy</strong> obs&#322;uguje funkcje urz&#261;dzenia, na przyk&#322;ad pasek stanu, ekran blokady czy szybkie ustawienia. Interfejs aplikacji nale&#380;y do konkretnego programu: w komunikatorze b&#281;d&#261; to lista rozm&oacute;w i pole wiadomo&#347;ci, a w mapach widok trasy i kontrolki nawigacji.</p><p>To rozr&oacute;&#380;nienie przydaje si&#281;, gdy co&#347; wygl&#261;da inaczej ni&#380; na zrzucie ekranu z instrukcji. Producent mo&#380;e zmieni&#263; wygl&#261;d ekranu g&#322;&oacute;wnego lub panelu systemowego, ale nie oznacza to automatycznie, &#380;e zmieni&#322; si&#281; sam Android albo aplikacja.</p><h2 id="nakladka-producenta-zmienia-wyglad-androida-a-aplikacja-ma-wlasne-ui">Nak&#322;adka producenta zmienia wygl&#261;d Androida, a aplikacja ma w&#322;asne UI</h2><p>Na dw&oacute;ch telefonach z Androidem te same ustawienia mog&#261; wygl&#261;da&#263; inaczej. Samsung stosuje <strong>One UI</strong>, Xiaomi rozwija <strong>HyperOS</strong>, a ich rozwi&#261;zania wp&#322;ywaj&#261; na uk&#322;ad element&oacute;w systemowych, personalizacj&#281; i dost&#281;p do cz&#281;&#347;ci funkcji.</p><p>To w&#322;a&#347;nie nak&#322;adka, czyli warstwa producenta dzia&#322;aj&#261;ca na systemie, cz&#281;sto odpowiada za r&oacute;&#380;nice w ekranie g&#322;&oacute;wnym czy panelu szybkich ustawie&#324;. Aplikacja mo&#380;e z kolei mie&#263; w&#322;asny uk&#322;ad i komponenty. Dlatego problem z wygl&#261;dem jednej aplikacji nie musi oznacza&#263;, &#380;e ca&#322;y interfejs telefonu dzia&#322;a nieprawid&#322;owo.</p><p><strong>Moja ocena jest prosta:</strong> przy analizie problemu najpierw rozdzieli&#322;bym system, nak&#322;adk&#281; i aplikacj&#281;. Dzi&#281;ki temu &#322;atwiej ustali&#263;, czy szuka&#263; opcji w ustawieniach telefonu, w konfiguracji programu, czy w jego aktualizacji.</p><h2 id="android-i-ios-inaczej-prowadza-przez-te-same-zadania">Android i iOS inaczej prowadz&#261; przez te same zadania</h2><p>Wykonanie podobnej czynno&#347;ci mo&#380;e wymaga&#263; innego gestu zale&#380;nie od telefonu. Na przyk&#322;ad panel sterowania w iPhonie otwiera si&#281; gestem od g&oacute;rnej kraw&#281;dzi ekranu; <a href="https://support.apple.com/guide/iphone/use-and-customize-control-center-iph59095ec58/27/ios/27" target="_blank" rel="noopener noreferrer nofollow">instrukcja Apple dotycz&#261;ca centrum sterowania</a> opisuje te&#380; r&oacute;&#380;nice zale&#380;ne od modelu.</p><p>Android pozostawia producentom wi&#281;cej swobody w sposobie prezentowania cz&#281;&#347;ci funkcji, ale aplikacja nadal musi uwzgl&#281;dnia&#263; obszary zaj&#281;te przez systemowe paski. Dokumentacja <a href="https://developer.android.com/design/ui/mobile/guides/foundations/system-bars" target="_blank" rel="noopener noreferrer nofollow">Android Developers o paskach systemowych</a> wyja&#347;nia, &#380;e interfejs aplikacji mo&#380;e uk&#322;ada&#263; tre&#347;&#263; tak&#380;e pod nimi, wi&#281;c projekt musi chroni&#263; wa&#380;ne elementy przed zas&#322;oni&#281;ciem.</p><p>Dla osoby tworz&#261;cej frontend oznacza to praktyczny test: nie wystarczy sprawdzi&#263; jednego zrzutu ekranu. Trzeba zobaczy&#263;, czy przyciski i tre&#347;&#263; pozostaj&#261; dost&#281;pne przy r&oacute;&#380;nych metodach nawigacji oraz po zmianie rozmiaru ekranu.</p><h2 id="maly-przycisk-moze-byc-trudny-do-trafienia-nawet-gdy-wyglada-dobrze">Ma&#322;y przycisk mo&#380;e by&#263; trudny do trafienia, nawet gdy wygl&#261;da dobrze</h2><p>Ikona wielko&#347;ci paznokcia mo&#380;e wygl&#261;da&#263; elegancko, ale obs&#322;uga kciukiem szybko ujawni problem. <strong>Obszar dotykowy</strong> to ca&#322;e pole reaguj&#261;ce na dotyk, kt&oacute;re mo&#380;e by&#263; wi&#281;ksze ni&#380; sama widoczna ikona.</p><p>W wytycznych <a href="https://developer.android.com/guide/topics/ui/accessibility/views/apps-views" target="_blank" rel="noopener noreferrer nofollow">Android Developers dotycz&#261;cych dost&#281;pno&#347;ci</a> zalecany minimalny obszar interaktywnych element&oacute;w wynosi 48 &times; 48 dp. dp to jednostka skalowana wzgl&#281;dem g&#281;sto&#347;ci ekranu, wi&#281;c nie nale&#380;y odczytywa&#263; jej jako sta&#322;ej liczby pikseli na ka&#380;dym telefonie.</p><p>Przy projektowaniu warto wi&#281;c sprawdzi&#263; nie tylko kolor i kszta&#322;t przycisku, lecz tak&#380;e to, czy da si&#281; go wygodnie nacisn&#261;&#263;. Je&#347;li ekran ma du&#380;o ciasno rozmieszczonych ikon, powi&#281;kszenie pola dotykowego mo&#380;e pom&oacute;c bez powi&#281;kszania samej grafiki.</p><h2 id="gdy-cos-na-ekranie-nie-dziala-najpierw-ustal-do-ktorej-warstwy-nalezy">Gdy co&#347; na ekranie nie dzia&#322;a, najpierw ustal, do kt&oacute;rej warstwy nale&#380;y</h2><p>Znikaj&#261;cy przycisk albo zas&#322;oni&#281;ty tekst mo&#380;e wynika&#263; z ustawie&#324; systemu, nak&#322;adki producenta lub b&#322;&#281;du aplikacji. Zamiast od razu zmienia&#263; kilka opcji naraz, zaw&#281;&#378; &#378;r&oacute;d&#322;o problemu.</p><table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Mo&#380;liwa przyczyna</th>
      <th scope="col">Co sprawdzi&#263;</th>
    </tr>
    <tr>
      <td>Inny wygl&#261;d ekranu g&#322;&oacute;wnego ni&#380; w instrukcji</td>
      <td>Nak&#322;adka producenta albo inny launcher</td>
      <td>Sprawd&#378; nazw&#281; modelu telefonu i ustawienia ekranu g&#322;&oacute;wnego</td>
    </tr>
    <tr>
      <td>Jedna aplikacja ma uci&#281;ty tekst lub przycisk</td>
      <td>Uk&#322;ad aplikacji nie uwzgl&#281;dnia rozmiaru ekranu lub obszaru systemowego</td>
      <td>Zaktualizuj aplikacj&#281; i sprawd&#378;, czy problem wyst&#281;puje w innych programach</td>
    </tr>
    <tr>
      <td>Gest nawigacji zachowuje si&#281; inaczej ni&#380; oczekiwano</td>
      <td>Aktywna inna metoda nawigacji albo gest systemowy</td>
      <td>Odszukaj w ustawieniach telefonu opcje nawigacji systemowej</td>
    </tr>
  </tbody>
</table><p><strong>Najpierw por&oacute;wnaj zachowanie kilku aplikacji.</strong> Je&#347;li k&#322;opot pojawia si&#281; tylko w jednej, podejrzenie pada na jej interfejs. Gdy dotyczy ca&#322;ego telefonu, sprawd&#378; ustawienia systemu i nak&#322;adki, zanim uznasz, &#380;e winna jest aplikacja.</p><h2 id="najlepszy-interfejs-nie-zmusza-do-zgadywania">Najlepszy interfejs nie zmusza do zgadywania</h2><p>Dobry interfejs podpowiada, gdzie jeste&#347;, co mo&#380;esz zrobi&#263; i jaki b&#281;dzie skutek dotkni&#281;cia elementu. W aplikacji do pracy mo&#380;e to oznacza&#263; wyra&#378;ny przycisk zapisu oraz komunikat po wys&#322;aniu formularza; w telefonie szybki dost&#281;p do podstawowych ustawie&#324;.</p><p>Je&#347;li projektujesz aplikacj&#281;, traktuj interfejs jako umow&#281; z u&#380;ytkownikiem: widoczny element powinien zachowywa&#263; si&#281; zgodnie z tym, co sugeruje jego wygl&#261;d. Gdy korzystanie z telefonu wymaga zgadywania, problem le&#380;y zwykle nie w u&#380;ytkowniku, lecz w sposobie zaprojektowania tej umowy.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Frontend i UX</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/c0acf5d466d6cc9ad0c6fb626620cd5b/interfejs-w-telefonie-czym-rozni-sie-system-nakladka-i-aplikacja.webp"/>
      <pubDate>Thu, 05 Nov 2026 17:38:00 +0100</pubDate>
    </item>
    <item>
      <title>Nginx 403 Forbidden - jak znaleźć prawdziwą przyczynę?</title>
      <link>https://lukasz-zielinski.pl/nginx-403-forbidden-jak-znalezc-prawdziwa-przyczyne</link>
      <description>Nginx 403 Forbidden? Sprawdź error.log, indeks, uprawnienia i reguły dostępu. Poznaj bezpieczną diagnozę bez ryzykownego chmod 777.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Po wdro&#380;eniu aplikacji strona g&#322;&oacute;wna nagle zwraca <strong>403 Forbidden</strong>, cho&#263; Nginx dzia&#322;a, a pliki s&#261; na serwerze. Najcz&#281;&#347;ciej blokuje j&#261; brak pliku indeksowego, niedost&#281;pne uprawnienia albo regu&#322;a dost&#281;pu, ale sam kod odpowiedzi nie wskazuje jeszcze, kt&oacute;ra z tych przyczyn wyst&#261;pi&#322;a.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/aa663ce130e644252c368e0e0a330a32/nginx-403-forbidden-analiza-error-log-i-uprawnienia-plikow-diagram.webp" class="image article-image" loading="lazy" alt="Ikona serwera z tarcz&#261; i k&#322;&oacute;dk&#261;, symbolizuj&#261;ca bezpiecze&#324;stwo. Obok tr&oacute;jk&#261;t z wykrzyknikiem, ostrzegaj&#261;cy przed problemem. Tekst " forbidden nginx sugeruje b dost></p><div class="short-summary">
  <h2 id="najpierw-odczytaj-powod-z-logu-dopiero-potem-zmieniaj-konfiguracje">Najpierw odczytaj pow&oacute;d z logu, dopiero potem zmieniaj konfiguracj&#281;</h2>
  <ul>
    <li><strong>&bdquo;directory index &hellip; is forbidden&rdquo;</strong> zwykle oznacza brak pliku indeksowego w &#380;&#261;danym katalogu.</li>
    <li><strong>&bdquo;Permission denied&rdquo;</strong> kieruje do uprawnie&#324; pliku lub kt&oacute;rego&#347; katalogu nadrz&#281;dnego.</li>
    <li><strong>&bdquo;access forbidden by rule&rdquo;</strong> wskazuje na regu&#322;&#281; dost&#281;pu, na przyk&#322;ad <code>deny</code>.</li>
    <li><strong>Nie w&#322;&#261;czaj odruchowo <code>autoindex</code></strong>, bo zamiast strony mo&#380;esz ujawni&#263; publiczny spis plik&oacute;w.</li>
  </ul>
</div><h2 id="403-nie-podaje-przyczyny-ale-log-zwykle-ja-zdradza">403 nie podaje przyczyny, ale log zwykle j&#261; zdradza</h2><p>Kod 403 oznacza, &#380;e serwer odmawia dost&#281;pu do &#380;&#261;danego zasobu. W Nginx przyczyn&#261; mo&#380;e by&#263; konfiguracja strony, brak pliku indeksowego, prawa systemu plik&oacute;w lub ograniczenie dost&#281;pu dla danego adresu IP. <strong>Komunikat widoczny w przegl&#261;darce nie wystarcza do diagnozy</strong>, bo r&oacute;&#380;ne problemy mog&#261; wygl&#261;da&#263; identycznie.</p><p>Uwa&#380;am, &#380;e pierwsz&#261; zmian&#261; nie powinno by&#263; masowe ustawianie praw na plikach. Najpierw od&#347;wie&#380; stron&#281;, a zaraz potem sprawd&#378; najnowszy wpis w <code>error.log</code>. &#346;cie&#380;ka do logu zale&#380;y od konfiguracji, wi&#281;c je&#347;li standardowe miejsce jest puste, poszukaj dyrektywy <code>error_log</code> w konfiguracji serwera.</p><pre><code>sudo tail -n 50 /var/log/nginx/error.log</code></pre><p>Najbardziej przydatna jest ko&#324;c&oacute;wka wpisu, kt&oacute;ra nazywa problem. <strong>To ona rozstrzyga, czy szuka&#263; w plikach, konfiguracji dost&#281;pu, czy poza samym Nginx</strong>.</p><h2 id="tresc-wpisu-wskazuje-od-ktorego-testu-zaczac">Tre&#347;&#263; wpisu wskazuje, od kt&oacute;rego testu zacz&#261;&#263;</h2><p>Nie ka&#380;dy b&#322;&#261;d 403 oznacza problem z uprawnieniami. Przyk&#322;adowo komunikat o indeksie katalogu i komunikat o odmowie systemu operacyjnego prowadz&#261; do zupe&#322;nie innych napraw, dlatego najpierw dopasuj log do objawu.</p><table>
  <tbody>
    <tr>
      <th>Wpis w logu lub sytuacja</th>
      <th>Prawdopodobna przyczyna</th>
      <th>Co sprawdzi&#263;</th>
    </tr>
    <tr>
      <td><code>directory index of ".../" is forbidden</code></td>
      <td>&#379;&#261;dany katalog nie zawiera pliku indeksowego rozpoznawanego przez konfiguracj&#281;.</td>
      <td>Sprawd&#378; <code>root</code>, zawarto&#347;&#263; katalogu oraz dyrektyw&#281; <code>index</code>.</td>
    </tr>
    <tr>
      <td><code>Permission denied</code> lub <code>(13: Permission denied)</code></td>
      <td>Proces Nginx nie mo&#380;e odczyta&#263; pliku albo przej&#347;&#263; przez katalog na &#347;cie&#380;ce.</td>
      <td>Sprawd&#378; prawa pliku i katalog&oacute;w nadrz&#281;dnych oraz to, z jakim u&#380;ytkownikiem dzia&#322;a proces roboczy.</td>
    </tr>
    <tr>
      <td><code>access forbidden by rule</code></td>
      <td>&#379;&#261;danie trafia na regu&#322;&#281; ograniczaj&#261;c&#261; dost&#281;p.</td>
      <td>Przejrzyj dyrektywy <code>allow</code> i <code>deny</code> w pasuj&#261;cym bloku <code>location</code> lub <code>server</code>.</td>
    </tr>
    <tr>
      <td>Brak odpowiadaj&#261;cego wpisu w logu Nginx</td>
      <td>403 mo&#380;e zwraca&#263; inna warstwa, na przyk&#322;ad aplikacja, CDN, proxy lub panel hostingowy.</td>
      <td>Ustal, kt&oacute;ry komponent obs&#322;u&#380;y&#322; &#380;&#261;danie, i sprawd&#378; jego logi oraz nag&#322;&oacute;wki odpowiedzi.</td>
    </tr>
  </tbody>
</table><p>Przy regu&#322;ach dost&#281;pu kolejno&#347;&#263; ma znaczenie: Nginx sprawdza dyrektywy <code>allow</code> i <code>deny</code> po kolei, a&#380; znajdzie dopasowanie. Dokumentacja modu&#322;u <a href="https://nginx.org/en/docs/http/ngx_http_access_module.html" target="_blank" rel="noopener noreferrer nofollow">ngx_http_access_module</a> wskazuje te&#380;, &#380;e regu&#322;y z poziomu nadrz&#281;dnego s&#261; dziedziczone tylko wtedy, gdy w bie&#380;&#261;cym bloku nie zdefiniowano w&#322;asnych regu&#322; dost&#281;pu. To mo&#380;e wyja&#347;ni&#263;, dlaczego poprawka w jednym <code>location</code> nie zmienia zachowania innego.</p><h2 id="brak-indeksu-naprawiasz-bez-otwierania-katalogu">Brak indeksu naprawiasz bez otwierania katalogu</h2><p>Gdy w logu pojawia si&#281; informacja o zabronionym indeksie katalogu, sprawd&#378;, czy katalog wskazany przez <code>root</code> rzeczywi&#347;cie zawiera stron&#281; startow&#261;. Domy&#347;ln&#261; nazw&#261; w Nginx jest <code>index.html</code>; je&#347;li aplikacja korzysta z innego pliku, trzeba uwzgl&#281;dni&#263; go w konfiguracji <code>index</code>.</p><pre><code>location / {
    root /var/www/app/public;
    index index.html index.php;
}</code></pre><p>W przyk&#322;adzie &#347;cie&#380;ka <code>/var/www/app/public</code> musi odpowiada&#263; katalogowi, w kt&oacute;rym faktycznie znajduj&#261; si&#281; pliki serwowane przez Nginx. Dyrektywa <code>index</code> mo&#380;e te&#380; spowodowa&#263; wewn&#281;trzne przekierowanie do innego bloku <code>location</code>, wi&#281;c je&#347;li plik istnieje, a b&#322;&#261;d zostaje, sprawd&#378; r&oacute;wnie&#380; konfiguracj&#281; dopasowan&#261; do jego &#347;cie&#380;ki. Tak dzia&#322;a modu&#322; <a href="https://nginx.org/en/docs/http/ngx_http_index_module.html" target="_blank" rel="noopener noreferrer nofollow">ngx_http_index_module</a>.</p><p>Nie w&#322;&#261;czaj <code>autoindex on</code> jako szybkiego lekarstwa. Ta dyrektywa generuje list&#281; plik&oacute;w w katalogu, a nie stron&#281; aplikacji; je&#347;li trafi na publiczn&#261; &#347;cie&#380;k&#281;, mo&#380;e ujawni&#263; nazwy i struktur&#281; dost&#281;pnych tam zasob&oacute;w. Zostaw domy&#347;lne <code>autoindex off</code>, chyba &#380;e celowo udost&#281;pniasz katalogi. Opis dzia&#322;ania modu&#322;u znajduje si&#281; w dokumentacji <a href="https://nginx.org/en/docs/http/ngx_http_autoindex_module.html" target="_blank" rel="noopener noreferrer nofollow">ngx_http_autoindex_module</a>.</p><h2 id="przy-permission-denied-sprawdz-cala-sciezke-nie-sam-plik">Przy Permission denied sprawd&#378; ca&#322;&#261; &#347;cie&#380;k&#281;, nie sam plik</h2><p>Plik mo&#380;e mie&#263; prawo odczytu, a mimo to pozosta&#263; niedost&#281;pny dla Nginx, je&#347;li proces nie mo&#380;e przej&#347;&#263; przez kt&oacute;ry&#347; katalog nadrz&#281;dny. Sprawd&#378; wi&#281;c &#347;cie&#380;k&#281; od katalogu g&#322;&oacute;wnego a&#380; po plik, zamiast zmienia&#263; uprawnienia wy&#322;&#261;cznie na <code>index.html</code>.</p><pre><code>namei -l /var/www/app/public/index.html</code></pre><p>Wynik pokazuje uprawnienia kolejnych element&oacute;w &#347;cie&#380;ki. Por&oacute;wnaj je z u&#380;ytkownikiem procesu roboczego Nginx, kt&oacute;ry mo&#380;esz ustali&#263; w konfiguracji, mi&#281;dzy innymi przez dyrektyw&#281; <code>user</code>. <strong>Nie stosuj bez namys&#322;u rekurencyjnego <code>chmod 777</code></strong>: przyznaje szeroki dost&#281;p i zaciemnia w&#322;a&#347;ciw&#261; przyczyn&#281; problemu.</p><p>Je&#347;li prawa plik&oacute;w wygl&#261;daj&#261; poprawnie, sprawd&#378; dodatkowe mechanizmy systemowe, takie jak ACL lub SELinux, oraz spos&oacute;b montowania woluminu w kontenerze. Przy wdro&#380;eniu kontenerowym &#347;cie&#380;ka podana w <code>root</code> musi by&#263; dost&#281;pna wewn&#261;trz kontenera, a nie wy&#322;&#261;cznie na ho&#347;cie.</p><h2 id="po-zmianie-konfiguracji-sprawdz-czy-naprawiasz-wlasciwa-warstwe">Po zmianie konfiguracji sprawd&#378;, czy naprawiasz w&#322;a&#347;ciw&#261; warstw&#281;</h2><p>403 dla strony startowej i 403 tylko dla pliku statycznego sugeruj&#261; inne tropy. Je&#347;li b&#322;&#261;d dotyczy jednego endpointu aplikacji, sprawd&#378; tak&#380;e odpowied&#378; backendu; Nginx mo&#380;e przekazywa&#263; j&#261; dalej zamiast samodzielnie blokowa&#263; dost&#281;p.</p><p>Po edycji konfiguracji przetestuj jej sk&#322;adni&#281;, a dopiero p&oacute;&#378;niej prze&#322;aduj serwer. Polecenie <code>nginx -t</code> sprawdza poprawno&#347;&#263; konfiguracji, natomiast <code>nginx -T</code> dodatkowo wypisuje aktywn&#261; konfiguracj&#281;, co pomaga wykry&#263; plik do&#322;&#261;czany przez <code>include</code> lub nieoczekiwany blok obs&#322;uguj&#261;cy &#380;&#261;danie.</p><pre><code>sudo nginx -t
sudo systemctl reload nginx</code></pre><p>Je&#347;li konfiguracja przechodzi test, a 403 nadal wyst&#281;puje, sprawd&#378;, czy zmieniony blok faktycznie obs&#322;uguje ten host i adres URL. Warto te&#380; ponownie odczyta&#263; log po pojedynczym &#380;&#261;daniu, bo nowy wpis poka&#380;e, czy naprawa usun&#281;&#322;a pierwotn&#261; przyczyn&#281;, czy ods&#322;oni&#322;a kolejn&#261;.</p><h2 id="najbezpieczniejsza-naprawa-zaczyna-sie-od-jednego-wpisu">Najbezpieczniejsza naprawa zaczyna si&#281; od jednego wpisu</h2><p>Przy Nginx 403 najkr&oacute;tsza droga prowadzi od konkretnego &#380;&#261;dania do odpowiadaj&#261;cej mu linii w logu, a potem do jednej sprawdzanej zmiany. Brak indeksu wymaga poprawienia &#347;cie&#380;ki lub dyrektywy <code>index</code>, odmowa systemu plik&oacute;w wymaga sprawdzenia ca&#322;ej &#347;cie&#380;ki, a blokada regu&#322;&#261; prowadzi do konfiguracji <code>allow</code> i <code>deny</code>.</p><p>Po ka&#380;dej poprawce wykonaj ponownie to samo &#380;&#261;danie i sprawd&#378; nowy wpis. Dzi&#281;ki temu nie pomylisz skutecznej naprawy z przypadkowym obej&#347;ciem, kt&oacute;re otwiera dost&#281;p szerzej, ni&#380; wymaga tego aplikacja.</p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>DevOps i infrastruktura</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/dedbe92a2cb6f4f22d1fdbb7db2a9ada/nginx-403-forbidden-jak-znalezc-prawdziwa-przyczyne.webp"/>
      <pubDate>Thu, 05 Nov 2026 16:22:00 +0100</pubDate>
    </item>
    <item>
      <title>Czym jest skrypt i do czego służy w programowaniu?</title>
      <link>https://lukasz-zielinski.pl/czym-jest-skrypt-i-do-czego-sluzy-w-programowaniu</link>
      <description>Czym jest skrypt? Poznaj przykłady w Pythonie, Bashu i JavaScripcie oraz sprawdź, kiedy automatyzacja powtarzalnych zadań ma sens.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Co tydzie&#324; r&#281;cznie zmieniasz nazwy plik&oacute;w z raportami albo kopiujesz te same dane do kilku arkuszy? Skrypt mo&#380;e wykona&#263; tak&#261; seri&#281; polece&#324; automatycznie, cho&#263; to, co dok&#322;adnie zrobi i gdzie si&#281; uruchomi, zale&#380;y od j&#281;zyka oraz &#347;rodowiska. W programowaniu nazwa &bdquo;skrypt&rdquo; opisuje zwykle kr&oacute;tki program do zadania lub automatyzacji, ale granica mi&#281;dzy skryptem a innym programem nie jest sztywna.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/2b8d5c468fa35c9c7a77b034d5ffd93b/programista-automatyzujacy-powtarzalne-zadanie-za-pomoca-krotkiego-skryptu-kodu.webp" class="image article-image" loading="lazy" alt="Python skrypt co to? Kod serwera HTTP, kt&oacute;ry odbiera dane POST i uruchamia zewn&#281;trzny proces."></p><div class="short-summary">
<h2 id="skrypt-zamienia-powtarzalne-polecenia-w-automatyczne-dzialanie">Skrypt zamienia powtarzalne polecenia w automatyczne dzia&#322;anie</h2>
<ul>
<li><strong>Skrypt</strong> to kod zapisany tak, by &#347;rodowisko uruchomieniowe mog&#322;o wykona&#263; okre&#347;lone instrukcje.</li>
<li><strong>Przyk&#322;ady</strong> obejmuj&#261; skrypty Python, Bash, PowerShell i <a href="https://lukasz-zielinski.pl/try-catch-w-praktyce-jak-obslugiwac-wyjatki-bez-ukrywania-bledow">JavaScript</a>.</li>
<li><strong>Najlepiej zacz&#261;&#263; od zadania</strong>, kt&oacute;re cz&#281;sto si&#281; powtarza i ma jasno okre&#347;lone wej&#347;cie oraz wynik.</li>
<li><strong>&bdquo;Skrypt&rdquo; i &bdquo;program&rdquo; nie wykluczaj&#261; si&#281;</strong>, a samo s&#322;owo nie przes&#261;dza o sposobie uruchamiania kodu.</li>
</ul>
</div><h2 id="skrypt-wykonuje-instrukcje-w-okreslonym-srodowisku">Skrypt wykonuje instrukcje w okre&#347;lonym &#347;rodowisku</h2><p>Wyobra&#378; sobie folder pe&#322;en plik&oacute;w o nazwach &bdquo;raport_kopia&rdquo;, &bdquo;raport_kopia2&rdquo; i &bdquo;raport_nowy&rdquo;. Skrypt mo&#380;e przejrze&#263; folder, nada&#263; plikom sp&oacute;jne nazwy i zapisa&#263; wynik, zamiast czeka&#263;, a&#380; ka&#380;de z tych dzia&#322;a&#324; wykonasz r&#281;cznie. <strong>Jego sednem jest instrukcja dla komputera</strong>, a nie konkretny rozmiar kodu ani jeden obowi&#261;zkowy j&#281;zyk.</p><p>Okre&#347;lenie &bdquo;skrypt&rdquo; cz&#281;sto oznacza program uruchamiany przez interpreter lub inne &#347;rodowisko, na przyk&#322;ad pow&#322;ok&#281; systemow&#261; albo przegl&#261;dark&#281;. W praktyce granica bywa p&#322;ynna: kr&oacute;tki skrypt mo&#380;e rozrosn&#261;&#263; si&#281; do du&#380;ego narz&#281;dzia, a kod nazywany programem te&#380; mo&#380;e by&#263; wykonywany w &#347;rodowisku uruchomieniowym. <strong>S&#322;owo opisuje przede wszystkim rol&#281; kodu</strong>, nie pe&#322;n&#261; technologi&#281;, w kt&oacute;rej go napisano.</p><h2 id="python-bash-i-javascript-rozwiazuja-rozne-zadania">Python, Bash i JavaScript rozwi&#261;zuj&#261; r&oacute;&#380;ne zadania</h2><p>Jedno s&#322;owo, trzy bardzo r&oacute;&#380;ne miejsca pracy. <strong>Python</strong> sprawdza si&#281; przy przetwarzaniu danych i automatyzacji, <strong>Bash</strong> &#322;&#261;czy polecenia systemowe, a JavaScript mo&#380;e obs&#322;ugiwa&#263; zachowanie strony w przegl&#261;darce.</p><table>
<tbody>
<tr><th>Przyk&#322;ad</th><th>Typowe zadanie</th><th>Co musi go uruchomi&#263;</th></tr>
<tr><td>Skrypt Python</td><td>Porz&#261;dkowanie danych z plik&oacute;w CSV</td><td>Interpreter Python</td></tr>
<tr><td>Skrypt Bash</td><td>&#321;&#261;czenie polece&#324; terminala, na przyk&#322;ad przy kopii zapasowej</td><td>Pow&#322;oka zgodna ze sk&#322;adni&#261; skryptu</td></tr>
<tr><td>Skrypt JavaScript</td><td>Reakcja strony na klikni&#281;cie przycisku</td><td>Przegl&#261;darka lub &#347;rodowisko JavaScript</td></tr>
</tbody>
</table><p>To nie s&#261; wymienne narz&#281;dzia. Je&#347;li skrypt ma zmienia&#263; pliki na komputerze, Bash lub Python mog&#261; pasowa&#263; lepiej ni&#380; kod wykonywany w przegl&#261;darce; gdy chodzi o interakcj&#281; na stronie, zwykle wyb&oacute;r pada na JavaScript. Dokumentacja <a href="https://learn.microsoft.com/pl-pl/powershell/module/microsoft.powershell.core/about/about_scripts" target="_blank" rel="noopener noreferrer nofollow">Microsoft Learn o skryptach PowerShell</a> opisuje je jako zwyk&#322;e pliki tekstowe z poleceniami PowerShell, co dobrze pokazuje, jak mocno dzia&#322;anie skryptu wi&#261;&#380;e si&#281; z jego &#347;rodowiskiem.</p><h2 id="jesli-zadanie-powtarza-sie-i-ma-jasne-reguly-skrypt-zwykle-sie-oplaca">Je&#347;li zadanie powtarza si&#281; i ma jasne regu&#322;y, skrypt zwykle si&#281; op&#322;aca</h2><p>Nie ka&#380;de r&#281;czne dzia&#322;anie trzeba automatyzowa&#263;. Gdy wykonujesz je rzadko albo za ka&#380;dym razem podejmujesz inn&#261; decyzj&#281;, przygotowanie i sprawdzanie skryptu mo&#380;e zaj&#261;&#263; wi&#281;cej czasu ni&#380; sama praca. <strong>Najlepszym kandydatem jest zadanie powtarzalne, przewidywalne i mo&#380;liwe do opisania krok po kroku.</strong></p><table>
<tbody>
<tr><th>Sytuacja</th><th>Co mo&#380;e by&#263; przyczyn&#261; lub skutkiem</th><th>Co zrobi&#263;</th></tr>
<tr><td>Co tydzie&#324; zmieniasz nazwy plik&oacute;w wed&#322;ug tego samego wzoru</td><td>Powtarzalne regu&#322;y daj&#261; si&#281; zapisa&#263; w instrukcjach</td><td>Przetestuj skrypt najpierw na kopii kilku plik&oacute;w</td></tr>
<tr><td>Ka&#380;dy raport wymaga innych wyj&#261;tk&oacute;w i r&#281;cznej oceny</td><td>Automatyzacja mo&#380;e b&#322;&#281;dnie zmieni&#263; dane, kt&oacute;rych nie da si&#281; &#322;atwo odtworzy&#263;</td><td>Najpierw ustal jawne warunki i wyj&#261;tki albo zostaw decyzj&#281; cz&#322;owiekowi</td></tr>
<tr><td>Skrypt dzia&#322;a na plikach produkcyjnych lub wa&#380;nych danych</td><td>B&#322;&#261;d mo&#380;e nadpisa&#263; albo usun&#261;&#263; niew&#322;a&#347;ciwy plik</td><td>Dodaj tryb podgl&#261;du, kopi&#281; zapasow&#261; i sprawdzenie wyniku przed zmianami</td></tr>
</tbody>
</table><p>Przyk&#322;ad: raz w tygodniu pobierasz zestaw plik&oacute;w CSV, usuwasz puste wiersze i &#322;&#261;czysz dane w jeden raport. Je&#347;li uk&#322;ad plik&oacute;w i regu&#322;y czyszczenia pozostaj&#261; sta&#322;e, skrypt mo&#380;e wykona&#263; te kroki, a ty sprawdzasz gotowy plik. Gdy kolumny zmieniaj&#261; znaczenie zale&#380;nie od kontekstu, automatyzacja potrzebuje dodatkowych warunk&oacute;w. <strong>W przeciwnym razie wykona b&#322;&#281;dne polecenie szybciej ni&#380; cz&#322;owiek.</strong></p><p>Przyznam, &#380;e za dobry pierwszy skrypt uwa&#380;am taki, kt&oacute;rego wynik mo&#380;na &#322;atwo sprawdzi&#263; i odwr&oacute;ci&#263;. Zmiana nazw kopii roboczych jest bezpieczniejszym &#263;wiczeniem ni&#380; automatyczne kasowanie plik&oacute;w; zacznij od podgl&#261;du zmian, zanim pozwolisz kodowi je zatwierdzi&#263;.</p><h2 id="skrypt-nie-musi-byc-nieskompilowany-ani-maly">Skrypt nie musi by&#263; &bdquo;nieskompilowany&rdquo; ani ma&#322;y</h2><p>Popularne uproszczenie m&oacute;wi, &#380;e skrypt to zawsze kr&oacute;tki kod interpretowany linijka po linijce. Tymczasem okre&#347;lenie &bdquo;skrypt&rdquo; samo w sobie nie rozstrzyga, jak &#347;rodowisko przetwarza kod, a implementacje j&#281;zyk&oacute;w mog&#261; wykorzystywa&#263; r&oacute;&#380;ne mechanizmy wykonania. Dokumentacja <a href="https://docs.python.org/3/faq/programming.html" target="_blank" rel="noopener noreferrer nofollow">FAQ programistyczne Pythona</a> wyja&#347;nia mi&#281;dzy innymi, &#380;e uruchomienie pliku jako g&#322;&oacute;wnego skryptu r&oacute;&#380;ni si&#281; od importowania modu&#322;u; sam plik `.py` mo&#380;e pe&#322;ni&#263; r&oacute;&#380;ne role zale&#380;nie od sposobu u&#380;ycia.</p><p>Podobne rozr&oacute;&#380;nienie wida&#263; w JavaScripcie. W przegl&#261;darce klasyczny element `<code><script></script></code>` i modu&#322; `<code><script type="module"></script></code>` maj&#261; odmienne zasady &#322;adowania; modu&#322;y bez atrybutu <code>async</code> s&#261; domy&#347;lnie odraczane do czasu przetworzenia dokumentu. Szczeg&oacute;&#322;y opisuje <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script" target="_blank" rel="noopener noreferrer nofollow">dokumentacja elementu script w MDN</a>. Wniosek jest praktyczny: gdy kod nie rusza, sprawd&#378; najpierw &#347;rodowisko i spos&oacute;b uruchomienia, zamiast zak&#322;ada&#263;, &#380;e problem wynika z tego, i&#380; &bdquo;skrypt jest skryptem&rdquo;.</p><h2 id="pierwszy-skrypt-niech-rozwiazuje-maly-sprawdzalny-problem">Pierwszy skrypt niech rozwi&#261;zuje ma&#322;y, sprawdzalny problem</h2><p>Wybierz czynno&#347;&#263;, kt&oacute;r&#261; wykonujesz wed&#322;ug tych samych regu&#322;, na przyk&#322;ad dopisanie daty do nazw plik&oacute;w raportowych. Zapisz, jakie dane skrypt dostaje, co ma zmieni&#263; i jak potwierdzisz poprawny wynik. <strong>Tak zdefiniowane zadanie</strong> jest &#322;atwiejsze do zakodowania i bezpieczniejsze do przetestowania ni&#380; og&oacute;lne &bdquo;zautomatyzuj mi prac&#281;&rdquo;.</p><p>Je&#380;eli wynik da si&#281; &#322;atwo zweryfikowa&#263;, a pomy&#322;k&#281; mo&#380;na cofn&#261;&#263;, zacznij od prostego skryptu. Gdy kod ma podejmowa&#263; decyzje na podstawie niejednoznacznych danych albo zmienia&#263; wa&#380;ne pliki, najpierw dopracuj warunki i dodaj kontrol&#281;. Wtedy automatyzacja rzeczywi&#347;cie oszcz&#281;dza czas, zamiast ukrywa&#263; b&#322;&#261;d w szybszym procesie.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Programowanie</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/c0002bb11363e750a8d99eab0160afce/czym-jest-skrypt-i-do-czego-sluzy-w-programowaniu.webp"/>
      <pubDate>Thu, 05 Nov 2026 14:50:00 +0100</pubDate>
    </item>
    <item>
      <title>DECIMAL(p,s) w SQL - jak dobrać precyzję i skalę?</title>
      <link>https://lukasz-zielinski.pl/decimalps-w-sql-jak-dobrac-precyzje-i-skale</link>
      <description>DECIMAL(p,s) w SQL: sprawdź, jak dobrać precyzję i skalę, uniknąć zaokrągleń oraz różnic między PostgreSQL, MySQL i SQL Server.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Kwota 19,99 z&#322; w bazie po kilku operacjach zaczyna wygl&#261;da&#263; jak 19,989999&hellip; i raport przestaje si&#281; zgadza&#263;. Typ zwykle rozwi&#261;zuje problem: dla warto&#347;ci wymagaj&#261;cych dok&#322;adno&#347;ci wybierz <strong>DECIMAL(p, s)</strong>, ale jego parametry i zachowanie zale&#380;&#261; od silnika oraz wykonywanych dzia&#322;a&#324;.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/0ab02341f4c423161b51a4225f656bcd/sql-decimal-precision-scale-diagram-database-column-example.webp" class="image article-image" loading="lazy" alt="Hierarchia typ&oacute;w danych SQL: od NULL do STRING, INTEGER, DECIMAL i innych."></p><div class="short-summary">
<h2 id="decimal-przechowuje-wartosci-dokladnie-jesli-dobierzesz-wlasciwy-zakres">DECIMAL przechowuje warto&#347;ci dok&#322;adnie, je&#347;li dobierzesz w&#322;a&#347;ciwy zakres</h2>
<ul>
<li><strong>p</strong> oznacza &#322;&#261;czn&#261; liczb&#281; cyfr, a <strong>s</strong> liczb&#281; cyfr po separatorze dziesi&#281;tnym.</li>
<li><strong>DECIMAL(10,2)</strong> pozwala zapisa&#263; do o&#347;miu cyfr przed separatorem i dwie po nim.</li>
<li>Konwersja do mniejszej skali mo&#380;e <strong>zaokr&#261;gli&#263; warto&#347;&#263;</strong>, zamiast zg&#322;osi&#263; b&#322;&#261;d.</li>
<li>Regu&#322;y oblicze&#324; r&oacute;&#380;ni&#261; si&#281; mi&#281;dzy silnikami, wi&#281;c sprawd&#378; typ wyniku dzielenia i mno&#380;enia.</li>
<li><strong>FLOAT</strong> i <strong>DOUBLE</strong> s&#261; przybli&#380;one; dla kwot zwykle lepiej sprawdza si&#281; typ dziesi&#281;tny.</li>
</ul>
</div><h2 id="decimal102-nie-oznacza-dziesieciu-cyfr-przed-przecinkiem">DECIMAL(10,2) nie oznacza dziesi&#281;ciu cyfr przed przecinkiem</h2><p>Zapis <code>DECIMAL(p, s)</code> okre&#347;la pojemno&#347;&#263; kolumny: <strong>p</strong> to maksymalna liczba cyfr &#322;&#261;cznie, a <strong>s</strong> wskazuje, ile z nich mo&#380;e wyst&#261;pi&#263; po separatorze. W definicji <code>DECIMAL(10,2)</code> zostaje wi&#281;c osiem cyfr na cz&#281;&#347;&#263; ca&#322;kowit&#261; i dwie na u&#322;amkow&#261;.</p><p>W praktyce taki typ pasuje do ceny lub kwoty o dw&oacute;ch miejscach po przecinku, ale niekoniecznie do ka&#380;dej liczby zwi&#261;zanej z pieni&#281;dzmi. Je&#347;li przechowujesz kurs waluty, stawk&#281; podatku albo wynik pomiaru, dwa miejsca po separatorze mog&#261; uci&#261;&#263; potrzebn&#261; precyzj&#281;. <strong>Dobierz skal&#281; do danych &#378;r&oacute;d&#322;owych i regu&#322; biznesowych</strong>, nie do wygl&#261;du przyk&#322;adowego raportu.</p><h2 id="dokladnosc-nie-chroni-przed-cichym-zaokragleniem">Dok&#322;adno&#347;&#263; nie chroni przed cichym zaokr&#261;gleniem</h2><p>Kolumna dziesi&#281;tna mo&#380;e przechowywa&#263; warto&#347;&#263; dok&#322;adnie, a mimo to dosta&#263; inn&#261; liczb&#281; ni&#380; ta podana w zapytaniu. Dzieje si&#281; tak, gdy wej&#347;cie ma wi&#281;cej cyfr u&#322;amkowych, ni&#380; dopuszcza skala kolumny. Dokumentacja <a href="https://learn.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-server-ver17" target="_blank" rel="noopener noreferrer nofollow">Microsoft Learn dla DECIMAL i NUMERIC w SQL Server</a> opisuje zaokr&#261;glanie przy konwersji do ni&#380;szej precyzji lub skali.</p><p>Przyk&#322;adowo kwota <code>12,345</code> zapisana w kolumnie o skali 2 mo&#380;e zosta&#263; zaokr&#261;glona do dw&oacute;ch miejsc. To nie to samo co b&#322;&#261;d przepe&#322;nienia: za ma&#322;o miejsca na cz&#281;&#347;&#263; ca&#322;kowit&#261; mo&#380;e uniemo&#380;liwi&#263; zapis, podczas gdy nadmiar cyfr po separatorze mo&#380;e zosta&#263; zaokr&#261;glony. <strong>Testuj oba przypadki</strong>, szczeg&oacute;lnie przed migracj&#261; danych.</p><h2 id="ten-sam-zapis-typu-nie-gwarantuje-identycznego-zachowania-w-kazdej-bazie">Ten sam zapis typu nie gwarantuje identycznego zachowania w ka&#380;dej bazie</h2><p>Przy przej&#347;ciu mi&#281;dzy <a href="https://lukasz-zielinski.pl/sql-delete-jak-usuwac-dane-bezpiecznie">PostgreSQL</a>, MySQL i SQL Server naj&#322;atwiej przeoczy&#263; granice skali oraz limity deklaracji. <a href="https://lukasz-zielinski.pl/alter-table-bez-niespodzianek-jak-bezpiecznie-zmienic-tabele">PostgreSQL</a> pozwala jawnie zadeklarowa&#263; precyzj&#281; <code>numeric</code> do 1000 cyfr, podczas gdy SQL Server ogranicza precyzj&#281; <code>decimal</code> do 38, a MySQL dopuszcza maksymalnie 65 cyfr dla <code>DECIMAL</code>. To r&oacute;&#380;nice istotne przy przenoszeniu schematu, nie ciekawostka dokumentacyjna.</p><p>Jest te&#380; mniej oczywisty szczeg&oacute;&#322;: PostgreSQL dopuszcza ujemn&#261; skal&#281;, na przyk&#322;ad <code>NUMERIC(2,-3)</code>, kt&oacute;ra zaokr&#261;gla warto&#347;ci do tysi&#281;cy. Ta sk&#322;adnia nie jest przeno&#347;na do ka&#380;dego systemu SQL. <strong>Przed migracj&#261; sprawd&#378; definicje kolumn oraz wynikowe typy wyra&#380;e&#324;</strong>, bo zgodna nazwa typu nie oznacza zgodnych regu&#322;.</p><h2 id="dzielenie-moze-obciac-precyzje-zanim-wynik-trafi-do-kolumny">Dzielenie mo&#380;e obci&#261;&#263; precyzj&#281;, zanim wynik trafi do kolumny</h2><p>Za&#322;&oacute;&#380;my, &#380;e liczysz jednostkow&#261; cen&#281; jako sum&#281; <code>100,00</code> podzielon&#261; przez <code>3</code>. Oczekiwanym wynikiem mo&#380;e by&#263; warto&#347;&#263; z wieloma cyframi po przecinku, lecz konkretna baza ustala precyzj&#281; i skal&#281; wyniku wed&#322;ug regu&#322; dla dzia&#322;ania, a dopiero potem ewentualnie konwertuje go do typu kolumny.</p><p>W SQL Server wynik dzielenia typ&oacute;w dziesi&#281;tnych ma wyliczan&#261; precyzj&#281; i skal&#281;, a ca&#322;kowita precyzja nie mo&#380;e przekroczy&#263; 38. Gdy wynik wymaga wi&#281;cej miejsca, skala mo&#380;e zosta&#263; ograniczona, co mo&#380;e doprowadzi&#263; do zaokr&#261;glenia. Z kolei PostgreSQL zaznacza, &#380;e obliczenia na <code>numeric</code> s&#261; dok&#322;adne tam, gdzie to mo&#380;liwe, ale mog&#261; by&#263; wolniejsze od typ&oacute;w ca&#322;kowitych i zmiennoprzecinkowych. <strong>Typ wej&#347;ciowy wp&#322;ywa wi&#281;c na wynik po&#347;redni</strong>, nie tylko na zapis ko&#324;cowy.</p><p>Uwa&#380;am, &#380;e przy kwotach bezpieczniej jawnie rzutowa&#263; argumenty dzia&#322;ania i &#347;wiadomie zaokr&#261;gli&#263; wynik dopiero w wybranym miejscu, zamiast liczy&#263; na domy&#347;lne regu&#322;y silnika. Na przyk&#322;ad u&#380;yj <code>CAST(... AS DECIMAL(12,4))</code> dla obliczenia ceny jednostkowej, a p&oacute;&#378;niej osobno zdecyduj, czy wynik prezentowa&#263; i zapisywa&#263; z dwiema cyframi.</p><table>
<tbody>
<tr><th>Sytuacja</th><th>Mo&#380;liwa przyczyna</th><th>Co zrobi&#263;</th></tr>
<tr><td>Kwota po zapisie ma mniej cyfr u&#322;amkowych</td><td>Skala kolumny jest mniejsza ni&#380; precyzja wej&#347;cia</td><td>Zweryfikuj wymagan&#261; skal&#281; i zachowanie konwersji</td></tr>
<tr><td>Wstawienie du&#380;ej warto&#347;ci ko&#324;czy si&#281; b&#322;&#281;dem</td><td>Brak miejsca na cyfry przed separatorem</td><td>Zwi&#281;ksz precyzj&#281; albo ustal dozwolony zakres danych</td></tr>
<tr><td>Wynik dzielenia zaskakuje d&#322;ugo&#347;ci&#261;</td><td>Silnik wyznacza skal&#281; wyra&#380;enia wed&#322;ug w&#322;asnych regu&#322;</td><td>Sprawd&#378; typ wyniku i u&#380;yj jawnego rzutowania</td></tr>
<tr><td>Po migracji liczby zachowuj&#261; si&#281; inaczej</td><td>Silniki maj&#261; r&oacute;&#380;ne limity i obs&#322;ug&#281; skali</td><td>Przetestuj warto&#347;ci graniczne i dzia&#322;ania arytmetyczne</td></tr>
</tbody>
</table><h2 id="float-nie-zastepuje-decimal-przy-rozliczaniu-kwot">FLOAT nie zast&#281;puje DECIMAL przy rozliczaniu kwot</h2><p><code>FLOAT</code> i <code>DOUBLE</code> zapisuj&#261; warto&#347;ci jako przybli&#380;enia, dlatego nie ka&#380;da liczba dziesi&#281;tna ma w nich dok&#322;adn&#261; reprezentacj&#281;. Dokumentacja <a href="https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html" target="_blank" rel="noopener noreferrer nofollow">MySQL Reference Manual</a> wskazuje <code>DECIMAL</code> jako typ dok&#322;adny, stosowany mi&#281;dzy innymi przy danych pieni&#281;&#380;nych. W PostgreSQL <code>real</code> i <code>double precision</code> s&#261; opisane jako typy niedok&#322;adne, a <code>numeric</code> jako dok&#322;adny.</p><p>Regu&#322;a wyboru jest prosta. Je&#347;li warto&#347;&#263; musi zachowa&#263; ustalon&#261; liczb&#281; cyfr dziesi&#281;tnych, na przyk&#322;ad kwota faktury, stawka lub saldo, wybierz <strong>DECIMAL/NUMERIC</strong>; je&#347;li dane s&#261; pomiarami naukowymi, a dopuszczalne jest przybli&#380;enie i wa&#380;na jest wydajno&#347;&#263;, rozwa&#380; typ zmiennoprzecinkowy. Pami&#281;taj te&#380;, &#380;e format wy&#347;wietlania to osobna sprawa: zera ko&#324;cowe mog&#261; by&#263; prezentowane inaczej ni&#380; oczekujesz, mimo &#380;e warto&#347;&#263; jest poprawna.</p><h2 id="przed-wdrozeniem-sprawdz-trzy-przypadki-graniczne">Przed wdro&#380;eniem sprawd&#378; trzy przypadki graniczne</h2><p>Najwi&#281;cej b&#322;&#281;d&oacute;w wychodzi przy warto&#347;ciach skrajnych, a nie przy zwyk&#322;ym rekordzie z testowego &#347;rodowiska. Przed wdro&#380;eniem sprawd&#378; najwi&#281;ksz&#261; dozwolon&#261; kwot&#281;, najmniejszy u&#322;amek, kt&oacute;ry musi zosta&#263; zachowany, oraz rezultat dzielenia lub mno&#380;enia u&#380;ywanego w aplikacji.</p><p>W testach uwzgl&#281;dnij tak&#380;e zapis z nadmiarem miejsc po separatorze i sprawd&#378;, czy baza zaokr&#261;gla go zgodnie z oczekiwaniem. To kr&oacute;tki test, kt&oacute;ry cz&#281;sto rozstrzyga, czy definicja <code>DECIMAL(p,s)</code> odpowiada rzeczywistemu zakresowi danych, a nie tylko przyk&#322;adowej warto&#347;ci w kodzie.</p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>Bazy danych</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/75ee33ee675af294b854e01e2379dee6/decimalps-w-sql-jak-dobrac-precyzje-i-skale.webp"/>
      <pubDate>Thu, 05 Nov 2026 09:42:00 +0100</pubDate>
    </item>
    <item>
      <title>Ile wynoszą zarobki w Big Data? Porównaj ofertę UoP i B2B</title>
      <link>https://lukasz-zielinski.pl/ile-wynosza-zarobki-w-big-data-porownaj-oferte-uop-i-b2b</link>
      <description>Zarobki w Big Data zależą od roli i umowy. Sprawdź mediany dla Data Engineer oraz różnice między UoP i B2B przed negocjacją oferty.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Masz ofert&#281; na &bdquo;Big Data&rdquo; i pr&oacute;bujesz ustali&#263;, czy proponowana kwota jest rynkowa? W Polsce zarobki w tej specjalizacji cz&#281;sto mieszcz&#261; si&#281; w przedziale kilkunastu do ponad 30 tys. z&#322; miesi&#281;cznie, ale sama nazwa stanowiska nie m&oacute;wi jeszcze, czy por&oacute;wnujesz pensj&#281; brutto, czy kwot&#281; na fakturze.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/09ee29af48530e69cc8a5bafd4a112a2/inzynier-danych-big-data-praca-z-wykresami-danych-i-laptopem.webp" class="image article-image" loading="lazy" alt="M&#281;&#380;czyzna w garniturze analizuje dane na laptopie. Wizualizacja globalnej sieci i s&#322;owa kluczowe sugeruj&#261; prac&#281; z big data, co przek&#322;ada si&#281; na wysokie big data zarobki."></p><div class="short-summary">
<h2 id="o-wysokosci-zarobkow-decyduja-rola-doswiadczenie-i-forma-umowy">O wysoko&#347;ci zarobk&oacute;w decyduj&#261; rola, do&#347;wiadczenie i forma umowy</h2>
<ul>
<li><strong>Data Engineer</strong> i Data Scientist to osobne role, a ich wide&#322;ki nie s&#261; identyczne.</li>
<li><strong>UoP</strong> podaje si&#281; zwykle jako kwot&#281; brutto, a B2B jako kwot&#281; netto na fakturze.</li>
<li><strong>Mediana</strong> daje lepszy punkt odniesienia ni&#380; najwy&#380;sza kwota z og&#322;oszenia.</li>
<li><strong>SQL, Python i praca z chmur&#261;</strong> pomagaj&#261; wej&#347;&#263; w bardziej techniczne zadania, ale sama znajomo&#347;&#263; narz&#281;dzia nie gwarantuje podwy&#380;ki.</li>
</ul>
</div><h2 id="pod-haslem-big-data-kryja-sie-rozne-stanowiska">Pod has&#322;em Big Data kryj&#261; si&#281; r&oacute;&#380;ne stanowiska</h2><p>Jedna oferta dotyczy budowy potok&oacute;w danych, druga modelowania predykcyjnego, a trzecia raport&oacute;w dla biznesu. Wsp&oacute;lny szyld &bdquo;Big Data&rdquo; mo&#380;e wi&#281;c &#322;&#261;czy&#263; prac&#281; o innym poziomie odpowiedzialno&#347;ci i zupe&#322;nie innym wynagrodzeniu.</p><p>Najczytelniej rozdzieli&#263; trzy role. <strong>Data Engineer</strong> buduje systemy, kt&oacute;re zbieraj&#261;, przetwarzaj&#261; i udost&#281;pniaj&#261; dane. <strong>Data Scientist</strong> szuka w nich wzorc&oacute;w i tworzy modele analityczne. <strong>BI Analyst</strong> przygotowuje raporty i wspiera decyzje biznesowe. Granice bywaj&#261; p&#322;ynne, ale zakres obowi&#261;zk&oacute;w szybko pokazuje, do kt&oacute;rego profilu oferta jest najbli&#380;sza.</p><p>Przegl&#261;daj&#261;c zestawienia p&#322;ac, nie sprowadza&#322;bym wszystkich tych stanowisk do jednej &bdquo;&#347;redniej dla Big Data&rdquo;. Taki skr&oacute;t zaciera r&oacute;&#380;nice mi&#281;dzy in&#380;ynieri&#261; danych, analiz&#261; i uczeniem maszynowym, a to w&#322;a&#347;nie one pomagaj&#261; oceni&#263;, czy propozycja jest adekwatna do pracy.</p><h2 id="mediana-dla-data-engineer-wynosi-23-tys-zl-brutto-w-jednym-z-raportow">Mediana dla Data Engineer wynosi 23 tys. z&#322; brutto w jednym z raport&oacute;w</h2><p>Je&#347;li punktem odniesienia ma by&#263; konkretna liczba, <strong>Goldman Recruitment Salary Survey 2025</strong> podaje dla Data Engineer median&#281; 23 tys. z&#322; miesi&#281;cznie. Dolny kwartyl wynosi 18 tys. z&#322;, a g&oacute;rny 26 tys. z&#322;. To przedzia&#322; orientacyjny, nie obietnica stawki dla ka&#380;dej osoby ani wszystkich um&oacute;w.</p><p>To samo zestawienie pokazuje, dlaczego nie nale&#380;y uto&#380;samia&#263; r&oacute;l: mediana dla Data Scientist wynosi 24 tys. z&#322;, a dla BI Analyst 15 tys. z&#322;. R&oacute;&#380;nica nie opisuje automatycznie &bdquo;premii za Big Data&rdquo;; odzwierciedla odr&#281;bne stanowiska i zakresy pracy uj&#281;te w raporcie. <a href="https://goldmanrecruitment.pl/wp-content/uploads/2023/01/Goldman-Recruitment-Salary-Survey-2025.pdf" target="_blank" rel="noopener noreferrer nofollow">Goldman Recruitment Salary Survey 2025</a></p><p><strong>Mediana</strong> oznacza &#347;rodkow&#261; warto&#347;&#263; w zestawieniu, wi&#281;c nie jest tym samym co &#347;rednia arytmetyczna ani gwarantowana p&#322;aca. Przy rozmowie o ofercie sprawd&#378; te&#380;, czy raport i og&#322;oszenie dotycz&#261; podobnego poziomu do&#347;wiadczenia, lokalizacji oraz rodzaju umowy.</p><h2 id="kwota-b2b-na-fakturze-nie-jest-pensja-na-reke">Kwota B2B na fakturze nie jest pensj&#261; &bdquo;na r&#281;k&#281;&rdquo;</h2><p>Tu naj&#322;atwiej o fa&#322;szywe por&oacute;wnanie. Raport <strong>IT job market in Poland in 2025</strong> firmy Next Technology Professionals podaje dla Data Engineer na poziomie mid &#347;rednio 20 930 z&#322; na B2B oraz 18 152 z&#322; brutto na umowie o prac&#281;. Autorzy raportu wyja&#347;niaj&#261;, &#380;e kwota B2B jest warto&#347;ci&#261; netto na fakturze bez VAT, a kwota z UoP to wynagrodzenie brutto.</p><p>R&oacute;&#380;nica mi&#281;dzy tymi liczbami nie pokazuje wi&#281;c, &#380;e kontrakt B2B daje wy&#380;sz&#261; wyp&#322;at&#281; do dyspozycji. Z kwoty na fakturze osoba prowadz&#261;ca dzia&#322;alno&#347;&#263; finansuje mi&#281;dzy innymi sk&#322;adki, podatek, urlop i okresy bez zlece&#324;; na etacie cz&#281;&#347;&#263; tych element&oacute;w dzia&#322;a inaczej. <strong>Por&oacute;wnuj ca&#322;kowity uk&#322;ad wsp&oacute;&#322;pracy</strong>, nie same liczby obok siebie. <a href="https://nexttechnology.io/app/uploads/2025/07/INSIGHTS-REPORT-2025-AI-Data-Science-Machine-Learning-%E2%80%A8in-Poland.pdf" target="_blank" rel="noopener noreferrer nofollow">raport Next Technology Professionals o rynku pracy IT w Polsce w 2025 roku</a></p><p>Przy ofercie B2B dopytaj o p&#322;atny urlop, d&#322;ugo&#347;&#263; wypowiedzenia, ci&#261;g&#322;o&#347;&#263; projektu i rozliczanie nieobecno&#347;ci. Je&#347;li tych warunk&oacute;w brakuje, wy&#380;sza kwota na fakturze mo&#380;e oznacza&#263; mniejsz&#261; przewidywalno&#347;&#263; dochodu, a nie wy&#380;szy ekwiwalent etatu.</p><h2 id="wiecej-ofert-w-data-bi-nie-oznacza-latwego-wejscia-dla-juniora">Wi&#281;cej ofert w Data &amp; BI nie oznacza &#322;atwego wej&#347;cia dla juniora</h2><p>W danych No Fluff Jobs za 2025 rok kategoria <strong>Data &amp; BI odpowiada&#322;a za 12,4% opublikowanych ofert</strong>, a liczba og&#322;osze&#324; w ca&#322;ym sektorze IT wzros&#322;a o 44% wzgl&#281;dem poprzedniego roku. To sygna&#322;, &#380;e firmy ponownie rekrutowa&#322;y, lecz nie dow&oacute;d, &#380;e ka&#380;da osoba pocz&#261;tkuj&#261;ca bez trudu znajdzie prac&#281;.</p><p>W praktyce pracodawca mo&#380;e szuka&#263; osoby, kt&oacute;ra samodzielnie zadba o jako&#347;&#263; danych, zautomatyzuje ich przep&#322;yw i poradzi sobie z wdro&#380;eniem w chmurze. <strong>SQL i Python</strong> s&#261; dobrym fundamentem, ale o warto&#347;ci kandydata &#347;wiadcz&#261; te&#380; umiej&#281;tno&#347;&#263; diagnozowania b&#322;&#281;d&oacute;w w pipeline&rsquo;ach oraz wyja&#347;niania, jak powsta&#322; wynik. <a href="https://insights-aws.nofluffjobs.com/insights/raport-rynek-pracy-it/" target="_blank" rel="noopener noreferrer nofollow">raport No Fluff Jobs &bdquo;Rynek pracy IT 2025/2026&rdquo;</a></p><p>Oferty i komentarze os&oacute;b z bran&#380;y cz&#281;sto zbiegaj&#261; si&#281; w jednym punkcie: &bdquo;data&rdquo; to pojemna etykieta, a sama znajomo&#347;&#263; narz&#281;dzia nie przes&#261;dza o stawce. Uwa&#380;am, &#380;e portfolio najlepiej dzia&#322;a wtedy, gdy pokazuje ca&#322;y problem: sk&#261;d pochodz&#261; dane, jak je przetworzono i kto korzysta z wyniku.</p><h2 id="przed-negocjacja-sprawdz-co-dokladnie-obejmuje-oferta">Przed negocjacj&#261; sprawd&#378;, co dok&#322;adnie obejmuje oferta</h2><p>Je&#347;li kwota mocno odbiega od raport&oacute;w, najpierw ustal, czy rozmawiacie o tej samej roli i podstawie <a href="https://lukasz-zielinski.pl/administrator-it-co-naprawde-obejmuje-ta-praca">wynagrodzenia</a>. Dopiero potem oceniaj, czy r&oacute;&#380;nica wynika z poziomu seniority, specjalizacji, odpowiedzialno&#347;ci za system produkcyjny czy dodatkowych warunk&oacute;w umowy.</p><table>
<tbody>
<tr>
<th>Twoja sytuacja</th>
<th>Co mo&#380;e wyja&#347;nia&#263; r&oacute;&#380;nic&#281;</th>
<th>Co zrobi&#263;</th>
</tr>
<tr>
<td>Oferta podaje wy&#322;&#261;cznie &bdquo;Big Data Specialist&rdquo;</td>
<td>Nazwa nie precyzuje, czy chodzi o in&#380;ynieri&#281;, analiz&#281; czy modelowanie</td>
<td>Popro&#347; o zakres zada&#324;, technologie i odpowiedzialno&#347;&#263; za &#347;rodowisko produkcyjne</td>
</tr>
<tr>
<td>Por&oacute;wnujesz kwot&#281; B2B z pensj&#261; na etacie</td>
<td>Inny spos&oacute;b prezentacji wynagrodzenia i inne koszty po stronie pracownika</td>
<td>Przelicz oba warianty z uwzgl&#281;dnieniem podatk&oacute;w, sk&#322;adek, urlopu i przerw w pracy</td>
</tr>
<tr>
<td>Masz do&#347;wiadczenie z SQL i Pythonem, ale oferta wymaga chmury</td>
<td>Pracodawca mo&#380;e oczekiwa&#263; wdra&#380;ania i utrzymania przep&#322;yw&oacute;w danych, nie tylko kodowania</td>
<td>Por&oacute;wnaj wymagania z projektami w portfolio i negocjuj stawk&#281; przez zakres odpowiedzialno&#347;ci</td>
</tr>
<tr>
<td>Wysoka stawka wi&#261;&#380;e si&#281; z dy&#380;urami lub utrzymaniem systemu</td>
<td>Wynagrodzenie mo&#380;e uwzgl&#281;dnia&#263; wi&#281;ksz&#261; odpowiedzialno&#347;&#263; operacyjn&#261;</td>
<td>Ustal cz&#281;stotliwo&#347;&#263; dy&#380;ur&oacute;w, zasady rekompensaty i oczekiwany czas reakcji</td>
</tr>
</tbody>
</table><p>Gdybym negocjowa&#322; ofert&#281;, zacz&#261;&#322;bym od dopasowania jej do w&#322;a&#347;ciwej roli i formy umowy, a dopiero potem podawa&#322; oczekiwania. Taka kolejno&#347;&#263; chroni przed sytuacj&#261;, w kt&oacute;rej atrakcyjna liczba okazuje si&#281; stawk&#261; za szerszy zakres obowi&#261;zk&oacute;w albo kontraktem bez warunk&oacute;w, kt&oacute;re na etacie s&#261; oczywiste.</p><h2 id="najlepsza-stawka-wynika-z-zakresu-pracy-nie-z-etykiety">Najlepsza stawka wynika z zakresu pracy, nie z etykiety</h2><p>Przy ocenie zarobk&oacute;w w Big Data trzymaj si&#281; prostego porz&#261;dku: <strong>najpierw stanowisko, potem do&#347;wiadczenie, na ko&#324;cu typ umowy</strong>. Raportowe mediany pomagaj&#261; ustawi&#263; punkt odniesienia, ale nie zast&#261;pi&#261; pyta&#324; o odpowiedzialno&#347;&#263;, technologie i zasady wsp&oacute;&#322;pracy.</p><p>Je&#347;li oferta brzmi wysoko, lecz opisuje dy&#380;ury, utrzymanie platformy i odpowiedzialno&#347;&#263; za jako&#347;&#263; danych, por&oacute;wnaj j&#261; z rol&#261; o podobnym zakresie, nie z og&oacute;ln&#261; &#347;redni&#261; dla bran&#380;y. W rozmowie o wynagrodzeniu najlepiej broni&#261; si&#281; przyk&#322;ady z projekt&oacute;w: pokazuj&#261;, co potrafisz dowie&#378;&#263;, a nie tylko jakie narz&#281;dzia znasz.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Kariera i biznes IT</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/9c3d5196f5b6948cb0a21a5f1edc5c45/ile-wynosza-zarobki-w-big-data-porownaj-oferte-uop-i-b2b.webp"/>
      <pubDate>Tue, 03 Nov 2026 17:27:00 +0100</pubDate>
    </item>
    <item>
      <title>Czym jest HTML i jak różni się od CSS oraz JavaScriptu?</title>
      <link>https://lukasz-zielinski.pl/czym-jest-html-i-jak-rozni-sie-od-css-oraz-javascriptu</link>
      <description>Czym jest HTML i czym różni się od CSS oraz JavaScriptu? Poznaj strukturę, semantykę i sposoby diagnozowania problemów. Sprawdź przewodnik.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Masz przed sob&#261; stron&#281; z tekstem, nag&#322;&oacute;wkiem i przyciskiem, ale nie wiesz, co opisuje jej kod? <strong>HTML porz&#261;dkuje tre&#347;&#263; strony</strong>, cho&#263; sam nie odpowiada za ca&#322;y jej wygl&#261;d ani wszystkie reakcje na klikni&#281;cia. Ta r&oacute;&#380;nica szybko staje si&#281; praktyczna, gdy zaczynasz poprawia&#263; interfejs albo rozumie&#263; kod frontendu.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/815c27b3b26e7e25aaa2d8f2c4fac888/fragment-semantycznego-kodu-html-strony-internetowej-w-edytorze-widoczne-elementy-header-main-button-form.webp" class="image article-image" loading="lazy" alt="Wyja&#347;nienie, html co to: tworzenie stron internetowych, front-end i back-end. Grafika z blokami i planet&#261;."></p><div class="short-summary">
<h2 id="html-nadaje-tresci-strony-strukture-i-znaczenie">HTML nadaje tre&#347;ci strony struktur&#281; i znaczenie</h2>
<ul>
<li><strong>HTML</strong> opisuje elementy, takie jak nag&#322;&oacute;wki, akapity, linki i formularze.</li>
<li><strong>CSS</strong> ustawia wygl&#261;d, a <strong>JavaScript</strong> dodaje zachowania i interakcje.</li>
<li><strong>Znaczniki semantyczne</strong> pomagaj&#261; przegl&#261;darkom i technologiom asystuj&#261;cym rozpozna&#263; rol&#281; tre&#347;ci.</li>
<li><strong>HTML5</strong> to potoczna nazwa; wsp&oacute;&#322;czesny standard rozwija si&#281; jako HTML Living Standard.</li>
</ul>
</div><h2 id="html-opisuje-czym-sa-elementy-strony">HTML opisuje, czym s&#261; elementy strony</h2><p>Wyobra&#378; sobie artyku&#322;, w kt&oacute;rym wszystkie s&#322;owa maj&#261; ten sam wygl&#261;d i nie wiadomo, co jest tytu&#322;em, linkiem ani zwyk&#322;ym akapitem. HTML rozwi&#261;zuje ten problem, oznaczaj&#261;c role fragment&oacute;w tre&#347;ci za pomoc&#261; <strong>element&oacute;w i znacznik&oacute;w</strong>. Przegl&#261;darka odczytuje t&#281; struktur&#281; i na jej podstawie buduje stron&#281;.</p><p>Znacznik to zapis w nawiasach ostrych, na przyk&#322;ad <code><p></p></code>. Element obejmuje zwykle znacznik otwieraj&#261;cy, tre&#347;&#263; i znacznik zamykaj&#261;cy: <code><p>Tekst akapitu</p></code>. S&#261; te&#380; elementy bez znacznika zamykaj&#261;cego, jak <code><img></code>, kt&oacute;ry osadza obraz.</p><p>HTML rozwija skr&oacute;t <em>HyperText Markup Language</em>, czyli j&#281;zyk znacznik&oacute;w hipertekstowych. Jak wyja&#347;nia <a href="https://developer.mozilla.org/en-US/docs/Web/HTML" target="_blank" rel="noopener noreferrer nofollow">MDN</a>, tworzy podstawow&#261; struktur&#281; tre&#347;ci, a inne technologie zwykle odpowiadaj&#261; za jej prezentacj&#281; i zachowanie. Uwa&#380;am, &#380;e najlepiej my&#347;le&#263; o HTML jak o planie pomieszcze&#324;: nie wybiera koloru &#347;cian, ale m&oacute;wi, gdzie jest wej&#347;cie i kt&oacute;re drzwi prowadz&#261; dalej.</p><h2 id="html-css-i-javascript-rozwiazuja-rozne-problemy">HTML, CSS i JavaScript rozwi&#261;zuj&#261; r&oacute;&#380;ne problemy</h2><p>Przycisk mo&#380;e wygl&#261;da&#263; atrakcyjnie, a mimo to nie dzia&#322;a&#263; poprawnie. Dzieje si&#281; tak, gdy warstwa wizualna przes&#322;ania rol&#281; elementu albo brakuje kodu obs&#322;uguj&#261;cego dzia&#322;anie. Rozdzielenie zada&#324; tych trzech technologii u&#322;atwia znalezienie przyczyny.</p><table>
<tbody>
<tr><th>Technologia</th><th>Za co odpowiada</th><th>Przyk&#322;ad</th></tr>
<tr><td>HTML</td><td>Struktura i znaczenie tre&#347;ci</td><td>Nag&#322;&oacute;wek, formularz, przycisk wysy&#322;aj&#261;cy dane</td></tr>
<tr><td>CSS</td><td>Wygl&#261;d i uk&#322;ad</td><td>Kolor przycisku, odst&#281;py, rozmieszczenie kolumn</td></tr>
<tr><td>JavaScript</td><td>Zmiany i reakcje interfejsu</td><td>Pokazanie komunikatu po klikni&#281;ciu</td></tr>
</tbody>
</table><p>W typowym formularzu HTML okre&#347;la pola i przycisk, CSS nadaje im styl, a JavaScript mo&#380;e sprawdzi&#263; wpisane dane i wy&#347;wietli&#263; informacj&#281; bez prze&#322;adowania strony. Sam HTML potrafi jednak obs&#322;u&#380;y&#263; cz&#281;&#347;&#263; podstawowych zachowa&#324; formularza, wi&#281;c nie ka&#380;da interakcja wymaga skryptu.</p><h2 id="znaczniki-semantyczne-pomagaja-ludziom-i-narzedziom">Znaczniki semantyczne pomagaj&#261; ludziom i narz&#281;dziom</h2><p>Mo&#380;esz zbudowa&#263; stron&#281; z samych element&oacute;w <code><div>, ale wtedy kod niewiele m&oacute;wi o roli poszczeg&oacute;lnych fragment&oacute;w. Elementy takie jak <code><nav></nav></code>, <code><main></main></code>, <code><article></article></code> i <code><footer></footer></code> opisuj&#261; funkcj&#281; cz&#281;&#347;ci strony. T&#281; informacj&#281; mog&#261; wykorzysta&#263; przegl&#261;darki, czytniki ekranu i narz&#281;dzia analizuj&#261;ce dokument.

<p>R&oacute;&#380;nica jest widoczna w prostym przyk&#322;adzie: nawigacj&#281; zapisan&#261; jako <code><nav></nav></code> &#322;atwiej odr&oacute;&#380;ni&#263; od przypadkowego zestawu link&oacute;w w kontenerze <code><div>. Podobnie nag&#322;&oacute;wki powinny wynika&#263; z hierarchii tre&#347;ci, a nie z tego, &#380;e ich domy&#347;lny rozmiar pasuje do projektu. <a href="https://developers.google.com/style/semantic-tagging" target="_blank" rel="noopener noreferrer nofollow">Dokumentacja Google dotycz&#261;ca znacznik&oacute;w semantycznych</a> zaleca u&#380;ywa&#263; element&oacute;w zgodnie z ich przeznaczeniem, a uk&#322;ad wizualny ustawia&#263; przez CSS.

<p>Dla dost&#281;pno&#347;ci liczy si&#281; te&#380; j&#281;zyk dokumentu. Atrybut <code>lang</code> w elemencie <code></code> pomaga technologiom asystuj&#261;cym dobra&#263; wymow&#281;, a widoczny tekst linku powinien m&oacute;wi&#263;, dok&#261;d prowadzi. Samo &bdquo;kliknij tutaj&rdquo; nie daje takiej wskaz&oacute;wki, gdy link jest odczytywany poza otaczaj&#261;cym akapitem.</p>

<h2 id="html5-nie-oznacza-juz-osobnej-zamknietej-wersji">HTML5 nie oznacza ju&#380; osobnej, zamkni&#281;tej wersji</h2>
<p>Nazwa &bdquo;HTML5&rdquo; wci&#261;&#380; pojawia si&#281; w kursach i opisach ofert, ale mo&#380;e sugerowa&#263; co&#347; myl&#261;cego: &#380;e istnieje zestaw umiej&#281;tno&#347;ci ograniczony do jednej, zamro&#380;onej wersji. Wsp&oacute;&#322;czesna specyfikacja jest rozwijana jako <strong>HTML Living Standard</strong>, czyli standard aktualizowany w miar&#281; rozwoju platformy internetowej.</p>

<p><a href="https://html.spec.whatwg.org/multipage/introduction.html" target="_blank" rel="noopener noreferrer nofollow">WHATWG HTML Living Standard</a> wyja&#347;nia, &#380;e &bdquo;HTML5&rdquo; bywa u&#380;ywane jako potoczna nazwa nowoczesnych technologii internetowych, cho&#263; nie wszystkie z nich nale&#380;&#261; do samego HTML. W praktyce og&#322;oszenie o znajomo&#347;ci HTML5 zwykle oznacza znajomo&#347;&#263; wsp&oacute;&#322;czesnego HTML, a nie osobnego j&#281;zyka, kt&oacute;ry trzeba odr&oacute;&#380;ni&#263; od aktualnej specyfikacji.</p>

<h2 id="po-czym-poznac-czy-problem-lezy-w-html">Po czym pozna&#263;, czy problem le&#380;y w HTML</h2>
<p>Gdy co&#347; na stronie nie dzia&#322;a, zacznij od ustalenia, czy problem dotyczy <strong>struktury, wygl&#261;du czy zachowania</strong>. Ta szybka diagnoza ogranicza b&#322;&#261;dzenie po plikach i wskazuje, kt&oacute;rej warstwy szuka&#263;.</p>

<table>
<tbody>
<tr><th>Sytuacja</th><th>Prawdopodobny obszar</th><th>Co sprawdzi&#263;</th></tr>
<tr><td>Nie ma nag&#322;&oacute;wka albo linku</td><td>HTML lub &#378;r&oacute;d&#322;o tre&#347;ci</td><td>Czy element znajduje si&#281; w dokumencie i ma poprawny zapis</td></tr>
<tr><td>Element jest widoczny, ale &#378;le wygl&#261;da</td><td>CSS</td><td>Regu&#322;y styl&oacute;w, klasy i uk&#322;ad</td></tr>
<tr><td>Przycisk wygl&#261;da poprawnie, lecz klikni&#281;cie nic nie robi</td><td>JavaScript albo logika formularza</td><td>Czy element ma w&#322;a&#347;ciwe dzia&#322;anie i czy skrypt obs&#322;uguje zdarzenie</td></tr>
<tr><td>Czytnik ekranu nie rozpoznaje roli fragmentu</td><td>Semantyka HTML</td><td>Czy u&#380;yto elementu odpowiadaj&#261;cego funkcji tre&#347;ci</td></tr>
</tbody>
</table>

<p>Je&#347;li tekst jest obecny, ale ma niew&#322;a&#347;ciwy kolor, zmiana HTML raczej nie pomo&#380;e. Je&#347;li natomiast zamiast przycisku pojawia si&#281; niezrozumia&#322;y fragment albo nag&#322;&oacute;wki tworz&#261; przypadkow&#261; hierarchi&#281;, zacznij od struktury dokumentu.</p>

<h2 id="dobrze-napisany-html-jest-czytelny-takze-poza-ekranem">Dobrze napisany HTML jest czytelny tak&#380;e poza ekranem</h2>
<p>HTML to j&#281;zyk znacznik&oacute;w, kt&oacute;ry porz&#261;dkuje tre&#347;&#263; i opisuje funkcje element&oacute;w strony. <strong>CSS odpowiada za prezentacj&#281;, a JavaScript za wiele dodatkowych interakcji</strong>, cho&#263; przegl&#261;darka potrafi te&#380; wykona&#263; cz&#281;&#347;&#263; dzia&#322;a&#324; opisanych bezpo&#347;rednio w HTML.</p>

<p>Przy nauce frontendu zacznij od rozpoznawania element&oacute;w i ich znaczenia, zamiast zapami&#281;tywa&#263; same nazwy tag&oacute;w. Gdy kod jasno opisuje struktur&#281;, &#322;atwiej go rozwija&#263;, stylowa&#263; i udost&#281;pnia&#263; osobom korzystaj&#261;cym z r&oacute;&#380;nych urz&#261;dze&#324; oraz technologii asystuj&#261;cych.</p></div></code></p></div></code></p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>Frontend i UX</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/783cf6bd72263a98671c268741325a5d/czym-jest-html-i-jak-rozni-sie-od-css-oraz-javascriptu.webp"/>
      <pubDate>Tue, 03 Nov 2026 16:08:00 +0100</pubDate>
    </item>
    <item>
      <title>MB czy KB? Sprawdź, co jest większe i jak liczyć limit pliku</title>
      <link>https://lukasz-zielinski.pl/mb-czy-kb-sprawdz-co-jest-wieksze-i-jak-liczyc-limit-pliku</link>
      <description>Czy MB jest większe od KB? Sprawdź przeliczniki 1000 i 1024, różnice MB/MiB oraz wpływ jednostek na limity uploadu i transfer. Zobacz!</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Konfigurujesz limit uploadu i zastanawiasz si&#281;, czy plik o rozmiarze 800 KB zmie&#347;ci si&#281; w limicie 1 MB? <strong>Wi&#281;kszy jest MB</strong>, cho&#263; przelicznik zale&#380;y od tego, czy program u&#380;ywa jednostek dziesi&#281;tnych, czy binarnych.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/5d6c49f0eb339c0db7af2c7434cde858/porownanie-jednostek-danych-mb-kb-mib-kib-infografika.webp" class="image article-image" loading="lazy" alt="Wykres s&#322;upkowy pokazuje, co jest wi&#281;ksze: MB czy KB. S&#322;upki MB, GB, KB i TB rosn&#261;, ilustruj&#261;c jednostki pami&#281;ci."></p><div class="short-summary">
  <h2 id="mb-oznacza-wieksza-porcje-danych-niz-kb-ale-sprawdz-sposob-liczenia">MB oznacza wi&#281;ksz&#261; porcj&#281; danych ni&#380; KB, ale sprawd&#378; spos&oacute;b liczenia</h2>
  <ul>
    <li><strong>MB jest wi&#281;ksze od KB</strong> w obu popularnych sposobach zapisu jednostek.</li>
    <li><strong>1 MB = 1000 kB</strong> w uk&#322;adzie dziesi&#281;tnym.</li>
    <li><strong>1 MiB = 1024 KiB</strong> w uk&#322;adzie binarnym.</li>
    <li><strong>KB i MB bywaj&#261; niejednoznaczne</strong> w starszych programach i opisach.</li>
    <li><strong>Mbps to megabity na sekund&#281;</strong>, a MB/s to megabajty na sekund&#281;.</li>
  </ul>
</div><h2 id="mb-jest-wieksze-od-kb-niezaleznie-od-przyjetego-przelicznika">MB jest wi&#281;ksze od KB, niezale&#380;nie od przyj&#281;tego przelicznika</h2><p>R&oacute;&#380;nica mi&#281;dzy megabajtem a kilobajtem przypomina r&oacute;&#380;nic&#281; mi&#281;dzy kilometrem a metrem: oba opisuj&#261; t&#281; sam&#261; kategori&#281;, ale na innym poziomie skali. <strong>Megabajt (MB) jest wi&#281;kszy</strong>, a sp&oacute;r dotyczy tego, ile dok&#322;adnie kilobajt&oacute;w mie&#347;ci si&#281; w jednym megabajcie.</p><p>W zapisie dziesi&#281;tnym 1 MB to 1000 kB. W zapisie binarnym cz&#281;sto spotyka si&#281; 1 MB r&oacute;wne 1024 KB, ale precyzyjne symbole dla tej drugiej konwencji to <strong>MiB i KiB</strong>. Uwa&#380;am, &#380;e w&#322;a&#347;nie pomini&#281;te &bdquo;i&rdquo; jest &#378;r&oacute;d&#322;em wi&#281;kszo&#347;ci nieporozumie&#324;.</p><h2 id="mib-i-kib-odrozniaja-potegi-dwojki-od-dziesietnych">MiB i KiB odr&oacute;&#380;niaj&#261; pot&#281;gi dw&oacute;jki od dziesi&#281;tnych</h2><p>Je&#347;li sprawdzasz dokumentacj&#281; infrastruktury albo limit w systemie, pojedyncza litera potrafi zmieni&#263; interpretacj&#281; warto&#347;ci. Standard <a href="https://physics.nist.gov/cuu/Units/binary.html" target="_blank" rel="noopener noreferrer nofollow">NIST dotycz&#261;cy przedrostk&oacute;w binarnych</a> rozdziela jednostki dziesi&#281;tne, takie jak MB, od binarnych, takich jak MiB.</p><table>
  <tbody>
    <tr><th>Jednostka</th><th>Warto&#347;&#263; w bajtach</th><th>Typowy sens</th></tr>
    <tr><td>kB</td><td>1000 B</td><td>kilobajt dziesi&#281;tny</td></tr>
    <tr><td>MB</td><td>1 000 000 B</td><td>megabajt dziesi&#281;tny</td></tr>
    <tr><td>KiB</td><td>1024 B</td><td>kibibajt binarny</td></tr>
    <tr><td>MiB</td><td>1 048 576 B</td><td>mebibajt binarny</td></tr>
  </tbody>
</table><p>Takie rozr&oacute;&#380;nienie opisuje te&#380; <a href="https://styleguide.iec.ch/?docs=iec%2Ftypographic%2Funits-and-symbols" target="_blank" rel="noopener noreferrer nofollow">przewodnik terminologiczny IEC</a>: przedrostek &bdquo;kilo&rdquo; oznacza mno&#380;nik 1000, a &bdquo;kibi&rdquo; 1024. W praktyce spotkasz jednak starsze aplikacje, kt&oacute;re zapisuj&#261; KB lub MB, cho&#263; licz&#261; po binarnemu.</p><h2 id="limit-10-gb-moze-oznaczac-okolo-931-gib-w-systemie">Limit 10 GB mo&#380;e oznacza&#263; oko&#322;o 9,31 GiB w systemie</h2><p>To rozbie&#380;no&#347;&#263;, kt&oacute;ra potrafi zaskoczy&#263; przy konfiguracji przestrzeni na logi, kopie zapasowe albo pliki w chmurze. Je&#347;li dostawca podaje limit <strong>10 GB dziesi&#281;tnie</strong>, odpowiada on oko&#322;o <strong>9,31 GiB</strong>; panel pokazuj&#261;cy warto&#347;ci binarne mo&#380;e wi&#281;c wy&#347;wietli&#263; mniej ni&#380; oczekiwana liczba &bdquo;gigabajt&oacute;w&rdquo;, mimo &#380;e nie znikn&#281;&#322;o &#380;adne miejsce.</p><p>Nie oznacza to automatycznie b&#322;&#281;du po stronie us&#322;ugi. Przed ustawieniem alertu lub quota sprawd&#378;, czy dokumentacja opisuje pojemno&#347;&#263; w GB, czy GiB, a je&#347;li symbol nie jest obja&#347;niony, poszukaj informacji o liczbie bajt&oacute;w. Przy progach bliskich pe&#322;nego wykorzystania r&oacute;&#380;nica mo&#380;e zmieni&#263; moment uruchomienia alarmu.</p><h2 id="symbol-jednostki-podpowiada-jak-odczytac-plik-i-transfer">Symbol jednostki podpowiada, jak odczyta&#263; plik i transfer</h2><p>Sam rozmiar pliku to po&#322;owa pu&#322;apki. W <a href="https://lukasz-zielinski.pl/docker-compose-i-sieci-dlaczego-api-nie-laczy-sie-z-baza">sieci</a> &#322;atwo pomyli&#263; wielko&#347;&#263; danych z szybko&#347;ci&#261; &#322;&#261;cza, bo <strong>bajt i bit maj&#261; r&oacute;&#380;ne symbole</strong>: B oznacza bajt, a b bit.</p><table>
  <tbody>
    <tr><th>Co widzisz</th><th>Co oznacza</th><th>Jak to odczyta&#263;</th></tr>
    <tr><td>MB</td><td>megabajty</td><td>rozmiar danych</td></tr>
    <tr><td>Mb</td><td>megabity</td><td>jednostka danych, osiem razy mniejsza od bajtu</td></tr>
    <tr><td>MB/s</td><td>megabajty na sekund&#281;</td><td>szybko&#347;&#263; transferu w bajtach</td></tr>
    <tr><td>Mb/s lub Mbps</td><td>megabity na sekund&#281;</td><td>szybko&#347;&#263; &#322;&#261;cza w bitach</td></tr>
  </tbody>
</table><p>Je&#347;li wi&#281;c widzisz &bdquo;100 Mb/s&rdquo; przy &#322;&#261;czu, nie oznacza to pobierania 100 MB danych w sekund&#281;. To inna jednostka, a do tego rzeczywista pr&#281;dko&#347;&#263; transferu mo&#380;e zale&#380;e&#263; od narzut&oacute;w protoko&#322;u i warunk&oacute;w po&#322;&#261;czenia.</p><h2 id="przy-limicie-pliku-sprawdz-jednostke-w-komunikacie-bledu">Przy limicie pliku sprawd&#378; jednostk&#281; w komunikacie b&#322;&#281;du</h2><p>Komunikat &bdquo;maksymalny rozmiar 5 MB&rdquo; nie zawsze m&oacute;wi, czy aplikacja liczy dziesi&#281;tnie, czy binarnie. Tabela pomaga szybko oceni&#263;, sk&#261;d bierze si&#281; r&oacute;&#380;nica mi&#281;dzy rozmiarem pliku a limitem.</p><table>
  <tbody>
    <tr><th>Sytuacja</th><th>Prawdopodobna przyczyna</th><th>Co zrobi&#263;</th></tr>
    <tr><td>Plik ma mniej ni&#380; limit w bajtach, ale upload go odrzuca</td><td>Inny przelicznik MB lub narzut formatu</td><td>Sprawd&#378; rozmiar w bajtach i opis limitu po stronie aplikacji</td></tr>
    <tr><td>Panel pokazuje mniej GB ni&#380; etykieta us&#322;ugi</td><td>Jedna warto&#347;&#263; jest dziesi&#281;tna, druga binarna</td><td>Por&oacute;wnaj bajty albo szukaj symboli GiB i GB</td></tr>
    <tr><td>Pr&#281;dko&#347;&#263; pobierania jest ni&#380;sza ni&#380; liczba z umowy</td><td>Umowa podaje Mb/s, a program MB/s</td><td>Upewnij si&#281;, &#380;e por&oacute;wnujesz bity z bitami lub bajty z bajtami</td></tr>
  </tbody>
</table><p>Przy uploadzie najbezpieczniej por&oacute;wnywa&#263; <strong>warto&#347;ci w bajtach</strong>, je&#347;li s&#261; dost&#281;pne. Gdy dokumentacja podaje tylko &bdquo;MB&rdquo;, traktuj oznaczenie ostro&#380;nie i zostaw zapas, zamiast ustawia&#263; plik dok&#322;adnie na granicy limitu.</p><h2 id="najprostsza-zasada-to-odrozniac-skale-od-dokladnego-przelicznika">Najprostsza zasada to odr&oacute;&#380;nia&#263; skal&#281; od dok&#322;adnego przelicznika</h2><p>Na pytanie, co jest wi&#281;ksze, odpowied&#378; jest prosta: <strong>megabajt jest wi&#281;kszy od kilobajtu</strong>. Przy konfiguracji system&oacute;w nie zak&#322;adaj jednak, &#380;e ka&#380;de &bdquo;MB&rdquo; oznacza t&#281; sam&#261; liczb&#281; bajt&oacute;w.</p><p>W specyfikacji szukaj pary <strong>MB i kB</strong> dla warto&#347;ci dziesi&#281;tnych albo <strong>MiB i KiB</strong> dla binarnych. Ta drobna kontrola pozwala unikn&#261;&#263; zaskoczenia przy limitach uploadu, alertach pojemno&#347;ci i pomiarach transferu.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>DevOps i infrastruktura</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/ab7f4fb5a929aebaaa767edb7eadff7a/mb-czy-kb-sprawdz-co-jest-wieksze-i-jak-liczyc-limit-pliku.webp"/>
      <pubDate>Tue, 03 Nov 2026 13:28:00 +0100</pubDate>
    </item>
    <item>
      <title>Python print() od podstaw - sep, end i różnica między print a return</title>
      <link>https://lukasz-zielinski.pl/python-print-od-podstaw-sep-end-i-roznica-miedzy-print-a-return</link>
      <description>Python print() bez tajemnic: poznaj sep, end, f-stringi oraz różnicę między print() i return. Sprawdź, jak diagnozować błędy.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Skrypt wypisuje wynik oblicze&#324;, ale zamiast czytelnego komunikatu pokazuje kilka warto&#347;ci obok siebie albo puste miejsce. Funkcja <code>print()</code> wy&#347;wietla dane w strumieniu wyj&#347;ciowym i domy&#347;lnie ko&#324;czy wiersz znakiem nowej linii, cho&#263; szczeg&oacute;&#322;y zmieniaj&#261; argumenty wywo&#322;ania. <strong>To drobiazgi, kt&oacute;re szybko decyduj&#261; o tym, czy komunikat pomaga znale&#378;&#263; b&#322;&#261;d, czy tylko za&#347;mieca konsol&#281;.</strong></p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/41b6482f1405aa4a001a912f05da5758/python-print-function-code-editor-console-output-example.webp" class="image article-image" loading="lazy" alt="Wyja&#347;nienie funkcji python print i jej parametr&oacute;w: sep, end, file, flush. Pokazuje, jak u&#380;ywa&#263; jej do wypisywania danych."></p><div class="short-summary">
  <h2 id="najwazniejsze-informacje-o-print-w-pythonie">Najwa&#380;niejsze informacje o print() w Pythonie</h2>
  <ul>
    <li><strong>Podstawowe wywo&#322;anie:</strong> <code>print("Gotowe")</code> wypisuje tekst i domy&#347;lnie przechodzi do nowej linii.</li>
    <li><strong>Wiele argument&oacute;w:</strong> <a href="https://lukasz-zielinski.pl/czym-jest-skrypt-i-do-czego-sluzy-w-programowaniu">Python</a> rozdziela je spacj&#261;, chyba &#380;e ustawisz <code>sep</code>.</li>
    <li><strong>Wynik funkcji:</strong> <code>print()</code> wy&#347;wietla tre&#347;&#263;, a jej warto&#347;ci&#261; zwrotn&#261; jest <code>None</code>.</li>
    <li><strong>Formatowanie:</strong> <a href="https://lukasz-zielinski.pl/round-w-pythonie-jak-zaokraglac-bez-pulapek">f-string</a> pozwala wstawi&#263; warto&#347;&#263; zmiennej bez r&#281;cznego &#322;&#261;czenia tekstu.</li>
    <li><strong>Diagnozowanie b&#322;&#281;du:</strong> sprawd&#378;, czy problem dotyczy zawarto&#347;ci, separatora, ko&#324;ca wiersza czy miejsca zapisu.</li>
  </ul>
</div><h2 id="print-pokazuje-dane-ale-nie-oddaje-ich-do-dalszych-obliczen">print() pokazuje dane, ale nie oddaje ich do dalszych oblicze&#324;</h2><p>Wyobra&#378; sobie, &#380;e funkcja oblicza cen&#281; zam&oacute;wienia. Mo&#380;esz pokaza&#263; wynik w konsoli, ale samo wy&#347;wietlenie nie zapisuje go w zmiennej ani nie przekazuje do kolejnego fragmentu programu. <strong>Do tego s&#322;u&#380;y zwracanie warto&#347;ci, a nie drukowanie jej na ekranie.</strong></p><pre><code>def oblicz_cene(cena, liczba_sztuk):
    return cena * liczba_sztuk

suma = oblicz_cene(19.99, 3)
print(f"Do zap&#322;aty: {suma:.2f} z&#322;")</code></pre><p>Funkcja <code>oblicz_cene()</code> zwraca liczb&#281;, kt&oacute;r&#261; mo&#380;na przypisa&#263;, por&oacute;wna&#263; albo wykorzysta&#263; ponownie. <code>print()</code> zamienia przekazane obiekty na tekst i zapisuje je w strumieniu wyj&#347;ciowym; samo wywo&#322;anie zwraca <code>None</code>. Potwierdza to dokumentacja wbudowanych funkcji Pythona, kt&oacute;ra opisuje konwersj&#281; argument&oacute;w i zapis do strumienia. <strong>Je&#347;li p&oacute;&#378;niej potrzebujesz wyniku w kodzie, u&#380;yj <code>return</code>; je&#347;li chcesz go zobaczy&#263;, u&#380;yj <code>print()</code>.</strong> Uwa&#380;am, &#380;e to rozr&oacute;&#380;nienie oszcz&#281;dza pocz&#261;tkuj&#261;cym najwi&#281;cej nieporozumie&#324;.</p><h2 id="sep-i-end-zmieniaja-odstepy-miedzy-wartosciami-i-koniec-wiersza">sep i end zmieniaj&#261; odst&#281;py mi&#281;dzy warto&#347;ciami i koniec wiersza</h2><p>Wywo&#322;anie <code>print("Status", "OK")</code> wypisze <code>Status OK</code>, bo domy&#347;lnym separatorem argument&oacute;w jest pojedyncza spacja. Gdy przygotowujesz log lub prosty raport, mo&#380;esz zmieni&#263; separator i zako&#324;czenie wiersza osobno.</p><pre><code>print("2026", "11", "12", sep="-")
print("&#321;adowanie", end="...")
print("gotowe")</code></pre><p>Efekt to dwa wiersze: <code>2026-11-12</code> oraz <code>&#321;adowanie...gotowe</code>. Parametr <code>sep</code> dzia&#322;a mi&#281;dzy argumentami, a <code>end</code> dopisuje tekst po ostatnim z nich. Dokumentacja <a href="https://docs.python.org/3/library/functions.html" target="_blank" rel="noopener noreferrer nofollow">wbudowanej funkcji print</a> wskazuje te&#380;, &#380;e oba parametry musz&#261; by&#263; tekstem lub warto&#347;ci&#261; <code>None</code>. <strong>Je&#347;li wynik zlewa si&#281; w jeden ci&#261;g, obejrzyj <code>end</code>; je&#347;li brakuje odst&#281;p&oacute;w wewn&#261;trz komunikatu, sprawd&#378; <code>sep</code>.</strong></p><h2 id="f-string-ulatwia-czytelny-komunikat-bez-recznego-sklejania-tekstu">F-string u&#322;atwia czytelny komunikat bez r&#281;cznego sklejania tekstu</h2><p>Gdy w komunikacie maj&#261; pojawi&#263; si&#281; warto&#347;ci zmiennych, f-string zwykle daje prostszy zapis ni&#380; &#322;&#261;czenie fragment&oacute;w tekstu operatorem <code>+</code>. Wystarczy poprzedzi&#263; tekst liter&#261; <code>f</code> i umie&#347;ci&#263; wyra&#380;enie w nawiasach klamrowych.</p><pre><code>uzytkownik = "Ala"
zadania = 4
print(f"{uzytkownik} ma {zadania} zadania do wykonania.")</code></pre><p>Wynik: <code>Ala ma 4 zadania do wykonania.</code> Warto&#347;&#263; mo&#380;na te&#380; sformatowa&#263;, na przyk&#322;ad ograniczy&#263; liczb&#281; miejsc po przecinku: <code>print(f"{19.987:.2f}")</code> wy&#347;wietli <code>19.99</code>. F-stringi opisuje samouczek Pythona w rozdziale o <a href="https://docs.python.org/3/tutorial/inputoutput.html" target="_blank" rel="noopener noreferrer nofollow">wej&#347;ciu i wyj&#347;ciu</a>. <strong>Przy cenach, procentach i pomiarach formatowanie jest cz&#281;&#347;ci&#261; komunikatu</strong>, a nie kosmetycznym dodatkiem.</p><h2 id="gdy-wynik-wyglada-zle-diagnozuj-go-po-objawie">Gdy wynik wygl&#261;da &#378;le, diagnozuj go po objawie</h2><p>Ten sam pozorny problem, &bdquo;print nie dzia&#322;a&rdquo;, mo&#380;e mie&#263; kilka przyczyn: warto&#347;&#263; jest pusta, tekst trafi&#322; do innego strumienia albo program nie dotar&#322; do wywo&#322;ania funkcji. Zamiast zmienia&#263; kod na chybi&#322; trafi&#322;, dopasuj objaw do pierwszego testu.</p><table>
  <tbody>
    <tr>
      <th>Objaw</th>
      <th>Prawdopodobna przyczyna</th>
      <th>Co zrobi&#263;</th>
    </tr>
    <tr>
      <td>W konsoli pojawia si&#281; <code>None</code></td>
      <td>Wypisywana jest warto&#347;&#263; zwrotna funkcji, kt&oacute;ra niczego jawnie nie zwraca.</td>
      <td>Sprawd&#378;, czy funkcja ma zwraca&#263; dane przez <code>return</code>, czy tylko je wy&#347;wietla&#263;.</td>
    </tr>
    <tr>
      <td>Argumenty zlewaj&#261; si&#281; bez odst&#281;p&oacute;w</td>
      <td>Warto&#347;&#263; <code>sep</code> zosta&#322;a ustawiona na pusty tekst.</td>
      <td>Usu&#324; argument <code>sep</code> albo ustaw go na wybrany separator, na przyk&#322;ad <code>" "</code>.</td>
    </tr>
    <tr>
      <td>Tekst nie pojawia si&#281; od razu w procesie lub potoku</td>
      <td>Wyj&#347;cie mo&#380;e by&#263; buforowane.</td>
      <td>Ustaw <code>flush=True</code>, je&#347;li program ma natychmiast opr&oacute;&#380;ni&#263; bufor.</td>
    </tr>
    <tr>
      <td>Komunikat b&#322;&#281;du miesza si&#281; ze zwyk&#322;ym wynikiem</td>
      <td>Oba rodzaje komunikat&oacute;w trafiaj&#261; na standardowe wyj&#347;cie.</td>
      <td>U&#380;yj <code>file=sys.stderr</code> dla diagnostyki.</td>
    </tr>
  </tbody>
</table><p>W przypadku komunikatu diagnostycznego mo&#380;esz napisa&#263; <code>print("Nieprawid&#322;owy plik", file=sys.stderr)</code> po wcze&#347;niejszym <code>import sys</code>. Standardowe wyj&#347;cie i standardowy strumie&#324; b&#322;&#281;d&oacute;w s&#261; rozdzielone, wi&#281;c narz&#281;dzia uruchamiaj&#261;ce program mog&#261; inaczej obs&#322;u&#380;y&#263; wynik oraz diagnostyk&#281;. <strong>Je&#347;li tekst ma by&#263; cz&#281;&#347;ci&#261; raportu, wybierz plik lub standardowe wyj&#347;cie; je&#347;li ma opisywa&#263; b&#322;&#261;d, kieruj go do <code>stderr</code>.</strong></p><h2 id="wybierz-print-do-komunikatu-a-return-do-wyniku-funkcji">Wybierz print do komunikatu, a return do wyniku funkcji</h2><p>Naj&#322;atwiej podj&#261;&#263; decyzj&#281;, pytaj&#261;c, co ma zrobi&#263; nast&#281;pna linia kodu. Je&#347;li ma tylko pokaza&#263; u&#380;ytkownikowi status, u&#380;yj <code>print()</code>; je&#347;li ma dalej przetworzy&#263; obliczon&#261; warto&#347;&#263;, zwr&oacute;&#263; j&#261; z funkcji. Gdybym projektowa&#322; prost&#261; funkcj&#281; obliczeniow&#261;, zwraca&#322;bym z niej wynik, a wy&#347;wietlanie zostawi&#322; miejscu, kt&oacute;re odpowiada za interakcj&#281; z u&#380;ytkownikiem.</p><ul>
  <li><strong>Komunikat dla cz&#322;owieka:</strong> <code>print("Import zako&#324;czony")</code>.</li>
  <li><strong>Wynik do dalszych oblicze&#324;:</strong> <code>return liczba * stawka</code>.</li>
  <li><strong>Log post&#281;pu w jednej linii:</strong> zmie&#324; <code>end</code>, a w razie potrzeby wymu&#347; zapis przez <code>flush=True</code>.</li>
</ul><p>Je&#347;li budujesz aplikacj&#281; wi&#281;ksz&#261; ni&#380; kr&oacute;tki skrypt, sta&#322;e komunikaty diagnostyczne lepiej obs&#322;u&#380;y&#263; modu&#322;em <code>logging</code>, kt&oacute;ry pozwala rozr&oacute;&#380;nia&#263; poziomy i kierowa&#263; zapisy do r&oacute;&#380;nych miejsc. <strong>Do nauki i szybkiego podgl&#261;du wystarczy print()</strong>; w kodzie, kt&oacute;ry ma by&#263; utrzymywany i analizowany, wyb&oacute;r narz&#281;dzia powinien odpowiada&#263; temu, kto b&#281;dzie czyta&#322; komunikaty.</p><h2 id="jedno-pytanie-wystarczy-by-dobrac-wlasciwe-wyjscie">Jedno pytanie wystarczy, by dobra&#263; w&#322;a&#347;ciwe wyj&#347;cie</h2><p>Gdy w konsoli widzisz nieoczekiwany tekst, ustal najpierw, czy chcesz go wy&#347;wietli&#263;, zwr&oacute;ci&#263; z funkcji czy zapisa&#263; do konkretnego strumienia. Potem sprawd&#378; separator, zako&#324;czenie wiersza i format warto&#347;ci. <strong>Tak rozdzielisz problem z samymi danymi od problemu z ich prezentacj&#261;.</strong></p>]]></content:encoded>
      <author>Radosław Stępień</author>
      <category>Programowanie</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/d1f8fee7b7bbdec0da69e8c1021c0051/python-print-od-podstaw-sep-end-i-roznica-miedzy-print-a-return.webp"/>
      <pubDate>Tue, 03 Nov 2026 11:17:00 +0100</pubDate>
    </item>
    <item>
      <title>ORDER BY w SQL - jak ustalić stabilną kolejność wyników?</title>
      <link>https://lukasz-zielinski.pl/order-by-w-sql-jak-ustalic-stabilna-kolejnosc-wynikow</link>
      <description>ORDER BY w SQL ustala kolejność wyników, rozstrzyga remisy i stabilizuje paginację. Poznaj ASC, DESC, NULL oraz praktyczne przykłady.</description>
      <content:encoded><![CDATA[<?xml encoding="utf-8" ?><p>Raport pokazuje te same rekordy w innej kolejno&#347;ci po zmianie planu zapytania albo dodaniu limitu? Dodaj <code>ORDER BY</code>, bo tylko on okre&#347;la kolejno&#347;&#263; wyniku, cho&#263; przy powtarzaj&#261;cych si&#281; warto&#347;ciach sortowania nadal mo&#380;e zabrakn&#261;&#263; stabilnego porz&#261;dku. Cz&#281;sto wystarczy jeden dodatkowy warunek, ale jego wyb&oacute;r zale&#380;y od tego, czy tworzysz zwyk&#322;y raport, czy stronicujesz dane w aplikacji.</p><p><img src="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/post_image/e8cbdfc5810fe771dea7dd9d90884a90/sql-order-by-sortowanie-wynikow-zapytania-tabela-bazy-danych-przyklad-kodu.webp" class="image article-image" loading="lazy" alt="Zapytanie SQL pobiera tytu&#322;y i d&#322;ugo&#347;ci film&oacute;w, sortuj&#261;c je malej&#261;co wed&#322;ug d&#322;ugo&#347;ci, aby uzyska&#263; 5 najd&#322;u&#380;szych."></p><div class="short-summary">
  <h2 id="sortuj-jawnie-i-dodaj-rozstrzygajacy-warunek-przy-remisach">Sortuj jawnie i dodaj rozstrzygaj&#261;cy warunek przy remisach</h2>
  <ul>
    <li><strong>Bez ORDER BY</strong> kolejno&#347;&#263; zwracanych wierszy nie jest gwarantowana.</li>
    <li><strong>ASC</strong> oznacza sortowanie rosn&#261;ce i jest domy&#347;lne; <strong>DESC</strong> odwraca kierunek.</li>
    <li><strong>Wiele kolumn</strong> pozwala okre&#347;li&#263; kolejno&#347;&#263; g&#322;&oacute;wn&#261; i dodatkowe kryteria dla remis&oacute;w.</li>
    <li><strong>LIMIT lub paginacja</strong> wymagaj&#261; stabilnego sortowania, najlepiej z unikalnym identyfikatorem.</li>
    <li><strong>Sk&#322;adnia i obs&#322;uga NULL</strong> mog&#261; r&oacute;&#380;ni&#263; si&#281; mi&#281;dzy bazami danych.</li>
  </ul>
</div><h2 id="order-by-ustala-kolejnosc-wyniku-nie-kolejnosc-zapisu-danych">ORDER BY ustala kolejno&#347;&#263; wyniku, nie kolejno&#347;&#263; zapisu danych</h2><p>Gdy pobierasz list&#281; zg&#322;osze&#324;, produkt&oacute;w albo u&#380;ytkownik&oacute;w, sama kolejno&#347;&#263; rekord&oacute;w w tabeli niczego nie obiecuje. Bez klauzuli sortuj&#261;cej baza mo&#380;e zwr&oacute;ci&#263; wiersze w kolejno&#347;ci zale&#380;nej od planu wykonania i sposobu odczytu danych. <strong>Je&#347;li kolejno&#347;&#263; ma by&#263; widoczna dla u&#380;ytkownika, okre&#347;l j&#261; w zapytaniu.</strong></p><p>Podstawowa sk&#322;adnia wygl&#261;da tak:</p><pre><code>SELECT id, created_at, status
FROM tickets
ORDER BY created_at DESC;</code></pre><p>Wynik b&#281;dzie uporz&#261;dkowany od najnowszych zg&#322;osze&#324;. Pomini&#281;cie kierunku oznacza <code>ASC</code>, czyli porz&#261;dek rosn&#261;cy; <code>DESC</code> ustawia warto&#347;ci malej&#261;co. Jak opisuje <a href="https://www.postgresql.org/docs/17/queries-order.html" target="_blank" rel="noopener noreferrer nofollow">dokumentacja PostgreSQL dotycz&#261;ca sortowania wierszy</a>, kolejne wyra&#380;enia w klauzuli s&#261; u&#380;ywane do rozstrzygania remis&oacute;w wed&#322;ug ich kolejno&#347;ci.</p><p><strong>ORDER BY nie zmienia tabeli</strong> ani nie zapisuje nowej kolejno&#347;ci rekord&oacute;w. Porz&#261;dkuje wy&#322;&#261;cznie wynik konkretnego zapytania. Je&#347;li wynik trafia do widoku albo raportu, sortowanie trzeba okre&#347;li&#263; w zapytaniu, kt&oacute;re ten wynik zwraca.</p><h2 id="przy-remisie-dodaj-unikalny-identyfikator">Przy remisie dodaj unikalny identyfikator</h2><p>Dwa zg&#322;oszenia mog&#261; mie&#263; identyczny czas utworzenia, zw&#322;aszcza gdy aplikacja zapisuje je w kr&oacute;tkich odst&#281;pach. Wtedy samo <code>ORDER BY created_at DESC</code> nie okre&#347;la, kt&oacute;re z nich ma pojawi&#263; si&#281; pierwsze. <strong>Baza mo&#380;e zmieni&#263; ich wzajemn&#261; kolejno&#347;&#263;</strong>, cho&#263; g&#322;&oacute;wny warunek sortowania si&#281; nie zmieni&#322;.</p><p>W aplikacji wy&#347;wietlaj&#261;cej zg&#322;oszenia stabilniejszy wynik zapewni dodatkowy identyfikator:</p><pre><code>SELECT id, created_at, status
FROM tickets
ORDER BY created_at DESC, id DESC
LIMIT 20;</code></pre><p>Zak&#322;adaj&#261;c, &#380;e <code>id</code> jest unikalne, ka&#380;de zg&#322;oszenie ma teraz rozstrzygni&#281;te miejsce tak&#380;e w przypadku takiej samej daty. Dokumentacja <a href="https://dev.mysql.com/doc/refman/26.7/en/limit-optimization.html" target="_blank" rel="noopener noreferrer nofollow">MySQL o optymalizacji LIMIT</a> wyja&#347;nia, &#380;e przy r&oacute;wnych warto&#347;ciach kolumn sortuj&#261;cych rekordy mog&#261; by&#263; zwracane w r&oacute;&#380;nej kolejno&#347;ci, a dopisanie unikalnego pola pozwala j&#261; ustali&#263;.</p><p><strong>Regu&#322;a praktyczna:</strong> je&#347;li zapytanie zwraca ograniczon&#261; liczb&#281; rekord&oacute;w albo zasila strony wynik&oacute;w, dodaj na ko&#324;cu kolumn&#281; unikaln&#261;. Przy jednorazowym raporcie bez limitu remisy mog&#261; nie przeszkadza&#263;, ale w interfejsie u&#380;ytkownika potrafi&#261; powodowa&#263; przeskakiwanie pozycji mi&#281;dzy stronami.</p><h2 id="sortowanie-po-kilku-kolumnach-dziala-warstwowo">Sortowanie po kilku kolumnach dzia&#322;a warstwowo</h2><p>Lista zam&oacute;wie&#324; mo&#380;e najpierw grupowa&#263; rekordy wed&#322;ug statusu, a dopiero potem uk&#322;ada&#263; je dat&#261;. W takim zapytaniu ka&#380;da nast&#281;pna kolumna dzia&#322;a jako kryterium pomocnicze, gdy wcze&#347;niejsza ma t&#281; sam&#261; warto&#347;&#263;.</p><pre><code>SELECT id, status, created_at
FROM orders
ORDER BY status ASC, created_at DESC, id ASC;</code></pre><p>Tu statusy uk&#322;adaj&#261; si&#281; rosn&#261;co, a zam&oacute;wienia w obr&#281;bie statusu od najnowszych. Identyfikator rozstrzyga ewentualny remis daty. Kierunek dotyczy ka&#380;dej kolumny osobno: <code>ORDER BY status, created_at DESC</code> oznacza rosn&#261;cy status i malej&#261;c&#261; dat&#281;, a nie sortowanie malej&#261;ce po obu polach. <strong>Ta r&oacute;&#380;nica cz&#281;sto kryje si&#281; w poprawnym sk&#322;adniowo, lecz &#378;le u&#322;o&#380;onym wyniku.</strong></p><p>Mo&#380;esz sortowa&#263; r&oacute;wnie&#380; po wyra&#380;eniu lub aliasie, je&#347;li dany silnik bazy to dopuszcza. Na przyk&#322;ad <code>ORDER BY total_price DESC</code> mo&#380;e wskazywa&#263; alias wyliczony w <code>SELECT</code>. Z numerami pozycji, takimi jak <code>ORDER BY 2</code>, lepiej uwa&#380;a&#263;: zmiana kolejno&#347;ci kolumn w li&#347;cie <code>SELECT</code> zmienia wtedy r&oacute;wnie&#380; kryterium sortowania. <a href="https://learn.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-ver17" target="_blank" rel="noopener noreferrer nofollow">Dokumentacja Microsoft SQL Server</a> odradza takie odwo&#322;ania pozycyjne ze wzgl&#281;du na ich mniejsz&#261; czytelno&#347;&#263; i ryzyko pomy&#322;ki przy edycji zapytania.</p><h2 id="null-i-skladnia-ograniczania-wynikow-zaleza-od-silnika">NULL i sk&#322;adnia ograniczania wynik&oacute;w zale&#380;&#261; od silnika</h2><p>Pusta warto&#347;&#263; w sortowanej kolumnie potrafi wyl&#261;dowa&#263; na pocz&#261;tku albo na ko&#324;cu listy. Nie zak&#322;adaj, &#380;e ka&#380;da baza zrobi to tak samo. <a href="https://lukasz-zielinski.pl/sql-delete-jak-usuwac-dane-bezpiecznie">PostgreSQL</a> pozwala wskaza&#263; po&#322;o&#380;enie jawnie przez <code>NULLS FIRST</code> lub <code>NULLS LAST</code>, na przyk&#322;ad:</p><pre><code>SELECT name, due_date
FROM tasks
ORDER BY due_date ASC NULLS LAST;</code></pre><p>Ta sk&#322;adnia nie jest jednak identycznie obs&#322;ugiwana przez wszystkie popularne silniki. Je&#347;li zapytanie ma dzia&#322;a&#263; w PostgreSQL, MySQL i SQL Server, sprawd&#378; regu&#322;y sortowania warto&#347;ci <code>NULL</code> oraz mo&#380;liwo&#347;ci konkretnego systemu przed przeniesieniem klauzuli bez zmian. <strong>Przeno&#347;no&#347;&#263; zapytania ko&#324;czy si&#281; tam, gdzie zaczynaj&#261; si&#281; r&oacute;&#380;nice dialekt&oacute;w.</strong></p><p>R&oacute;&#380;ni si&#281; te&#380; spos&oacute;b ograniczania liczby wierszy: w MySQL cz&#281;sto u&#380;ywa si&#281; <code>LIMIT</code>, natomiast SQL Server obs&#322;uguje mi&#281;dzy innymi <code>OFFSET</code> i <code>FETCH</code> w klauzuli sortuj&#261;cej. Przy stronicowaniu sam stabilny porz&#261;dek nie wystarczy, je&#347;li dane zmieniaj&#261; si&#281; mi&#281;dzy kolejnymi &#380;&#261;daniami. Microsoft wskazuje, &#380;e stabilne wyniki paginacji wymagaj&#261; niezmienionych danych albo odpowiedniego poziomu izolacji transakcji.</p><h2 id="gdy-wynik-wyglada-zle-zacznij-od-rodzaju-bledu">Gdy wynik wygl&#261;da &#378;le, zacznij od rodzaju b&#322;&#281;du</h2><p>Zapytanie mo&#380;e wykona&#263; si&#281; bez b&#322;&#281;du, a mimo to da&#263; wynik, kt&oacute;ry myli odbiorc&#281;. Prawd&#281; m&oacute;wi&#261;c, cz&#281;&#347;ciej problemem jest niedopowiedziana regu&#322;a sortowania ni&#380; sama sk&#322;adnia. Poni&#380;sze rozpoznanie pozwala szybko ustali&#263;, co poprawi&#263;:</p><table>
  <tbody>
    <tr>
      <th scope="col">Sytuacja</th>
      <th scope="col">Prawdopodobna przyczyna</th>
      <th scope="col">Co zrobi&#263;</th>
    </tr>
    <tr>
      <td>Wiersze zmieniaj&#261; kolejno&#347;&#263; mi&#281;dzy uruchomieniami</td>
      <td>Brak <code>ORDER BY</code> albo nierozstrzygni&#281;te remisy</td>
      <td>Dodaj kryterium sortowania, a przy powtarzaj&#261;cych si&#281; warto&#347;ciach r&oacute;wnie&#380; unikalny identyfikator.</td>
    </tr>
    <tr>
      <td>Puste daty s&#261; w nieoczekiwanym miejscu</td>
      <td>Domy&#347;lne po&#322;o&#380;enie <code>NULL</code> w danym silniku</td>
      <td>Ustal, czy puste warto&#347;ci maj&#261; by&#263; na pocz&#261;tku, czy na ko&#324;cu, i zastosuj sk&#322;adni&#281; w&#322;a&#347;ciw&#261; dla bazy.</td>
    </tr>
    <tr>
      <td>Wynik stronicowany powtarza lub pomija rekordy</td>
      <td>Sortowanie po nieunikalnym polu albo zmiana danych mi&#281;dzy zapytaniami</td>
      <td>Rozszerz porz&#261;dek o unikalne pole; przy aktywnych zmianach sprawd&#378; strategi&#281; transakcji lub paginacji.</td>
    </tr>
    <tr>
      <td>Sortowanie nazw wygl&#261;da nielogicznie</td>
      <td>Regu&#322;y por&oacute;wnywania tekstu, czyli kolacja</td>
      <td>Sprawd&#378; kolacj&#281; kolumny i wymagania j&#281;zykowe dla polskich znak&oacute;w.</td>
    </tr>
  </tbody>
</table><p>Gdy sortowanie spowalnia zapytanie, nie zak&#322;adaj od razu, &#380;e trzeba doda&#263; indeks. Silnik mo&#380;e skorzysta&#263; z indeksu pasuj&#261;cego do warunk&oacute;w i kolejno&#347;ci sortowania, ale zale&#380;y to od zapytania oraz planu wykonania. <strong>Najpierw sprawd&#378; plan</strong>, a potem oce&#324;, czy indeks pomo&#380;e bez niepotrzebnego obci&#261;&#380;ania zapis&oacute;w do tabeli.</p><h2 id="dobre-sortowanie-zaczyna-sie-od-jasnej-reguly">Dobre sortowanie zaczyna si&#281; od jasnej regu&#322;y</h2><p>Najpierw zdecyduj, co oznacza &bdquo;pierwszy&rdquo; rekord: najnowszy, najta&#324;szy, alfabetycznie pierwszy czy najwy&#380;szy priorytet. Potem zapisz t&#281; regu&#322;&#281; w <code>ORDER BY</code> i rozstrzygnij remisy, je&#347;li kolejno&#347;&#263; ma by&#263; powtarzalna. <strong>To prostsze ni&#380; p&oacute;&#378;niejsze szukanie przyczyny, dla kt&oacute;rej rekord zmieni&#322; miejsce na kolejnej stronie.</strong></p><p>Uwa&#380;am, &#380;e przy zapytaniu z limitem unikalny identyfikator powinien by&#263; domy&#347;lnym ostatnim kryterium, chyba &#380;e istnieje inny zestaw p&oacute;l gwarantuj&#261;cy unikalny porz&#261;dek. Dzi&#281;ki temu wynik opisuje regu&#322;&#281; aplikacji, a nie przypadkow&#261; decyzj&#281; planu wykonania.</p>]]></content:encoded>
      <author>Tymoteusz Maciejewski</author>
      <category>Bazy danych</category>
      <media:thumbnail url="https://frce8xp4ye4n.compat.objectstorage.eu-frankfurt-1.oraclecloud.com/blog-assets/thumbnail/1fbd4d1e0c512bae86f5e95fc930e2df/order-by-w-sql-jak-ustalic-stabilna-kolejnosc-wynikow.webp"/>
      <pubDate>Mon, 02 Nov 2026 10:51:00 +0100</pubDate>
    </item>
  </channel>
</rss>