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

<channel>
	<title>Technologie &#8211; Nearshore Software Development Company &#8211; IT Outsourcing Services</title>
	<atom:link href="https://nearshore-it.eu/pl/technologie/feed/" rel="self" type="application/rss+xml" />
	<link>https://nearshore-it.eu/pl/</link>
	<description>We are Nearshore Software Development Company with 14years of experience in delivering a large scale IT projects in the areas of PHP, JAVA, .NET, BI and MDM.</description>
	<lastBuildDate>Tue, 27 Jan 2026 08:25:50 +0000</lastBuildDate>
	<language>pl-PL</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>

<image>
	<url>https://nearshore-it.eu/wp-content/uploads/2023/01/cropped-inetum-favicon-300x300-1-32x32.png</url>
	<title>Technologie &#8211; Nearshore Software Development Company &#8211; IT Outsourcing Services</title>
	<link>https://nearshore-it.eu/pl/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Azure Service Bus – usługa, która usprawnia obsługę komunikatów i kolejki w nowoczesnych aplikacjach</title>
		<link>https://nearshore-it.eu/pl/artykuly/azure-service-bus/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/azure-service-bus/#respond</comments>
		
		<dc:creator><![CDATA[Bartosz Brandt]]></dc:creator>
		<pubDate>Mon, 26 Jan 2026 14:30:09 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[Application development]]></category>
		<category><![CDATA[Cloud engineering]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=37834</guid>

					<description><![CDATA[Azure Service Bus to dojrzały broker komunikatów klasy enterprise, który w ekosystemie Microsoft Azure odpowiada za niezawodną komunikację między mikroserwisami i systemami zewnętrznymi. Artykuł pokazuje, jak kolejki, topics, subskrypcje i sesje pozwalają budować systemy odporne na przeciążenia i awarie oraz dlaczego wzorce takie jak publish/subscribe, request–response, outbox i inbox są dziś fundamentem architektury event-driven. Jeśli projektujesz skalowalne aplikacje i chcesz świadomie wybrać model komunikacji — ten materiał pomoże Ci podjąć właściwe decyzje architektoniczne.]]></description>
										<content:encoded><![CDATA[
<p>Podczas tworzenia nowoczesnych aplikacji coraz rzadziej wybierana jest architektura monolityczna. W dzisiejszych czasach znacznie częściej są to modularne monolity lub <a href="https://nearshore-it.eu/pl/artykuly/mikroserwisy-nowa-jakosc-w-miedzynarodowych-projektach-it/">mikroserwisy</a>. Często również spotykamy integracje z systemami zewnętrznymi oraz architekturę event-driven, które sprawiają, że kluczowym elementem staje się niezawodna komunikacja pomiędzy komponentami. W ekosystemie Microsoft Azure rolę tę bardzo często pełni usługa Service Bus – dojrzały broker komunikatów klasy enterprise.</p>



<div class="table-of-contents">
    <p class="title"></p>
    <ol>
                    <li><a href="#czym-jest-usluga-service-bus-i-dlaczego-microsoft-stawia-na-komunikaty-w-chmurze">1.  Czym jest usługa Service Bus i dlaczego Microsoft stawia na komunikaty w chmurze?</a></li>
                    <li><a href="#kolejki-topics-i-subskrypcje-oraz-sesje-jak-dziala-usluga-azure-service-bus">2.  Kolejki, Topics i subskrypcje oraz sesje – jak działa usługa Azure Service Bus?</a></li>
                    <li><a href="#azure-service-bus-queue-vs-topic-kiedy-wybrac-ktore-rozwiazanie">3.  Azure Service Bus Queue vs Topic – kiedy wybrać które rozwiązanie?</a></li>
                    <li><a href="#azure-service-bus-patterns-wzorce-ktore-warto-znac">4.  Azure Service Bus Patterns – wzorce, które warto znać</a></li>
                    <li><a href="#monitoring-i-diagnostyka-azure-service-bus-alerts-i-integracja-z-application-insights">5.  Monitoring i diagnostyka: Azure Service Bus Alerts i integracja z Application Insights</a></li>
                    <li><a href="#zabezpieczenia-w-azure-service-bus-rbac-sas-i-protokol-amqp">6.  Zabezpieczenia w Azure Service Bus – RBAC, SAS i protokół AMQP</a></li>
                    <li><a href="#podsumowanie-co-warto-zapamiętać">7.  Podsumowanie – co warto zapamiętać?</a></li>
                    <li><a href="#czesto-zadawane-pytania">8.  Często zadawane pytania</a></li>
            </ol>
</div>


<h2 class="wp-block-heading" id="czym-jest-usluga-service-bus-i-dlaczego-microsoft-stawia-na-komunikaty-w-chmurze">Czym jest usługa Service Bus i dlaczego Microsoft stawia na komunikaty w chmurze?</h2>



<p>Azure Service Bus pozwala oddzielić producentów komunikatów od ich konsumentów. Dzięki temu aplikacje nie muszą znać się nawzajem ani działać w tym samym czasie. Komunikaty mogą być bezpiecznie przechowywane, ponawiane i przetwarzane asynchronicznie, co znacząco poprawia stabilność całego systemu.</p>



<p>Z perspektywy architekta jest to jedno z kluczowych narzędzi do budowy systemów odpornych na przeciążenia i chwilowe awarie.</p>



<p>Azure Service Bus to zarządzana usługa message brokera, oferująca:</p>



<ul class="wp-block-list">
<li>kolejki (Queues),</li>



<li>tematy i subskrypcje (Topics &amp; Subscriptions),</li>



<li>transakcje,</li>



<li>obsługę kolejki utraconych wiadomości (dead-letter queue),</li>
</ul>



<p>Nowoczesne systemy IT konsekwentnie promują komunikację asynchroniczną za pomocą kolejek z kilku powodów:</p>



<ul class="wp-block-list">
<li>zwiększa skalowalność,</li>



<li>upraszcza rozwój mikroserwisów,</li>



<li>pozwala niezależnie wdrażać i rozwijać komponenty niezależnie od użytych technologii do ich wytworzenia,</li>



<li>pozwala lepiej wykorzystać zasoby chmurowe dostępne np. w środowisku Microsoft Azure.</li>
</ul>



<h2 class="wp-block-heading" id="kolejki-topics-i-subskrypcje-oraz-sesje-jak-dziala-usluga-azure-service-bus">Kolejki, Topics i subskrypcje oraz sesje – jak działa usługa Azure Service Bus?</h2>



<h3 class="wp-block-heading">Service Bus Queue – kolejki usługi service bus</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img fetchpriority="high" decoding="async" width="756" height="620" src="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_1.png" alt="Service Bus Queue – kolejki usługi service bus " class="wp-image-37838" title="Azure Service Bus – usługa, która usprawnia obsługę komunikatów i kolejki w nowoczesnych aplikacjach 1" srcset="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_1.png 756w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_1-300x246.png 300w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_1-482x395.png 482w" sizes="(max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:16px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Kolejki w Azure Service Bus realizują model <strong>point-to-point</strong>, w którym każdy komunikat trafia do kolejki i jest przetwarzany <strong>przez jednego konsumenta</strong>. Nadawca i odbiorca są od siebie niezależni – komunikaty mogą być wysyłane i odbierane w różnym czasie, co zwiększa odporność systemu na awarie i chwilowe przeciążenia.</p>



<p>Usługa wykorzystuje mechanizm <strong>Peek-Lock</strong>, który tymczasowo blokuje komunikat po jego odebraniu. Dopiero po poprawnym przetworzeniu jest on usuwany z kolejki. W przypadku wystąpienia błędu może zostać ponownie udostępniony innemu odbiorcy lub trafić do <strong>dead-letter queue</strong>, co ułatwia diagnostykę problemów. Mechanizm Peek-Lock pozwala konsumentowi tymczasowo zablokować komunikat w kolejce. W przypadku wygaśnięcia blokady (np. z powodu timeoutu), komunikat staje się dostępny dla innych konsumentów, co może prowadzić do powtórnego odbioru.</p>



<p>Jedna kolejka może być obsługiwana przez wiele instancji konsumentów. Azure Service Bus automatycznie rozdziela komunikaty pomiędzy nich, zapewniając <strong>naturalny load balancing</strong> bez dodatkowej logiki po stronie aplikacji.</p>



<p>Kolejki sprawdzają się szczególnie dobrze w scenariuszach takich jak:</p>



<ul class="wp-block-list">
<li>przetwarzanie zadań w tle,</li>



<li>kolejkowanie żądań i ochrona systemów przed przeciążeniem,</li>



<li>równoważenie obciążenia pomiędzy wieloma instancjami usług,</li>



<li>asynchroniczna integracja systemów.</li>
</ul>



<h3 class="wp-block-heading">Topics i subskrypcje</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="756" height="1080" src="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_2.png" alt="Topics i subskrypcje " class="wp-image-37841" title="Azure Service Bus – usługa, która usprawnia obsługę komunikatów i kolejki w nowoczesnych aplikacjach 2" srcset="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_2.png 756w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_2-210x300.png 210w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_2-277x395.png 277w" sizes="(max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:16px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Topics w Azure Service Bus realizują wzorzec <strong>publish/subscribe</strong>, w którym jeden komunikat może zostać dostarczony do <strong><a href="https://nearshore-it.eu/pl/artykuly/systemy-rozproszone-niezalezne-od-platformy-wprowadzenie-do-dapr-io/" data-type="link" data-id="https://nearshore-it.eu/pl/artykuly/systemy-rozproszone-niezalezne-od-platformy-wprowadzenie-do-dapr-io/">wielu niezależnych odbiorców</a></strong>. Producent wysyła komunikat do tematu (Topic), nie wiedząc, kto i ile systemów będzie go konsumować. Każda subskrypcja działa jak osobna kolejka, posiadająca własny stan, retry oraz dead-letter queue.</p>



<p>Największą zaletą Topics są <strong>subskrypcje z filtrami</strong>, które pozwalają określić, jakie komunikaty trafią do danego odbiorcy. Filtry SQL lub reguły oparte o właściwości komunikatu umożliwiają precyzyjne routowanie zdarzeń bez dodatkowej logiki po stronie producenta.</p>



<p>Każda subskrypcja może być obsługiwana przez wiele instancji konsumentów, co, podobnie jak w przypadku kolejek, umożliwia<strong> równoległe przetwarzanie i load balancing</strong>. Jednocześnie różne subskrypcje mogą przetwarzać ten sam komunikat w zupełnie inny sposób lub w innym tempie.</p>



<p>Topics i subskrypcje sprawdzają się szczególnie dobrze w scenariuszach takich jak:</p>



<ul class="wp-block-list">
<li>architektura event-driven,</li>



<li>propagacja zdarzeń domenowych,</li>



<li>integracja wielu systemów reagujących na te same zdarzenia,</li>



<li>oddzielenie logiki biznesowej od procesów pomocniczych (np. powiadomień, audytu, raportowania).</li>
</ul>



<p>Dzięki modelowi publish/subscribe Azure Service Bus Topics umożliwiają budowę elastycznych i łatwo rozszerzalnych systemów, w których dodanie nowego odbiorcy nie wymaga zmian po stronie nadawcy.</p>



<h3 class="wp-block-heading">Sesje</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="756" height="560" src="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_3.png" alt="Sesje - Azure Service Bus" class="wp-image-37844" title="Azure Service Bus – usługa, która usprawnia obsługę komunikatów i kolejki w nowoczesnych aplikacjach 3" srcset="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_3.png 756w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_3-300x222.png 300w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_3-495x367.png 495w" sizes="(max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:16px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Sesje w Azure Service Bus to mechanizm umożliwiający <strong>grupowanie powiązanych komunikatów</strong> i przetwarzanie ich w <strong>ściśle określonej kolejności</strong>. Każdy komunikat posiada SessionId, a wszystkie komunikaty z tym samym identyfikatorem trafiają do tej samej sesji i są obsługiwane sekwencyjnie przez jednego konsumenta.</p>



<p>W praktyce oznacza to, że choć kolejka lub subskrypcja może być przetwarzana równolegle przez wiele instancji odbiorców, to <strong>w ramach jednej sesji nigdy nie dochodzi do przetwarzania równoległego</strong>. Azure Service Bus blokuje sesję na czas jej obsługi przez konkretnego konsumenta, co eliminuje problemy z kolejnością i <a href="https://nearshore-it.eu/pl/artykuly/pulapki-wspolbieznosci-narzut-synchronizacji-watkow/">współbieżnością</a>.</p>



<p>Sesje są szczególnie przydatne w scenariuszach, gdzie:</p>



<ul class="wp-block-list">
<li>kolejność komunikatów ma znaczenie (np. workflow, procesy krok po kroku),</li>



<li>komunikaty dotyczą jednego obiektu biznesowego (np. OrderId),</li>



<li>wymagane jest przetwarzanie stanowe (stateful processing),</li>



<li>system musi zachować spójność bez skomplikowanej synchronizacji.</li>
</ul>



<p>Sesje mogą być używane zarówno w Queue, jak i w subskrypcjach Topiców. Dzięki nim Azure Service Bus łączy wysoką skalowalność z kontrolą kolejności, co jest trudne do osiągnięcia w klasycznych systemach kolejkowych bez dodatkowej logiki po stronie aplikacji.</p>



<h2 class="wp-block-heading" id="azure-service-bus-queue-vs-topic-kiedy-wybrac-ktore-rozwiazanie">Azure Service Bus Queue vs Topic – kiedy wybrać które rozwiązanie?</h2>



<p>Wybór pomiędzy <strong>Queue</strong> a <strong>Topic</strong> w Azure Service Bus zależy przede wszystkim od tego, <strong>ile systemów ma przetwarzać dany komunikat</strong> i w jaki sposób ma on być obsłużony.</p>



<p>Queue najlepiej sprawdzi się w scenariuszach typu point-to-point, gdzie komunikat ma zostać przetworzony dokładnie raz przez jeden komponent. Jest to idealne rozwiązanie dla zadań w tle, kolejkowania żądań czy równoważenia obciążenia pomiędzy wieloma instancjami tej samej usługi. Queue upraszcza architekturę i minimalizuje liczbę zależności pomiędzy komponentami.</p>



<p>Topic warto wybrać wtedy, gdy komunikat reprezentuje zdarzenie, na które powinno zareagować wiele niezależnych systemów. Dzięki subskrypcjom i filtrom możliwe jest selektywne dostarczanie komunikatów do różnych odbiorców bez modyfikowania producenta. Topic naturalnie wspiera architekturę event-driven i ułatwia dalszą rozbudowę systemu.</p>



<p>W praktyce często stosuje się oba mechanizmy jednocześnie:</p>



<ul class="wp-block-list">
<li>Queue do obsługi zadań i procesów technicznych,</li>



<li>Topic do publikowania zdarzeń domenowych.</li>
</ul>



<p>Dobrze dobrany model komunikacji upraszcza architekturę i pozwala skalować system bez kosztownych refaktoryzacji w przyszłości.</p>



<h2 class="wp-block-heading" id="azure-service-bus-patterns-wzorce-ktore-warto-znac">Azure Service Bus Patterns – wzorce, które warto znać</h2>



<h3 class="wp-block-heading"><strong>Azure&nbsp;Service Bus&nbsp;Request-Response&nbsp;pattern</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="756" height="490" src="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_4.png" alt="Azure Service Bus Request-Response pattern" class="wp-image-37847" title="Azure Service Bus – usługa, która usprawnia obsługę komunikatów i kolejki w nowoczesnych aplikacjach 4" srcset="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_4.png 756w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_4-300x194.png 300w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_4-495x321.png 495w" sizes="auto, (max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:16px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Request–Response Pattern w Azure Service Bus umożliwia realizację komunikacji dwukierunkowej w sposób <strong>asynchroniczny</strong>, bez konieczności bezpośredniego połączenia pomiędzy nadawcą a odbiorcą. Zamiast klasycznego wywołania synchronicznego (np. HTTP), klient wysyła komunikat z żądaniem do kolejki lub tematu, a odpowiedź otrzymuje jako osobny komunikat.</p>



<p>W praktyce klient wysyła żądanie do <strong>Request Queue</strong>, dołączając informacje pozwalające na korelację odpowiedzi (np. CorrelationId lub nazwę kolejki odpowiedzi). Usługa odbierająca żądanie przetwarza je w swoim tempie i publikuje wynik do Response Queue, z której klient odbiera odpowiedź.</p>



<p>Takie&nbsp;podejście&nbsp;zapewnia:&nbsp;</p>



<ul class="wp-block-list">
<li>brak blokowania zasobów po stronie klienta,</li>



<li>odporność na opóźnienia i chwilową niedostępność usług,</li>



<li>lepszą skalowalność w porównaniu do komunikacji synchronicznej.</li>
</ul>



<p>Request–Response Pattern sprawdza się szczególnie w scenariuszach, gdzie odpowiedź jest wymagana, ale nie musi być natychmiastowa – np. w integracjach między mikroserwisami, procesach długotrwałych czy komunikacji pomiędzy systemami o różnej wydajności. W połączeniu z mechanizmami Azure Service Bus, takimi jak retry i dead-letter queue, wzorzec ten pozwala budować niezawodne i elastyczne rozwiązania komunikacyjne.</p>



<h3 class="wp-block-heading">Outbox Pattern</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="756" height="490" src="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_5.png" alt="Outbox Pattern - Azure Service Bus" class="wp-image-37850" title="Azure Service Bus – usługa, która usprawnia obsługę komunikatów i kolejki w nowoczesnych aplikacjach 5" srcset="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_5.png 756w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_5-300x194.png 300w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_5-495x321.png 495w" sizes="auto, (max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:16px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Outbox Pattern to wzorzec architektoniczny, który rozwiązuje problem <strong>spójności pomiędzy zapisem danych a publikacją komunikatu</strong>. W systemach opartych na komunikatach często pojawia się ryzyko, że dane zostaną zapisane w bazie, ale zdarzenie nie trafi do brokera (lub odwrotnie). Outbox Pattern eliminuje ten problem.</p>



<p>W praktyce, zamiast wysyłać komunikat bezpośrednio do Azure Service Bus, aplikacja zapisuje go najpierw do tabeli Outbox w tej samej transakcji co dane biznesowe. Dzięki temu zapis danych i „intencja wysłania komunikatu” stają się operacją atomową. Osobny proces (np. background worker) odczytuje wpisy z Outboxa i publikuje je do Azure Service Bus.</p>



<p>Takie podejście zapewnia:</p>



<ul class="wp-block-list">
<li>brak utraty komunikatów,</li>



<li>odporność na awarie sieci i brokera,</li>



<li>możliwość bezpiecznego ponowienia wysyłki.</li>
</ul>



<p>Outbox Pattern jest szczególnie przydatny w architekturze mikroserwisów i systemach event-driven, gdzie zdarzenia domenowe muszą być publikowane w sposób <strong>pewny i powtarzalny</strong>. W połączeniu z mechanizmami Azure Service Bus, takimi jak ponowienia wysyłki czy deduplikacja, stanowi solidną podstawę do budowy niezawodnej komunikacji między systemami. Outbox Pattern szczególnie dobrze współpracuje z bazami danych wspierającymi transakcje, pozwalając na spójne zapisanie danych biznesowych i komunikatu w jednym kroku.</p>



<h3 class="wp-block-heading">Inbox Pattern</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="756" height="540" src="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_6.png" alt="nearshore 2026.01.20 graphic 6" class="wp-image-37854" title="Azure Service Bus – usługa, która usprawnia obsługę komunikatów i kolejki w nowoczesnych aplikacjach 6" srcset="https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_6.png 756w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_6-300x214.png 300w, https://nearshore-it.eu/wp-content/uploads/2026/01/nearshore_2026.01.20_graphic_6-495x354.png 495w" sizes="auto, (max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:16px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Inbox Pattern to wzorzec architektoniczny, który rozwiązuje problem <strong>wielokrotnego przetwarzania tego samego komunikatu</strong>. W systemach opartych na komunikatach – takich jak Azure Service Bus – ponowne dostarczenie komunikatu jest zachowaniem poprawnym (np. po błędzie lub timeoutach), dlatego aplikacja musi być na to przygotowana.</p>



<p>W praktyce każdy odebrany komunikat jest najpierw rejestrowany w <strong>Inboxie</strong> – najczęściej w postaci zapisu jego unikalnego identyfikatora (MessageId) w bazie danych. Dopiero jeśli komunikat nie był wcześniej przetwarzany, trafia on do logiki biznesowej. Duplikaty są bezpiecznie ignorowane, co zapewnia <strong>idempotentność</strong> operacji.</p>



<p>Inbox Pattern zapewnia:</p>



<ul class="wp-block-list">
<li>ochronę przed skutkami retry i ponownych dostarczeń,</li>



<li>spójność danych w przypadku awarii podczas przetwarzania,</li>



<li>możliwość bezpiecznego skalowania konsumentów.</li>
</ul>



<h2 class="wp-block-heading" id="monitoring-i-diagnostyka-azure-service-bus-alerts-i-integracja-z-application-insights">Monitoring i diagnostyka: Azure Service Bus Alerts i integracja z Application Insights</h2>



<p>Skuteczne wykorzystanie Azure Service Bus w środowisku produkcyjnym wymaga odpowiedniego <strong>monitoringu i diagnostyki</strong>, które pozwalają szybko reagować na problemy z przetwarzaniem komunikatów. Platforma Azure udostępnia w tym zakresie gotowe mechanizmy oparte o Azure Monitor.</p>



<p>Azure Service Bus publikuje szereg metryk, takich jak liczba aktywnych komunikatów, długość dead-letter queue czy czas przetwarzania. Na ich podstawie można konfigurować Alert Rules, które automatycznie powiadomią zespół o potencjalnych problemach, np. rosnącej liczbie komunikatów w kolejce lub błędach po stronie konsumentów.</p>



<p>Dla głębszej diagnostyki Service Bus integruje się z Application Insights, umożliwiając śledzenie komunikatów w kontekście całego przepływu aplikacji. Dzięki korelacji telemetrycznej możliwe jest przeanalizowanie, jak komunikat przechodzi przez kolejne komponenty systemu i gdzie pojawiają się opóźnienia lub błędy.</p>



<p>Połączenie alertów, metryk i telemetryki aplikacyjnej pozwala nie tylko reagować na incydenty, ale także <strong>proaktywnie wykrywać problemy</strong>, zanim wpłyną one na użytkowników końcowych.</p>



<h2 class="wp-block-heading" id="zabezpieczenia-w-azure-service-bus-rbac-sas-i-protokol-amqp">Zabezpieczenia w Azure Service Bus – RBAC, SAS i protokół AMQP</h2>



<p>Azure Service Bus oferuje mechanizmy bezpieczeństwa klasy enterprise, które pozwalają precyzyjnie kontrolować dostęp do komunikatów i chronić komunikację pomiędzy komponentami systemu. Usługa wspiera zarówno nowoczesne uwierzytelnianie oparte o <strong>Azure Active Directory</strong>, jak i tradycyjne mechanizmy kluczy dostępowych.</p>



<p>RBAC (Role-Based Access Control) umożliwia zarządzanie uprawnieniami przy użyciu ról przypisanych do użytkowników, aplikacji i tożsamości zarządzanych. Pozwala to na centralne i spójne zarządzanie dostępem do kolejek, tematów i subskrypcji, bez konieczności przechowywania wrażliwych danych, takich jak hasła czy klucze dostępu, w kodzie aplikacji. W kontekście Azure Service Bus można stosować predefiniowane role – między innymi Data Owner, Data Sender i Data Receiver – które pozwalają na granularne zarządzanie dostępem do wysyłania, odbioru lub pełnego zarządzania zasobami komunikacyjnymi.</p>



<p>Alternatywą lub uzupełnieniem RBAC są <strong>SAS (Shared Access Signatures)</strong>, czyli tokeny dostępu z określonym zakresem uprawnień i czasem ważności. SAS sprawdzają się w scenariuszach integracyjnych, gdzie wymagany jest ograniczony i kontrolowany dostęp do zasobów Service Bus.</p>



<p>Komunikacja z Azure Service Bus odbywa się z wykorzystaniem protokołu <strong>AMQP 1.0</strong>, który zapewnia wysoką wydajność, niezawodność oraz wsparcie dla scenariuszy enterprise. AMQP umożliwia stabilne połączenia, efektywne przesyłanie komunikatów i pełne wykorzystanie zaawansowanych funkcji usługi. Azure Service Bus obsługuje również protokół HTTP jako alternatywę dla AMQP w przypadku aplikacji, które nie wspierają AMQP. Zaleca się jednak korzystanie z AMQP w przypadku systemów wymagających niskiej latencji i trwałych połączeń.</p>



<p>Połączenie RBAC, SAS i AMQP pozwala budować bezpieczne, skalowalne i zgodne z najlepszymi praktykami rozwiązania komunikacyjne w chmurze Azure.</p>



<h2 class="wp-block-heading" id="podsumowanie-co-warto-zapamiętać">Podsumowanie – co warto zapamiętać?</h2>



<p>Azure Service Bus to kluczowe narzędzie komunikacyjne w chmurze Microsoft Azure, pozwalające na tworzenie nowoczesnych aplikacji opartych na architekturze asynchronicznej. Dzięki bogatemu zestawowi funkcji – takich jak kolejki, tematy i subskrypcje, sesje, oraz wsparcie dla wzorców projektowych (Request-Response,<br>Outbox, Inbox) – usługa umożliwia skalowalność, niezawodność i elastyczność systemów.</p>



<p>Zintegrowane mechanizmy bezpieczeństwa (RBAC, SAS, AMQP) oraz zaawansowane monitorowanie (Application Insights, Azure Monitor) gwarantują pełną kontrolę i stabilność rozwiązania, czyniąc je niezbędnym elementem w ekosystemie<br>nowoczesnych aplikacji chmurowych.</p>



<p>Jeżeli temat cię zaciekawił i chcesz korzystać z usługi w swoim projekcie, zajrzyj do <a href="https://learn.microsoft.com/en-us/azure/service-bus-messaging/" target="_blank" rel="noopener">Microsoft Learn</a> na Azure Portal, by uzyskać więcej informacji.</p>



<h2 class="wp-block-heading" id="czesto-zadawane-pytania">Często zadawane pytania:</h2>


<div id="rank-math-faq" class="rank-math-block">
<div class="rank-math-list ">
<div id="faq-question-1769434111748" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Co to jest Azure Service Bus i kiedy warto go używać?</strong></h3>
<div class="rank-math-answer ">

<p>Azure Service Bus to zarządzany broker komunikatów klasy enterprise w Microsoft Azure, który umożliwia asynchroniczną komunikację między komponentami systemu, takimi jak mikroserwisy, aplikacje czy zewnętrzne systemy. Warto go używać, gdy:<br />&#8211; Chcesz zwiększyć odporność systemu na przeciążenia i chwilowe awarie.<br />&#8211; Potrzebujesz niezawodnej komunikacji w systemach event-driven lub przy integracji między usługami.<br />&#8211; Tworzysz aplikacje wymagające kolejki, publish-subscribe, transakcyjnego przetwarzania lub obsługi sesji.</p>

</div>
</div>
<div id="faq-question-1769434170038" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jakie są różnice pomiędzy kolejkami (Queue) a tematami (Topics) w Azure Service Bus?</strong> </h3>
<div class="rank-math-answer ">

<p>&#8211; Queue (kolejka): Każdy komunikat trafia do jednego odbiorcy (model point-to-point). Idealne dla zadań w tle, równoważenia obciążenia i ochrony systemu przed przeciążeniem.<br />&#8211; Topics (tematy): Komunikaty mogą być dostarczone do wielu odbiorców dzięki subskrypcjom (wzorzec publish-subscribe). Doskonałe dla architektury event-driven i integracji wielu systemów.</p>

</div>
</div>
<div id="faq-question-1769434197385" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jak działają sesje w Azure Service Bus?</strong></h3>
<div class="rank-math-answer ">

<p>Sesje umożliwiają grupowanie komunikatów na podstawie SessionID i przetwarzanie ich w określonej kolejności (sekwencyjnie) przez jednego konsumenta. Dzięki blokowaniu sesji podczas obsługi wiadomości, Azure Service Bus gwarantuje, że komunikaty w ramach jednej sesji nie będą przetwarzane równolegle. Sesje są szczególnie przydatne tam, gdzie spójność i kolejność są kluczowe, np. w procesach workflow.</p>

</div>
</div>
<div id="faq-question-1769434224557" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Co to jest Dead-Letter Queue i kiedy jest używana?</strong> </h3>
<div class="rank-math-answer ">

<p>Dead-Letter Queue to specjalna kolejka w Azure Service Bus, w której umieszczane są komunikaty, które:<br />&#8211; Nie zostały poprawnie przetworzone po określonej liczbie prób.<br />&#8211; Zawierają błędy lub nie spełniają wymagań konsumenta. Dead-Letter Queue pomaga w diagnostyce problemów i zapewnia ich późniejsze rozwiązywanie.</p>

</div>
</div>
<div id="faq-question-1769434249989" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jakie mechanizmy bezpieczeństwa oferuje Azure Service Bus?</strong> </h3>
<div class="rank-math-answer ">

<p>Azure Service Bus oferuje:<br />&#8211; RBAC (Role-Based Access Control): Zarządzanie uprawnieniami za pomocą ról przypisanych do użytkowników, aplikacji lub zarządzanych tożsamości, bez konieczności przechowywania sekretów.<br />&#8211; SAS (Shared Access Signature): Tokeny dostępu o ograniczonym czasie ważności i zakresie uprawnień, wygodne w scenariuszach integracyjnych.<br />&#8211; AMQP 1.0: Bezpieczny i niezawodny protokół komunikacyjny o wysokiej wydajności.</p>

</div>
</div>
<div id="faq-question-1769434273643" class="rank-math-list-item">
<h3 class="rank-math-question ">Jakie wzorce projektowe wspiera Azure Service Bus?</h3>
<div class="rank-math-answer ">

<p>Azure Service Bus wspiera kilka kluczowych wzorców projektowych:<br />&#8211; Request-Response Pattern: Asynchroniczna komunikacja dwukierunkowa, oparta na kolejce żądań i odpowiedzi.<br />&#8211; Outbox Pattern: Mechanizm zapewniający spójność między zapisami w bazie danych a publikacją komunikatów. Chroni przed utratą komunikatów w przypadku awarii.<br />&#8211; Inbox Pattern: Obsługa ponownych dostarczeń komunikatów poprzez rejestrowanie MessageID w celu zapewnienia idempotentności.</p>

</div>
</div>
<div id="faq-question-1769434308990" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jak monitorować i diagnozować Azure Service Bus w środowisku produkcyjnym?</strong> </h3>
<div class="rank-math-answer ">

<p>Do monitorowania i diagnostyki możesz użyć: <br />&#8211; Azure Monitor: Śledzenie metryk takich jak liczba aktywnych komunikatów, czas przetwarzania, długość Dead-Letter Queue i częstotliwość błędów. <br />&#8211; Application Insights: Pozwala na korelację wiadomości w kontekście całego systemu, analizę opóźnień i lokalizację problemów. <br />&#8211; Alerts i reguły powiadomień w Azure Monitor umożliwiają proaktywne wykrywanie problemów i szybkie reagowanie. </p>

</div>
</div>
<div id="faq-question-1769434337858" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Czy mogę korzystać z protokołu HTTP z Azure Service Bus?</strong></h3>
<div class="rank-math-answer ">

<p>Tak, oprócz protokołu AMQP 1.0, Azure Service Bus pozwala na korzystanie z protokołu HTTP jako alternatywy. HTTP może być stosowane w prostszych scenariuszach, gdy AMQP nie jest dostępny lub wymagany. </p>

</div>
</div>
<div id="faq-question-1769434352885" class="rank-math-list-item">
<h3 class="rank-math-question ">Jakie praktyki pomagają poprawić skalowalność systemu przy użyciu Azure Service Bus?</h3>
<div class="rank-math-answer ">

<p>Aby zwiększyć skalowalność systemu:<br />&#8211; Korzystaj z mechanizmu retry i dead-letter queue.<br />&#8211; Wykorzystuj filtry w subskrypcjach Topics dla precyzyjnego routowania zdarzeń.<br />&#8211; Używaj kolejek dla zadań w tle oraz tematów dla propagacji zdarzeń domenowych w architekturze event-driven.<br />&#8211; Grupuj komunikaty za pomocą sesji, aby kontrolować ich kolejność.</p>

</div>
</div>
<div id="faq-question-1769434379306" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jak zoptymalizować bezpieczeństwo w Azure Service Bus?</strong></h3>
<div class="rank-math-answer ">

<p>Aby poprawić bezpieczeństwo: <br />&#8211; Używaj RBAC do zarządzania dostępem, unikając przechowywania kluczy w aplikacjach. <br />&#8211; Generuj tokeny SAS o ograniczonych uprawnieniach i krótszym czasie ważności. <br />&#8211; Chroń strumienie komunikacji za pomocą protokołu AMQP, który wspiera szyfrowanie i autoryzację. </p>

</div>
</div>
</div>
</div>]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/azure-service-bus/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Optymalizacja kodu C# w .NET &#8211; techniki poprawy wydajności kodu aplikacji </title>
		<link>https://nearshore-it.eu/pl/artykuly/optymalizacja-kodu-c-sharp-w-dot-net-techniki-poprawy-wydajnosci/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/optymalizacja-kodu-c-sharp-w-dot-net-techniki-poprawy-wydajnosci/#respond</comments>
		
		<dc:creator><![CDATA[Tomasz Janicki]]></dc:creator>
		<pubDate>Wed, 17 Dec 2025 15:08:10 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=37786</guid>

					<description><![CDATA[Dowiedz się, jak praktyczna optymalizacja kodu C# w .NET – oparta na realnych benchmarkach – pozwoliła zmniejszyć liczbę maszyn z 10 do 3. Konkretne techniki, mierzalne wyniki i przykłady, które możesz od razu zastosować w swoich aplikacjach.]]></description>
										<content:encoded><![CDATA[
<p>Jeśli masz wrażenie, że krytyczny fragment kodu działa „trochę za wolno”, ten artykuł jest dla ciebie. Pokażę na realnym przykładzie z produkcji, jak optymalizacja kodu pozwoliła zejść z 10 do 3 maszyn w&nbsp;Azure&nbsp;&#8211; bez zmiany funkcjonalności aplikacji. Zamiast teoretyzować, przejdziemy przez konkretne techniki optymalizacji wydajności kodu C#, które możesz od razu zastosować w swoim projekcie opartym o&nbsp;framework&nbsp;.NET.&nbsp;</p>



<p>Dowiesz&nbsp;się:&nbsp;</p>



<ul class="wp-block-list">
<li>kiedy&nbsp;warto&nbsp;optymalizować&nbsp;</li>



<li>jak&nbsp;mierzyć&nbsp;wydajność&nbsp;kodu&nbsp;</li>



<li>jak dobrać algorytm i struktury danych, aby zwiększyć wydajność aplikacji,&nbsp;</li>



<li>a także jak robić to w sposób, który nie zabija całkowicie czytelności kodu.&nbsp;</li>
</ul>



<div class="table-of-contents">
    <p class="title"></p>
    <ol>
                    <li><a href="#wprowadzenie-od-10-do-3-maszyn-realna-historia-optymalizacji-kodu">1.  Wprowadzenie: od 10 do 3 maszyn: realna historia optymalizacji kodu</a></li>
                    <li><a href="#kiedy-i-jak-przeprowadzac-optymalizacje-kodu">2.  Kiedy i jak przeprowadzać optymalizację kodu?</a></li>
                    <li><a href="#typy-optymalizacji">3.  Typy optymalizacji</a></li>
                    <li><a href="#ogolne-zasady-jak-pisac-wydajny-kod-który-nadal-da-się-utrzymac">4.  Ogólne zasady &#8211; jak pisać wydajny kod, który nadal da się utrzymać</a></li>
                    <li><a href="#faq">5.  FAQ</a></li>
            </ol>
</div>


<h2 class="wp-block-heading" id="wprowadzenie-od-10-do-3-maszyn-realna-historia-optymalizacji-kodu"><strong>Wprowadzenie: od 10 do 3 maszyn: realna historia optymalizacji kodu</strong></h2>



<p>Powodem powstania tego tekstu jest chęć podzielenia się doświadczeniem z optymalizacji kodu zdobytym podczas pracy nad prawdziwą aplikacją w chmurze. Dwa lata temu byłem członkiem zespołu, który miał za zadanie programować system hostowany na platformie Microsoft&nbsp;Azure. System, zbudowany w oparciu o&nbsp;Azure&nbsp;Functions&nbsp;i .NET 7, przetwarzał strumień zdarzeń JSON:&nbsp;parsowanie, walidacja, budowa modeli &#8211; wszystko w czasie zbliżonym do rzeczywistego. Wymóg biznesowy był prosty, ale wymagający obliczeniowo: wydajność aplikacji na poziomie 2000 zdarzeń na sekundę.&nbsp;</p>



<p>Pierwsze <a href="/pl/artykuly/testy-niefunkcjonalne/" target="_blank" rel="noreferrer noopener">testy wydajności</a> pokazały brutalną prawdę &#8211; przy domyślnej implementacji potrzebowaliśmy aż 10 maszyn w dedykowanym planie Azure. Po serii mikrooptymalizacji i ponownej analizie wydajności okazało się, że ten sam ruch obsłużymy przy pomocy 3 maszyn o identycznych parametrach. To nie była magia czy zasługa intuicji. To był efekt świadomego podejścia do zarządzania pamięcią, doboru algorytmów, pracy na strukturach danych i mierzenia czasu wykonania. </p>



<p>Kod źródłowy przykładów, benchmarki i wyniki dotyczące wydajności znajdziesz w repozytorium&nbsp;<a href="https://staging.nearshore-it.eu/pl/artykuly/github-copilot-asystent-ai/" target="_blank" rel="noreferrer noopener">GitHub</a>.&nbsp;<br><a href="https://github.com/tomekjanicki/Performance" target="_blank" rel="noreferrer noopener">https://github.com/tomekjanicki/Performance</a>&nbsp;&#8211; każdy benchmark w osobnym katalogu projektu Performance. Możesz je samodzielnie uruchomić, aby sprawdzić zachowanie na swojej maszynie, komendą:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">dotnet run -c Release --project .\Performance\Performance.csproj&amp;nbsp;-- --memory true&amp;nbsp;</pre>



<h2 class="wp-block-heading" id="kiedy-i-jak-przeprowadzac-optymalizacje-kodu"><strong>Kiedy i jak przeprowadzać optymalizację kodu?</strong>&nbsp;</h2>



<p>Istotną kwestią jest to, że optymalizacja kodu pod względem czasu wykonania lub zużycia pamięci&nbsp;ma sens tylko wtedy, gdy jakąś operację wykonujemy znaczącą ilość razy&nbsp;w stosunkowo krótkim czasie i zależy nam na jak najkrótszym czasie wykonania zadania przy jak najmniejszej konsumpcji zasobów.&nbsp;&nbsp;</p>



<p>Generalnie tylko w tym przypadku należy wykonywać optymalizację, gdyż jednym z ważnych czynników jest to, że kod po takiej optymalizacji jest zazwyczaj dużo mniej czytelny i trudniejszy do zrozumienia.&nbsp;&nbsp;</p>



<p>Do identyfikacji takich obszarów kodu można użyć narzędzia typu&nbsp;profiler&nbsp;np.&nbsp;<a href="https://www.jetbrains.com/dotmemory" target="_blank" rel="noopener">https://www.jetbrains.com/dotmemory</a>, <a href="https://www.jetbrains.com/profiler" target="_blank" rel="noopener">https://www.jetbrains.com/profiler</a>&nbsp;lub&nbsp;narzędzi&nbsp;dostarczanych z Visual Studio. Mając zidentyfikowane takie fragmenty kodu, można przystąpić do optymalizacji.&nbsp;&nbsp;</p>



<p>Optymalizacja polega na próbie napisania kodu realizującego tę samą funkcjonalność w sposób bardziej wydajny i&nbsp;porównaniu&nbsp;obydwu implementacji pod względem czasu wykonania i zużycia pamięci.&nbsp;&nbsp;</p>



<p>Narzędziem,&nbsp;które&nbsp;staje się de facto standardem, jeśli chodzi o pomiar wydajności kodu przy przeprowadzaniu&nbsp;mikrooptymalizacji&nbsp;na platformie .NET, jest&nbsp;<a href="https://benchmarkdotnet.org" target="_blank" rel="noopener">BenchmarkDotNet</a> &#8211; jest to narzędzie,&nbsp;którego&nbsp;Microsoft wewnętrznie używa do monitoringu wydajności podczas tworzenia samej platformy .NET. Narzędzie to jest wpięte w proces CI, które monitoruje, czy określone fragmenty kodu nie są mniej wydajne po wprowadzonych zmianach. Jeśli wydajność kodu się pogarsza, wtedy zmiany w takim kodzie są ponownie sprawdzane.&nbsp;&nbsp;</p>



<p>Idealnie byłoby też, gdyby testy były przeprowadzane na dokładnie takiej samej maszynie, na jakiej uruchamiany jest kod produkcyjnie &#8211; tzn. chodzi o model procesora, ilość pamięci i system operacyjny.&nbsp;W przeszłości zdarzało się, że dana optymalizacja poprawiała wydajność na danym środowisku, ale pogarszała na innym &#8211; generalnie takie sytuacje są stosunkowo rzadkie.&nbsp;&nbsp;</p>



<p>W przypadku każdego testu będzie prezentowana tabela z wynikami &#8211; w przedstawionych rezultatach testów najbardziej będą istotne kolumny&nbsp;<strong>Mean&nbsp;</strong>oznaczające czas wykonania i&nbsp;<strong>Allocated&nbsp;</strong>oznaczające zużycie pamięci.&nbsp;&nbsp;</p>



<p>Podsumowując &#8211; w praktyce warto optymalizować, gdy:&nbsp;</p>



<ul class="wp-block-list">
<li>ten sam algorytm wykonujesz setki tysięcy lub miliony razy,&nbsp;</li>



<li>fragment jest w krytycznym hot-path&nbsp;(np. wewnątrz wąskiej pętli przetwarzania),&nbsp;</li>



<li>dotyczy intensywnej komunikacji z bazy danych, API albo serwer musi utrzymać bardzo dużą liczbę zapytań,&nbsp;</li>



<li>czujesz, że szybkość i efektywność są kluczowe dla doświadczenia użytkownika (np. czas ładowania ekranu,&nbsp;responsywność&nbsp;panelu).&nbsp;</li>
</ul>



<p>W innych przypadkach lepiej skupić się na czytelności kodu i jakości projektu&nbsp;</p>



<h2 class="wp-block-heading" id="typy-optymalizacji"><strong>Typy optymalizacji</strong>&nbsp;</h2>



<p>Jak już wcześniej wspomniałem, artykuł rozpatruje dwa typy optymalizacji.&nbsp;W pierwszym celem jest skrócenie czasu wykonania, a w drugim &#8211; zmniejszenie konsumpcji pamięci.&nbsp;&nbsp;</p>



<p>W wielu przypadkach&nbsp;optymalizacja zużycia pamięci przynosi znacznie bardziej spektakularne rezultaty (pośrednio też wpływając na czas wykonania), gdyż pamięć jest łatwo zaalokować, ale proces zwalniania pamięci ze sterty jest dużo bardziej skomplikowany. Więcej o działaniu mechanizmu&nbsp;Garbage&nbsp;Collector&nbsp;można znaleźć pod tym adresem&nbsp;<a href="https://www.youtube.com/watch?v=BeuNvhd1L_g" target="_blank" rel="noreferrer noopener">https://www.youtube.com/watch?v=BeuNvhd1L_g</a>.&nbsp;</p>



<h2 class="wp-block-heading"><strong>B01&nbsp;Logging&nbsp;&#8211; kiedy logi zabijają wydajność aplikacji</strong>&nbsp;</h2>



<p>Logowanie (logging) może znacząco wpłynąć na konsumpcję zasobów, zwłaszcza gdy jest wykonywane setki tysięcy razy. Szczegółowe wyniki benchmarków dla tego scenariusza zostały opublikowane w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B01Logging.LoggingBenchmark-report-github.md" target="_blank" rel="noopener">B01 Logging – pełne wyniki benchmarków</a>, do którego będziemy się odnosić w dalszej części sekcji.</p>



<p>Przy porównywaniu wyników<strong> </strong>widać, że gdy mamy włączony poziom logowania i fizycznie logujemy wiadomości, to zużycie pamięci i czasy wykonania są bardzo podobne (testy zaczynające się od <code>LogInformationLevelEnabled</code>). Największe różnice widać, gdy wywołamy metody logujące, ale poziom logowania nie jest włączony (testy zaczynające się od <code>LogDebugLevelNotEnabled</code>). Wtedy najlepsze wyniki osiągamy, używając trybu generowania kodu (<code data-enlighter-language="generic" class="EnlighterJSRAW">LogDebugLevelNotEnabledSourceGenerated</code>).  </p>



<p>Więcej informacji: <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator" target="_blank" rel="noreferrer noopener">https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator</a>. Najgorsze wyniki otrzymujemy w przypadku wykorzystania mechanizmu string interpolacji (<code>LogDebugLevelNotEnabledStringInterpolation</code>) &#8211; ze względu na naturę obiektu string, który jest niezmienny, za każdym razem generujemy nowy string i alokujemy pamięć, nawet gdy w rzeczywistości nic nie logujemy.  </p>



<p>Dodatkowo, gdy mamy na poziomie projektu (<code>Performance.csproj</code>) ustawiony poziom analizy kodu kompilatora na „latest-recommended”, to kompilator generuje ostrzeżenia CA1848: Use the LoggerMessage delegates i CA2254: Template should be a static expression. Więcej o CA2254 można znaleźć pod tym adresem <a href="https://www.youtube.com/watch?v=6zoMd_FwSwQ" target="_blank" rel="noreferrer noopener">https://www.youtube.com/watch?v=6zoMd_FwSwQ</a> </p>



<h2 class="wp-block-heading"><strong>B02&nbsp;Enums&nbsp;i generatory: szybsze&nbsp;TryParse&nbsp;/&nbsp;ToString</strong>&nbsp;</h2>



<p>Wywoływanie metod <code>TryParse</code> oraz <code>ToString</code> na obiektach typu wyliczeniowego wiąże się z użyciem refleksji, co ma bezpośredni wpływ na <strong>czas wykonania</strong> i zużycie pamięci. Zastępując te metody alternatywnymi implementacjami opartymi o <strong>generowanie kodu</strong>, można znacząco poprawić wydajność — jednym z takich rozwiązań jest biblioteka <a href="https://www.nuget.org/packages/Supernova.Enum.Generators" target="_blank" rel="noopener">Supernova.Enum.Generators</a>.</p>



<p>Różnice są wyraźnie widoczne w zestawieniu <strong>czasu wykonania oraz alokacji pamięci</strong> pomiędzy podejściem standardowym a wersją generowaną (<code>Standard</code> vs <code>SourceGenerated</code>), co zostało szczegółowo pokazane w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B02Enums.EnumBenchmark-report-github.md" target="_blank" rel="noopener">B02 Enums – pełne wyniki benchmarków</a>.</p>



<p>Łatwą alternatywą w przypadku metody&nbsp;<code data-enlighter-language="generic" class="EnlighterJSRAW">ToString</code>&nbsp;jest zbudowanie przy starcie aplikacji statycznego słownika i pobieranie wartości tekstowej na postawie wartości&nbsp;<code data-enlighter-language="generic" class="EnlighterJSRAW">enum</code>.&nbsp;</p>



<h2 class="wp-block-heading"><strong>B03&nbsp;Closures: ukryty wróg w lambdach</strong>&nbsp;</h2>



<p>W przypadku wyrażeń lambda sposobem na poprawę wydajności jest unikanie <em>closures</em> (więcej o <em>closures</em> w artykule <a href="https://csharpindepth.com/Articles/Closures" target="_blank" rel="noopener"> C# in Depth</a>) poprzez przekazywanie zewnętrznego stanu do środka funkcji lambda jako parametr.</p>



<p>Na podstawie testu (<code>ExecuteWithoutClosure</code>) widać, że następuje znaczące skrócenie czasu wykonania oraz nie występuje alokacja pamięci.</p>



<p>Szczegółowe wyniki benchmarku zostały opisane w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B03Closures.ClosuresBenchmark-report-github.md" target="_blank" rel="noopener">B03 Closures – pełne wyniki benchmarków</a>.</p>



<p>To dobry przykład na to, jak drobna zmiana stylu pisania kodu może pomóc w optymalizacji kodu bez większej utraty jego czytelności.</p>



<h2 class="wp-block-heading"><strong>B04&nbsp;Spans&nbsp;&lt;T&gt;: przyspieszenie&nbsp;parserów&nbsp;i praca „na krawędzi” pamięci</strong>&nbsp;</h2>



<p>Użycie obiektów typu <em>span</em> (więcej o <em>span</em> w artykule <a href="https://learn.microsoft.com/en-us/archive/msdn-magazine/2018/january/csharp-all-about-span-exploring-a-new-net-mainstay" target="_blank" rel="noopener">C# – All About Span: Exploring a New .NET Mainstay</a>) znacząco przyśpiesza działanie kodu, redukując potrzebę dodatkowych alokacji pamięci. Jest on szczególnie przydatny we wszelkiego rodzaju parserach, które wyciągają dane z istniejącego obiektu, tworząc wirtualne okno w pamięci w przetwarzanym obiekcie, zapobiegając tym samym nowym alokacjom.</p>



<p>Obydwa testy realizują identyczną funkcjonalność, przetwarzając tekst na listę z wartościami typu liczbowego. Jak widać, test <code>GetResultSpan</code> jest znacząco szybszy i alokuje mniej pamięci w porównaniu do testu <code>GetResultClassic</code>.</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B04Spans.SpanBenchmark-report-github.md" target="_blank" rel="noopener">B04 Spans – pełne wyniki benchmarków</a>.</p>



<p>Jeśli twoja aplikacja intensywnie parsuje tekst (np. logi, CSV, payloady z API), to użycie spanów może znacząco wpłynąć na poprawę wydajności.</p>



<p>W&nbsp;benchmarkach:&nbsp;</p>



<ul class="wp-block-list">
<li>klasyczna implementacja alokuje nowe tablice/stringi,&nbsp;</li>



<li>implementacja ze&nbsp;spanami&nbsp;jest znacząco szybsza i zużywa mniej pamięci.&nbsp;</li>
</ul>



<p>To już dotyczy zaawansowanych technik, ale w parserach, systemach na <a href="/azure-iot-edge-computing/" target="_blank" rel="noreferrer noopener">edge</a> (np. IoT, funkcje serverless) i usługach API różnica bywa kolosalna. </p>



<h2 class="wp-block-heading"><strong>B05&nbsp;Static&nbsp;&#8211;&nbsp;pola statyczne zamiast ciągłego tworzenia kolekcji</strong>&nbsp;</h2>



<p>Kolejnym przykładem jest kod, który np. sprawdza bieżącą wartość na podstawie niezmiennej listy wartości. Gdy ta lista jest niezmienna, warto zadeklarować ją na poziomie klasy jako pole statyczne i zamiast za każdym razem tworzyć nową listę, przekazywać tę zadeklarowaną instancję do wywołania funkcji sprawdzającej.</p>



<p>Jak widać, test <code>GetValidValuesStatic</code> znacząco obniża czas wykonania i zużycie pamięci w porównaniu do <code>GetValidValuesNotStatic</code>.</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B05Static.StaticBenchmark-report-github.md" target="_blank" rel="noopener">B05 Static – pełne wyniki benchmarków</a>.</p>



<h2 class="wp-block-heading"><strong>B06&nbsp;Capacity&nbsp;&#8211;&nbsp;jak jedna linijka może znacznie poprawić szybkość listy</strong>&nbsp;</h2>



<p>Przy dodawaniu elementów do obiektu typu generyczna lista dobrym zaleceniem jest ustawienie docelowego rozmiaru listy (jeśli znamy albo w przybliżeniu jesteśmy w stanie określić docelowy rozmiar listy). Ustawienie to wpływa na to, że wewnętrznie tablica, która przechowuje elementy, nie jest wielokrotnie realokowana i kod działa zauważalnie szybciej (<code>ProcessWithCapacity</code> vs <code>ProcessWithoutCapacity</code>).</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B06Capacity.CapacityBenchmark-report-github.md" target="_blank" rel="noopener">B06 Capacity – pełne wyniki benchmarków</a>.</p>



<p>To jedna z tych drobnych zmian, które w intensywnych strukturach danych (np. listy obiektów DTO) robią dużą różnicę.</p>



<h2 class="wp-block-heading"><strong>B07 Linq vs Dictionary&nbsp;i&nbsp;FrozenDictionary</strong></h2>



<p>Następnym przykładem jest sytuacja, w której wyszukujemy elementy po określonych unikalnych kluczach. Jeśli dane, na których wyszukujemy, są niezmienne lub wielokrotnie przeprowadzamy wyszukiwanie na tych samych danych, to opłaca się zamiast używać LINQ (<code>GetUsersByIdsLinq</code>) zbudować słownik i przeprowadzać wyszukiwanie w tym słowniku (<code>GetUsersByIdsAlreadyBuiltDictionary</code>).</p>



<p>Natomiast w sytuacji, gdy słownik musi zostać najpierw utworzony (<code>GetUsersByIdsBuildDictionary</code>), operacja ta jest znacznie bardziej czasochłonna i alokuje więcej pamięci. Dodatkowo do porównania został dołączony niedawno wprowadzony typ <em>Frozen Dictionary</em> (więcej informacji w dokumentacji <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen.frozendictionary-2?view=net-9.0" target="_blank" rel="noopener">FrozenDictionary – Microsoft Learn</a>), który — jak widać — konsumuje jeszcze więcej zasobów podczas budowy (<code>GetUsersByIdsBuildFrozenDictionary</code>), ale jest minimalnie szybszy przy odczycie (<code>GetUsersByIdsAlreadyBuiltFrozenDictionary</code>).</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie<a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B07LinqVsDictionary.LinqVsDictionaryBenchmark-report-github.md" target="_blank" rel="noopener"> B07 LINQ vs Dictionary – pełne wyniki benchmarków</a>.</p>



<p>Jeżeli dane, np. z bazy danych, są ładowane rzadko, a odczyty są bardzo częste, to jest to idealny kandydat na zoptymalizowany kod z wykorzystaniem słownika.</p>



<h2 class="wp-block-heading"><strong>B08 Interface vs&nbsp;Implementation</strong>&nbsp;</h2>



<p>W pewnych przypadkach sposobem na optymalizację jest implementacja kodu za pomocą obiektu typu wartościowego zamiast <a href="file:///C:/pl/artykuly/c-11-sprawdz-co-nowego/" target="_blank" rel="noreferrer noopener">obiektu referencyjnego</a> (<code>GetStructResultDirectly</code>) &#8211; dzięki temu zabiegowi możemy w pewnych sytuacjach zminimalizować dodatkowe alokacje pamięci. Jednak należy zwrócić uwagę, że nie należy tego obiektu przekazywać jako interfejs (<code>GetStructResultAsInterface</code>) (gdyż wymusza to operację <em>boxing</em>). W przypadku klasy nie ma to praktycznie żadnego znaczenia. </p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B08InterfaceVsImplementation.InterfaceVsImplementationBenchmark-report-github.md" target="_blank" rel="noopener">B08 Interface vs Implementation – pełne wyniki benchmarków</a>.</p>



<p>Czasem zastosowanie <code>record struct</code> zamiast klasy pozwala eliminować część alokacji. Warunek: </p>



<ul class="wp-block-list">
<li>nie przekazujesz struktury jako interfejsu (boxing zwiększa koszt),&nbsp;</li>



<li>struktura jest używana w algorytmie intensywnie przeliczającym dane.&nbsp;</li>
</ul>



<p>W przeciwnym razie&nbsp;przeciążenie mentalne&nbsp;i ryzyko napisania błędnych konstrukcji jest większe niż korzyści.&nbsp;</p>



<h2 class="wp-block-heading"><strong>B09 List&nbsp;Manipulations&nbsp;zakresy zamiast pojedynczych operacji</strong>&nbsp;</h2>



<p>Kolejną istotną rzeczą w przypadku pracy z klasą typu generyczna lista jest efektywność dodawania lub usuwania elementów z listy.</p>



<p>Jest to szczególnie ważne, gdy programista dodaje lub usuwa zbiór elementów na początku listy. Widać wyraźnie, że dodawanie (<code>InsertItemsAtTheBeginningOneByOne</code>) lub usuwanie (<code>RemoveItemsAtTheBeginningOneByOne</code>) elementów pojedynczo jest najmniej efektywne — związane jest to z wielokrotną realokacją wewnętrznej tablicy obiektu typu list. Warto wtedy skorzystać z metod operujących na zakresach (<code>InsertItemsAtTheBeginningByRange</code>, <code>RemoveItemsAtTheBeginningByRange</code>) lub zbudować całkowicie nową listę, korzystając z LINQ (<code>RemoveItemsAtTheBeginningByLinq</code>).</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie<a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B09ListManipulations.ListManipulationsBenchmark-report-github.md" target="_blank" rel="noopener"> B09 List Manipulations – pełne wyniki benchmarków</a>.</p>



<h2 class="wp-block-heading"><strong>B10&nbsp;Stack&nbsp;Alloc&nbsp;Array&nbsp;Pool&nbsp;&#8211;&nbsp;zarządzanie pamięcią dla wymagających</strong>&nbsp;</h2>



<p>Tworząc kod, który intensywnie operuje na małych tablicach, warto rozważyć alokowanie elementów tej tablicy na stosie zamiast na stercie.</p>



<p>Warto użyć wyrażenia <code>stackalloc</code> (więcej informacji w dokumentacji <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc" target="_blank" rel="noopener">stackalloc – Microsoft Learn</a>), mając na uwadze ograniczenia stosu. W przypadku gdy potrzebujemy użyć tablicy o większym rozmiarze, można skorzystać z obiektu <code>ArrayPool</code> (zob. <a href="https://learn.microsoft.com/en-us/dotnet/api/system.buffers.arraypool-1?view=net-9.0" target="_blank" rel="noopener">ArrayPool&lt;T&gt; – Microsoft Learn</a>), który minimalizuje nowe alokacje pamięci, reużywając już zaalokowaną pamięć.</p>



<p>W tym konkretnym przykładzie została dwukrotnie zaimplementowana metoda wyliczająca hash z zawartości obiektu — osobno dla małego i dużego obiektu. Pierwsza implementacja jest klasyczna (<code>ExecuteHashCalculatorWithClassicSmallData</code>, <code>ExecuteHashCalculatorWithClassicLargeData</code>), a druga wykorzystuje <code>stackalloc</code> i array pool (<code>ExecuteHashCalculatorWithStackAllocOrArrayPoolSmallData</code>, <code>ExecuteHashCalculatorWithStackAllocOrArrayPoolLargeData</code>). Jak widać, zoptymalizowane metody konsumują dużo mniej pamięci i działają szybciej lub porównywalnie z klasyczną implementacją.</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie<a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B10StackAllocArrayPool.StackAllocArrayPoolBenchmark-report-github.md" target="_blank" rel="noopener"> B10 StackAlloc &amp; ArrayPool – pełne wyniki benchmarków</a>.</p>



<p>W&nbsp;przykładach:&nbsp;</p>



<ul class="wp-block-list">
<li>klasyczny kod &#8211; alokuje nowe tablice przy każdym wywołaniu,&nbsp;</li>



<li>wersja ze&nbsp;stackalloc&nbsp;i&nbsp;ArrayPool&nbsp;&#8211; znacząco redukuje zużycia pamięci przy zachowaniu wysokiej szybkości działania.&nbsp;</li>
</ul>



<p>To świetny przykład, jak świadome zarządzanie tablicami może odciążyć zarówno CPU, jak i GC.&nbsp;</p>



<h2 class="wp-block-heading"><strong>B11&nbsp;Throwing&nbsp;Exceptions</strong>&nbsp;</h2>



<p>Jeżeli chodzi o kod, który przeprowadza np. walidację danych wprowadzanych przez użytkownika, mamy dwa sposoby przekazywania użytkownikowi informacji, że wprowadzone dane nie są zgodne z określonymi regułami. Pierwszym sposobem jest rzucanie wyjątków, a drugim zastosowanie wzorca <em>result</em>, w którym przekazujemy informację o potencjalnych problemach. Porównując test <code>CreateUserWithResult</code> z <code>CreateUserWithException</code>, widać spory narzut czasowy oraz alokacji pamięci w przypadku tego drugiego.</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B11ThrowingExceptions.ThrowingExceptionsBenchmark-report-github.md" target="_blank" rel="noopener">B11 Throwing Exceptions – pełne wyniki benchmarków</a>.</p>



<h2 class="wp-block-heading"><strong>B12 Serialization JSON: UTF8,&nbsp;nie&nbsp;string</strong>&nbsp;</h2>



<p>W przypadku serializacji i deserializacji JSON przy użyciu <code>System.Text.Json</code> warto bazować bezpośrednio na danych binarnych kodowanych do formatu UTF8, na którym opiera się komunikacja sieciowa (<code>SerializeDirectlyToUtf8</code>, <code>DeserializeDirectlyFromUtf8</code>), z pominięciem transkodowania do obiektu typu <code>string</code> (<code>SerializeToStringToUtf8</code>, <code>DeserializeFromUtf8FromString</code>), który przechowuje dane w formacie UTF16. Porównując poniższe testy, widać znaczące różnice w zużyciu pamięci.</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie<a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B12Serialization.SerializationBenchmark-report-github.md" target="_blank" rel="noopener"> B12 Serialization – pełne wyniki benchmarków</a>.</p>



<h2 class="wp-block-heading"><strong>B13 Dictionary&nbsp;Alternate&nbsp;Lookup</strong>&nbsp;</h2>



<p>W przypadku wyszukiwania w słowniku można skorzystać z mechanizmu <em>Dictionary alternate lookup</em>, umożliwiającego przeszukiwanie słownika przy użyciu klucza innego typu niż ten, z którym został on pierwotnie utworzony. Jest to możliwe dzięki strukturze <code>AlternateLookup</code>, która używa klasy <code>IAlternateEqualityComparer</code> do porównywania różnych typów kluczy, co pozwala na poprawę wydajności — na przykład wyszukiwanie danych za pomocą klasy <code>ReadOnlySpan&lt;char&gt;</code> (<code>CountWords2</code>) zamiast przydzielania nowego ciągu znaków (<code>CountWords1</code>). W tym przykładzie widać ogromne różnice w konsumpcji pamięci.</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B13DictionaryAlternateLookup.DictionaryAlternateLookupBenchmark-report-github.md" target="_blank" rel="noopener">B13 Dictionary Alternate Lookup – pełne wyniki benchmarków</a>.</p>



<h2 class="wp-block-heading"><strong>B14&nbsp;Structs</strong>&nbsp;</h2>



<p>W przypadku definiowania nowych obiektów typu wartościowego zalecanym sposobem definiowania tego typu obiektów jest korzystanie z konstrukcji <code>record struct</code> zamiast <code>struct</code>. Ten pierwszy ma generowane przez kompilator metody <code>GetHashCode</code> i <code>ToString</code>. Standardowy <code>struct</code> używa refleksji do implementacji tych metod, która jest dużo mniej efektywna. Jest to szczególnie ważne, jeżeli tak zdefiniowanej struktury używamy jako klucza w słowniku lub korzystamy z obiektu typu <code>HashSet</code>. Metoda <code>GetDictionaryKeyAsRecordStruct</code> działa dużo efektywniej niż <code>GetDictionaryKeyAsStruct</code>.</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie <a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B14Structs.StructsBenchmark-report-github.md" target="_blank" rel="noopener">B14 Structs – pełne wyniki benchmarków</a>.</p>



<h2 class="wp-block-heading"><strong>B15&nbsp;Streams</strong>&nbsp;</h2>



<p>W przypadku przetwarzania dużych zbiorów danych zamiast klasycznego przetwarzania wszystkich danych w pamięci warto rozważyć zastosowanie obiektów typu <em>stream</em> oraz <code>I(Async)Enumerable</code>. Zaprezentowany przykład realizuje funkcjonalność czytania z pliku każdego wiersza, zamiany go na obiekt, wyliczenia wartości średniej i zapisania wyliczonej wartości średniej wraz z oryginalnymi wartościami w pliku wynikowym.</p>



<p>W pierwszej implementacji (<code>AsyncProcessingGetRowsWriteRows</code>) wszystkie wiersze źródłowe są wczytywane do pamięci, a następnie cała kolekcja wiersz po wierszu zapisywana jest w pliku wynikowym. W drugiej implementacji (<code>AsyncStreamProcessingReWrite</code>) naraz pobierany jest tylko jeden wiersz, wykonywane są obliczenia na tym wierszu, a wynik zapisywany jest bezpośrednio w pliku wynikowym. Z porównania wyników widać, że pierwsza implementacja jest minimalnie szybsza, ale zużywa dużo więcej pamięci.</p>



<p>Szczegółowe wyniki benchmarku zostały przedstawione w raporcie<a href="https://github.com/tomekjanicki/Performance/blob/master/Performance/results/Performance.B15Streams.StreamsBenchmark-report-github.md" target="_blank" rel="noopener"> B15 Streams – pełne wyniki benchmarków</a>.</p>



<p>Jeśli twój system pracuje na dużych plikach, logach lub danych z bazy danych, strumieniowe przetwarzanie pozwoli utrzymać stabilną wydajność twoich aplikacji, nawet gdy wolumen danych rośnie.</p>



<h2 class="wp-block-heading" id="ogolne-zasady-jak-pisac-wydajny-kod-który-nadal-da-się-utrzymac"><strong>Ogólne zasady &#8211; jak pisać wydajny kod, który nadal da się utrzymać</strong>&nbsp;</h2>



<p>Na koniec kilka zasad, które warto zapamiętać, jeśli chcesz zwiększyć wydajność aplikacji, ale nadal spać spokojnie:&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Zaczynaj od algorytmu.&nbsp;</strong>Dobry algorytm i odpowiednie struktury danych często dają więcej niż lokalne&nbsp;mikrooptymalizacje.&nbsp;</li>



<li><strong>Mierz, nie zgaduj. Używaj narzędzi</strong>&nbsp;&#8211; Visual Studio,&nbsp;BenchmarkDotNet, logów &#8211; aby mierzyć realne problemy.&nbsp;</li>



<li><strong>Myśl o całości</strong>&nbsp;&#8211; od bazy po UI. To, jak kod &#8222;rozmawia&#8221; z bazą danych, jak obsługuje API, jak działa po stronie serwera i jak zarządza pamięcią, ma wpływ na całe doświadczenie użytkownika.&nbsp;</li>



<li><strong>Korzystaj&nbsp;z&nbsp;pomocy społeczności&nbsp;i dokumentacji.&nbsp;</strong>Dokumentacja Microsoft, kursy Microsoft&nbsp;Learn, repozytoria GitHub i przykłady&nbsp;kodu&nbsp;innych zespołów to świetne dodatkowe zasoby, które mogą pokazać ci gotowe techniki optymalizacji.&nbsp;</li>



<li><strong>Pamiętaj o użytkowniku.</strong>&nbsp;Dla biznesu liczy się krótszy czas odpowiedzi, mniejsze koszty utrzymania, mniej maszyn, stabilność działania. Techniczne detale służą temu, by dowieźć lepszą wydajność i realne korzyści.&nbsp;</li>
</ul>



<p>Dobrze zaprojektowany, wydajny i efektywny kod C# nie musi być „magiczny” i niezrozumiały. Można łączyć pragmatyzm z jakością &#8211; tak, aby zwiększyć wydajność aplikacji tam, gdzie to naprawdę ma znaczenie, a jednocześnie zachować sensowną czytelność dla kolejnych osób, które będą ten kod rozwijać i programować w nim nowe funkcje.&nbsp;</p>



<h2 class="wp-block-heading" id="faq">FAQ&nbsp;</h2>


<div id="rank-math-faq" class="rank-math-block">
<div class="rank-math-list ">
<div id="faq-question-1765977988901" class="rank-math-list-item">
<h3 class="rank-math-question ">Co to jest optymalizacja kodu .NET i dlaczego optymalizacja kodu to ważny element? </h3>
<div class="rank-math-answer ">

<p>Optymalizacja kodu .NET to proces poprawiania szybkości, zużycia pamięci i ogólnej efektywności wykonywania kodu w aplikacjach opartych na .NET. Optymalizacja kodu to ważny aspekt tworzenia oprogramowania, ponieważ wpływa na doświadczenie użytkownika, koszty infrastruktury i stabilność systemu. Przy optymalizacji warto uwzględnić silnik uruchomieniowy .NET, bibliotekę używaną przez twój kod oraz unikać przedwczesnej optymalizacji, która może skomplikować implementację bez realnych korzyści. </p>

</div>
</div>
<div id="faq-question-1765978013395" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jakie narzędzia w Visual Studio pomagają mierzyć wydajność kodu?</strong> </h3>
<div class="rank-math-answer ">

<p>Visual Studio oferuje profiler, diagnosery i narzędzia do mierzenia wydajności, które pozwalają śledzić czas wykonywania kodu, zużycie pamięci i<strong> </strong>liczbę utworzonych objects. Dzięki tym narzędziom możesz znaleźć wąskie gardła, porównać różne implementacje i zdecydować, jakie zmiany przyniosą największą poprawę. W praktyce przed optymalizacją warto zmierzyć baseline, aby wiedzieć, co rzeczywiście wymaga poprawy. </p>

</div>
</div>
<div id="faq-question-1765978030450" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jak optymalizacja wpływa na zużycie zasobów i kiedy warto wyłączyć pewne funkcje?</strong> </h3>
<div class="rank-math-answer ">

<p>Optymalizacja wpływa bezpośrednio na zużycie zasobów takich jak pamięć i CPU. Czasami warto wyłączyć funkcje generujące nadmierne alokacje lub kosztowne operacje w tle, szczególnie gdy obciążenie jest wysokie. Przy optymalizacji twojego kodu należy analizować, czy bardziej opłacalne będzie zoptymalizować algorytm, zmienić bibliotekę czy wyłączyć rzadko używane elementy, które obciążają silnik wykonywania kodu. </p>

</div>
</div>
<div id="faq-question-1765978063823" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jak efektywnie mierzyć i analizować czas wykonywania kodu w .NET?</strong> </h3>
<div class="rank-math-answer ">

<p>Aby mierzyć czas wykonywania kodu, użyj wbudowanych profilerów, narzędzi do mierzenia wydajności, logowania z timestampami lub bibliotek do benchmarków (np. BenchmarkDotNet). Zbieraj metryki w warunkach zbliżonych do produkcji i uwzględniaj warunki brzegowe. Unikaj przedwczesnej optymalizacji &#8211; najpierw zidentyfikuj hotspoty za pomocą narzędzi do mierzenia wydajności, a potem skup się na tym, by zoptymalizować fragmenty, które rzeczywiście wpływają na wydajność. </p>

</div>
</div>
<div id="faq-question-1765978085075" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Kiedy należy zoptymalizować kod, a kiedy lepiej użyć gotowej biblioteki?</strong> </h3>
<div class="rank-math-answer ">

<p>Jeśli problem leży w algorytmie lub alokacjach, warto zoptymalizować kod samodzielnie, jednak często gotowa biblioteka oferuje dobrze przetestowane i zoptymalizowane rozwiązania, które oszczędzają czas. Przy wyborze biblioteki sprawdź jej wpływ na wykonywanie kodu, kompatybilność z silnikiem .NET i licencję. </p>

</div>
</div>
<div id="faq-question-1765978101702" class="rank-math-list-item">
<h3 class="rank-math-question "><strong>Jak uniknąć przedwczesnej optymalizacji i jakie praktyki stosować?</strong> </h3>
<div class="rank-math-answer ">

<p>Unikaj przedwczesnej optymalizacji &#8211; skup się w pierwszej kolejności na poprawności i czytelności kodu. Stosuj profilowanie i mierzenie wydajności przed wprowadzaniem zmian. Praktyki takie jak cache&#8217;owanie wyników, minimalizowanie alokacji objects, używanie struktur i spanów w krytycznych sekcjach oraz asynchroniczne operacje IO pomagają tworzyć zoptymalizowany kod bez niepotrzebnego ryzyka. </p>

</div>
</div>
</div>
</div>]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/optymalizacja-kodu-c-sharp-w-dot-net-techniki-poprawy-wydajnosci/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic</title>
		<link>https://nearshore-it.eu/pl/artykuly/programowanie-ai-claude-code/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/programowanie-ai-claude-code/#respond</comments>
		
		<dc:creator><![CDATA[Adam Osiak]]></dc:creator>
		<pubDate>Wed, 13 Aug 2025 14:54:49 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=37449</guid>

					<description><![CDATA[Stuczna inteligencja wykorzystywana jest coraz chętniej przez programistów w obrębie bardziej złożonych zadań, a modele AI stają się coraz bardziej zaawansowane. Gemini, Github Copilot czy Microsoft Copilot rozpoczęły rewolucję w kodowaniu i dziś trudno wyobrazić sobie realizację codziennych zadań bez pomocy tych narzędzi.]]></description>
										<content:encoded><![CDATA[
<div class="table-of-contents">
    <p class="title">Go to:</p>
    <ol>
                    <li><a href="#Wprowadzenie-do-Claude-Code:-twój-agent-AI">1.  Wprowadzenie do Claude Code: twój agent AI</a></li>
                    <li><a href="#Jak-zacząć-z-narzędziem-Claude-Code?">2.  Jak zacząć z narzędziem Claude Code?</a></li>
                    <li><a href="#Case-study:-System-rezerwacji-sal-konferencyjnych">3.  Case study: System rezerwacji sal konferencyjnych</a></li>
                    <li><a href="#Krok-1:-AI-dekoduje-chaos:-analiza-wymagań">4.  Krok 1: AI dekoduje chaos: analiza wymagań</a></li>
                    <li><a href="#Krok-2:-Od-wymagań-do-architektury-w 5-minut">5.  Krok 2: Od wymagań do architektury w 5 minut</a></li>
                    <li><a href="#Krok-3:-Meta-prompting.-Twój-plan-implementacji">6.  Krok 3: Meta-prompting. Twój plan implementacji</a></li>
                    <li><a href="#Krok-4:-Implementacja">7.  Krok 4: Implementacja</a></li>
                    <li><a href="#Jak-kodować?-3-praktyczne-porady-na-start">8.  Jak kodować? 3 praktyczne porady na start</a></li>
                    <li><a href="#Sztuczna inteligencja w programowaniu: podsumowanie">9.  Sztuczna inteligencja w programowaniu: podsumowanie</a></li>
            </ol>
</div>


<p>Szukając odpowiedzi na pytanie, jakiego asystenta AI używać, by programować wydajniej i lepiej, warto przyjrzeć się narzędziu Claude od firmy Anthropic. W artykule znajdziesz informacje o tym, czym jest Claude Code<strong>,</strong> jak zacząć i korzystać z Claude, oraz przegląd najlepszych praktyk programistycznych.  </p>



<h2 class="wp-block-heading" id="Wprowadzenie-do-Claude-Code:-twój-agent-AI">Wprowadzenie do Claude Code: twój agent AI</h2>



<p>Wyobraź sobie, że patrzysz na brief od klienta i zamiast spędzać kolejne godziny na pisaniu boilerplate&#8217;u, wpisujesz w terminal: &#8222;stwórz kompletne REST API na podstawie tych wymagań&#8221;. Po chwili masz gotowy, działający kod z obsługą błędów, walidacją i testami. To jest właśnie Claude Code.</p>



<p><strong>Przeczytaj także: <a href="https://nearshore-it.eu/pl/artykuly/najlepsze-ai-for-coding-w-2025-roku-czego-uzywac-do-generowania-kodu/" data-type="post" data-id="34778">Najlepsze AI for coding w 2025 roku</a></strong></p>



<h3 class="wp-block-heading"><a></a>Czym właściwie jest Claude Code firmy Anthropic?</h3>



<p>Claude Code to narzędzie CLI (Command Line Interface) stworzone przez Anthropic. To tak, jakby mieć doświadczonego pair programming partnera, który pomaga w każdym zadaniu: od analizy i dokumentacji legacy code po implementację nowych funkcjonalności. Claude Code przy każdym zadaniu pomaga trzymać się zasad czystego programowania i stosuje wzorce projektowe.</p>



<p>Przykładowe prompty mogą wyglądać tak:u</p>



<p>Zamiast godzin analizy, wpisujemy:</p>



<p><em>&#8222;Przeanalizuj projekt i stwórz do niego szczegółową dokumentację&#8221;</em></p>



<p>Zamiast ręcznego refactoringu:</p>



<p><em>&#8222;Przekształć klasy w tym module zgodnie z SOLID&#8221;</em></p>



<p>Zamiast pisania testów:</p>



<p><em>&#8222;Wygeneruj testy jednostkowe dla klasy PaymentService&#8221;</em></p>



<p>Za chwilę pokażę ci na realnym przykładzie, jak wykorzystam Claude Code do przekształcenia chaotycznych wymagań klienta w działający system. Ale najpierw &#8211; szybki start.</p>



<h2 class="wp-block-heading" id="Jak-zacząć-z-narzędziem-Claude-Code?">Jak zacząć z narzędziem Claude Code?</h2>



<p>Zanim przejdę do case study, pokażę ci, jak rozpocząć pracę z Claude Code.</p>



<h3 class="wp-block-heading"><a></a>Instalacja w 3 krokach:</h3>



<ol start="1" class="wp-block-list">
<li>Sprawdzam wymagania &#8211; potrzebuję zainstalowanego <a href="http://node.js" target="_blank" rel="noopener">Node.js</a> 18+ oraz dostępu do API Anthropic (minimum w wersji Pro).</li>



<li>Instaluję Claude Code za pomocą komendy “npm install -g @anthropic-ai/claude-code”.<br></li>
</ol>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="513" height="114" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic01.png" alt="claude code" class="wp-image-37493" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 7" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic01.png 513w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic01-300x67.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic01-495x110.png 495w" sizes="auto, (max-width: 513px) 100vw, 513px" /></figure>



<ol start="1" class="wp-block-list">
<li>Wywołuję Claude Code poleceniem “claude”. Następnie wybieram opcję z kontem Claude </li>
</ol>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="720" height="410" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic02.png" alt="claude code" class="wp-image-37496" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 8" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic02.png 720w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic02-300x171.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic02-495x282.png 495w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>



<p>Finalnie Claude Code jest gotowy do działania:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="601" height="605" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic03.png" alt="claude code agent ai" class="wp-image-37499" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 9" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic03.png 601w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic03-298x300.png 298w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic03-150x150.png 150w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic03-392x395.png 392w" sizes="auto, (max-width: 601px) 100vw, 601px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="695" height="397" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic04.png" alt="claude code agent ai" class="wp-image-37502" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 10" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic04.png 695w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic04-300x171.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic04-495x283.png 495w" sizes="auto, (max-width: 695px) 100vw, 695px" /></figure>



<h3 class="wp-block-heading"><a></a>Pierwszy prompt &#8211; pokaż, co potrafisz, Claude</h3>



<p>Zacznijmy od czegoś prostego. Załóżmy, że chcę napisać grę w kółko i krzyżyk w HTML. Sprawdźmy, czy Claude sobie z tym poradzi</p>



<p>Claude przystępuje do pracy:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="699" height="186" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic05.png" alt="claude code agent ai" class="wp-image-37505" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 11" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic05.png 699w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic05-300x80.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic05-495x132.png 495w" sizes="auto, (max-width: 699px) 100vw, 699px" /></figure>



<p>Następnie prosi mnie o pozwolenie zapisania pliku, który stworzył:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="690" height="273" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic06.png" alt="claude code agent ai" class="wp-image-37508" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 12" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic06.png 690w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic06-300x119.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic06-495x196.png 495w" sizes="auto, (max-width: 690px) 100vw, 690px" /></figure>



<p>Sprawdźmy, jak wygląda strona, którą stworzył:</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="400" height="580" data-id="37511" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic07.png" alt="claude code agent ai" class="wp-image-37511" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 13" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic07.png 400w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic07-207x300.png 207w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic07-272x395.png 272w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="400" height="580" data-id="37514" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic08.png" alt="nearshore 2025.07.25 graphic08" class="wp-image-37514" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 14" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic08.png 400w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic08-207x300.png 207w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic08-272x395.png 272w" sizes="auto, (max-width: 400px) 100vw, 400px" /></figure>
</figure>



<p></p>



<p>W mniej niż 30 sekund otrzymałem grę w kółko i krzyżyk zaimplementowaną w HTML, JS i CSS.</p>



<h3 class="wp-block-heading"><a></a>Integracja z istniejącym projektem</h3>



<p>Claude Code idealnie spisuje się w pracy na istniejących już projektach. Na potrzeby artykułu stworzyłem podstawową aplikację Spring Boot.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="686" height="1072" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic09.png" alt="claude code agent ai" class="wp-image-37517" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 15" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic09.png 686w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic09-192x300.png 192w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic09-253x395.png 253w" sizes="auto, (max-width: 686px) 100vw, 686px" /></figure>



<p>Aby poprawnie rozpocząć pracę na istniejącym projekcie, pomocna będzie komenda /init.</p>



<p>Komenda /init to polecenie, które:</p>



<ul class="wp-block-list">
<li>Skanuje całą strukturę projektu</li>



<li>Tworzy mapę zależności między modułami</li>



<li>Identyfikuje użyte technologie i frameworki</li>



<li>Buduje kontekst, którego Claude będzie używał we wszystkich kolejnych interakcjach</li>
</ul>



<p>Po wykonaniu /init w głównym katalogu projektu zostanie utworzony plik CLAUDE.md. To &#8222;instrukcja obsługi&#8221; projektu dla agenta AI.</p>



<p>Sprawdźmy, jak to działa w praktyce</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="2324" height="834" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10.png" alt="claude code agent ai" class="wp-image-37520" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 16" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10.png 2324w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10-300x108.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10-1296x465.png 1296w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10-768x276.png 768w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10-1536x551.png 1536w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10-2048x735.png 2048w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10-495x178.png 495w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic10-1320x474.png 1320w" sizes="auto, (max-width: 2324px) 100vw, 2324px" /></figure>



<p>Claude tworzy listę z czynności, jakie musi wykonać, aby poprawnie przygotować plik <a href="http://claude.md" target="_blank" rel="noopener">CLAUDE.md</a>.</p>



<p>Po chwili mogę sprawdzić, co znajduje się w tym pliku:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1918" height="1016" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic11.png" alt="claude code agent ai" class="wp-image-37523" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 17" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic11.png 1918w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic11-300x159.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic11-1296x687.png 1296w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic11-768x407.png 768w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic11-1536x814.png 1536w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic11-495x262.png 495w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic11-1320x699.png 1320w" sizes="auto, (max-width: 1918px) 100vw, 1918px" /></figure>



<p>Ten plik mogę edytować, dodając własne wytyczne, standardy kodowania czy konkretne wymagania projektu. Claude będzie je respektował w każdej interakcji.</p>



<p>Teraz, gdy mam już działające narzędzie, czas sprawdzić jego prawdziwą moc. Przejdźmy do realnego przypadku: systemu, który muszę dostarczyć klientowi w rekordowo krótkim czasie.</p>



<h2 class="wp-block-heading" id="Case-study:-System-rezerwacji-sal-konferencyjnych">Case study: System rezerwacji sal konferencyjnych</h2>



<p>Wyobraźmy sobie sytuację:</p>



<p>Do mojego zespołu trafia zlecenie od klienta, dużej firmy farmaceutycznej z Warszawy. Potrzebują systemu rezerwacji sal konferencyjnych &#8222;na wczoraj&#8221;. Termin? 4 tygodnie. Budżet? Napięty. Oczekiwania? Wysokie.</p>



<p>Przykładowy brief:</p>



<p><em>“Potrzebujemy systemu do zarządzania naszymi salami konferencyjnymi.</em><br><em>Mamy 15 sal na 3 piętrach, pracownicy ciągle się kłócą o rezerwacje.</em><br><em>Co ma robić:</em><br><em>&#8211; Pokazywać, które sale są wolne</em></p>



<p><em>&#8211; Rezerwować sale (z góry na cały dzień albo na godziny)</em></p>



<p><em>&#8211; Anulować rezerwacje</em></p>



<p><em>&#8211; Sale mają różne wyposażenie (projektor, flipchart, videokonferencja) &#8211; trzeba to jakoś oznaczyć</em></p>



<p><em>&#8211; Ma działać na komórkach!!! To ważne</em></p>



<p><em>&#8211; Szef chce raporty &#8211; która sala jest najpopularniejsza, wykorzystanie, itp.</em></p>



<p><em>Aha, zapomniałem &#8211; niektóre sale można łączyć (np. 201 + 202 = duża sala).</em></p>



<p><em>I jeszcze jedno &#8211; tylko niektórzy mogą rezerwować sale premium (10. piętro).”</em></p>



<h3 class="wp-block-heading"><a></a>Wyzwania, które można zauważyć</h3>



<ol class="wp-block-list">
<li><strong>Niejasne wymagania</strong>: &#8222;jakoś oznaczyć&#8221;, &#8222;raporty&#8221; &#8211; każde z tych wyrażeń może oznaczać coś zupełnie innego.</li>



<li><strong>Ukryte złożoności</strong>:</li>



<li>Łączenie sal: Czy rezerwacja jednej blokuje możliwość rezerwacji drugiej?</li>



<li>Uprawnienia: Kto decyduje o dostępie do sal premium?</li>



<li>&#8222;Na godziny&#8221;: Czy są jakieś minimalne/maksymalne czasy?</li>



<li>System raportowania: Jak szczegółowy? Dla kogo?</li>



<li><strong>Sprzeczne priorytety</strong>: &#8222;na wczoraj&#8221; vs &#8222;zraporty i zaawansowane funkcje&#8221;</li>



<li><strong>Techniczne wyzwania</strong>:</li>



<li>Responsywność (różne urządzenia mobilne)</li>



<li>Dostępność w czasie rzeczywistym (dwóch użytkowników nie może zarezerwować tej samej sali)</li>



<li>Logika łączenia sal (skomplikowane zależności)</li>



<li>System uprawnień (różne poziomy dostępu)</li>
</ol>



<p></p>



<h3 class="wp-block-heading"><a></a>Klasyczne podejście vs Claude Code</h3>



<p>Bez AI pierwszy tydzień spędzilibyśmy na:</p>



<ul class="wp-block-list">
<li>Tworzeniu obszernej dokumentacji wymagań</li>



<li>Projektowaniu architektury</li>



<li>Długich sesjach szacowania zadań w zespole</li>
</ul>



<p>Zamiast tego wykorzystam Claude Code do natychmiastowej analizy i dekompozycji “chaosu”. Za chwilę pokażę ci, jak w 15 minut przekształcę ten chaotyczny email w uporządkowany plan projektu z konkretnymi zadaniami i harmonogramem.<a></a></p>



<h2 class="wp-block-heading" id="Krok-1:-AI-dekoduje-chaos:-analiza-wymagań">Krok 1: AI dekoduje chaos: analiza wymagań</h2>



<p>Wprowadzę w Claude Code poniższy prompt:</p>



<p><em>&#8222;Przeanalizuj poniższe wymagania biznesowe od klienta i:<br>1. Wyodrębnij wszystkie funkcjonalności (jawne i ukryte)<br>2. Uporządkuj je metodą MoSCoW<br>3. Zidentyfikuj niejasności i potencjalne problemy</em></p>



<p><em>[wklejony brief od klienta]<br>Wynik zapisz w pliku .md&#8221;</em></p>



<p>Claude przystępuje do pracy, tworząc listę zadań. Po 15 sekundach otrzymuję kompletną analizę:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1828" height="390" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic12.png" alt="claude code agent ai" class="wp-image-37526" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 18" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic12.png 1828w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic12-300x64.png 300w" sizes="auto, (max-width: 1828px) 100vw, 1828px" /></figure>



<p><strong>Must have (MVP):</strong></p>



<ul class="wp-block-list">
<li>Przeglądanie dostępności sal w czasie rzeczywistym</li>



<li>Rezerwacja sali na konkretny dzień/godziny</li>



<li>Anulowanie własnych rezerwacji</li>



<li>Wyświetlanie wyposażenia sal</li>



<li>Responsywny interfejs (mobile-first)</li>



<li>Podstawowa autoryzacja użytkowników</li>



<li>Podstawowe zapobieganie konfliktom (brak podwójnych rezerwacji)</li>
</ul>



<p><strong>Should have:</strong></p>



<ul class="wp-block-list">
<li>System uprawnień dla sal premium</li>



<li>Łączenie sal (z blokowaniem zależności)</li>



<li>Podstawowe raporty wykorzystania</li>



<li>Walidacja minimalnego czasu rezerwacji (np. 30 min)</li>



<li>Historia rezerwacji użytkownika</li>
</ul>



<p><strong>Could have:</strong></p>



<ul class="wp-block-list">
<li>Rezerwacje cykliczne</li>



<li>Wyszukiwanie sal po wyposażeniu</li>



<li>Eksport raportów do Excela</li>



<li>Powiadomienia o zbliżających się rezerwacjach</li>
</ul>



<p><strong>Won&#8217;t have (w MVP):</strong></p>



<ul class="wp-block-list">
<li>Zaawansowana analityka predykcyjna</li>



<li>Integracja z systemami budynku (klimatyzacja, światło)</li>
</ul>



<h3 class="wp-block-heading"><a></a>Pierwsze zaskoczenie: Claude wyłapał ukryte wymagania</h3>



<p>Co mnie zaskoczyło? Claude zauważył rzeczy, o których klient nie wspomniał, ale które są oczywiste:</p>



<ol start="1" class="wp-block-list">
<li><strong>Konflikt rezerwacji:</strong> Co, jeśli dwóch użytkowników próbuje zarezerwować tę samą salę równocześnie?</li>



<li><strong>Anulowanie z wyprzedzeniem:</strong> Czy można anulować rezerwację 5 minut przed czasem?</li>



<li><strong>Łączenie sal = problem dostępności:</strong> Jeśli ktoś rezerwuje salę 201+202 jako połączoną, system musi automatycznie blokować je pojedynczo.</li>



<li><strong>Widoczność rezerwacji:</strong> Czy wszyscy widzą, kto zarezerwował salę, czy tylko dostępny jest fakt rezerwacji?</li>
</ol>



<p>Claude Code w kilka chwil wykonał solidną pracę. Po omówieniu z klientem niejasności, mogę przejść do następnego kroku: zaprojektowania architektury systemu.</p>



<h2 class="wp-block-heading" id="Krok-2:-Od-wymagań-do-architektury-w-5-minut">Krok 2: Od wymagań do architektury w 5 minut</h2>



<p>Mając uporządkowane wymagania, klasycznie zorganizowalibyśmy sesję spotkań architektonicznych. Zamiast tego, wykorzystam Claude Code do wygenerowania propozycji architektury.</p>



<p>Prompt do generowania architektury:</p>



<p><em>“Na podstawie tych wymagań zaprojektuj architekturę systemu:<br>1. Zaproponuj stack technologiczny (uzasadnij wybór)<br>2. Opisz strukturę modułów/serwisów<br>3. Zaplanuj model danych<br>4. Stwórz harmonogram implementacji dla 3 developerów na 4 tygodnie<br>5. Zidentyfikuj ryzyka techniczne<br>Kontekst: zespół zna React, Spring Boot i PostgreSQL<br>Zapisz ten plan w pliku .md”</em></p>



<p><br>Claude ponownie przystępuje do pracy:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1280" height="352" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic13.png" alt="claude code agent ai" class="wp-image-37529" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 19" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic13.png 1280w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic13-300x83.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic13-768x211.png 768w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic13-495x136.png 495w" sizes="auto, (max-width: 1280px) 100vw, 1280px" /></figure>



<h3 class="wp-block-heading"><a></a>Wynik? Kompletny plan techniczny</h3>



<p><strong>Stack technologiczny z uzasadnieniem:</strong></p>



<p><strong>Frontend: React + TypeScript + Tailwind CSS</strong></p>



<ul class="wp-block-list">
<li>React: zespół zna tę technologię</li>



<li>TypeScript: złożona logika biznesowa wymaga typowania</li>



<li>Tailwind: szybkie tworzenie responsywnych interfejsów</li>
</ul>



<p><strong>Backend: Spring Boot + Spring Data JPA</strong></p>



<ul class="wp-block-list">
<li>Spring Boot: zespół ma doświadczenie w tej technologii</li>



<li>Spring Security: gotowe rozwiązania dla autoryzacji</li>



<li>Spring Data JPA: praca z relacjami (sale łączone)</li>
</ul>



<p></p>



<p><strong>Baza: PostgreSQL</strong></p>



<ul class="wp-block-list">
<li>Relacje między salami, rezerwacjami, użytkownikami</li>



<li>Transakcje dla rezerwacji (ACID)</li>



<li>Wydajne zapytania dla raportów</li>
</ul>



<p>Struktura modułów frontend:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="452" height="629" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic19.png" alt="claude code agent ai" class="wp-image-37547" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 20" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic19.png 452w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic19-216x300.png 216w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic19-284x395.png 284w" sizes="auto, (max-width: 452px) 100vw, 452px" /></figure>



<p></p>



<p><strong>Modele danych (wybrane):</strong></p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="468" height="519" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic20.png" alt="claude code agent ai" class="wp-image-37550" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 21" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic20.png 468w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic20-271x300.png 271w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic20-356x395.png 356w" sizes="auto, (max-width: 468px) 100vw, 468px" /></figure>



<p><strong>Przykładowy plan implementacji (pierwsze dwa tygodnie)</strong></p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1922" height="1281" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic14.png" alt="claude code agent ai" class="wp-image-37532" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 22" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic14.png 1922w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic14-300x200.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic14-1296x864.png 1296w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic14-768x512.png 768w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic14-1536x1024.png 1536w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic14-495x330.png 495w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic14-1320x880.png 1320w" sizes="auto, (max-width: 1922px) 100vw, 1922px" /></figure>



<p>Plan jest gotowy, dzięki czemu jestem gotowy do działania. Ale jest jeszcze jedna rzecz do zrobienia: czas na meta-prompting.</p>



<h2 class="wp-block-heading" id="Krok-3:-Meta-prompting.-Twój-plan-implementacji">Krok 3: Meta-prompting. Twój plan implementacji</h2>



<p>Tu zaczyna się prawdziwa magia Claude Code. Zamiast ręcznie tworzyć zadania w Jirze, poproszę AI o wygenerowanie kompletnego zestawu promptów, które przeprowadzą nas przez całą implementację.</p>



<h3 class="wp-block-heading"><a></a>Czym jest meta-prompting?</h3>



<p>Meta-prompting to technika, w której używamy AI do generowania promptów dla&#8230; AI. Brzmi trochę jak incepcja &#8211; w praktyce to świetne narzędzie. Claude Code analizuje plan implementacyjny i następnie tworzy serię instrukcji, które później mogę wykonywać krok po kroku.</p>



<p><strong>Mój prompt:</strong></p>



<p><em>&#8222;Przeanalizuj architekturę systemu rezerwacji sal z pliku system_architecture_plan.md i wygeneruj kompletną listę promptów do implementacji MVP.</em></p>



<p><em>Dla każdego promptu podaj:</em></p>



<p><em>&#8211; Co dokładnie ma zostać zaimplementowane</em></p>



<p><em>&#8211; Jakie edge case&#8217;y uwzględnić</em></p>



<p><em>&#8211; Z czym się integruje</em></p>



<p><em>Grupuj prompty według modułów. Zacznij od podstaw (model danych),</em></p>



<p><em>skończ na funkcjach biznesowych. Wynik zapisz w pliku .md&#8221;</em></p>



<p>Claude wygenerował komplet promptów dla MVP. Oto przykładowe z nich:</p>



<p><strong>Moduł: Model danych</strong></p>



<p><em>Prompt 1: &#8222;Stwórz encje JPA dla systemu rezerwacji sal: Room, Booking, User.</em></p>



<p><em>Room musi obsługiwać relację many-to-many dla sal łączonych.</em></p>



<p><em>Dodaj indeksy dla room.floor i booking.startTime.</em></p>



<p><em>Equipment przechowuj jako JSON (PostgreSQL jsonb).&#8221;</em></p>



<p><em>Prompt 2: &#8222;Napisz Liquibase migration dla modelu danych.</em></p>



<p><em>Dodaj constraint: booking.endTime &gt; booking.startTime.</em></p>



<p><em>Stwórz trigger blokujący nakładające się rezerwacje.&#8221;</em></p>



<p><strong>Moduł: REST API</strong></p>



<p><em>Prompt 7: &#8222;Stwórz RoomController z endpointami:</em></p>



<p><em>GET /rooms &#8211; z filtrowaniem po floor, capacity, equipment</em></p>



<p><em>GET /rooms/available?start=&amp;end= &#8211; dostępne w czasie</em></p>



<p><em>GET /rooms/{id}/schedule &#8211; kalendarz sali</em></p>



<p><em>Dodaj @Cacheable dla GET /rooms.&#8221;</em></p>



<p><em>Prompt 8: &#8222;Zaimplementuj BookingController:</em></p>



<p><em>POST /bookings &#8211; nowa rezerwacja (dto validation)</em></p>



<p><em>DELETE /bookings/{id} &#8211; anulowanie</em></p>



<p><em>GET /bookings/my &#8211; rezerwacje użytkownika</em></p>



<p><em>Obsłuż @ExceptionHandler dla custom wyjątków.&#8221;</em></p>



<p>Od teraz mogę rozpocząć implementację MVP. W kolejnym kroku pokażę ci, jak wykorzystam te prompty w praktyce &#8211; z rzeczywistym kodem, który Claude wygeneruje.</p>



<h2 class="wp-block-heading" id="Krok-4:-Implementacja">Krok 4: Implementacja</h2>



<p>Mając gotowe prompty, przyszedł czas na prawdziwy test &#8211; implementację. Pokażę ci trzy przykłady, w jaki sposób Claude Code przekształcił moje prompty w działający kod.</p>



<h3 class="wp-block-heading"><a></a>Przykład 1: Model danych z obsługą sal łączonych</h3>



<p>Prompt:</p>



<p><em>&#8222;Stwórz encje JPA dla systemu rezerwacji sal: Room, Booking, User. Room musi obsługiwać relację many-to-many dla sal łączonych. Dodaj indeksy dla room.floor i booking.startTime. Equipment przechowuj jako JSON (PostgreSQL jsonb).&#8221;</em></p>



<p>Claude Code wygenerował:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Entity

@Table(name = "rooms", indexes = {

    @Index(name = "idx_room_floor", columnList = "floor")

})

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

public class Room {

    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

    @Column(nullable = false, unique = true)

    private String name;

    @Column(nullable = false)

    private Integer floor;

    private Integer capacity;

    @Type(type = "jsonb")

    @Column(columnDefinition = "jsonb")

    private Map&lt;String, Object> equipment;

    private Boolean isPremium = false;

    @ManyToMany

    @JoinTable(

        name = "mergeable_rooms",

        joinColumns = @JoinColumn(name = "room_id"),

        inverseJoinColumns = @JoinColumn(name = "mergeable_with_id")

    )

    @JsonIgnore

    private Set&lt;Room> mergeableWith = new HashSet&lt;>();

    // Helper method - Claude dodał to sam!

    public boolean canBeMergedWith(Room other) {

        return mergeableWith.contains(other) ||

               other.getMergeableWith().contains(this);

    }

}

@Entity

@Table(name = "bookings", indexes = {

    @Index(name = "idx_booking_start_time", columnList = "startTime"),

    @Index(name = "idx_booking_room_time", columnList = "room_id,startTime,endTime")

})

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

public class Booking {

    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)

    @JoinColumn(nullable = false)

    private Room room;

    @ManyToOne(fetch = FetchType.LAZY)

    @JoinColumn(nullable = false)

    private User user;

    @Column(nullable = false)

    private LocalDateTime startTime;

    @Column(nullable = false)

    private LocalDateTime endTime;

    @Enumerated(EnumType.STRING)

    private BookingStatus status = BookingStatus.ACTIVE;

    @ManyToMany

    @JoinTable(name = "booking_merged_rooms")

    private Set&lt;Room> mergedRooms = new HashSet&lt;>();

    @PrePersist

    @PreUpdate

    private void validateTimes() {

        if (endTime.isBefore(startTime) || endTime.equals(startTime)) {

            throw new IllegalArgumentException("End time must be after start time");

        }

    }

}</pre>



<p></p>



<h3 class="wp-block-heading"><a></a>Przykład 2: Serwis z logiką konfliktów</h3>



<p>Prompt:</p>



<p><em>&#8222;Zaimplementuj BookingService.createBooking() z logiką: &#8211; Sprawdź konflikty (również dla sal łączonych) &#8211; Waliduj uprawnienia premium &#8211; Transakcja obejmuje wszystkie sale (jeśli łączone) &#8211; Rzuć custom exceptions&#8221;</em></p>



<p>Claude Code wygenerował:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Service

@Transactional

@RequiredArgsConstructor

@Slf4j

public class BookingService {

    private final BookingRepository bookingRepository;

    private final RoomRepository roomRepository;

    @Transactional(isolation = Isolation.SERIALIZABLE)

    public Booking createBooking(BookingCreateDto dto, User currentUser) {

        log.info("Creating booking for user {} from {} to {}",

                 currentUser.getEmail(), dto.getStartTime(), dto.getEndTime());

        // Pobierz główną salę

        Room mainRoom = roomRepository.findById(dto.getRoomId())

            .orElseThrow(() -> new RoomNotFoundException(dto.getRoomId()));

        // Sprawdź uprawnienia premium

        if (mainRoom.getIsPremium() &amp;&amp; !currentUser.getCanBookPremium()) {

            throw new InsufficientPermissionsException(

                "User " + currentUser.getEmail() + " cannot book premium rooms"

            );

        }

        // Zbierz wszystkie sale do rezerwacji

        Set&lt;Room> roomsToBook = new HashSet&lt;>();

        roomsToBook.add(mainRoom);

        if (dto.getMergedRoomIds() != null &amp;&amp; !dto.getMergedRoomIds().isEmpty()) {

            Set&lt;Room> mergedRooms = new HashSet&lt;>(

                roomRepository.findAllById(dto.getMergedRoomIds())

            );

            // Waliduj czy sale mogą być połączone

            for (Room mergedRoom : mergedRooms) {

                if (!mainRoom.canBeMergedWith(mergedRoom)) {

                    throw new RoomsCannotBeMergedException(

                        mainRoom.getName(), mergedRoom.getName()

                    );

                }

                if (mergedRoom.getIsPremium() &amp;&amp; !currentUser.getCanBookPremium()) {

                    throw new InsufficientPermissionsException(

                        "Cannot book premium room: " + mergedRoom.getName()

                    );

                }

            }

            roomsToBook.addAll(mergedRooms);

        }

        // Sprawdź konflikty dla wszystkich sal

        for (Room room : roomsToBook) {

            List&lt;Booking> conflicts = bookingRepository

                .findConflictingBookings(

                    room.getId(),

                    dto.getStartTime(),

                    dto.getEndTime()

                );

            if (!conflicts.isEmpty()) {

                throw new RoomNotAvailableException(

                    room.getName(),

                    dto.getStartTime(),

                    dto.getEndTime()

                );

            }

        }

        // Twórz rezerwację

        Booking booking = Booking.builder()

            .room(mainRoom)

            .user(currentUser)

            .startTime(dto.getStartTime())

            .endTime(dto.getEndTime())

            .status(BookingStatus.ACTIVE)

            .mergedRooms(roomsToBook.stream()

                .filter(r -> !r.equals(mainRoom))

                .collect(Collectors.toSet()))

            .build();

        return bookingRepository.save(booking);

    }

}</pre>



<h3 class="wp-block-heading"><a></a>Przykład 3: Endpoint z cache’owaniem</h3>



<p><em>&#8222;Stwórz RoomController z endpointami: GET /rooms &#8211; z filtrowaniem po floor, capacity, equipment GET /rooms/available?start=&amp;end= &#8211; dostępne w czasie Dodaj @Cacheable dla GET /rooms.&#8221;</em></p>



<p>Claude Code wygenerował:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@RestController

@RequestMapping("/api/rooms")

@RequiredArgsConstructor

@Slf4j

public class RoomController {

    private final RoomService roomService;

    private final RoomAvailabilityService availabilityService;

    @GetMapping

    @Cacheable(value = "rooms", key = "#floor + '_' + #minCapacity + '_' + #equipment")

    public ResponseEntity&lt;List&lt;RoomDto>> getRooms(

            @RequestParam(required = false) Integer floor,

            @RequestParam(required = false) Integer minCapacity,

            @RequestParam(required = false) String equipment) {

        log.debug("Fetching rooms with filters - floor: {}, capacity: {}, equipment: {}",

                  floor, minCapacity, equipment);

        List&lt;Room> rooms = roomService.findRooms(floor, minCapacity, equipment);

        return ResponseEntity.ok(

            rooms.stream()

                .map(RoomMapper::toDto)

                .collect(Collectors.toList())

        );

    }

    @GetMapping("/available")

    public ResponseEntity&lt;List&lt;AvailableRoomDto>> getAvailableRooms(

            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime start,

            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime end,

            @RequestParam(required = false) Integer minCapacity,

            @RequestParam(required = false) Boolean includeMergeable) {

        if (end.isBefore(start)) {

            throw new ValidationException("End time must be after start time");

        }

        if (Duration.between(start, end).toHours() > 24) {

            throw new ValidationException("Cannot check availability for more than 24 hours");

        }

        List&lt;AvailableRoomDto> availableRooms = availabilityService

            .findAvailableRooms(start, end, minCapacity, includeMergeable);

        return ResponseEntity.ok(availableRooms);

    }

}</pre>



<h3 class="wp-block-heading"><a></a>Demo modułu frontend przygotowane przez AI</h3>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1206" height="797" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic15.png" alt="claude code agent ai" class="wp-image-37535" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 23" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic15.png 1206w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic15-300x198.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic15-768x508.png 768w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic15-495x327.png 495w" sizes="auto, (max-width: 1206px) 100vw, 1206px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="620" height="618" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic16.png" alt="claude code agent ai" class="wp-image-37538" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 24" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic16.png 620w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic16-300x300.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic16-150x150.png 150w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic16-396x395.png 396w" sizes="auto, (max-width: 620px) 100vw, 620px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1193" height="430" src="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic17.png" alt="claude code agent ai" class="wp-image-37541" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 25" srcset="https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic17.png 1193w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic17-300x108.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic17-768x277.png 768w, https://nearshore-it.eu/wp-content/uploads/2025/08/nearshore_2025.07.25_graphic17-495x178.png 495w" sizes="auto, (max-width: 1193px) 100vw, 1193px" /></figure>



<h3 class="wp-block-heading"><a></a>Podsumowanie implementacji</h3>



<p>Ogromna ilość czasu została zaoszczędzona przy zaledwie trzech zadaniach. Przy 23 zadaniach dla całego MVP, oszczędności mogą sięgać dni. Co warto dodać: kod był spójny, przetestowany i zawierał obsługę przypadków brzegowych.</p>



<h2 class="wp-block-heading" id="Jak-kodować?-3-praktyczne-porady-na-start">Jak kodować? 3 praktyczne porady na start</h2>



<p>Po miesiącu pracy z Claude Code, zebrałem kilka porad, które mogą pomóc efektywnie pracować z tym narzędziem.</p>



<h3 class="wp-block-heading"><a></a>1. Zacznij od małych, dobrze zdefiniowanych zadań</h3>



<p>Nie powinniśmy rozwiązywać złożonych problemów pojedynczym promptem. Claude Code działa świetnie, gdy dajemy mu konkretne zadania.</p>



<p><strong>Źle:</strong></p>



<p><em>&#8222;stwórz cały system logowania z rejestracją i resetowaniem hasła&#8221;</em></p>



<p><strong>Dobrze:</strong></p>



<p><em>&#8222;stwórz model User z bcrypt hashowaniem hasła&#8221;</em></p>



<p><em>&#8222;dodaj endpoint POST /auth/register z walidacją email&#8221;</em></p>



<p><em>&#8222;zaimplementuj JWT token generation w Spring Security&#8221;</em></p>



<p>Mniejsze zadania = bardziej przewidywalny i testowalny kod. Łatwiej też zlokalizować ewentualne problemy i zrozumieć, co dokładnie robi wygenerowany kod.</p>



<h3 class="wp-block-heading"><a></a>2. Zawsze sprawdzaj kod, który stworzy AI</h3>



<p>Claude Code generuje imponujący kod, ale to wciąż twoja odpowiedzialność jako dewelopera, aby sprawdzić poprawność&nbsp;tego kodu.</p>



<p>Co powinieneś sprawdzić:</p>



<ul class="wp-block-list">
<li>Czy kod kompiluje się bez błędów?</li>



<li>Czy nazewnictwo jest zgodne z konwencjami projektu?</li>



<li>Czy obsłużone są podstawowe edge case&#8217;y?</li>



<li>Czy nie ma wartości na stałe zapisanych w kodzie<a>?</a></li>



<li>Czy logi są na odpowiednim poziomie (debug/info/error)?</li>
</ul>



<p><strong>Pro tip:</strong> Skonfiguruj swoje IDE, żeby automatycznie formatowało kod według twoich standardów.</p>



<h3 class="wp-block-heading">Wykorzystuj kontekst projektu: Claude Code zna twój kod</h3>



<p>Ogromną przewagą nad innymi narzędziami AI w Claude Code jest to, że rozumie kontekst projektu.</p>



<p>Zamiast takiego prompta:</p>



<p><em>&#8222;napisz metodę do obliczania ceny z VAT używając BigDecimal&#8221;</em></p>



<p>Możesz bezpośrednio odnieść&nbsp;się&nbsp;do projektu:</p>



<p><em>&#8222;dodaj metodę calculatePriceWithVat do PriceService, która używa tej samej logiki co calculateDiscount&#8221;</em></p>



<p>Claude Code automatycznie:</p>



<ul class="wp-block-list">
<li>Sprawdzi, jak wygląda PriceService</li>



<li>Użyje tych samych konwencji nazewnictwa</li>



<li>Zastosuje podobny styl obsługi błędów</li>



<li>Doda odpowiednie importy</li>
</ul>



<p><strong>Pro tip:</strong> po wykonaniu komendy /init możesz odwoływać się do dowolnych plików i klas w projekcie. Claude Code &#8222;pamięta&#8221; strukturę i może naśladować istniejące wzorce.</p>



<p>Pamiętaj, Claude Code to narzędzie, nie zamiennik dla myślenia. Im lepiej zdefiniujesz problem, tym lepsze dostaniesz rozwiązanie.</p>



<p><strong>Przeczytaj także:</strong></p>



<ul class="wp-block-list">
<li><strong><a href="https://nearshore-it.eu/pl/artykuly/zod-ai-schema-validation/"> Zod AI</a></strong></li>
</ul>



<h2 class="wp-block-heading">Sztuczna inteligencja w programowaniu: podsumowanie</h2>



<p>Mam nadzieję, że ten wpis pokazał możliwości, jakie oferuje Claude Code w codziennej pracy developera. Ale to, co opisałem, to zaledwie ułamek potencjału tego narzędzia.</p>



<h3 class="wp-block-heading"><a></a>Zaawansowane możliwości Claude Code, które warto eksplorować</h3>



<p>Claude Code to potężne narzędzie, które skrywa znacznie więcej zaawansowanych funkcjimogących &nbsp;mogą zrewolucjonizować Twój workflow:</p>



<p><strong>Sub-agenci:</strong> możliwość delegowania zadań do wyspecjalizowanych &#8222;pod-agentów&#8221;. Na przykład: jeden agent analizuje wymagania, drugi projektuje architekturę, trzeci implementuje kod. Każdy z nich może mieć własny kontekst i specjalizację.</p>



<p><strong>Model Context Protocol (MCP):</strong> otwarty protokół pozwalający Claude Code integrować się z zewnętrznymi narzędziami i źródłami danych. Możesz podłączyć własne API, bazy danych czy systemy firmowe, dając AI dostęp do aktualnych danych projektu.</p>



<p><strong>Autonomiczne debugowanie:</strong> Claude Code może samodzielnie analizować błędy, testować hipotezy i proponować poprawki. Wystarczy wskazać mu niedziałający test lub stack trace. Claude samodzielnie uruchomi test i przeanalizuje, co jest nie tak.</p>



<h3 class="wp-block-heading"><a></a>Chcesz wypróbować Claude Code?</h3>



<p>Jeśli zainteresował cię ten wpis, możesz rozpocząć swoją przygodę z Claude Code już dziś. Narzędzie jest obecnie dostępne w wersji research preview &#8211; więcej informacji znajdziesz na<a href="https://www.anthropic.com/claude" target="_blank" rel="noopener"> </a><a href="https://www.anthropic.com/claude" target="_blank" rel="noopener">blogu Anthropic</a>.</p>



<h3 class="wp-block-heading"><a></a>Na zakończenie</h3>



<p>Claude Code to dopiero początek rewolucji w sposobie, w jaki tworzymy oprogramowanie. To narzędzie, które już dziś pozwala ogromnie przyspieszyć development, zachowując przy tym wysoką jakość kodu.</p>



<p>Pamiętaj jednak: to wciąż narzędzie, nie zamiennik dla dewelopera. Największą wartość uzyskasz, łącząc możliwości AI z ludzką kreatywnością, zrozumieniem kontekstu biznesowego i umiejętnością podejmowania strategicznych decyzji.</p>



<p>Czy za kilka lat będziemy programować zupełnie inaczej? Wszystko na to wskazuje. Pytanie brzmi: czy będziesz wśród tych, którzy wykorzystają tę zmianę, czy tych, którzy są wobec niej sceptyczni?</p>



<p><a id="_msocom_1"></a></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><br></style><div class="promotion-box promotion-box--image-left "><div class="tiles latest-news-once"><div class="tile"><div class="tile-image"><img decoding="async" src="https://nearshore-it.eu/wp-content/uploads/2025/02/Code-Faster-Tlo-2.jpg" alt="Code Faster Tlo 2" title="Programowanie z AI: Od wymagań klienta do działającej aplikacji z Claude Code od Antrophic 26"></div><div class="tile-content"><p class="entry-title client-name">AI w programowaniu | bezpłatny e-book</p>
Zautomatyzuj kodowanie z AI! Pobierz darmowy e-book i odkryj nowe możliwości
<br /><br />
<a class="btn btn-primary" href="https://www.engage.inetum.com/ebook-code-faster-build-smarter/" target="_blank" rel="noopener">Pobierz teraz!</a></div></div></div></div></td></tr></tbody></table></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/programowanie-ai-claude-code/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Zod &#038; AI – schema validation w projektach AI – przewodnik TypeScript </title>
		<link>https://nearshore-it.eu/pl/artykuly/zod-ai-schema-validation/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/zod-ai-schema-validation/#respond</comments>
		
		<dc:creator><![CDATA[Mateusz Jerzyk]]></dc:creator>
		<pubDate>Wed, 28 May 2025 15:11:11 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=37201</guid>

					<description><![CDATA[W pracy z AI największym wyzwaniem jest często… samo AI. Modele generują dane w różnym formacie, czasem brakuje klucza, czasem typ się nie zgadza – a nasz projekt musi cały czas działać bezbłędnie. Wystarczy drobna zmiana prompta, nowa wersja modelu albo niespodziewany fallback, by struktura danych zaczęła robić problemy w najmniej oczekiwanym momencie.  ]]></description>
										<content:encoded><![CDATA[
<div class="table-of-contents">
    <p class="title">Przejdź do:</p>
    <ol>
                    <li><a href="#Biblioteka-Zod">1.  Biblioteka Zod</a></li>
                    <li><a href="#Czym-jest-walidacja-danych-Zod">2.  Czym jest walidacja danych Zod i dlaczego jest tak ważna?  </a></li>
                    <li><a href="#Jak-używać-Zod-w-aplikacjach-opartych-na-AI?">3.  Jak używać Zod w aplikacjach opartych na AI? </a></li>
                    <li><a href="#Zastosowanie-Zod-w-preprocessingu-danych">4.  Zastosowanie Zod w preprocessingu danych  </a></li>
                    <li><a href="#Jak-Zod-usprawnia-deployment-modeli-AI?">5.  Jak Zod usprawnia deployment modeli AI?  </a></li>
                    <li><a href="#Kluczowe-cechy-Zod-w-JavaScript">6.  Kluczowe cechy Zod w JavaScript  </a></li>
                    <li><a href="#Jak-zaimplementować-walidację-formularza-z-użyciem-Zod?">7.  Jak zaimplementować walidację formularza z użyciem Zod?  </a></li>
            </ol>
</div>


<h2 class="wp-block-heading" id="Biblioteka-Zod"><strong>Biblioteka Zod</strong>&nbsp;</h2>



<p>I właśnie tutaj dobrym rozwiązaniem jest Zod: lekka, szybka biblioteka do walidacji danych dla TypeScript, która pozwala jasno określić, jakich struktur oczekujemy od inputu. Zamiast zgadywać, czy odpowiedź będzie zgodna z oczekiwaniami, po prostu ją walidujemy. Jeśli coś się nie zgadza – dostajemy informację o błędzie i jasny komunikat. Jeśli wszystko gra – możemy bezpiecznie przetwarzać dane dalej. Mamy nad wszystkim kontrolę, jeszcze zanim przekażemy dalej dane do naszej logiki biznesowej.&nbsp;&nbsp;</p>



<p>Zod działa jak filtr bezpieczeństwa – pozwala odrzucić błędne odpowiedzi, zanim trafią do logiki aplikacji. Dzięki temu zyskujemy nie tylko większą kontrolę, ale też spokój ducha: <strong>nawet jeśli AI trochę „zbłądzi”, warstwa frontend to odpowiednio obsłuży i tego nie odczuje.&nbsp;&nbsp;</strong></p>



<h2 class="wp-block-heading" id="Czym-jest-walidacja-danych-Zod"><strong>Czym jest walidacja danych Zod i dlaczego jest tak ważna?&nbsp;</strong>&nbsp;</h2>



<p>Zod to biblioteka TypeScript / JavaScript, która umożliwia tworzenie schematów danych (schemas), wykorzystywanych zarówno do walidacji danych w czasie rzeczywistym, jak i do generowania typów w czasie kompilacji. Dzięki niej możemy opisać strukturę danych, której aplikacja oczekuje, i automatycznie sprawdzić, czy rzeczywiste dane, które przekazaliśmy do inputu spełniają wszystkie nasze założenia.&nbsp;&nbsp;</p>



<p>W kontekście AI – gdzie dane zwracane przez modele bywają nieprzewidywalne i często nie trzymają się jednej struktury, <strong>walidacja staje się wręcz obowiązkowa. </strong>Nawet drobna zmiana w odpowiedzi modelu może wywołać błąd w aplikacji, jeśli nasz kod zakłada konkretną strukturę danych. Zod pozwala temu zapobiec, sprawdzając zgodność danych, zanim trafią dalej do logiki biznesowej.&nbsp;&nbsp;</p>



<p><strong>Przeczytaj także:</strong></p>



<ul class="wp-block-list">
<li><a href="https://nearshore-it.eu/pl/artykuly/najlepsze-ai-for-coding-w-2025-roku-czego-uzywac-do-generowania-kodu/" data-type="post" data-id="34778">Najlepsze AI for coding</a></li>



<li><a href="https://nearshore-it.eu/pl/artykuly/github-copilot-asystent-ai/" data-type="post" data-id="34871">AI w programowaniu: Github Copilot </a></li>
</ul>



<p></p>



<h2 class="wp-block-heading" id="Jak-używać-Zod-w-aplikacjach-opartych-na-AI?-"><strong>Jak używać Zod w aplikacjach opartych na AI? </strong><strong>(validation in AI with Zod)</strong>&nbsp;</h2>



<p>Zod można zintegrować z dowolną aplikacją JavaScript, zarówno po stronie frontendu, jak i backendu. W kontekście AI najczęściej wykorzystywany jest do:&nbsp;&nbsp;</p>



<ul class="wp-block-list">
<li>walidacji odpowiedzi z API (np. OpenAI),&nbsp;&nbsp;</li>



<li>generowania interfejsów dynamicznych,&nbsp;&nbsp;</li>



<li>utrzymywania spójnych kontraktów danych między frontendem a modelem.&nbsp;&nbsp;</li>
</ul>



<p>Dzięki helperowi zodResponseFormat w SDK OpenAI możemy łatwo powiązać schemat Zod z odpowiedzią modelu:&nbsp;&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const MathResponse = z.object({
  steps: z.array(z.object({
    explanation: z.string(),
    output: z.string(),
  })),
  final_answer: z.string(),
});

const completion = await client.beta.chat.completions.parse({
  model: 'gpt-4o',
  messages: [...],
  response_format: zodResponseFormat(MathResponse, 'math_response'),
});
</pre>



<p>Taka integracja sprawia, że odpowiedź modelu jest walidowana automatycznie i możemy bezpiecznie korzystać z jej zawartości w aplikacji.&nbsp;&nbsp;</p>



<p>Jeśli korzystamy z funkcji narzędzi (tool calls), możemy użyć zodFunction, by automatycznie zmapować argumenty na typy Zod:&nbsp;&nbsp;</p>



<p></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const queryArgs = z.object({ ... });

const completion = await client.beta.chat.completions.parse({
  model: 'gpt-4o',
  messages: [...],
  tools: [zodFunction({ name: 'query', parameters: QueryArgs })],
});
</pre>



<p>Zod daje nam kontrolę nad strukturą danych – zarówno tych zwracanych przez model, jak i tych przekazywanych do funkcji. Dzięki temu unikamy błędów wynikających z niespójności formatu i mamy większą przewidywalność działania aplikacji.&nbsp;&nbsp;</p>



<h2 class="wp-block-heading" id="Zastosowanie-Zod-w-preprocessingu-danych"><strong>Zastosowanie Zod w preprocessingu danych&nbsp;</strong>&nbsp;</h2>



<p>Zod sprawdza się nie tylko po stronie odbioru danych z modelu AI, ale również wcześniej – podczas przygotowania danych wejściowych. Preprocessing to moment, w którym możemy upewnić się, że to, co wysyłamy do modelu, jest kompletne, poprawnie sformatowane i zgodne z oczekiwanym typem.&nbsp;&nbsp;</p>



<h3 class="wp-block-heading">Typowe zastosowania Zod w preprocessingu:&nbsp;&nbsp;</h3>



<ul class="wp-block-list">
<li>walidacja danych wprowadzanych przez użytkownika przed wysłaniem zapytania do AI,&nbsp;&nbsp;</li>



<li>konwersja typów, np. zamiana ciągów znaków (stringa) na daty,&nbsp;&nbsp;</li>



<li>czyszczenie i porządkowanie danych z zewnętrznych źródeł, jak API czy formularze.&nbsp;&nbsp;</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const dateSchema = z.string().transform(str => new Date(str));
const parsedDate = dateSchema.parse("2024-08-06"); // => obiekt typu Date
</pre>



<p>Dzięki funkcji <strong>.transform()</strong> możemy nie tylko sprawdzić, czy dane mają odpowiedni format, ale też przekształcić wprowadzone dane do postaci, która jest odpowiednio dostosowana do dalszego przetwarzania w aplikacji. To szczególnie przydatne, gdy dane mają służyć jako prompt lub parametr w zapytaniu do modelu AI.&nbsp;&nbsp;</p>



<p>Preprocessing z użyciem Zod to prosty sposób na zminimalizowanie błędów i zwiększenie kontroli nad danymi, zanim jeszcze trafią do modelu.&nbsp;&nbsp;</p>



<h2 class="wp-block-heading" id="Jak-Zod-usprawnia-deployment-modeli-AI?"><strong>Jak Zod usprawnia deployment modeli AI?&nbsp;</strong>&nbsp;</h2>



<p>Zod to nie tylko narzędzie deweloperskie – jego zastosowanie ma realne przełożenie na jakość wdrożeń modeli AI w środowiskach produkcyjnych. Pozwala budować solidny bufor bezpieczeństwa pomiędzy często nieprzewidywalnym modelem AI a wymaganiami naszej aplikacji.&nbsp;&nbsp;</p>



<h3 class="wp-block-heading">Biblioteka Zod w procesie deploymentu pomaga:&nbsp;&nbsp;</h3>



<ul class="wp-block-list">
<li>Zwiększyć odporność aplikacji na zmiany – zmiana prompta, wersji modelu czy struktury danych nie musi oznaczać błędów, jeśli dane przechodzą przez schematy walidacyjne tworzone przez Zoda.&nbsp;&nbsp;</li>



<li>Szybciej debugować problemy – zamiast domyślać się, co poszło nie tak, dostajemy jasne, czytelne komunikaty o błędach.&nbsp;&nbsp;</li>



<li>Pisać testy jednostkowe – schematy Zod mogą pełnić funkcję walidatorów i źródła przykładowych danych wejściowych do testów.&nbsp;&nbsp;</li>
</ul>



<p>Zamiast więc opierać się na założeniu, że wszystko w końcowej fazie projektu działa, możemy zbudować system, który rzeczywiście przewiduje błędy i potrafi się przed nimi obronić.&nbsp;&nbsp;</p>



<p>Z perspektywy wdrożeniowej oznacza to mniej awarii, większą spójność danych i łatwiejsze utrzymanie całego pipeline’u – od prompta po końcowy interfejs użytkownika.&nbsp;&nbsp;</p>



<h2 class="wp-block-heading" id="Kluczowe-cechy-Zod-w-JavaScript"><strong>Kluczowe cechy Zod w JavaScript&nbsp;</strong>&nbsp;</h2>



<p>Zod oferuje nowoczesne podejście do walidacji danych w JavaScript i TypeScript. Jego główne zalety to:&nbsp;&nbsp;</p>



<ul class="wp-block-list">
<li>Deklaratywność – schematy są czytelne, przejrzyste i proste do napisania. Możemy z łatwością tworzyć złożone struktury bez nadmiaru kodu.&nbsp;&nbsp;</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const UserSchema = z.object({
  name: z.string().min(3),
  age: z.number().int().positive(),
  email: z.string().email(),
});
</pre>



<ul class="wp-block-list">
<li>Bezpośrednia integracja z TypeScriptem – Zod automatycznie wyciąga typy z definicji schematów (z.infer), dzięki czemu nie musimy pisać typów dwa razy.&nbsp;&nbsp;</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">type User = z.infer&lt;typeof UserSchema>;</pre>



<ul class="wp-block-list">
<li>Walidacja i transformacja w jednym miejscu – możemy nie tylko sprawdzać dane, ale też odpowiednio je przekształcać (np. string → Date, liczba → boolean, itp.).&nbsp;&nbsp;</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const DateSchema = z.string().transform(str => new Date(str));
const parsedDate = DateSchema.parse("2024-08-06");
</pre>



<ul class="wp-block-list">
<li>Obsługa błędów – metody safeParse i parse pozwalają wygodnie obsługiwać błędy. Pierwsza nie rzuca wyjątku, a druga daje pełną kontrolę nad błędami typu ZodError.&nbsp;&nbsp;</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const result = UserSchema.safeParse(userData);
if (!result.success) {
  console.log(result.error.format());
}
</pre>



<ul class="wp-block-list">
<li>Czytelne komunikaty walidacyjne – błędy można formatować, w pełni kontrolować, mapować i wyświetlać w aplikacjach frontendowych w sposób przyjazny dla użytkownika.&nbsp;&nbsp;</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">function formatZodErrors(error: z.ZodError) {
  return error.errors.reduce((acc, err) => {
    const field = err.path.join(".");
    acc[field] = err.message;
    return acc;
  }, {} as Record&lt;string, string>);
}
</pre>



<ul class="wp-block-list">
<li>Rozszerzalność – dzięki metodzie <strong>.refine()</strong> możemy łatwo dodawać własne warunki i logikę walidacyjną.&nbsp;&nbsp;</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const PasswordSchema = z.string()
  .min(8, "Hasło musi mieć min. 8 znaków")
  .refine(val => /\d/.test(val), {
    message: "Hasło musi zawierać cyfrę",
  });
</pre>



<ul class="wp-block-list">
<li>Chaining – możemy łączyć wiele reguł walidacyjnych w łańcuchach co ułatwia tworzenie złożonych walidacji, np. <strong>.min(3).max(20).regex(&#8230;),.&nbsp;</strong>&nbsp;</li>
</ul>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const NameSchema = z.string()
  .min(3, "Za krótkie")
  .max(50, "Za długie")
  .regex(/^[a-zA-Z\s]+$/, "Tylko litery i spacje");

</pre>



<ul class="wp-block-list">
<li>Użyteczność w całym stacku – Zod sprawdza się zarówno walidacji danych użytkownika w formularzach (React Hook Form), jak i walidacji odpowiedzi API czy typów w bazach danych&nbsp;&nbsp;</li>
</ul>



<h2 class="wp-block-heading" id="Jak-zaimplementować-walidację-formularza-z-użyciem-Zod?"><strong>Jak zaimplementować walidację formularza z użyciem Zod?&nbsp;</strong>&nbsp;</h2>



<p>Zod doskonale integruje się z popularnymi narzędziami do obsługi formularzy, takimi jak React Hook Form. Dzięki temu możemy w prosty sposób połączyć walidację danych z typowaniem w TypeScript i uzyskać czytelny kod oraz spójne komunikaty błędów.&nbsp;&nbsp;</p>



<p>Załóżmy, że tworzymy prosty formularz rejestracyjny. Najpierw definiujemy schema:&nbsp;&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const RegisterSchema = z.object({
  name: z.string().min(3, "Imię musi mieć co najmniej 3 znaki"),
  email: z.string().email("Niepoprawny adres e-mail"),
  password: z.string()
    .min(8, "Hasło musi mieć co najmniej 8 znaków")
    .refine(val => /\d/.test(val), {
      message: "Hasło musi zawierać cyfrę",
    }),
});
</pre>



<p>Następnie łączymy schema z formularzem:&nbsp;&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';

const form = useForm({
  resolver: zodResolver(RegisterSchema),
});

const { register, handleSubmit, formState: { errors } } = form;
</pre>



<p>W JSX podpinamy pola i wyświetlamy błędy:&nbsp;&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;form onSubmit={handleSubmit(formDetails => console.log(formDetails))}>
  &lt;input {...register("name")} placeholder="Imię" />
  {errors.name &amp;&amp; &lt;p>{errors.name.message}&lt;/p>}

  &lt;input {...register("email")} placeholder="Email" />
  {errors.email &amp;&amp; &lt;p>{errors.email.message}&lt;/p>}

  &lt;input {...register("password")} placeholder="Hasło" type="password" />
  {errors.password &amp;&amp; &lt;p>{errors.password.message}&lt;/p>}

  &lt;button type="submit">Zarejestruj się&lt;/button>
&lt;/form>
</pre>



<p>Taka integracja daje nam:&nbsp;&nbsp;</p>



<ul class="wp-block-list">
<li>automatyczną walidację pól,&nbsp;&nbsp;</li>



<li>pełne typowanie danych,&nbsp;&nbsp;</li>



<li>spójne i konfigurowalne komunikaty błędów,&nbsp;&nbsp;</li>



<li>prostą integrację z istniejącym kodem Reacta.&nbsp;&nbsp;</li>
</ul>



</style><div class="promotion-box promotion-box--image-left "><div class="tiles latest-news-once"><div class="tile"><div class="tile-image"><img decoding="async" src="https://nearshore-it.eu/wp-content/uploads/2025/02/Code-Faster-Tlo-2.jpg" alt="Code Faster Tlo 2" title="Zod &amp; AI – schema validation w projektach AI – przewodnik TypeScript  27"></div><div class="tile-content"><p class="entry-title client-name">AI w programowaniu | bezpłatny e-book</p>
Zautomatyzuj kodowanie z AI! Pobierz darmowy e-book i odkryj nowe możliwości
<br /><br />
<a class="btn btn-primary" href="https://www.engage.inetum.com/ebook-code-faster-build-smarter/" target="_blank" rel="noopener">Pobierz teraz!</a></div></div></div></div>



<h2 class="wp-block-heading"><strong>Podsumowanie&nbsp;</strong>&nbsp;</h2>



<p>W świecie, gdzie <strong>dane generowane przez AI są dynamiczne i często nieprzewidywalne, </strong>warto zadbać o silne fundamenty naszych projektów. Zod może pełnić rolę warstwy ochronnej – zapewniając <strong>walidację, transformację i typowanie danych </strong>w jednym miejscu. To nie tylko techniczny dodatek, ale kluczowy element architektury, który pozwala budować odporne, stabilne i łatwe w utrzymaniu integrację z modelami AI.&nbsp;&nbsp;</p>



<p>Zod to solidna biblioteka z rosnącą społecznością i aktywnym wsparciem, którą z powodzeniem można wykorzystać nie tylko w integracjach z wykorzystaniem AI, ale także w codziennych projektach frontendowych – od formularzy po obsługę API.&nbsp;&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/zod-ai-schema-validation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AI w programowaniu – jak sztuczna inteligencja wspomaga automatyzację? </title>
		<link>https://nearshore-it.eu/pl/artykuly/ai-w-programowaniu-automatyzacja/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/ai-w-programowaniu-automatyzacja/#respond</comments>
		
		<dc:creator><![CDATA[Mateusz Mirecki]]></dc:creator>
		<pubDate>Mon, 14 Apr 2025 12:36:25 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=34914</guid>

					<description><![CDATA[Temat sztucznej inteligencji od dawna rozpala ludzką wyobraźnię, stając się obiektem fascynacji oraz źródłem pytań o granice ludzkiego poznania. Jednym z przykładów niech będzie książka autorstwa Stanisława Lema – “Golem XIV”, w której przedstawia on wizję hiperrozwiniętej AI, przewyższającej człowieka pod względem intelektualnym i filozoficznym. ]]></description>
										<content:encoded><![CDATA[
<p></p>



<p>I choć treść książki ma pesymistyczne wybrzmienie, może stanowić źródło inspiracji na temat drogi rozwoju sztucznej inteligencji w dalekiej przyszłości i zmusić do refleksji nad kierunkiem podążania przez współczesne algorytmy. Chociaż obecne możliwości AI nie są jeszcze aż tak rozwinięte (w porównaniu do przytoczonego Golema), to już mają istotny wpływ na cyfrową transformację, przekształcając świat na wielu płaszczyznach.&nbsp;</p>



<div class="table-of-contents">
    <p class="title">Go to:</p>
    <ol>
                    <li><a href="#AI-w-programowaniu">1.  AI w programowaniu  </a></li>
                    <li><a href="#korzyści-z-użycia-AI-w-procesie-tworzenia-oprogramowania">2.  Korzyści z użycia AI w procesie tworzenia oprogramowania </a></li>
                    <li><a href="#AI-w-praktyce-Tworzymy-prompty-do-testowania">3.  Tworzymy prompty do testowania</a></li>
                    <li><a href="#sztuczna-inteligencja-w-testach">4.  Sztuczna inteligencja w testach</a></li>
                    <li><a href="#najlepsze-narzędzia-AI-dla-programistów-i-testerów">5.  Najlepsze narzędzia AI dla programistów i testerów </a></li>
            </ol>
</div>


<h2 class="wp-block-heading" id="AI-w-programowaniu-">AI w programowaniu&nbsp;&nbsp;</h2>



<h3 class="wp-block-heading">Generowanie kodu&nbsp;&nbsp;</h3>



<p>Od jakiegoś czasu narzędzia sztucznej inteligencji rewolucjonizują wiele obszarów, nie pomijając procesu tworzenia oprogramowania. Wprowadzają nowe możliwości zwiększające nie tylko produktywność, ale też dokładność i innowacyjność, przyspieszają również sam proces tworzenia oprogramowania. W tym momencie należy wyróżnić przede wszystkim generatywną sztuczną inteligencję (GenAI – uogólniając, to AI potrafiąca tworzyć nowe treści), która usprawnia cały proces poprzez automatyzację istotnych kroków – generowania pomysłów, gromadzenia wymagań, a także kodowania oraz jego nieodłącznego procesu testowania.&nbsp;</p>



<h3 class="wp-block-heading">Wsparcie prac programistycznych&nbsp;</h3>



<p>AI szybko staje się integralną częścią oprogramowania wykorzystywanego w developmencie aplikacji, będąc jednym z elementów cyfrowej transformacji przedsiębiorstw. Zespoły deweloperskie dostosowują swoje środowiska, integrując narzędzia sztucznej inteligencji, zapewniając nie tylko interoperacyjność, ale również stawiają czoła nowym wyzwaniom, jak choćby bezpieczeństwo danych. Rosnąca rola AI w tym obszarze podkreśla jej potencjał do zrewolucjonizowania metod tworzenia oprogramowania.&nbsp;</p>



<h3 class="wp-block-heading">Wykorzystanie algorytmów w automatyzacji&nbsp;</h3>



<p>Obecnie mamy do dyspozycji wiele narzędzi, za pomocą których znacząco można przyspieszyć prace nad projektem. Interpretują opisy tworzone w języku naturalnym (prompty) i generują sugestie, kod, zasoby potrzebne do testów i wiele innych, przydatnych rzeczy – zależnie od potrzeb. Zaawansowane algorytmy analizują środowisko, kod, optymalizując rozwiązania i wspomagając zespoły w codziennej pracy. Umożliwiają również analizę ogromnych zbiorów danych, wspierając optymalizację wydajności aplikacji oraz przewidywanie potencjalnych problemów. Ma to znaczący wpływ na szybkość tworzenia kodu, redukcję ludzkich błędów, przyczynia się do poprawy bezpieczeństwa, a przede wszystkim pozwala programistom skupić się na realizowaniu bardziej złożonych i kreatywnych zadań.&nbsp;</p>



<h2 class="wp-block-heading" id="korzyści-z-użycia-AI-w-procesie-tworzenia-oprogramowania-">Jakie są korzyści z użycia AI w procesie tworzenia oprogramowania&nbsp;</h2>



<p>Korzyści w ujęciu ogólnym przedstawiłem we wstępie, więc w tej sekcji postaram się zwięźle opisać kilka konkretnych przykładów, które moim zdaniem zasługują na szczególną uwagę:&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Przewidywanie błędów</strong> – poprzez analizę wzorców w repozytoriach projektu narzędzia AI mogą pomóc wykryć potencjalne błędy, luki lub podatności.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Testowanie</strong> – odpowiednio przygotowane wymagania i kryteria akceptacji mogą posłużyć za bazę do stworzenia scenariuszy testowych, dzięki czemu znacznie skraca się czas, potrzebny zwykle na wymyślanie ich od podstaw. W asyście AI można także pokusić się o refaktoryzację już istniejących przypadków testowych, co może pomóc w ich optymalizacji i zwiększeniu pokrycia testów.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Generowanie kodu</strong> – dzięki narzędziom AI programiści mają możliwość korzystania z pomocy wirtualnego asystenta, który wspomaga ich w codziennej pracy. Na podstawie danych wejściowych pisanych w języku naturalnym, asystent AI zasugeruje fragment kodu lub wygeneruje całą funkcję, co przyspiesza pracę i może automatyzować rutynowe działania (np. pisanie prostych, schematycznych skryptów). <br></li>



<li><strong>Optymalizacja i refaktoryzacja</strong> – łączy się z powyższym. Z pomocą AI można optymalizować istniejący kod, dzięki czemu aplikacja może być stabilniejsza, bezpieczniejsza, wydajniejsza, a więc i bardziej niezawodna.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Bezpieczeństwo</strong> – z pomocą narzędzi AI można pokusić się o próbę zidentyfikowania potencjalnych luk bezpieczeństwa, a w przypadku ich znalezienia – AI zasugeruje poprawki. Narzędzia te pozwalają również analizować zachowanie uzytkowników i wykrywać nietypowe działania, wskazujące na przykład na próby ataku lub potencjalne przejęcie konta klienta. &nbsp;<br>&nbsp;<br>Tak działa na przykład <a href="https://bank.pl/plebiscyt-bity-2021-pierwsze-miejsce-dla-weryfikacji-behawioralnej-z-systemu-moje-ing/)" target="_blank" rel="noreferrer noopener">weryfikacja behawioralna banku ING.</a> Algorytmy AI na bieżąco uczą się zachowania użytkownika poprzez analizowanie jego interakcji z aplikacją banku, co zwiększa prawdopodobieństwo zablokowania dostępu do konta w przypadku przejęcia go przez przestępcę. Innym przykładem niech będzie sytuacja <a href="https://www.forbes.com/sites/daveywinder/2024/11/05/google-claims-world-first-as-ai-finds-0-day-security-vulnerability/" target="_blank" rel="noreferrer noopener">opisana przez Google</a> –&nbsp; dzięki sztucznej inteligencji udało się znaleźć błąd 0-day (nieznana podatność lub luka, mogąca zostać wykorzystana do przeprowadzenia ataku). &nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Zarządzanie</strong> – można i w tym procesie zaprzęgnąć sztuczną inteligencję i wykorzystać ją w celu zautomatyzowania planowania i zarządzania zasobami. Mając historyczne dane, narzędzia AI mogą zasugerować potencjalny czas trwania nowych etapów tworzenia oprogramowania i pomóc w odpowiedniej alokacji zasobów w celu optymalnego ich wykorzystania.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Tworzenie dokumentacji</strong> – wielu programistów nie przepada za sporządzaniem dokumentacji. Jest to czasochłonny proces, który można by poświęcić między innymi na rozwój i utrzymanie kodu. I w tym aspekcie sztuczna inteligencja wyciąga pomocną dłoń – jest doskonałym narzędziem do prowadzenia dokumentacji projektowej, odciążając programistów. Na podstawie kodu aplikacji tworzy opis i zapewnia stałą aktualizację dokumentacji.&nbsp;&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Projektowanie UX</strong> – można wykorzystać AI do wspomagania projektowania doświadczenia użytkowników. Przykładowo – prowadząc testy A/B i wykorzystując dane z nich zgromadzone, AI może zasugerować odpowiedni interfejs bądź funkcjonalność. Odpowiednie polecenia w&nbsp; narzędziu AI generującym obrazy pomogą wygenerować szablon UI, mogący stanowić bazę pod ostateczny wygląd aplikacji.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Pomoc w tworzeniu bardziej inteligentnych aplikacji</strong> – wprowadzając zaawansowane funkcje AI do tworzonego programu (na przykład rozpoznawanie mowy, czat) można podnieść wartość i atrakcyjność aplikacji, dzięki czemu będzie ona wyróżniała się na tle konkurencji i może zwiększyć liczbę jej użytkowników.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Analiza danych użytkowników</strong> – AI może analizować dane użytkowników w celu poprawy doświadczeń podczas korzystania z aplikacji. Szczególne korzyści może przynieść to branży e-commerce, gdzie AI wspiera&nbsp; tworzenie algorytmów rekomendacji, dzięki czemu klienci mogą widzieć reklamy i sugestie produktów najbardziej pasujące do ich potrzeb.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Wspomaganie DevOps i CI/CD</strong> – z pomocą AI można analizować systemowe logi, raporty, historie wdrożeń, aby wykrywać anomalie i przewidywać potencjalne awarie. Narzędzia takie jak Datadog czy Splunk wykorzystują uczenie maszynowe do monitorowania aplikacji i infrastruktury w czasie rzeczywistym. Wdrożenie AI w <a href="https://nearshore-it.eu/pl/tag/devops/" data-type="post_tag" data-id="566">DevOps</a> i CI/CD pozwala zespołom programistycznym i operacyjnym na bardziej efektywne zarządzanie cyklem życia oprogramowania.&nbsp;</li>
</ul>



<h2 class="wp-block-heading" id="AI-w-praktyce?-Tworzymy-prompty-do-testowania">Jak korzystać z narzędzi AI w praktyce? Tworzymy prompty do testowania&nbsp;</h2>



<p>Poniżej zaprezentuję prosty przykład wykorzystania AI jako asystenta w programowaniu. Bazę stanowi kod Playwright dostępny bezpośrednio po zainstalowaniu narzędzia. Znajduje się w nim plik z przykładowymi testami, w którym utworzę jeden dodatkowy test z wykorzystaniem GitHub Copilot. Test jest prosty: polega na otwarciu strony domowej Playwright, kliknięciu przycisku<strong> ‘Get Started’ </strong>i asercji przekierowania na stronę <strong>&#8217;https://playwright.dev/docs/intro&#8217;</strong> poprzez zweryfikowanie poprawności adresu URL i tekstu wyświetlonego na niej nagłówka (Installation).&nbsp;</p>



<ol start="1" class="wp-block-list">
<li>Prompt opisujący test:&nbsp;</li>
</ol>



<p><strong>Write a test that navigates to 'https://playwright.dev/&#8217; page and clicks 'Get started&#8217; button. Then verify that user has landed on 'https://playwright.dev/docs/intro&#8217; page by verifying page header text that should be 'Installation&#8217;.</strong>&nbsp;</p>



<ol start="2" class="wp-block-list">
<li>Odpowiedź wygenerowana przez Copilot:&nbsp;</li>
</ol>



<p>Here’s the Playwright test that navigates to the 'https://playwright.dev/&#8217; page, clicks the 'Get started&#8217; button, and verifies that the user has landed on the 'https://playwright.dev/docs/intro&#8217; page by checking the page header text:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import { test, expect } from '@playwright/test'; 

test('navigate to Get Started and verify Installation page', async ({ page }) => { 

  // Navigate to the Playwright homepage 

  await page.goto('https://playwright.dev/'); 

  // Click the 'Get started' button 

  await page.getByRole('link', { name: 'Get started' }).click(); 

  // Verify the URL is correct 

  await expect(page).toHaveURL('https://playwright.dev/docs/intro'); 

  // Verify the page header text is 'Installation' 

  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); 

});</pre>



<p>Copilot stworzył test, dodatkowo opatrując komentarzem każdą znajdującą się w nim akcję. Poniżej zamieszczam zrzut ekreanu z VS Code, na którym widać UI z wykorzystaniem czatu AI.&nbsp;</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1937" height="1051" src="https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1.png" alt="ai w programowaniu " class="wp-image-34937" title="AI w programowaniu – jak sztuczna inteligencja wspomaga automatyzację?  28" srcset="https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1.png 1937w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1-300x163.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1-1296x703.png 1296w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1-768x417.png 768w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1-1536x833.png 1536w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1-495x269.png 495w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1-1320x716.png 1320w" sizes="auto, (max-width: 1937px) 100vw, 1937px" /></figure>



<p>Następnie poprosiłem Copilota o małą refaktoryzację stworzonego przez niego kodu – aby zaktualizował go poprzez przeniesienie hardkodowanych wartości do zmiennych w celu poprawy czytelności kodu.&nbsp;</p>



<p>&nbsp;<br>1. Prompt:&nbsp;&nbsp;</p>



<p><strong>Refactor the proposed code by moving hardcoded values to variables, in order to make the code more readable.</strong>&nbsp;</p>



<p>2. Odpowiedź:&nbsp;</p>



<p>Here’s the refactored code with hardcoded values moved to variables for better readability:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import { test, expect } from '@playwright/test'; 

test('navigate to Get Started and verify Installation page', async ({ page }) => { 

  // Define reusable variables 

  const baseUrl = 'https://playwright.dev/'; 

  const getStartedLinkName = 'Get started'; 

  const expectedUrl = 'https://playwright.dev/docs/intro'; 

  const expectedHeader = 'Installation'; 

  // Navigate to the Playwright homepage 

  await page.goto(baseUrl); 

  // Click the 'Get started' button 

  await page.getByRole('link', { name: getStartedLinkName }).click(); 

  // Verify the URL is correct 

  await expect(page).toHaveURL(expectedUrl); 

  // Verify the page header text is 'Installation' 

  await expect(page.getByRole('heading', { name: expectedHeader })).toBeVisible(); 

});</pre>



<p>Zgodnie z przewidywaniem Copilot poradził sobie z tym zadaniem poprawnie, identyfikując parametry mogące być przypisane do zmiennych i tworząc je.&nbsp;</p>



<p>Na koniec poprosiłem o stworzenie dokumentacji testu:&nbsp;</p>



<p>&nbsp;<br>1. Prompt:&nbsp;<br><br><strong>Write and apply a description of the test that could be used as documentation.</strong>&nbsp;</p>



<p>2. Odpowiedź:&nbsp;<br>&nbsp;<br>Test Description:&nbsp;</p>



<p>Test Name: Navigate to Get Started and Verify Installation Page&nbsp;</p>



<p>This test verifies the navigation flow on the Playwright documentation website. It performs the following steps:&nbsp;<br>&nbsp;</p>



<ol start="1" class="wp-block-list">
<li>Navigates to the Playwright homepage (https://playwright.dev/).&nbsp;</li>
</ol>



<ol start="2" class="wp-block-list">
<li>Clicks the &#8222;Get started&#8221; link on the homepage.&nbsp;</li>
</ol>



<ol start="3" class="wp-block-list">
<li>Verifies that the user is redirected to the &#8222;Introduction&#8221; page (https://playwright.dev/docs/intro).&nbsp;&nbsp;</li>
</ol>



<ol start="4" class="wp-block-list">
<li>Confirms that the page header text is &#8222;Installation&#8221;.&nbsp;</li>
</ol>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1937" height="1051" src="https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1.png" alt="ai w programowaniu " class="wp-image-34934" title="AI w programowaniu – jak sztuczna inteligencja wspomaga automatyzację?  29" srcset="https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1.png 1937w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-300x163.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1296x703.png 1296w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-768x417.png 768w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1536x833.png 1536w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-495x269.png 495w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2025.04.10_screen_1-1320x716.png 1320w" sizes="auto, (max-width: 1937px) 100vw, 1937px" /></figure>



<p></p>



<h2 class="wp-block-heading" id="sztuczna-inteligencja-w-testach">Nie tylko programowanie – sztuczna inteligencja w testach&nbsp;</h2>



<p>Testowanie to krytyczny etap w wytwarzaniu oprogramowania. Ma kluczowe znaczenie w gwarantowaniu jakości kodu, niezawodności, wiarygodności i bezpieczeństwa tworzonego systemu. Obecnie testowanie napotyka na swojej drodze różne trudności. Rosnąca złożoność struktur oprogramowania sprawia, że przetestowanie wielu potencjalnych ścieżek mogących zawierać błędy staje się po prostu skomplikowane.&nbsp;Narzędzia technologii AI znajdują zastosowania i tutaj – za ich pomocą tester może zoptymalizować swoją pracę w zakresie:&nbsp;</p>



<ul class="wp-block-list">
<li><strong>generowania przypadków testowych,</strong> które można w dalszym etapie modyfikować, gdy zajdzie taka potrzeba;&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>wspomagania generowania skryptów automatycznych</strong> – z wykorzystaniem narzędzi typu Copilot;&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>automatyzacji powtarzalnych zadań</strong> – co pozwala zaoszczędzić czas i skupić się na bardziej istotnych lub skomplikowanych zadaniach;&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>analizowania i tworzenia raportów testowych</strong> – dzięki asyście przy analizie i tworzeniu raportów można uzyskać bardziej szczegółowe dane na temat wyników testów, co pozwala na uzyskanie jakościowych informacji na temat stanu oprogramowania i ewentualnych błędów;&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>tworzenia danych testowych</strong> – AI może analizować wymagania aplikacji oraz specyfikację systemu, aby automatycznie generować odpowiednie dane testowe, które będą używane w różnych scenariuszach testowych. Dane mogą być bardzo różnorodne, co przekłada się na ich lepszą reprezentatywność dla rzeczywistych przypadków użycia aplikacji. Również przypadki brzegowe (edge cases), które bywają trudne do przewidzenia, mogą zostać zidentyfikowanie przez AI i odpowiednio pokryte danymi wejściowymi. Dzięki temu z pozoru rzadkie, ale ważne scenariusze, mogące mieć wpływ na stabilność aplikacji, mogą zostać zidentyfikowane i odpowiednio zaadresowane. Zwiększa to również pokrycie testów, pomagając w wykrywaniu potencjalnych problemów, które mogłyby umknąć tradycyjnym metodom testowania;&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>tworzenie dokumentacji testowej</strong> – AI można wykorzystać do tworzenia i utrzymywania dokumentacji testowej.&nbsp;</li>
</ul>



<h2 class="wp-block-heading" id="najlepsze-narzędzia-AI-dla-programistów-i-testerów">Jakie są najlepsze narzędzia AI dla programistów i testerów&nbsp;</h2>



<p>Na rynku istnieją już setki, jeśli nie tysiące narzędzi wykorzystujących sztuczną inteligencję. Możliwości tych innowacyjnych rozwiązań z powodzeniem&nbsp; mogą być wykorzystywane przez programistów i testerów. Wybór odpowiednich rozwiązań może jednak stanowić wyzwanie, dlatego warto skupić się na tych, które rzeczywiście zwiększają efektywność pracy, automatyzują powtarzalne zadania i pomagają unikać błędów. Wśród dostępnych narzędzi znajdują się zarówno inteligentni asystenci wspomagający pisanie kodu, jak i zaawansowane systemy do testowania, analizy błędów oraz optymalizacji <a href="https://nearshore-it.eu/pl/artykuly/automatyzacja-ci-cd/" data-type="post" data-id="30743">procesów CI/CD. </a></p>



<p>W tej sekcji krótko omówię kilka narzędzi, których wykorzystanie może usprawnić codzienną pracę w projekcie.&nbsp;</p>



<h3 class="wp-block-heading">GitHub Copilot&nbsp;</h3>



<p><strong>To obecnie jedno z najpopularniejszych narzędzi wspomagających pisanie kodu.</strong> Za jego pomocą można pisać kod efektywniej i szybciej, dzięki czemu programiści mogą więcej czasu poświęcić na rozwój oprogramowania w szerszym kontekście – współpracy w zespole czy skupieniu się na problemach związanych z logiką w aspekcie całościowym aplikacji. Słowem – zwiększa produktywność i przyspiesza wytwarzanie oprogramowania.&nbsp;</p>



<p>Narzędzia takie jak GitHub na bieżąco w trakcie pisania kodu sugerują rozwiązania, można też użyć funkcji czatu w celu uzyskania pomocy dotyczącej pisanego kodu. Istnieje też możliwość korzystania z niego przez CLI.&nbsp;</p>



<p>Dodatkowo w wersji Enterprise oferuje opcję generowania opisu pull requestów oraz tworzenie i zarządzanie dokumentacjami repozytoriów w formie baz wiedzy (knowledge bases), które stanowią kontekst dla czatu Copilot. Dzięki temu <a href="https://docs.github.com/en/enterprise-cloud@latest/copilot/customizing-copilot/managing-copilot-knowledge-bases" target="_blank" rel="noreferrer noopener">Copilot</a> przeszukuje bazę wiedzy pod kątem odpowiednich informacji i zwraca zsyntezowaną odpowiedź. &nbsp;</p>



<p><strong>Doskonale sprawdza się jako narzędzie do uzupełniania kodu, </strong>w szczególności dla przypadków, w których zwykle poszukujemy inspiracji w internecie, np. na StackOverFlow. Często zdarza się, że podobny problem, nad którym pracujemy, został już kiedyś napotkany i opisany, więc analiza danego wątku pozwala na zaimplementowanie rozwiązania w swoim kodzie. Dzięki Copilotowi można pominąć ten etap i za pomocą odpowiedniego prompta sprecyzować, czego potrzebujemy. Z dużym prawdopodobieństwem wygenerowany zostanie odpowiedni kod, nie zawsze idealny, ale wystarczający, żeby po niewielkich modyfikacjach otrzymać działającą funkcję.&nbsp;</p>



<p>Jego zaletą jest też możliwość zintegrowania go z najpopularniejszymi IDE – Visual Studio, Visual Studio Code, JetBrains.&nbsp;</p>



<h3 class="wp-block-heading">Cursor&nbsp;</h3>



<p>Cursor, w przeciwieństwie do GitHub Copilota, nie jest jedynie rozszerzeniem, <strong>ale pełnym IDE korzystającym z narzędzi AI. </strong>Został zaprojektowany w celu zwiększenia produktywności programistów poprzez integrację zaawansowanych funkcji sztucznej inteligencji bezpośrednio ze środowiskiem kodowania. Warto wiedzieć, że powstał na bazie VS Code (jest jego forkiem), a więc zachowuje interfejs i ekosystem VS Code, co ułatwia ewentualne przejście na ten edytor.&nbsp;</p>



<p>Posiada opcje takie jak generowanie, przewidywanie i uzupełnianie kodu oraz automatyczne poprawianie.&nbsp;</p>



<p>Jego kluczową cechą jest sposób “rozumienia” przez niego kodu – <strong>analizuje cały kontekst projektu.</strong> Oferuje kilka dodatkowych funkcji, dzięki którym asystent AI może działać jeszcze dokładniej. Jest to na przykład indeksowanie bazy kodu (które jest włączone domyślnie), każdy nowo dodany plik zostanie zaindeksowany i włączony do kontekstu aplikacji. Oprócz indeksowania plików, oferuje również tworzenie reguł dostosowujących działanie AI: globalnie oraz z ograniczeniami w ramach konkretnego projektu.&nbsp;</p>



<h3 class="wp-block-heading">ChatGPT&nbsp;</h3>



<p>To jedno z najpopularniejszych narzędzi AI dostępne w internecie, może być również z powodzeniem wykorzystane w inżynierii oprogramowania. Jest uniwersalne zarówno dla programistów jak i testerów – za jego pomocą można tworzyć między innymi kod, skrypty, dane testowe, scenariusze – i tak dalej. Dzięki wszechstronności może być wykorzystany jako asystent służący dobrą radą w wielu aspektach.&nbsp;</p>



<p>Oprócz czata GPT można w tym celu wykorzystać również inne narzędzia ogólnego przeznaczenia bazujące na LLM, jak Gemini czy Microsoft Copilot.&nbsp;</p>



<h3 class="wp-block-heading">Applitools&nbsp;</h3>



<p>To narzędzie służące głównie do testowania, monitorowania i zarządzania wizualnym aspektem aplikacji. Wykorzystuje sztuczną inteligencję do wykonywania testów wizualnych, <strong>skutecznie identyfikując wizualne błędy w aplikacjach, </strong>na przykład przez analizę elementów wyświetlanych w interfejsie – czy nie nakładają się na siebie, są w jakiś sposób niewidoczne, wychodzą poza swój obszar. Swoje testy może wykonywać na wielu przeglądarkach i platformach. Można za jego pomocą sprawdzać również pliki PDF. Applitools można zintegrować z popularnymi narzędziami do automatyzacji testów, takimi jak Selenium, Playwright, Appium, Cypress.&nbsp;</p>



<h3 class="wp-block-heading">Amazon CodeGuru&nbsp;</h3>



<p>To narzędzie wspierające przegląd kodu. Dzięki wykorzystaniu uczenia maszynowego i zautomatyzowanego procesu “rozumowania” pomaga zidentyfikować luki w kodzie, dostarcza zalecenia dotyczące sposobu ich naprawienia i śledzi ich status aż do momentu ich zamknięcia. Można je zintegrować na dowolnym etapie wytwarzania oprogramowania, włączając je w proces CI/CD. Twórcy dodatkowo zapewniają, że <strong>nie jest konieczne wykorzystywanie dodatkowych maszyn wirtualnych</strong> w celu jego uruchomienia – wystarczy zintegrować CodeGuru z wykorzystywanymi już narzędziami, a w zależności od obciążenia będzie samoczynnie skalowany w górę lub w dół.&nbsp;</p>



<h3 class="wp-block-heading">Testcraft&nbsp;</h3>



<p>To bezpłatne i otwartoźródłowe rozszerzenie przeglądarki, wykorzystujące sztuczną inteligencję do wspomagania testowania. Jego kluczową cechą jest <strong>możliwość generowania pomysłów na testy w oparciu o elementy widoczne na stronie internetowej.</strong> Pozwala również na automatyczne generowanie skryptów testowych dla popularnych frameworków automatyzacji – Playwright, Cypress, czy biblioteki Selenium. Skrypty można wygenerować w wielu językach programowania, znajdzie więc miłośników zarówno wśród testerów manualnych, jak i automatyzujących.&nbsp;</p>



<h2 class="wp-block-heading">Podsumowanie: Wykorzystanie AI w programowaniu i testowaniu&nbsp;&nbsp;</h2>



<p>Dobrze zaimplementowana sztuczna inteligencja może odegrać kluczową rolę w rozwoju oprogramowania, znacząco przyspieszając i usprawniając procesy na różnych etapach tworzenia oprogramowania. Dzięki AI można automatyzować pisanie kodu, testowanie, debugowanie oraz zarządzanie procesami CI/CD, co prowadzi do <strong>zwiększenia efektywności, redukcji kosztów i minimalizacji liczby błędów.&nbsp;</strong></p>



<p>Jednak należy pamiętać o drugiej stronie medalu. Sztuczna inteligencja, choć pozwala oszczędzać czas i ułatwia wykonywanie powtarzalnych zadań, nie zawsze generuje poprawne lub optymalne rozwiązania. Mając na uwadze fakt, że nowoczesne aplikacje często składają się z wielu modułów, są zintegrowane z wieloma zewnętrznymi usługami i systemami, sztuczna inteligencja, mimo że stanowi potężne wsparcie, nie zawsze jest bezbłędna, zwłaszcza w tak złożonych środowiskach.&nbsp;&nbsp;</p>



<p>AI dobrze radzi sobie z podstawowymi i średnio zaawansowanymi zadaniami, ale <strong>może mieć trudności z bardziej skomplikowanymi zagadnieniami, </strong>np. optymalizacją wydajności w dużych systemach, ze specyficznymi wzorcami projektowymi czy zaawansowanym debugowaniem. Nie można pominąć również potencjalnych zagrożeń w kwestii bezpieczeństwa.&nbsp;</p>



<p>Ostatecznie, <strong>AI powinna być traktowana jako wsparcie, </strong>a nie całkowite zastępstwo dla ludzkiej wiedzy i doświadczenia. Skuteczność automatyzacji opartej na AI zależy od jej mądrego wykorzystania. W połączeniu z kompetencjami specjalistów może ona stać się potężnym narzędziem wspierającym rozwój i utrzymanie wysokiej jakości oprogramowania.&nbsp; Jednak wymaga świadomej kontroli i odpowiedzialnego wdrażania w procesy technologiczne.&nbsp;&nbsp;</p>



<p>Choć obecne systemy AI, w tym narzędzia wspierające programistów i testerów, nie osiągnęły jeszcze poziomu przedstawionego przez Lema w “Golem XIV”, to ich rola w cyfrowej transformacji staje się coraz bardziej widoczna. Sztuczna inteligencja zyskuje na znaczeniu, automatyzując powtarzalne procesy, optymalizując kod oraz wspomagając analizy danych w czasie rzeczywistym. Współczesne algorytmy, choć bardzo zaawansowane, nie są jeszcze pozbawione błędów i ograniczeń, szczególnie w kontekście złożonych aplikacji oraz integracji z innymi systemami. To, co dziś oferuje sztuczna inteligencja, to jedynie przedsmak tego, co może się wydarzyć w przyszłości.&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/ai-w-programowaniu-automatyzacja/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Jak używać narzędzia GitHub Copilot – asystenta AI w programowaniu? </title>
		<link>https://nearshore-it.eu/pl/artykuly/github-copilot-asystent-ai/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/github-copilot-asystent-ai/#respond</comments>
		
		<dc:creator><![CDATA[Maciej Woźnica]]></dc:creator>
		<pubDate>Fri, 04 Apr 2025 12:03:15 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=34871</guid>

					<description><![CDATA[To narzędzie daje deweloperom nowe, ogromne możliwości, m.in. poprzez generowanie, optymalizację oraz pomoc przy refaktoryzacji kodu. W tym artykule sprawdzimy, jak efektywnie wykorzystać GitHub Copilot w codziennych zadaniach programistycznych.  ]]></description>
										<content:encoded><![CDATA[
<p></p>



<p><br>Według badań firmy <a href="https://www.mckinsey.com/industries/technology-media-and-telecommunications/our-insights/navigating-the-generative-ai-disruption-in-software" target="_blank" rel="noreferrer noopener">McKinsey</a> rozwiązania AI i low-code mogą pozytywnie wpłynąć na produktywność deweloperów, zwiększając ją nawet o 45%. Jednym z cenionych narzędzi bazujących na sztucznej inteligencji jest GitHub Copilot, który zmienia oraz usprawnia proces programowania. </p>



<div class="table-of-contents">
    <p class="title">Przejdź do:</p>
    <ol>
                    <li><a href="#Jak-korzystać-z-GitHub-Copilot-w-codziennym-programowaniu?">1.  GitHub Copilot w codziennym programowaniu</a></li>
                    <li><a href="#Jakie-możliwości-funkcji-GitHub-Copilot-oferuje-programistom?">2.  Możliwości funkcji GitHub Copilot</a></li>
                    <li><a href="#GitHub-Copilot---pomoc-w-rozwiązywaniu-problemów-z-kodem">3.  GitHub Copilot &#8211; pomoc w rozwiązywaniu problemów z kodem</a></li>
                    <li><a href="#Jakie-są-opinie-użytkowników-na-temat-narzędzia-GitHub-Copilot?-(wady-i-zalety)">4.  Opinie użytkowników, wady i zalety rozwiązania</a></li>
                    <li><a href="#Gdzie-dowiedzieć-się-więcej-o-GitHub-Copilot?">5.  Gdzie dowiedzieć się więcej o GitHub Copilot? </a></li>
            </ol>
</div>


<h2 class="wp-block-heading" id="Jak-korzystać-z-GitHub-Copilot-w-codziennym-programowaniu?">Jak korzystać z GitHub Copilot w codziennym programowaniu?&nbsp;</h2>



<p>Aby rozpocząć korzystanie z GitHub Copilot, musimy spełnić kilka prostych warunków. </p>



<p>Po pierwsze – jeśli nie posiadamy konta na github.com – musimy je założyć. Będzie to niezbędny krok do aktywowania subskrypcji naszego asystenta. Jeśli to mamy już za sobą, logujemy się na swoje konto, wybieramy pakiet, który odpowiada naszym potrzebom. Dostępnych mamy kilka wariantów – od planu darmowego służącego do nauki po plan dla profesjonalistów.&nbsp;</p>



<p>Kolejnym krokiem, jaki musimy podjąć, jest uruchomienie naszego ulubionego edytora kodu i instalacja wtyczki. Następnie łączymy swoje konto GitHub z IDE i nasz osobisty asystent jest gotowy do pracy. Od tej pory GitHub Copilot analizuje kod w naszych plikach!&nbsp;</p>



<p>Dzięki analizie Copilot jest w stanie podpowiedzieć nam kolejne linie, metody oraz algorytmy. W chwili, gdy zaczynamy pisać kod, asystent proponuje autouzupełnienie – możemy je zaakceptować, wciskając klawisz Tab, lub odrzucić.&nbsp;</p>



<p>Różnica pomiędzy autouzupełnianiem kodu, jaką znamy z popularnych IDE (VSC lub JetBrains), jest taka, że edytory udzielają nam podpowiedzi, bazując na wcześniej zadeklarowanych klasach, zmiennych, metodach oraz zasadach składni. <br> <br>Copilot idzie nieco dalej. Wykorzystuje AI oraz modele językowe do przewidywania całych bloków kodu. Nie jest ograniczony jedynie składnią &#8211; sugeruje gotowe metody, a nawet algorytmy; podpowiedzi są dużo bardziej zaawansowane niż w przypadku tradycyjnego autouzupełniania. </p>



<pre class="wp-block-code"><code>// Create a function to validate an email address 
function isValidEmail(email: string): bBoolean{...}

</code></pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="756" height="213" src="https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2024.04.02_graphic_1.png" alt="ai in coding - validate email" class="wp-image-34899" title="Jak używać narzędzia GitHub Copilot – asystenta AI w programowaniu?  30" srcset="https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2024.04.02_graphic_1.png 756w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2024.04.02_graphic_1-300x85.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2024.04.02_graphic_1-495x139.png 495w" sizes="auto, (max-width: 756px) 100vw, 756px" /></figure>



<p>Skuteczne okazuje się również generowanie kodu na podstawie komentarzy. Przykładowo, gdy chcemy napisać metodę, możemy po prostu opisać ją jako komentarz, a Copilot zaproponuje gotową implementację: <br>  </p>



<p>Kolejnym sposobem na skuteczną komunikację z Copilotem jest też funkcja czatu. Wystarczy, że wciśniemy kombinację klawiszy CTRL + I i pojawi się okienko, w którym możemy zadawać pytania naszemu asystentowi.&nbsp;</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="756" height="130" src="https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2024.04.02_graphic_2.png" alt="nearshore 2024.04.02 graphic 2" class="wp-image-34905" title="Jak używać narzędzia GitHub Copilot – asystenta AI w programowaniu?  31" srcset="https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2024.04.02_graphic_2.png 756w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2024.04.02_graphic_2-300x52.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/04/nearshore_2024.04.02_graphic_2-495x85.png 495w" sizes="auto, (max-width: 756px) 100vw, 756px" /></figure>



<h2 class="wp-block-heading" id="Jakie-możliwości-funkcji-GitHub-Copilot-oferuje-programistom?">Jakie możliwości funkcji GitHub Copilot oferuje programistom?&nbsp;</h2>



<p>Asystent AI może wspierać nas na różnych etapach rozwoju oprogramowania:&nbsp;</p>



<p></p>



<ul class="wp-block-list">
<li><strong>Generowanie kodu w czasie rzeczywistym</strong> – analizuje nasze poczynania i sugeruje zmiany – od pojedynczych sugestii po całe klasy lub funkcje. </li>
</ul>



<ul class="wp-block-list">
<li><strong>Tworzenie całych struktur kodu</strong> – gdy poprosimy Copilota o wygenerowanie całego komponentu, np. w <a href="https://nearshore-it.eu/pl/artykuly/pojedynek-gigantow-react-vs-angular/" data-type="post" data-id="29169">React / Angularze</a>, modułu w Nest.js lub zapytań SQL – bez problemu zareaguje wygenerowaniem odpowiednich linii kodu.&nbsp;</li>
</ul>



<pre class="wp-block-code"><code>// Create a service to connect to the API&nbsp;<br>&nbsp;&nbsp;</code></pre>



<ul class="wp-block-list">
<li><strong>Tworzenie testów jednostkowych</strong> – ogromną zaletą Copilota jest możliwość autotworzenia UT. Jest w stanie wygenerować testy, np. w znanych frameworkach, jak Jest czy Jasmine. Na podstawie analizy implementacji funkcji podpowiada nam odpowiednie przypadki testowe.&nbsp;</li>
</ul>



<pre class="wp-block-code"><code>// Create a UT for getUsers function.&nbsp;<br>&nbsp;&nbsp;</code></pre>



<ul class="wp-block-list">
<li><strong>Optymalizowanie oraz refaktoring kodu</strong> – któż z nas nie widział mnóstwa powtarzających się metod lub niewydajnych rozwiązań? Copilot bierze ten ciężar na siebie i sugeruje <s> </s>alternatywy – bardziej wydajne i zgodne z najlepszymi zasadami.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Generowanie dokumentacji kodu</strong> – Copilot może pomóc w generowaniu użytecznych komentarzy w formacie JSDoc lub Markdown, dzięki czemu ułatwimy innym programistom pracę nad naszym kodem – nie tracąc czasu na ręczne pisanie komentarzy.&nbsp;</li>
</ul>



<pre class="wp-block-code"><code>/**&nbsp;<br>* Gets user data based on user ID&nbsp;<br>* @param userId – user ID&nbsp;<br>* @returns User object or null&nbsp;<br>*/&nbsp;<br>&nbsp;&nbsp;</code></pre>



<h2 class="wp-block-heading" id="GitHub-Copilot---pomoc-w-rozwiązywaniu-problemów-z-kodem">Jak GitHub Copilot może pomóc w rozwiązywaniu problemów z kodem?&nbsp;</h2>



<p>Poza standardową pomocą w codziennych czynnościach związanych z kodem Copilot zapewnia także wsparcie w debugowaniu i naprawianiu błędów. Jest w stanie przeanalizować kod pod kątem potencjalnych bugów, np.:&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Nieodpowiednia składnia</strong> – brak nawiasu, średnika czy innego elementu składniowego.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Naprawa nieprawidłowych typów</strong> – np. próba przypisania nieodpowiedniego typu do zmiennej.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Błędne / nieistniejące nazwy zmiennych lub funkcji.&nbsp;</strong></li>
</ul>



<p>Jeśli mamy problem z działaniem metody – wystarczy, że zakomunikujemy to naszemu pomocnikowi:&nbsp;</p>



<pre class="wp-block-code"><code>// The following function is not working properly, fix it&nbsp;<br>function getUserData(id: number) {&nbsp;<br>&nbsp; return fetch(`/api/user/${id}`).then((res) =&gt; res.json());&nbsp;<br>}&nbsp;<br>&nbsp;&nbsp;</code></pre>



<p>Otrzymamy poprawiony kod:&nbsp;</p>



<pre class="wp-block-code"><code>async function getUserData(id: number) {&nbsp;<br>&nbsp; try {&nbsp;<br>&nbsp;&nbsp;&nbsp; const response = await fetch(`/api/user/${id}`);&nbsp;<br>&nbsp;&nbsp;&nbsp; if (!response.ok) throw new Error("data download error");&nbsp;<br>&nbsp;&nbsp;&nbsp; return await response.json();&nbsp;<br>&nbsp; } catch (error) {&nbsp;<br>&nbsp;&nbsp;&nbsp; console.error(error);&nbsp;<br>&nbsp;&nbsp;&nbsp; return null;&nbsp;<br>&nbsp; }&nbsp;<br>}&nbsp;<br>&nbsp;&nbsp;</code></pre>



<p>Jakie są najlepsze praktyki podczas korzystania z GitHub Copilot?&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Zawsze sprawdzaj wygenerowany kod.</strong> Copilot generuje kod, który na pierwszy rzut oka wygląda dobrze, ale może zawierać błędy.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Stosuj precyzyjne prompty i opisy funkcji.</strong> Im dokładniejszy opis, tym lepsze wyniki.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Zwracaj uwagę na bezpieczeństwo.</strong> Unikaj generowania kodu zawierającego wrażliwe dane.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Wykorzystuj Copilota jako narzędzie edukacyjne.</strong> Można go używać do nauki nowych wzorców czy technologii.&nbsp;</li>
</ul>



<h2 class="wp-block-heading" id="Jakie-są-opinie-użytkowników-na-temat-narzędzia-GitHub-Copilot?-(wady-i-zalety)">Jakie są opinie użytkowników na temat narzędzia GitHub Copilot? (wady i zalety)&nbsp;</h2>



<p>Według ogólnodostępnych badań:&nbsp;&nbsp;&nbsp;</p>



<ul class="wp-block-list">
<li>Deweloperzy korzystający z Copilota byli w stanie ukończyć zadania nawet o <a href="https://github.blog/news-insights/research/research-quantifying-github-copilots-impact-on-developer-productivity-and-happiness/" target="_blank" rel="noreferrer noopener"><strong>55% szybciej</strong></a><strong> </strong>niż ci, którzy z niego nie korzystali.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><a href="https://github.blog/news-insights/research/research-quantifying-github-copilots-impact-in-the-enterprise-with-accenture/" target="_blank" rel="noreferrer noopener"><strong>70% deweloperów</strong></a><strong> </strong>deklarowało znacznie mniejszy wysiłek umysłowy przy wykonywaniu powtarzalnych zadań.&nbsp;</li>
</ul>



<p><strong>Tyle statystyki, a jak to wygląda w praktyce?</strong> Copilot rodzi bardzo mieszane uczucia wśród użytkowników. Z jednej strony, usłyszymy głosy, że jest to rewolucja w wytwarzaniu oprogramowania, a narzędzie poprawia produktywność i ułatwia rozwiązywanie problemów. Z drugiej zaś strony są też nie do końca pozytywne opinie, które wskazują na przykład na jakość generowanego kodu oraz zagrożenia dotyczące bezpieczeństwa.&nbsp;<br>&nbsp;<br>Moje doświadczenie potwierdza te obserwacje. W moim środowisku Copilot cieszy się dużym zainteresowaniem – programiści doceniają przede wszystkim to, że mogą zaoszczędzić czas na pisaniu kodu czy testów jednostkowych. Ale z drugiej strony podchodzą do narzędzia sceptycznie, zwracając uwagę na błędy, które popełnia, lub nieefektywne rozwiązania.&nbsp;</p>



<p><strong>Przeczytaj także: <a href="https://nearshore-it.eu/pl/artykuly/najlepsze-ai-for-coding-w-2025-roku-czego-uzywac-do-generowania-kodu/">The best AI for coding &#8211; czego używać w 2025 roku?</a></strong></p>



<h3 class="wp-block-heading"><strong>Zalety tworzenia oprogramowania z GitHub Copilot:&nbsp;</strong></h3>



<ul class="wp-block-list">
<li>Zwiększenie produktywności.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li>Wsparcie dla Junior Developerów i osób uczących się nowych technologii.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li>Obsługa wielu języków programowania.&nbsp;</li>
</ul>



<h3 class="wp-block-heading"><strong>Wady tworzenia oprogramowania z GitHub Copilot:</strong>&nbsp;</h3>



<ul class="wp-block-list">
<li>Możliwość generowania błędnego kodu.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li>Czasem proponuje przestarzałe rozwiązania.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li>Ograniczona wersja darmowa – pełna funkcjonalność wymaga opłaty.&nbsp;</li>
</ul>



<h2 class="wp-block-heading" id="Gdzie-dowiedzieć-się-więcej-o-GitHub-Copilot?">Gdzie dowiedzieć się więcej o GitHub Copilot?&nbsp;</h2>



<p>Najlepszym miejscem jest <strong>oficjalna dokumentacja</strong>. Warto też sprawdzić kursy na YouTube:&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Traversy Media </strong>– przegląd Copilota i jego możliwości.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Fireship </strong>– szybkie wprowadzenie w kilka minut.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>The Primeagen </strong>– krytyczna analiza Copilota w praktyce.&nbsp;</li>
</ul>



<p>Poza darmowymi materiałami warto odwiedzić:&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Udemy</strong> – kursy dla różnych języków.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Pluralsight</strong> – kursy dla profesjonalistów.&nbsp;</li>
</ul>



<ul class="wp-block-list">
<li><strong>Coursera</strong> – akademickie podejście do AI w programowaniu.&nbsp;</li>
</ul>



<h2 class="wp-block-heading">Podsumowanie: AI w programowaniu&nbsp;</h2>



<p>Narzędzia bazujące na sztucznej inteligencji stają się coraz lepsze i dzięki temu odciążają programistów już chyba w każdym projekcie IT. Możemy programować szybciej, oszczędzając czas na powtarzalnych zadaniach, takich jak pisanie testów jednostkowych czy przeglądanie dokumentacji. Z drugiej jednak strony – wymagają uważności, czujności i świadomości ograniczeń tej technologii. Wykorzystanie takich narzędzi jak GitHub Copilot wymaga od nas ciągłego poszerzania wiedzy w zakresie możliwości AI, do czego was zachęcam!&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/github-copilot-asystent-ai/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Najlepsze AI for coding w 2025 roku: czego używać do generowania kodu?</title>
		<link>https://nearshore-it.eu/pl/artykuly/najlepsze-ai-for-coding-w-2025-roku-czego-uzywac-do-generowania-kodu/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/najlepsze-ai-for-coding-w-2025-roku-czego-uzywac-do-generowania-kodu/#respond</comments>
		
		<dc:creator><![CDATA[Paweł Adamowicz]]></dc:creator>
		<pubDate>Thu, 27 Mar 2025 13:36:37 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[AI]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=34778</guid>

					<description><![CDATA[Odkryj najlepsze AI do programowania w 2025 roku! Których narzędzi używać, a których unikać, by uzyskać najlepsze efekty w programowaniu.]]></description>
										<content:encoded><![CDATA[
<p>W dzisiejszym artykule przyjrzymy się tematowi, który jest obecnie bardzo na czasie, a mianowicie AI w programowaniu. Sztuczna inteligencja jest coraz bardziej powszechna wśród programistów na różnych etapach tworzenia oraz rozwoju oprogramowania. Kiedy pierwszy raz widziałem AI w akcji, byłem zaskoczony jej możliwościami. Nie było to narzędzie doskonałe, ale mimo wszystko zrobiło na mnie wrażenie.&nbsp;</p>



<p>Na chwilę obecną posiadamy wiele narzędzi, modeli AI oraz bardzo dużo integracji z oprogramowaniem, z którego korzystamy na co dzień, więc każdy znajdzie coś dla siebie. Nieważne, czy programujesz, zajmujesz się marketingiem, czy grafiką – AI jest obecne wszędzie… Zapraszam was do dalszej części artykułu, gdzie porozmawiamy o tym, jak AI w codziennej pracy pozwala programistom przyspieszyć wydajność oraz poprawić jakość i czytelność naszego kodu.&nbsp;</p>



<div class="table-of-contents">
    <p class="title">Quick links</p>
    <ol>
                    <li><a href="#AI-for-coding:-najlepsze-narzędzia-AI-do-programowania-w-2025-r.">1.  AI for coding: najlepsze narzędzia AI do programowania w 2025 r. </a></li>
                    <li><a href="#Jakie-są-najlepsze-AI-do-generowania-kodu?">2.  Jakie są najlepsze AI do generowania kodu?</a></li>
                    <li><a href="#Które-narzędzia-AI-są-darmowe?">3.  Które narzędzia AI są darmowe?</a></li>
                    <li><a href="#Jakie-są-dostępne-funkcje-AI-w-edytorach-kodu,-takich-jak-VS-Code?">4.  Jakie są dostępne funkcje AI w edytorach kodu, takich jak VS Code?</a></li>
                    <li><a href="#Jak-AI-wpływa-na-jakość-kodu">5.  Jak AI wpływa na jakość kodu</a></li>
                    <li><a href="#Jak-AI-może-pomóc-w-code-review">6.  Jak AI może pomóc w code review</a></li>
                    <li><a href="#Najlepsze-praktyki-używania-AI-do-poprawy-jakości-kodu">7.  Najlepsze praktyki używania AI do poprawy jakości kodu</a></li>
                    <li><a href="#Korzyści-użycia-AI-w-programowaniu">8.  Korzyści użycia AI w programowaniu</a></li>
                    <li><a href="#Potencjalne-pułapki-z-AI-w-programowaniu">9.  Potencjalne pułapki z AI w programowaniu</a></li>
                    <li><a href="#Różnice-między-różnymi-asystentami-AI">10.  Różnice między różnymi asystentami AI</a></li>
                    <li><a href="#Porównanie-różnych-modeli-AI-do-programowania">11.  Porównanie różnych modeli AI do programowania</a></li>
                    <li><a href="#Co-wyróżnia-Gemini-Code-Assist-spośród-innych-narzędzi?">12.  Co wyróżnia Gemini Code Assist spośród innych narzędzi?</a></li>
                    <li><a href="#Najnowsze-trendy-w-obszarze-AI-for-coding-w-2025-roku">13.  Najnowsze trendy w obszarze AI for coding w 2025 roku</a></li>
                    <li><a href="#Najlepsze-praktyki-korzystania-z-AI-w-programowaniu">14.  Najlepsze praktyki korzystania z AI w programowaniu</a></li>
            </ol>
</div>


<h2 class="wp-block-heading" id="AI-for-coding:-najlepsze-narzędzia-AI-do-programowania-w-2025-r.">AI for coding: najlepsze narzędzia AI do programowania w 2025 r.</h2>



<p>Czy wiesz, że <strong>już nawet 76% osób </strong>zajmujących się programowaniem korzysta lub planuje używać narzędzi związanych z AI w swojej codziennej pracy? Albo że użytkownicy Copilota wykonywali zadania <strong>o około 55% szybciej niż bez AI?</strong> Tak wynika z przeprowadzonej przez <a href="https://stackoverflow.blog/2025/01/28/how-engineering-teams-can-thrive-in-2025/" target="_blank" rel="noreferrer noopener">Stack Overflow</a> w 2024 roku ankiety.&nbsp;&nbsp;</p>



<p>Na chwilę obecną narzędzia AI są już tak zaawansowane, że nie tylko kod generują, ale również wspierają cały cykl tworzenia oprogramowania.&nbsp;</p>



<h2 class="wp-block-heading" id="Jakie-są-najlepsze-AI-do-generowania-kodu?">Jakie są najlepsze AI do generowania kodu?</h2>



<p>Część z was pewnie ma już swoje ulubione narzędzia, z których korzysta na co dzień. Obecnie najbardziej popularne narzędzia, o których pewnie słyszała większość osób w branży, to GitHub Copilot, ChatGPT (OpenAI) i Amazon CodeWhisperer.&nbsp;</p>



<p>Ta wymieniona trójka to pionierzy wśród asystentów i chatbotów AI, ale na rynku są też inne narzędzia, o których opowiem za chwilę.&nbsp;</p>



<ul class="wp-block-list">
<li><strong>GitHub Copilot</strong>&nbsp;</li>
</ul>



<p>Zacznijmy od GitHub Copilota – pioniera wśród asystentów AI, który korzysta z modeli OpenAI. Możemy go zintegrować z popularnym VS Code, dzięki czemu podczas pisania kodu będziemy mieli podpowiedzi bezpośrednio w edytorze.&nbsp;</p>



<ul class="wp-block-list">
<li><strong>ChatGPT</strong>&nbsp;</li>
</ul>



<p>Kolejnym ciekawym narzędziem, o którym pewnie słyszała większość z was, jest ChatGPT. Chat ten korzysta z modeli OpenAI, czyli tak samo jak Copilot, ale z tą różnicą, że nie jest on zintegrowany z edytorami. Pomoże ci napisać fragmenty kodu albo rozwiązać jakiś problem związany z kodem.&nbsp;</p>



<ul class="wp-block-list">
<li><strong>CodeWhisperer</strong>&nbsp;</li>
</ul>



<p>Z topowej trójki zostaje nam jeszcze CodeWhisperer od Amazon. Jest to swojego rodzaju asystent do programowania z użyciem usług takich jak AWS i nie tylko, więc jeśli zajmujesz się tematyką chmurową, to myślę, że warto go sprawdzić!&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Tabnine</strong>&nbsp;</li>
</ul>



<p>Poza tymi, które wymieniłem, są jeszcze inne narzędzia. Zacznijmy od Tabnine. Narzędzie to jest oparte na autouzupełnianiu i, co najważniejsze, może działać jako self-hosted, gwarantując, że nasz kod nigdzie nie wypłynie.&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Codeium</strong>&nbsp;</li>
</ul>



<p>Możliwe, że część użytkowników słyszała o darmowej alternatywie dla Copilota, a mianowicie Codeium. Użytkownicy bardzo chwalą narzędzie, że działa całkiem przyzwoicie jako alternatywa, zapewnia automatyczne uzupełnianie i sugestie kodu, które wcale nie ustępują komercyjnym rozwiązaniom.&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Gemini Code Assist</strong>&nbsp;</li>
</ul>



<p>Ostatnim z popularnych AI, tym razem od Google, jest Gemini Code Assist. Narzędzie to potrafi zrobić nawet code review, więc jeśli szukasz AI, które wstępnie sprawdzi twój kod, to może warto spróbować?&nbsp;</p>



<p>Jak widzisz, mamy tutaj całkiem sporo narzędzi i ciężko jest jednoznacznie stwierdzić, które narzędzie będzie dla ciebie odpowiednie, a jeszcze trudniej wskazać, które będzie najlepsze z nich wszystkich. Każdy z nas oczekuje czegoś innego. Jedni będą pracować z technologiami AWS i wybiorą CodeWhisperer, a ktoś inny postawi na privacy-first i wybierze Tabnine. Znajdą się też osoby, dla których wystarczy chatbot, i wybiorą ChatGPT. W mojej ocenie każde z tych narzędzi na pewno pomoże ci w codziennej pracy.&nbsp;</p>



<h2 class="wp-block-heading" id="Które-narzędzia-AI-są-darmowe?">Które narzędzia AI są darmowe?</h2>



<p>Z narzędzi wymienionych do generowania kodu mamy dostępnych kilka opcji, ale zawsze trzeba zwracać uwagę na to, czy będziemy z nich korzystać hobbystycznie, czy realizując projekt komercyjny.&nbsp;</p>



<p>Większość narzędzi jest darmowa dla użytkowników indywidualnych, a za lepsze wersje lub dodatki trzeba po prostu zapłacić.&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Google Gemini Code Assist</strong> – udostępnia darmowy plan z bardzo wysokimi limitami zapytań i, według mnie, jest to najlepsza alternatywa spośród wszystkich wymienionych.&nbsp;</li>



<li><strong>Amazon CodeWhisperer</strong> – ma plan darmowy, ale tylko dla użytkowników indywidualnych, więc jeśli tworzysz projekt dla siebie w technologiach np. AWS, warto go sprawdzić.&nbsp;</li>



<li><strong>Codeium</strong> – dla użytkowników indywidualnych jest całkowicie darmowy, oferuje nielimitowane podpowiedzi kodu i wspiera wiele języków programowania. Według mnie to bardzo ciekawy wybór.&nbsp;</li>



<li><strong>ChatGPT</strong> – tak jak wspominałem na początku i pewnie nie skłamię, pisząc, że większość osób w branży IT słyszała o tym chatbocie. W wersji bezpłatnej pomoże ci wygenerować np. komponent w React albo zrobić refaktoryzację kodu, jeśli oczywiście wpiszesz odpowiedni prompt. Jednak za wersję premium trzeba już zapłacić.&nbsp;</li>
</ul>



<p>Są też inne narzędzia wymienione wcześniej takie jak <strong>GitHub Copilot, Tabnine,</strong> które są co prawda bezpłatne w podstawowej wersji i będą nam generowały kod, ale jeśli oczekujemy od nich czegoś więcej, to trzeba wykupić pełny plan lub specjalną subskrypcję, więc nie są w pełni darmowe.&nbsp;</p>



<p>Tak naprawdę, jeśli tworzymy coś hobbistycznie i w mniejszej skali, to większość tych narzędzi będzie dla nas dostępna za darmo (z większymi lub mniejszymi limitami). Wszystko zależy więc od licencji, i od tego, do czego użyjemy danego narzędzia. Pamiętajmy też o tym, że to, co w momencie pisania artykułu jest darmowe, za miesiąc może już nie być, bo licencja się zmieni, więc warto sprawdzić to na własną rękę przed instalacją.&nbsp;</p>



<h2 class="wp-block-heading" id="Jakie-są-dostępne-funkcje-AI-w-edytorach-kodu,-takich-jak-VS-Code?">Jakie są dostępne funkcje AI w edytorach kodu, takich jak VS Code?</h2>



<p>Większość narzędzi, które wcześniej wymieniałem, posiada integracje z popularnymi edytorami np. (VS Code) lub IDE. Github Copilot może zostać włączony bezpośrednio w VS Code, dzięki czemu możemy się cieszyć podpowiedziami w kodzie właściwie od razu.&nbsp;</p>



<p>Copilot Chat pozwala za to zadawać pytania o kod, a Copilot w trybie „agent” wykonuje już złożone polecenia, np. uruchamia unit testy.&nbsp;</p>



<p>Tak jak widzimy, mamy cały wachlarz możliwości – od chatu w VS Code, poprzez autouzupełnianie kodu,&nbsp; na uruchamianiu unit testów czy modyfikowaniu całych plików kończąc. Dodatkowo pamiętajmy, że z powyżej wymienionych mamy narzędzia, które nie wysyłają kodu na zewnętrzne serwery, więc nawet przy projektach o wysokich wymaganiach bezpieczeństwa nasze zespoły security będą zadowolone, a dzięki temu będziemy mogli korzystać z AI.&nbsp;</p>



<h2 class="wp-block-heading" id="Jak-AI-wpływa-na-jakość-kodu">Jak AI wpływa na jakość kodu</h2>



<p>AI to nie tylko generowanie kodu komponentów i rozwiązywanie codziennych problemów w kodzie. Na chwilę obecną AI potrafi przeanalizować istniejący kod w poszukiwaniu błędów lub celem sugerowania innych usprawnień. Powiem więcej, zrobi refaktoryzację i code review! Możemy ustawić takie narzędzie AI jako dodatkowego „recenzenta” naszego kodu, który wykrywa np. podejrzany kod marnej jakości, czyli tzw. „code smells”, a nawet luki w bezpieczeństwie.&nbsp;</p>



<h2 class="wp-block-heading" id="Jak-AI-może-pomóc-w-code-review">Jak AI może pomóc w code review</h2>



<p>Dla przykładu, Gemini Code Review wykona analizę pull requesta i podkreśli fragmenty, na które warto zwrócić uwagę i ewentualnie je poprawić.&nbsp;</p>



<p>Jeśli korzystasz z GitHuba i jego rozwiązań, to Gemini Code Assist wyłapie nawet niespójności w konwencji kodowania i sprawdzi, czy ich przestrzegasz.&nbsp;</p>



<p>Tak jak widzisz, temat jest bardzo rozległy, i jeśli dobrze dobierzemy narzędzia AI, to możemy uniknąć wielu roboczogodzin przy sprawdzaniu tego typu rzeczy podczas rozwoju oprogramowania. AI wyłapie te niuanse za nas, a my będziemy mogli skupić się na innej pracy.&nbsp;</p>



<h2 class="wp-block-heading" id="Najlepsze-praktyki-używania-AI-do-poprawy-jakości-kodu">Najlepsze praktyki używania AI do poprawy jakości kodu</h2>



<p>1. Sprawdzaj&nbsp;</p>



<p>Zasada numer jeden, której według mnie należy przestrzegać, to ta, że AI ma ci pomóc w „nakierowaniu” na rozwiązanie twojego problemu. Pamiętaj, aby zweryfikować wszystko, co podpowie ci AI, bo nie zawsze odpowiedzi, które otrzymasz, będą prawidłowe. Jeśli już zastosujesz się do powyższej zasady, to możemy przejść dalej.&nbsp;</p>



<p>Słyszałem już od wielu osób, że AI bardzo pomaga w pisaniu testów jednostkowych, przynajmniej we frontendzie. Pisanie testów jednostkowych do najprzyjemniejszych nie należy, a w wielu przypadkach trzeba napisać bardzo dużo powtarzającego się kodu typu boilerplate. AI wygeneruje ci unit testy bardzo szybko i zaoszczędzisz przy tym sporo czasu na development, ale pamiętaj – zawsze weryfikuj to, co dostarcza ci AI.&nbsp;</p>



<p>2.  Postaw na iteracyjną refaktoryzację&nbsp;</p>



<p>Kolejną rzeczą, do której według mnie AI sprawdzi się na co dzień, jest iteracyjna refaktoryzacja i ulepszanie twojego kodu. Wiesz, jak wygląda kod, w którym ktoś dopisał kawałek kodu w pośpiechu, bez większego zastanowienia, aby tylko działało? Czasami taki kod jest zupełnie nieczytelny, albo dochodzi do wielu zagnieżdżeń i tzw. <em>ifologii</em>. W takim przypadku AI poprawi to za ciebie i zasugeruje ci optymalne rozwiązanie. Pozbędziesz się w ten sposób mało czytelnego kodu, a twoje funkcje będą bardziej przejrzyste, kod ładnie sformatowany, a pull request dla osób robiących ci review – przyjemniejszy do czytania.&nbsp;</p>



<p>3. Bądź elastyczny&nbsp;&nbsp;</p>



<p>Pamiętaj, że AI nie zwalnia z samodzielnego myślenia, a najlepsze efekty osiągniesz, gdy będziesz weryfikować, ale i stosować pomysły, które według ciebie sprawdzą się w danym projekcie.&nbsp;</p>



<p>Tutaj trzeba wybrać, co jest odpowiednie w danej chwili.&nbsp;&nbsp;</p>



<h2 class="wp-block-heading" id="Korzyści-użycia-AI-w-programowaniu">Korzyści użycia AI w programowaniu</h2>



<ul class="wp-block-list">
<li><strong>Oszczędność czasu</strong>&nbsp;</li>
</ul>



<p>Ja osobiście dostrzegam tutaj dwie główne korzyści – oszczędność czasu na prostych i powtarzalnych zadaniach oraz zwiększenie produktywności. AI świetnie sprawdza się przy generowaniu powtarzalnego i żmudnego kodu typu boilerplate, więc możemy ten czas poświęcić na coś bardziej kreatywnego. </p>



<ul class="wp-block-list">
<li><strong>Większa produktywność&nbsp;</strong>&nbsp;</li>
</ul>



<p>Druga rzecz to produktywność – taki asystent może sprawić, że zajmiemy się trudniejszymi zadaniami, a te proste oddamy AI, więc będziemy też bardziej produktywni.&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Łatwiejsze wyszukiwanie&nbsp;</strong>&nbsp;</li>
</ul>



<p>Ważną i niedocenianą rzeczą jest też fakt, że AI dobrze radzi sobie z dokumentacjami. Nie musimy już walczyć z przeszukiwaniem internetu czy dokumentacji, aby znaleźć jakieś informacje – AI zrobi to dużo szybciej. Dzięki temu możemy poświęcić się pracy bardziej kreatywnej, czyli skupić się np. na architekturze aplikacji, a nie na powtarzalnej i nudnej „drobnicy”.&nbsp;</p>



<h2 class="wp-block-heading" id="Potencjalne-pułapki-z-AI-w-programowaniu">Potencjalne pułapki z AI w programowaniu</h2>



<ul class="wp-block-list">
<li><strong>Halucynacje AI</strong>&nbsp;</li>
</ul>



<p>Jednym z największych problemów związanych z AI jest to, że doświadczają tzw. halucynacji. To, co czasami wydaje się na pierwszy rzut oka poprawne, po głębszej analizie może (ale nie musi) zawierać błędy logiczne, albo może robić coś zupełnie innego, niż oczekujemy.&nbsp;</p>



<p>Jeśli porcja kodu, którą dostaliśmy od AI, jest duża, to może zdarzyć się, że będzie to trudne do wykrycia. Jeśli nie masz dobrych unit testów, to możesz nawet nie zdawać sobie sprawy, że AI właśnie dodało ci błąd w kodzie, albo, co gorsza, wprowadzić podatność bezpieczeństwa, z której nawet nie zdajesz sobie sprawy.&nbsp;</p>



<ul class="wp-block-list">
<li>Brak rozwoju kompetencji programistycznych&nbsp;</li>
</ul>



<p>Kolejną pułapką jest spadek umiejętności osób, które korzystają z AI na co dzień. Jeśli będziemy zdawali się wyłącznie na AI i jesteśmy na początkującej drodze, to nasze kompetencje mogą ulec zanikowi albo nie zrobimy takiego progresu, jaki byśmy chcieli. Nie oszukujmy się, ale jeśli ktoś dostaje gotowe rozwiązanie, to jest duża szansa, że nie nauczy się tego na własną rękę i nie będzie potrafił wyjaśnić logiki działania wygenerowanego kodu. Nie mówię tutaj tylko o AI, ale generalnie o tzw. gotowcach. Krótkoterminowo raczej nikt na tym nie ucierpi, ale zastanowiłbym się, czy przy długofalowym korzystaniu z tego narzędzia nasze umiejętności rozwiązywania problemów nie spadną drastycznie.&nbsp;</p>



<p>Zalecałbym szczególnie juniorom, aby analizowali kod i pisali go samodzielnie, a to, co wygeneruje AI, traktowali bardziej jak odpowiedź na Stack Overflow, czyli bardziej jako sugestię i materiał do dalszego researchu.&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Kwestie prawne</strong>&nbsp;</li>
</ul>



<p>Na koniec pamiętajmy też o kwestiach prawnych. Nie od dzisiaj wiadomo, że chatboty i inne generatory kodu uczą się na „cudzym” kodzie, który jest np. publicznie dostępny. Zawsze sprawdzajmy i czytajmy polityki prywatności i licencje, aby wiedzieć, co udostępniamy AI, ale jednocześnie też uważajmy na to, co samo AI nam dostarcza, aby nie otrzymać kodu łudząco podobnego do jakiegoś fragmentu z np. open source. Pamiętajmy też o aspektach security i polityce firmy, bo chyba nie chcemy, aby nasze poufne hasła czy klucze API krążyły w sieci, bo były przez nas używane w promptach, a co za tym idzie, mogły zostać użyte do trenowania modeli, prawda?&nbsp;</p>



<h2 class="wp-block-heading" id="Różnice-między-różnymi-asystentami-AI">Różnice między różnymi asystentami AI</h2>



<p>Ilość narzędzi AI oraz różnego rodzaju asystentów potrafi przytłoczyć, a podejrzewam, że to dopiero początek. Spróbujemy zaraz porównać kilka modeli AI oraz narzędzi, które posłużą nam do programowania i codziennej pracy z kodem.&nbsp;</p>



<h2 class="wp-block-heading" id="Porównanie-różnych-modeli-AI-do-programowania">Porównanie różnych modeli AI do programowania</h2>



<p>Obecnie na rynku mamy sporo popularnych modeli AI oraz asystentów programowania, ale generalnie ich cel jest zbliżony – mają <strong>ułatwić i przyspieszyć pisanie kodu.</strong> Jeśli chodzi o główne różnice, to za wszystkim stoją różne modele językowe i firmy, które nad nimi pracują.&nbsp;</p>



<p>Przykładowo, GitHub Copilot korzysta z OpenAI, CodeWhisperer od Amazon jest trenowany na kodzie źródłowym open-source, a inne narzędzia korzystają z własnych modeli, które możemy uruchomić lokalnie (Tabnine), więc mamy tutaj alternatywę dla usług chmurowych.&nbsp;</p>



<p>I teraz pewnie część z was się domyśli, że OpenAI będzie nam płynnie odpowiadał w wielu językach, a CodeWhisperer będzie z kolei lepszy w kontekście AWS, bo na takich danych był trenowany. Tak właśnie jest z tymi narzędziami – takie są subtelne różnice między nimi.&nbsp;</p>



<p>Różnice, które dostrzegamy gołym okiem, będą dla nas widoczne <strong>w integracjach i ekosystemie. </strong>Mamy z jednej strony chatboty bez możliwości wejścia w kontekst projektu (chociaż są pluginy pod ChatGPT, które integrują go z edytorem), a z drugiej strony mamy Tabnine, CodeWhisperer i Gemini jako wtyczki bezpośrednio pod IDE, które dają podpowiedzi na żywo w kodzie.&nbsp;</p>



<p>Warto też zwrócić uwagę na licencję i koszty, i tutaj, jak się pewnie domyślacie, mamy dużą rozpiętość – od darmowych po bardzo drogie. Jeśli chodzi o mnie, to chyba poleciłbym któreś z tych darmowych i najbardziej dostępnych AI – Gemini lub Codeium. Dają praktycznie nieograniczone możliwości korzystania z AI bez opłat, co może być decydującym czynnikiem w niektórych przypadkach.&nbsp;&nbsp;</p>



<p>Z drugiej strony firma może chcieć wykorzystać narzędzie, które będzie zgodne z politykami wewnętrznymi i wtedy trzeba będzie zapłacić więcej (np. Tabnine on-premise ze względów bezpieczeństwa).&nbsp;</p>



<p>Jak widzicie, mamy tutaj spore różnice, jeśli chodzi o modele, narzędzia, pluginy oraz modele subskrypcji i licencji. Generalnie, jeśli chodzi o samą funkcjonalność, to jest ona bardzo podobna – dostajemy wygenerowany kod na podstawie prompta, ale czasami mamy możliwość skorzystania z dodatkowych funkcjonalności, takich jak np. agent mode w Copilot.&nbsp;</p>



<p>W trybie agent mode AI nie tylko podpowiada nam kod, który chcemy dodać, ale też może modyfikować całe pliki projektu i wykonywać dodatkowe czynności, np. uruchamiać komendę do unit testów. Ciekawe, prawda?&nbsp;</p>



<h2 class="wp-block-heading" id="Co-wyróżnia-Gemini-Code-Assist-spośród-innych-narzędzi?">Co wyróżnia Gemini Code Assist spośród innych narzędzi?</h2>



<p>Wyobraź sobie, że masz pod ręką wirtualnego asystenta, który robi również np. code review. Właśnie tak w skrócie działa <strong>Gemini Code Assist.</strong> Jeśli tworzysz projekt hobbistyczny, jest on dostępny od Google całkowicie za darmo, a do tego oferuje bardzo wysokie limity miesięczne, których raczej w standardowej sytuacji nie będziesz w stanie wykorzystać.&nbsp;</p>



<p>Google zadbało również o to, aby dostroić asystenta do zadań stricte programistycznych, ponieważ był trenowany na rzeczywistych przypadkach kodowania. Wyróżniającą cechą jest także fakt, że Gemini potrafi czytać bardzo duży kontekst naraz. Oznacza to, że można mu przekazać cały kod źródłowy do analizy, co stanowi bardzo duży krok naprzód w porównaniu do innych narzędzi.&nbsp;</p>



<p>Jeśli szukasz wsparcia w pisaniu kodu w edytorze za pomocą AI, chcesz, aby asystent zrobił code review i podał sugestie, co poprawić (nawet pod względem code guide w obecnym projekcie), warto zainteresować się Gemini.&nbsp;</p>



<h2 class="wp-block-heading" id="Najnowsze-trendy-w-obszarze-AI-for-coding-w-2025-roku">Najnowsze trendy w obszarze AI for coding w 2025 roku</h2>



<p>Na chwilę obecną widać <strong>gwałtowne przyspieszenie rozwoju narzędzi typu AI for coding.</strong> Duże firmy technologiczne, takie jak Microsoft, Amazon czy Google, prześcigają się we wprowadzaniu AI do swoich produktów.&nbsp;&nbsp;&nbsp;</p>



<p>Ostatnio widziałem, że AI nie tylko generuje kod, ale potrafi stworzyć taska w Jira nawet na podstawie treści nieczytelnej dla człowieka (np. z logów błędu na AWS). Mało tego – rozpisuje odpowiednie subtaski w bardzo ciekawy sposób, więc nie tracimy już cennego czasu na takie prace. Wystarczy, że wkleimy kawałek kodu i zweryfikujemy to, co nam podpowiada AI. Wydaje mi się, że AI będzie coraz bardziej wspierać tworzenie dokumentacji, testów, konfiguracji np. CI/CD czy analizę wymagań w oparciu o przyjętą architekturę projektu.&nbsp;</p>



<h2 class="wp-block-heading" id="Najlepsze-praktyki-korzystania-z-AI-w-programowaniu">Najlepsze praktyki korzystania z AI w programowaniu</h2>



<p>AI, tak jak każde inne narzędzie, potrafi pomóc, ale też trzeba uważać na pewne pułapki. Przedstawię kilka propozycji w kolejności od tych najważniejszych według mnie, które są warte przeczytania i zastosowania, kiedy będziesz korzystać z AI na co dzień w swojej pracy z kodem.&nbsp;</p>



<ol start="1" class="wp-block-list">
<li>Zasada numer jeden – dbaj o prywatność swojego kodu i zasady panujące w danym projekcie (lub, jeśli pracujesz dla kogoś – w danej firmie lub organizacji). Warto upewnić się, czy korzystanie z AI w tym przypadku jest zgodne z umową lub polityką firmy/organizacji. Sprawdź też dodatkowo, czy można wyłączyć trenowanie modeli na twoim kodzie i nigdy nie wrzucaj danych, które są tajemnicą przedsiębiorstwa, do prompta. Jeśli już musisz, to zanonimizuj kod tak, aby nie zawierał danych wrażliwych, unikalnych projektowo nazw funkcji czy zmiennych, a kodu nigdy nie dało się powiązać z danym klientem/projektem/firmą czy czymkolwiek. Mam nadzieję, że wiesz, o co mi chodzi.&nbsp;</li>



<li>AI ma ci pomagać, a nie wyręczać cię w codziennej pracy. Ma być bardziej pomocnikiem przy generowaniu powtarzalnego kodu, np. unit testów, lub nakierować cię na jakieś rozwiązanie. Sprawdź zawsze kod, który dostarcza ci AI. Przeanalizuj i zrozum, w jaki sposób AI dodało np. funkcję w kodzie. Taka refleksja nad kodem będzie ćwiczyła twój umysł, a dzięki temu umiejętności pozostaną na wysokim poziomie.&nbsp;</li>



<li>Przy pisaniu testów jednostkowych stosujemy zasadę nr 2, ale dodatkowo uruchamiamy testy. Zobaczmy, czy rzeczywiście sprawdzają to, co trzeba, sprawdźmy, czy testowane są np. przypadki brzegowe. Zmuś się do analizowania tego kodu, tak jak by to był zwykły pull request na repozytorium do sprawdzenia. Błędy się zdarzają, więc zawsze sprawdzaj dwa razy.&nbsp;&nbsp;</li>



<li>Warto wykorzystać technologię AI do robienia rzeczy, które wychodzą jej lepiej od innych, a te bardziej złożone – lepiej robić na własną rękę. Jeśli masz do wyboru wygenerowanie np. unit testów, zrobienie konwersji jednego formatu na drugi lub optymalizację już istniejącej funkcji, to AI sprawdzi się tutaj dużo lepiej, niż miałaby stworzyć to od podstaw. Skomplikowaną architekturę oraz funkcje zostaw sobie na start, a jeśli poziom skomplikowania się zwiększy lub potrzebujesz refaktoryzacji – wtedy udaj się z pytaniem do AI po sugestie. Nie zaniedbuj szkolenia się w danej dziedzinie. Wiem, że AI potrafi nas odciążyć i trochę zwolnić z myślenia, ale to nie powód, aby nie doszkalać się z danej dziedziny. Unikaj szczególnie “metody Copy’ego Paste&#8217;a”, czyli kopiowania i wklejania treści kodu bez przeczytania i zrozumienia, co się tam dzieje.&nbsp;</li>
</ol>



<h2 class="wp-block-heading">Podsumowanie&nbsp;</h2>



<p>Tak naprawdę, jeśli zastosujemy te zasady w naszej codziennej pracy, to będzie się nam pracowało dużo lepiej, a jednocześnie zapewnimy większe bezpieczeństwo naszego kodu. Nasze umiejętności pozostaną na wysokim poziomie, a efektywność będzie rosła dzięki wsparciu AI.&nbsp;</p>



<p>Temat, który dzisiaj omówiliśmy, jest bardzo rozległy i dynamiczny, ale mam nadzieję, że zaciekawiłem was nim i odpowiedziałem na parę nurtujących pytań. Na koniec powiem jeszcze chyba najważniejszą rzecz odnośnie AI. Ostatecznie to my dostarczamy kod i się pod nim podpisujemy, nie AI. Trzeba o tym pamiętać i zachować po prostu zdrowy rozsądek – tak jak we wszystkim.&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/najlepsze-ai-for-coding-w-2025-roku-czego-uzywac-do-generowania-kodu/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python i AI, Float i nie tylko – czyli jak produktywniej pracować z Pythonem? </title>
		<link>https://nearshore-it.eu/pl/artykuly/python-i-ai/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/python-i-ai/#respond</comments>
		
		<dc:creator><![CDATA[Patryk Fiedorowicz]]></dc:creator>
		<pubDate>Tue, 11 Feb 2025 12:08:19 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=34615</guid>

					<description><![CDATA[Jak zwiększyć efektywność pracy w Pythonie i zadbać o czysty kod? Jak asystenci AI wspierają codzienną pracę programistów? Przeczytaj artykuł i odkryj, jak programować efektywniej dzięki narzędziom AI i Machine Learning! ]]></description>
										<content:encoded><![CDATA[
<p>Podczas konferencji Python Summit 2024 zorganizowanej przez społeczność PyData i PyWaw w Warszawie w grudniu ubiegłego roku, miałem możliwość zapoznania się z prelekcjami na temat generatywnej sztucznej inteligencji, uczenia maszynowego, inżynierii danych, technologii webowych, cyberbezpieczeństwa, testowania, architektury systemów czy dobrych praktyk pisania czystego kodu. W pamięć zapadły mi szczególnie dwie prelekcje, które zainspirowały mnie do napisania tego artykułu. Pierwsza z nich dotyczyła produktywnej pracy z Pythonem (prelegent: Sebastian Buczyński, Software Architect / Consultant / Trainer z Bottega IT Minds), natomiast druga obejmowała temat liczb zmiennoprzecinkowych Float w Pythonie (Konrad Gawda, Cloud Evangelist z Orange Polska).</p>



<p>Zrozumienie poruszonych aspektów pozwala odpowiedzieć na istotne pytania. Jakie struktury wykorzystywać, by uniknąć krytycznych błędów? Jak zwiększyć efektywność pracy w Pythonie i zadbać o czysty kod? Jak asystenci AI wspierają codzienną pracę programistów?</p>



<div class="table-of-contents">
    <p class="title"></p>
    <ol>
                    <li><a href="#przykłady-problemów-z-liczbami-zmiennoprzecinkowymi">1.  Przykłady problemów z liczbami zmiennoprzecinkowymi</a></li>
                    <li><a href="#Float-–-liczby-zmiennoprzecinkowe-w-Pythonie">2.  Float – liczby zmiennoprzecinkowe w Pythonie</a></li>
                    <li><a href="#Developer-Experience-–-jak-mierzyć-efektywność-developera?">3.  Developer Experience – jak mierzyć efektywność developera?</a></li>
                    <li><a href="#Narzędzia-do-efektywnej-pracy-w-Pythonie">4.  Narzędzia do efektywnej pracy w Pythonie</a></li>
                    <li><a href="#Asystenci-AI-jako-wsparcie-produktywnej-pracy">5.  Asystenci AI jako wsparcie produktywnej pracy</a></li>
                    <li><a href="#Podsumowanie">6.  Podsumowanie</a></li>
            </ol>
</div>


<h2 class="wp-block-heading" id="przykłady-problemów-z-liczbami-zmiennoprzecinkowymi">Trochę historii na początek – przykłady problemów z liczbami zmiennoprzecinkowymi</h2>



<h3 class="wp-block-heading">Błąd systemu obrony przeciwrakietowej Patriot&nbsp;</h3>



<p>Podczas wojny w Zatoce Perskiej w 1991 roku system nie zadziałał prawidłowo i nie przechwycił rakiety Scud, która uderzyła w koszary wojskowe w Dhahran w Arabii Saudyjskiej, zabijając 28 osób. Przyczyną był błąd w obliczeniach czasu. System śledził czas za pomocą liczby całkowitej reprezentującej liczbę taktów zegara, przy czym każdy takt odpowiadał za około 0.1 sekundy. Aby obliczyć dokładny czas, liczba całkowita była mnożona przez 0.1, która w pamięci była reprezentowana jako liczba przybliżona ze względu na ograniczenia formatu IEEE 754. Z każdym kolejnym cyklem zegara błąd się kumulował, przez aż 100 godzin od uruchomienia systemu, ostatecznie narastając do około 0.34 sekundy. Ta różnica spowodowała, że system obliczył błędne położenie rakiety Scud i nie zadziałał na czas. Po incydencie wprowadzono aktualizację oprogramowania, która resetowała zegar systemowy częściej, zmniejszając wpływ kumulacji błędów. Ta tragiczna w skutkach historia amerykańskiego systemu obrony rakietowej Patriot to jeden z klasycznych przykładów błędu wynikającego z ograniczeń liczb zmiennoprzecinkowych. Ta historia pokazuje, że w tak istotnych obliczeniach należy unikać stosowania przybliżeń i używać precyzyjniejszych typów danych.&nbsp;&nbsp;</p>



<h3 class="wp-block-heading">Wybory parlamentarne w Schleswig-Holstein&nbsp;</h3>



<p>Innym przykładem są wybory parlamentarne z 1992 r. w niemieckim Schleswig-Holstein. W tym, jak i w większości niemieckich landów, obowiązuje system proporcjonalny, w którym partie muszą uzyskać co najmniej 5% głosów, aby otrzymać mandaty w parlamencie. Wyniki wyborów były prezentowane w procentach, a zaokrąglenia miały miejsce na różnych etapach obliczeń. Partia Zielonych uzyskała 4.97%, ale na etapie prezentacji wyników wartość została zaokrąglona do 5%, a więc próg został spełniony, co całkowicie zmieniło rozkład mandatów w parlamencie. Doprowadziło to do wielu kontrowersji i publicznej debaty, jednak mimo to wyniki zostały uznane za wiążące. W systemie nie przewidziano procedury na wypadek błędu zaokrąglenia.&nbsp;&nbsp;</p>



<h2 class="wp-block-heading" id="Float-–-liczby-zmiennoprzecinkowe-w-Pythonie">Float – liczby zmiennoprzecinkowe w Pythonie</h2>



<p>W tym kontekście bardzo ciekawą prelekcją z mojej perspektywy była ta o typie Float, czyli liczbach zmiennoprzecinkowych w Pythonie.&nbsp;&nbsp;</p>



<p>Liczby te można tworzyć na różne sposoby, poprzez dosłowne przekazanie liczby, czyli np. 1.0, używając klasy tj. float(1) lub poprzez działania matematyczne takie jak 1/1.&nbsp;</p>



<h3 class="wp-block-heading">Standard IEEE 754 binary64&nbsp;</h3>



<p>Z dokumentacji Pythona dowiadujemy się, że we wszystkich znanych implementacjach interpretera Pythona float zdefiniowany jest jako double. Bardziej szczegółowo typ ten jest opisany według standardu IEEE 754 binary64 i wygląda to następująco:&nbsp;</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="756" height="150" src="https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_1.png" alt="Python i AI" class="wp-image-34637" title="Python i AI, Float i nie tylko – czyli jak produktywniej pracować z Pythonem?  32" srcset="https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_1.png 756w, https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_1-300x60.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_1-495x98.png 495w" sizes="auto, (max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Patrząc po kolei od lewej:&nbsp;</p>



<ul class="wp-block-list">
<li>1 bit jest poświęcony na znak (liczba dodatnia lub ujemna).&nbsp;</li>



<li>11 bitów wyraża wykładnik potęgowy.&nbsp;</li>



<li>52 bity wyrażają ułamek.&nbsp;</li>
</ul>



<p>A wszystko to można przedstawić za pomocą poniższego wzoru:&nbsp;</p>



<p>(-1)^sign x 2^(exp-1023) x 1.fraction&nbsp;</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="756" height="160" src="https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_2.png" alt="Python i AI" class="wp-image-34640" title="Python i AI, Float i nie tylko – czyli jak produktywniej pracować z Pythonem?  33" srcset="https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_2.png 756w, https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_2-300x63.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_2-495x105.png 495w" sizes="auto, (max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Według omówionego standardu poniżej kilka przykładów reprezentacji binarnej:&nbsp;</p>



<p><strong>a) Liczba 0.0&nbsp;</strong></p>



<p>0 (sign) 00000000000 (exponent) </p>



<p>(0).0000000000000000000000000000000000000000000000000000 (fraction)&nbsp;</p>



<p><strong>b) Liczba 1.0 = 1 x 1.0 = 2^0 x 1.0 = 2^(1024-1024) x 1.0&nbsp;</strong></p>



<p>0 (sign) 01111111111 (exponent) </p>



<p>(1).0000000000000000000000000000000000000000000000000000 (fraction)&nbsp;</p>



<p><strong>c) Liczba 3.0 = 2 x 1.5 = 2^1 x 1.5 =2^(1025-1024) x 1.5&nbsp;</strong></p>



<p>0 (sign) 10000000000 (exponent) </p>



<p>(1).1000000000000000000000000000000000000000000000000000 (fraction)&nbsp;</p>



<h3 class="wp-block-heading">Precyzja typu Float&nbsp;</h3>



<p>Powyższe przykłady są dość proste z punktu widzenia reprezentacji binarnej, jednak problem pojawia się przy liczbach niecałkowitych, ponieważ nie zawsze jesteśmy w stanie zapisać je w pamięci z pełną precyzją. Można to zaobserwować, używając w Pythonie metody as_integer_ratio(), aby sprawdzić, jakie liczby są użyte do dzielenia, by uzyskać oczekiwany wynik. Jak widać na poniższym przykładzie, dla liczby 0.1 nie ma liczb 1 i 10, jak byśmy tego oczekiwali, tylko 3602879701896397 i 36028797018963968. Są to liczby, które dają najbardziej precyzyjne przybliżenie do 0.1 i możliwe do zapisu w pamięci według omawianego standardu. Natomiast to, że wywołując print() na obliczeniu 1/10 otrzymujemy 0.1, wynika wyłącznie z tego, że print() automatycznie zaokrągla nam do najkrótszego zapisu dziesiętnego, który się mieści w ramach ostatniego bitu precyzji.&nbsp;&nbsp;</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="756" height="54" src="https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_3.png" alt="Python i AI" class="wp-image-34644" title="Python i AI, Float i nie tylko – czyli jak produktywniej pracować z Pythonem?  34" srcset="https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_3.png 756w, https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_3-300x21.png 300w, https://nearshore-it.eu/wp-content/uploads/2025/02/nearshore_2025.02.05_graphic_3-495x35.png 495w" sizes="auto, (max-width: 756px) 100vw, 756px" /></figure></div>


<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Inną przydatną metodą w Pythonie, pozwalającą zyskać więcej informacji na temat floatów, jest <strong>sys.float_info. </strong>Dzięki niej możemy się dowiedzieć, że float pozwala na przechowywanie do 15 cyfr znaczących (dodatkowo ewentualnie znak plus-minus i/lub przecinek).&nbsp;&nbsp;</p>



<p>To wszystko może sprawić, że zaczniemy się zastanawiać nad tym, jak dużo ucieka nam precyzji podczas używania typu float. Do tego przydatna jest metoda <strong>math.ulp() </strong>(czyli Unit in the Last Place), co w praktyce zwraca nam różnicę pomiędzy podaną liczbą a następną, którą jesteśmy w stanie zapisać w tym formacie w pamięci. W przypadku małych liczb te różnice są bardzo marginalne, jednak przy takiej liczbie jak 2^52 ta różnica wynosi już równo 1.0. Oznacza to, że właściwie od tej liczby wzwyż całkowicie tracimy części ułamkowe. Idąc dalej, przy 2^53 różnica ta wynosi już 2.0. Zatem ważnym wnioskiem jest, by tak dużych liczb, nawet całkowitych, nie przechowywać jako float, ponieważ tylko liczby parzyste w tym przypadku zachowałyby swoją precyzję.&nbsp;</p>



<h3 class="wp-block-heading">Symbole specjalne&nbsp;</h3>



<p>W standardzie IEEE 754 przewidziano również miejsce dla specjalnych symboli. Jeśli 11-bitowa część exponent jest cała wypełniona jedynkami, a 52-bitowa część wyrażająca ułamek wypełniona zerami, to mamy do czynienia z reprezentacją binarną nieskończoności. Zapełniając zerem bit odpowiedzialny za znak otrzymujemy plus nieskończoność, a jedynką minus nieskończoność.&nbsp;</p>



<p>Z kolei mając również 11-bitową część exponent wypełnioną jedynkami, ale także część wyrażającą ułamek wypełnioną jedynkami, otrzymujemy symbol NaN (Not a Number). Wszelkie operacje porównujące takie jak =, &gt;, &lt; z udziałem NaN zwracają False, co może być problematyczne w różnych okolicznościach. Zwłaszcza kiedy użytkownik ma braki w danych i sądzi, że porównywana jest faktyczna liczba, a nie pusta reprezentacja w postaci NaN.&nbsp;&nbsp;</p>



<h3 class="wp-block-heading">Zaokrąglenia&nbsp;</h3>



<p>Co jednak, jeśli nie jest potrzebna nam aż taka dokładność i chcemy uprościć jakieś obliczenia? Odpowiedzią są zaokrąglenia i należy wiedzieć, że uzyskać je można na różne sposoby. Co istotne, nie różnią się jedynie nazwy funkcji, ale ich implementacje mają odrębne podejścia. W prezentacji podczas Python Summit 2024 przedstawiono następujące metody:&nbsp;</p>



<ol start="1" class="wp-block-list">
<li><strong>Funkcja round() </strong>– zaokrągla zadaną liczbę do najbliższej liczby z określoną liczbą miejsc po przecinku, domyślnie do liczby całkowitej. Natomiast szczególnym przypadkiem jest sytuacja, gdy liczba jest równo w połowie i w obie strony jest taka sama odległość. Wtedy najmniej znacząca cyfra zaokrąglana jest do liczby parzystej, co według statystyków minimalizuje skumulowany błąd podczas wykonywania wielu operacji zaokrąglania. Czyli przykładowo zarówno 1.5, jak i 2.5 zostaną zaokrąglone do 2, jeśli interesuje nas liczba całkowita. Co ciekawe, w przypadku takich liczb jak 1.15 i 1.25 również obie powinny zostać zaokrąglone do 1.2, gdyby chcieć zachować dokładność do jednego miejsca po przecinku. Jednak tylko 1.25 zwróci poprawnie 1.2, a dla 1.15 zostanie zwrócone 1.1. Wynika to właśnie z tego, że liczby 1.15 nie da się precyzyjnie przechować w pamięci według standardu IEEE 754, a będzie to 1.1499999999999999. Czyli nie jest to de facto równo w połowie, a więc zaokrągli w dół do 1.1.&nbsp;</li>
</ol>



<ol start="2" class="wp-block-list">
<li><strong>int() lub math.trunc()</strong> – co prawda nie są to funkcje zaokrąglające, tylko obcinające liczbę, ale ich efekt działa tak, jakbyśmy zaokrąglali liczbę w kierunku 0. Czyli przykładowo 1.9 zostanie ucięte (zaokrąglone) do 1, natomiast -1.9 zostanie sprowadzone do -1.&nbsp;&nbsp;</li>
</ol>



<ol start="3" class="wp-block-list">
<li><strong>math.floor() lub x // 1</strong> – pierwsza z nich po prostu zaokrągla w dół, w kierunku –nieskończoności. Natomiast druga to dzielenie bez reszty, przy czym dzieląc przez jeden, uzyskamy ten sam efekt co w przypadku pierwszej funkcji. Przykładowo dla obu z nich -1.9 zostanie zaokrąglone do -2, a 1.9 do 1.&nbsp;</li>
</ol>



<ol start="4" class="wp-block-list">
<li><strong>math.ceil() </strong>– zaokrąglanie w górę, w kierunku + nieskończoności. Używając tego samego przykładu -1.9 zostanie zaokrąglone do -1, natomiast 1.9 zaokrągli do 2.&nbsp;</li>
</ol>



<h2 class="wp-block-heading" id="Developer-Experience-–-jak-mierzyć-efektywność-developera?">Developer Experience – jak mierzyć efektywność developera?</h2>



<p>W przeszłości na różne sposoby próbowano mierzyć efektywność developerów. Jedną z bardziej popularnych, a zarazem nietrafionych metod, było mierzenie efektywności poprzez liczbę napisanych linii kodu. Podczas drugiej z wspomnianych prezentacji przytoczono koncepcję, która nie tyle pozwala na mierzenie produktywności, co pomaga zadbać o efektywne środowisko pracy. Mowa tutaj o DevEX (Developer Experience), które wyróżnia 3 filary:&nbsp;</p>



<ol start="1" class="wp-block-list">
<li><strong>Stan przepływu (Flow state)</strong> – z punktu widzenia developera jest to stan głębokiego skupienia, w którym jesteśmy w stanie spokojnie pracować. Jeśli cele nie są jasno doprecyzowane, może wystąpić konieczność przerwania zadania, by ustalić nieścisłości.&nbsp;</li>



<li><strong>Pętle zwrotne (Feedback loops) </strong>– oznacza, ile czasu mija, zanim developer się dowie, że kod nie działa. W przypadku testów jednostkowych ten feedback jest bardzo szybki, ale w przypadku code review na feedback trzeba zaczekać dłużej.&nbsp;</li>



<li><strong>Ładunek kognitywny (Cognitive load)</strong> – oznacza wysiłek umysłowy wymagany do skutecznego pisania kodu. Jeśli programista spotyka się z projektem o innej strukturze niż zwykle albo nie ma do dyspozycji dokumentacji, do której zawsze miał dostęp, ten ładunek będzie wyższy.&nbsp;</li>
</ol>



<h2 class="wp-block-heading" id="Narzędzia-do-efektywnej-pracy-w-Pythonie">Narzędzia do efektywnej pracy w Pythonie</h2>



<p>Wielu programistów rozpoczyna przygodę z Pythonem, gdyż zachęca ich intuicyjna składnia i wszechstronność zastosowań tego języka w analizie danych. W miarę rozwoju umiejętności w naturalny sposób poszukujemy narzędzi pozwalających zwiększyć efektywność pracy i ułatwiających życie. Podczas kolejnej prezentacji, w której miałem okazję brać udział w trakcie Python Summit 2024, zostały omówione takie narzędzia:&nbsp;</p>



<ol start="1" class="wp-block-list">
<li><strong>Formatery&nbsp;</strong>&nbsp;</li>
</ol>



<p>Formatowanie kodu to bardzo istotny aspekt, ponieważ to od tego głównie będzie zależało, czy programiście wygodnie się czyta oraz pisze kod. Jednak każdy z nas może mieć nieco inne preferencje, przyzwyczajenia, dlatego najlepiej, aby został przyjęty jeden ściśle określony sposób formatowania. Zaleca się korzystanie ze standardu PEP 8. Jest to dość długi dokument, dlatego dbanie samodzielnie o każdy szczegół mogłoby być bardzo czasochłonne – ładunek kognitywny rośnie. Dodatkowo podczas code review to byłaby rzecz, na którą trzeba zwracać uwagę, zatem przekłada się to na dodatkowy czas poświęcony po stronie zespołu, a i pętla zwrotna się wydłuża. I tutaj z pomocą przychodzą formatery kodu, które mogą wykonać całą pracę za nas. Przykładowe formatery kodu w Pythonie to:<strong> black, isort, ruff, yapf.</strong>&nbsp;</p>



<ol start="2" class="wp-block-list">
<li><strong>Lintery</strong>&nbsp;</li>
</ol>



<p>Są to narzędzia do statycznej analizy kodu, dzięki którym możemy dowiedzieć się o niektórych błędach jeszcze przed uruchomieniem kodu. Ponadto lintery są w stanie naprawiać za nas takie błędy jak np. literówki powstałe poprzez użycie nieistniejącej zmiennej. Inne kwestie, które mogą być sprawdzane automatycznie, to ilość znaków w każdej linii, długość nazw funkcji, zmiennych, ilość argumentów do funkcji itp. Przykłady linterów w Pythonie to: <strong>pylint, flake8, ruff.</strong>&nbsp;<br>&nbsp;</p>



<ol start="3" class="wp-block-list">
<li><strong>Adnotacje typów i type checkery</strong>&nbsp;</li>
</ol>



<p>W kwestii typów zmiennych Python jest bardzo liberalny, ponieważ mamy tu do czynienia z typowaniem dynamicznym. Mimo to określanie typów, jakie przewidujemy dla danych zmiennych, jest postrzegane jako dobra praktyka w Pythonie. Jest to funkcja, która została wprowadzona od wersji Pythona 3.5. Należy mieć na uwadze, że adnotacje typów są jedynie komentarzem i nie są uwzględniane przez program, o ile nie ma zewnętrznej biblioteki, która by je interpretowała. Używając jednak PyCharma, jednego z najpopularniejszych IDE dla Pythona, możemy odnieść korzyści z adnotacji typów natychmiastowo. PyCharm posiada wbudowany type checker, dzięki czemu będziemy widzieć różne podpowiedzi dotyczące typów. Inne popularne zewnętrzne type checkery to: <strong>mypy, pyright </strong>czy też<strong> pyre.</strong>&nbsp;</p>



<p>Rekomendacja dotycząca omówionych narzędzi bardzo przypadła mi do gustu. Według prelegentów Python Summit 2024 dobrym wyborem będzie <strong>ruff</strong>, ponieważ świetnie sprawdza się zarówno jako formater, jak i linter. Zastępuje inne narzędzia oraz jest bardzo szybki. Dodatkowym argumentem, by się bliżej przyjrzeć tej bibliotece, jest to, że w planach jest rozszerzenie jej funkcjonalności również o type checker. Jednak na ten moment należy korzystać ze sprawdzonych i popularnych narzędzi do sprawdzania typów, takich jak <strong>mypy </strong>oraz <strong>pyright.&nbsp;</strong>&nbsp;</p>



<h2 class="wp-block-heading" id="Asystenci-AI-jako-wsparcie-produktywnej-pracy">Asystenci AI jako wsparcie produktywnej pracy</h2>



<p>Na koniec temat, bez którego trudno obecnie wyobrazić sobie przyszłość programowania – mianowicie narzędzia sztucznej inteligencji. Poza wspomnianymi tradycyjnymi narzędziami do usprawniania pracy w Pythonie podczas konferencji w prezentacjach osobną część poświęcono nowoczesnym podejściom do tworzenia oprogramowania wykorzystującym asystentów AI.&nbsp;&nbsp;</p>



<p>O ile obecnie raczej nie ma co liczyć na to, że napiszą za nas cały program, o tyle mogą świetnie się sprawdzić jako usprawnienie pracy. Zainstalowanie takiej wtyczki jak chociażby Copilot może przyspieszyć proste operacje czy też tworzenie komentarzy dzięki trafnym podpowiedziom.&nbsp;&nbsp;</p>



<p>Jeśli nie pamiętamy składni, argumentów biblioteki etc., sprawdzanie dokumentacji może okazać się już zbędne. Asystenci AI mogą również przyspieszyć pisanie prostych testów jednostkowych. Warto jednak najpierw napisać kilka z nich samodzielnie, by asystent mógł lepiej rozpoznać poprawny wzór.&nbsp;</p>



<p>Poniżej kilka przykładów najbardziej popularnych narzędzi programistycznych.&nbsp;&nbsp;&nbsp;</p>



<ul class="wp-block-list">
<li><strong>GitHub Copilot</strong> – narzędzie analizuje kontekst kodu i pozwala zautomatyzować, a tym samym przyspieszyć uzupełnianie fragmentów kodu. Przydatny w tworzeniu i przeglądzie dokumentacji oraz wyszukiwaniu konkretnych rozwiązań.&nbsp;</li>



<li><strong>Supermaven</strong> – sugeruje zależności i poprawki w kodzie, eliminując błędy i optymalizując wydajność aplikacji. Narzędzie może zasugerować użycie najlepszej biblioteki pod kątem danego projektu, co skraca czas analizy i przyspiesza proces wdrażania nowych rozwiązań.&nbsp;</li>



<li><strong>Cursor AI</strong> – usprawnia pracę programistów Python dzięki inteligentnemu autouzupełnianiu, generowaniu kodu na podstawie języka naturalnego oraz możliwości szybkiego refactoringu.&nbsp;</li>



<li><strong>Tabnine </strong>– pozwala uzupełniać kod w czasie rzeczywistym, co zwiększa produktywność i pomaga unikać błędów składniowych, a także eliminuje powtarzalność zadań związanych z pisaniem kodu.&nbsp;</li>



<li><strong>S</strong><strong>ourcegraph Cody</strong> <strong>– </strong>sprawdza się świetnie w<strong> </strong>zaawansowanym przeszukiwaniu kodu. Pozwala na zrozumienie zależności w projektach oraz – dzięki kontekstowej analizie całej bazy kodu – na szybkie odnajdywanie i poprawianie błędów.&nbsp;</li>
</ul>


</style><div class="promotion-box promotion-box--image-left "><div class="tiles latest-news-once"><div class="tile"><div class="tile-image"><img decoding="async" src="https://nearshore-it.eu/wp-content/uploads/2025/02/Code-Faster-Tlo-2.jpg" alt="Code Faster Tlo 2" title="Python i AI, Float i nie tylko – czyli jak produktywniej pracować z Pythonem?  35"></div><div class="tile-content"><p class="entry-title client-name">AI w programowaniu | bezpłatny e-book</p>
Zautomatyzuj kodowanie z AI! Pobierz darmowy e-book i odkryj nowe możliwości
<br /><br />
<a class="btn btn-primary" href="https://www.engage.inetum.com/ebook-code-faster-build-smarter/" target="_blank" rel="noopener">Pobierz teraz!</a></div></div></div></div>



<h2 class="wp-block-heading" id="Podsumowanie">Podsumowanie</h2>



<p>Mnogość dostępnych technologii w świecie IT potrafi przyprawić o zawrót głowy. Samo określenie roli w projekcie IT jeszcze nie determinuje wyboru narzędzi, z których będziemy korzystać. Decydować o tym będą w głównej mierze wymagania systemu. Czy powinien być nastawiony na wydajne przetwarzanie dużych ilości danych, czy może bardziej istotna jest prostota w implementacji i szybkie wdrożenie rozwiązania kosztem niższej wydajności? Odpowiedzenie sobie na te pytania czasem nie wystarczy, ponieważ bywa, że kilka technologii spełnia wszystkie wymagania i wybór sprowadza się do względów czysto estetycznych i preferencji osobistych.&nbsp;&nbsp;</p>



<p>Na szczęście są społeczności i organizacje, które skupiają ludzi zainteresowanych określoną tematyką i pomagają odnaleźć się w gąszczu wiedzy oraz poszerzać horyzonty, by być na bieżąco. Dla osób związanych zawodowo z językiem programowania Python takim miejscem jest właśnie konferencja Python Summit. Prelekcje dostępne w trakcie Python Summit 2024 i zagadnienia, które omówiłem, stanowią tylko mały wycinek wiedzy, jaki można było wynieść z tego spotkania. Zapewniam, że każdy znalazłby coś dla siebie, nawet jeśli wybrane przeze mnie tematy nie są w centrum zainteresowania danego programisty.&nbsp;</p>



<p>Przeczytaj także nasze artykuły dotyczące bibliotek Python:&nbsp;&nbsp;</p>



<ul class="wp-block-list">
<li><a href="https://nearshore-it.eu/pl/artykuly/numpy-wstep-do-biblioteki-python/" target="_blank" rel="noreferrer noopener">NumPy</a>&nbsp;</li>



<li><a href="https://nearshore-it.eu/pl/artykuly/biblioteka-matplotlib/" target="_blank" rel="noreferrer noopener">Matplotlib</a>&nbsp;</li>



<li><a href="https://nearshore-it.eu/pl/artykuly/biblioteki-python-pandas/" target="_blank" rel="noreferrer noopener">Pandas</a>&nbsp;</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/python-i-ai/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Jak wygląda proces dostarczania oprogramowania oparty na CI/CD?</title>
		<link>https://nearshore-it.eu/pl/artykuly/proces-dostarczania-oprogramowania-ci-cd/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/proces-dostarczania-oprogramowania-ci-cd/#respond</comments>
		
		<dc:creator><![CDATA[Mateusz Mirecki]]></dc:creator>
		<pubDate>Wed, 28 Aug 2024 08:39:59 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[Cloud engineering]]></category>
		<category><![CDATA[DevOps]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/?p=28712</guid>

					<description><![CDATA[Główna korzyść z CI to wczesne wykrywanie błędów, co prowadzi do szybszego wdrażania nowych funkcji, większej stabilności oprogramowania i lepszej współpracy między programistami.]]></description>
										<content:encoded><![CDATA[
<p>Aby zobrazować, jak CI działa w praktyce, można posłużyć się przykładem: kod źródłowy aplikacji został zmieniony, ponieważ powstała nowa funkcjonalność. Praca rozpoczyna się od utworzenia kopii głównego repozytorium kodu. System kontroli wersji przechowuje kod źródłowy w repozytorium. Aktualny stan aplikacji jest zwykle przechowywany w głównej gałęzi repozytorium (zwanej także jako „master&#8221;). Programista, zaczynając pracę nad nową funkcjonalnością, tworzy lokalnie kopię głównego repozytorium, która staje się bazą do stworzenia nowej funkcjonalności (a więc dokonania zmian w kodzie źródłowym).&nbsp;&nbsp;&nbsp;</p>



<div class="table-of-contents">
    <p class="title">Przejdź do:</p>
    <ol>
                    <li><a href="#Automatyzacja-i-testowanie">1.  Automatyzacja i testowanie</a></li>
                    <li><a href="#Integracja-i-aktualizacja-">2.  Integracja i aktualizacja </a></li>
                    <li><a href="#Zarządzanie-błędami-i-powiadomienia-">3.  Zarządzanie błędami i powiadomienia </a></li>
                    <li><a href="#Praktyka-DevOps-">4.  Praktyka DevOps </a></li>
                    <li><a href="#Zalety-podejścia-DevOps">5.  Zalety podejścia DevOps</a></li>
                    <li><a href="#Automatyzacja-i-shift-left-testing-">6.  Automatyzacja i shift-left testing </a></li>
                    <li><a href="#Projektowanie-małych-komponentów-i-usług-">7.  Projektowanie małych komponentów i usług </a></li>
                    <li><a href="#Projektowanie-danych-testowych-wykorzystywanych-w-ciągłym-testowaniu-">8.  Projektowanie danych testowych wykorzystywanych w ciągłym testowaniu </a></li>
                    <li><a href="#Rola-testów-jednostkowych-w-ciągłym-testowaniu-">9.  Rola testów jednostkowych w ciągłym testowaniu </a></li>
                    <li><a href="#Jakie-narzędzia-wykorzystywane-są-w-procesie-dostarczania-oprogramowania-z-CI/CD?-">10.  Jakie narzędzia wykorzystywane są w procesie dostarczania oprogramowania z CI/CD? </a></li>
                    <li><a href="#Podsumowanie-">11.  Podsumowanie </a></li>
            </ol>
</div>


<h2 class="wp-block-heading" id="Automatyzacja-i-testowanie">Automatyzacja i testowanie</h2>



<p>Zmiany nie będą dotyczyły tylko kodu samej aplikacji, ale też testów (tworzenie testów jednostkowych nowej funkcjonalności). Jednym z kluczowych atrybutów ciągłej integracji jest wysoki stopień wykorzystania zautomatyzowanych testów. Po zakończeniu wprowadzania zmian na lokalnym komputerze wykonywany jest zautomatyzowany proces kompilacji (build). W procesie tym pobierany jest kod źródłowy z lokalnego repozytorium, który jest następnie kompilowany, łączony z plikiem wykonywalnym, a na końcu przeprowadzane są testy automatyczne. Build uznaje się za prawidłowy, gdy kompilacja oraz testy zakończą się poprawnie, bez błędów.&nbsp;&nbsp;</p>



<h2 class="wp-block-heading" id="Integracja-i-aktualizacja">Integracja i<strong> </strong>aktualizacja</h2>



<p>Następnym krokiem jest zatwierdzenie zmian w repozytorium. Na tym etapie należy uwzględnić zmiany wprowadzone przez innych członków w zespole, ponieważ w międzyczasie zmiany innego programisty mogły zostać już zintegrowane z głównym repozytorium tworzonego oprogramowania. Należy więc najpierw zaktualizować lokalną gałąź z kodem z głównej gałęzi <strong>(master)</strong> i ponownie uruchomić zautomatyzowaną kompilację <strong>(build).</strong> Jeżeli w trakcie tego procesu pojawią się konflikty (zmiany w kodzie kolidujące ze zmianami wprowadzonymi przez innych programistów), należy je rozwiązać i ponownie uruchomić kompilację. Gdy zakończy się ona powodzeniem, zmiany można zatwierdzić i zintegrować z głównym repozytorium.&nbsp;</p>



<p>W tym momencie wykonywana jest ponowna kompilacja, lecz tym razem jest ona przeprowadzana na serwerze integracyjnym. Zdarza się, że podczas kompilacji na lokalnej stacji roboczej coś może zostać przeoczone, przez co główne repozytorium zostanie zaktualizowane w nieodpowiedni sposób. Dopiero gdy zmiany w głównym repozytorium zbudują się poprawnie na serwerze CI, można je będzie uznać za zakończone sukcesem.&nbsp;</p>



<p>Jeśli dojdzie do konfliktów w plikach zmienionych przez innych programistów, zwykle będą one wychwycone, gdy programista zatwierdzający zmiany utworzy zaktualizowaną kopię roboczą, a sama kompilacja zakończy się niepowodzeniem. Błąd jest szybko wyłapany, a zadaniem programistów jest zlokalizowanie źródła błędów i naprawienie ich. W środowisku CI należy unikać sytuacji, w których przez dłuższy czas kompilacje integracyjne kończą się błędem – trzeba je naprawić najszybciej, jak to możliwe.&nbsp;</p>



<p>Po pomyślnej kompilacji na serwerze ciągłej integracji nowe zmiany można wprowadzić na przykład na środowiska testowe, gdzie testerzy będą mogli przeprowadzać testy na aktualnej wersji oprogramowania zawierającej najnowsze zmiany.&nbsp;</p>



<h2 class="wp-block-heading" id="Zarządzanie-błędami-i-powiadomienia">Zarządzanie błędami i powiadomienia</h2>



<p>Na każdym etapie procesu ciągłej integracji po stronie serwera, w razie niepowodzenia w budowaniu projektu, można zaimplementować narzędzia raportujące błędy. W ten sposób, w przypadku wystąpienia błędu w którymś kroku kompilacji – odpowiedni użytkownicy mogą zostać powiadomieni, na przykład za pomocą wiadomości e-mail lub powiadomienia na firmowym czacie.&nbsp;</p>



<p>Przykładowy ogólny schemat procesu ciągłej integracji:&nbsp;</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="762" height="426" src="https://nearshore-it.eu/wp-content/uploads/2024/08/blog_2024.05.16_graphic_2.png" alt="chemat procesu ciągłej integracji CI" class="wp-image-28713" title="Jak wygląda proces dostarczania oprogramowania oparty na CI/CD? 36" srcset="https://nearshore-it.eu/wp-content/uploads/2024/08/blog_2024.05.16_graphic_2.png 762w, https://nearshore-it.eu/wp-content/uploads/2024/08/blog_2024.05.16_graphic_2-300x168.png 300w, https://nearshore-it.eu/wp-content/uploads/2024/08/blog_2024.05.16_graphic_2-495x277.png 495w" sizes="auto, (max-width: 762px) 100vw, 762px" /></figure></div>


<h2 class="wp-block-heading" id="Praktyka-DevOps">Praktyka DevOps</h2>



<p>Termin DevOps pochodzi z połączenia dwóch słów: development i operations (programowanie i operacje). Służy do określenia podejścia do rozwoju oprogramowania zakładającego zmniejszanie barier pomiędzy zespołami deweloperskimi i operacyjnymi firmy. Celem DevOps jest skrócenie czasu wprowadzenia produktu na rynek. Oznacza to przyjęcie i wdrożenie pewnych praktyk w celu skrócenia czasu od identyfikacji nowego wymagania do momentu jego wdrożenia dla klientów. W podejściu tym wykorzystywana jest omawiana ciągła integracja i ciągłe dostarczanie, które pomagają skrócić czas wprowadzenia produktu na rynek i stworzyć oprogramowanie lepszej jakości.&nbsp;</p>



<h3 class="wp-block-heading" id="Historia-i-rozwój">Historia i rozwój</h3>



<p>Celem DevOps jest skrócenie czasu wprowadzenia produktu na rynek. Filozofia DevOps narodziła się w 2008 roku podczas konferencji Agile w Toronto, kiedy&nbsp; Patrick Debois wygłosił wykład pod tytułem „Infrastructure and Operations“. Wyjaśnił w nim zastosowanie podejścia Agile do budowy infrastruktury, a na koniec zaproponował lepszą metodę komunikacji oraz pomysły, dzięki którym programiści mogliby „ poszerzać swoje horyzonty”, w sensie pogłębiania wiedzy systemowej niezbędnej do zapewnienia płynniejszego procesu wydawania oprogramowania. Mijały lata, a podejście DevOps stawało się coraz bardziej popularne, a w ślad za nim pojawiła się nowa rola w świecie IT – inżynier DevOps.&nbsp;&nbsp;</p>



<h3 class="wp-block-heading" id="Rola-inżyniera-DevOps">Rola inżyniera DevOps</h3>



<p>Inżynier DevOps stanowi swego rodzaju pomost pomiędzy programistami a działem operacyjnym. W większości przypadków rola, jaką przyjmuje, jest ich mieszanką (inżynierowie ci muszą posiadać wiedzę niezbędną do doradzania i zarządzania problemem z obu dyscyplin). W niektórych przypadkach odpowiedzialność inżyniera DevOps związana jest z ciągłą integracją i dostarczaniem. Inne obowiązki obejmują zarządzanie infrastrukturą, zazwyczaj w postaci kodu (IaC) oraz pomoc we wdrażaniu optymalnych praktyk DevOps w całej firmie. Czasem inżyniera DevOps postrzega się go także jako osobę odpowiedzialną głównie za utrzymanie oprogramowania w środowisku produkcyjnym i automatyzację procesów, rozwiązywanie problemów, administrowanie systemem.&nbsp; Rola inżyniera DevOps jest zróżnicowana i może zmieniać się w zależności od firmy.&nbsp;</p>



<h2 class="wp-block-heading">Zalety podejścia DevOps</h2>



<h3 class="wp-block-heading">Efektywność i współpraca&nbsp;</h3>



<p>Zespoły, które wdrażają podejście DevOps, stają się bardziej wydajne, dzięki czemu tworzone oprogramowanie wydawane jest nie tylko szybciej, ale też jest bardziej stabilne. Lepsza współpraca i zwiększona produktywność pozwalają też osiągać cele biznesowe, takie jak szybsze wprowadzenie produktu na rynek czy utrzymanie jego niezawodności i stabilności w każdych warunkach. Zastosowanie metodyki DevOps nie tylko pozwala zautomatyzować i optymalizować procesy za pomocą technologii. Jest to przede wszystkim zmiana kultury wewnątrz organizacji i ludzi zaangażowanych w ten proces.&nbsp;&nbsp;</p>



<p>Wdrożenie kultury DevOps wymaga głębokich zmian w dotychczasowym sposobie pracy zespołów i przestrzegania określonych zasad, jednak te zmiany pozwalają stworzyć środowisko pracy o wysokiej wydajności.&nbsp;&nbsp; Cechą charakterystyczną DevOps jest ścisła współpraca między zespołami. Różne zespoły, na przykład zespoły deweloperów i odpowiedzialne za operacje, muszą dzielić się swoimi procesami, priorytetami i problemami. Muszą także wspólnie planować pracę oraz cele i środki związane z ich osiągnięciem. W miarę jak zespoły dostosowują się do nowej rzeczywistości, obowiązki w poszczególnych rolach również zaczynają się poszerzać. Na przykład deweloperzy stają się odpowiedzialni nie tylko za tworzenie aplikacji w fazie programowania, ale też za wydajność i stabilność w fazie działania. Jednocześnie zespół operacji uwzględnia nadzór, zabezpieczenia i zgodność w fazach planowania i programowania.&nbsp;&nbsp;</p>



<h3 class="wp-block-heading">Elastyczność i reaktywność&nbsp;</h3>



<p>Elastyczność zespołów pozwala na wydawanie oprogramowania w krótszych cyklach. Łatwiej jest planować wdrażanie zmian i zarządzać ryzykiem – to droga do stworzenia stabilnego produktu. Krótsze cykle wydawania nowych wersji pozwalają także sprawniej reagować na zmiany zachodzące na rynku, dzięki czemu można szybciej dostosować się do zmian potrzeb klientów i nie odstawać od konkurencji. Podejście DevOps stanowi state-of-the-art nowoczesnego tworzenia oprogramowania i jest dziś pierwszym wyborem wielu firm z tego powodu, że promuje najlepsze praktyki niezbędne do poprawy jakości oprogramowania. DevOps wymaga zmiany nie tylko w sposobie myślenia o infrastrukturze, ale także w&nbsp; zakresie dobrego projektowania i organizowania wewnętrznej infrastruktury firmy.&nbsp;&nbsp;&nbsp;</p>



<h3 class="wp-block-heading">Ciągłe testowanie&nbsp;</h3>



<p>Ciągłe testowanie (Continuous Testing, CT) to umiejętne wykorzystanie pewnych narzędzi i technik. Cytując <a href="https://sjsi.org/ist-qb/do-pobrania/" target="_blank" rel="noreferrer noopener">sylabus ISTQB</a>, ciągłe testowanie to:&nbsp;&nbsp;</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>„Podejście obejmujące proces wczesnego, częstego, szerokiego, automatycznego testowania w celu otrzymania możliwie szybko informacji zwrotnej o poziomie ryzyka biznesowego związanego z aplikacją przed jej wydaniem”.&nbsp;&nbsp;</p>
</blockquote>



<p></p>



<p>Podejście to znacznie skraca czas potrzebny do wykonania testów manualnych.&nbsp;</p>



<p>Głównym celem wprowadzenia podejścia CI/CD jest poprawa jakości wydawanego oprogramowania, a ciągłe testowanie i kontrola powinny być częścią tego procesu.&nbsp; Celem ciągłego testowania jest zapewnienie, że wydawane oprogramowanie będzie niezawodne.&nbsp; W tym celu tworzy się różnego rodzaju testy, które mogą być wykonywane automatycznie za każdym razem, gdy oprogramowanie jest budowane.&nbsp;</p>



<h3 class="wp-block-heading">Poziomy testów w ciągłym testowaniu&nbsp;</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" width="762" height="320" src="https://nearshore-it.eu/wp-content/uploads/2024/08/blog_2024.05.16_graphic_3.png" alt="Poziomy testów w ciągłym testowaniu " class="wp-image-28716" style="width:1160px;height:auto" title="Jak wygląda proces dostarczania oprogramowania oparty na CI/CD? 37" srcset="https://nearshore-it.eu/wp-content/uploads/2024/08/blog_2024.05.16_graphic_3.png 762w, https://nearshore-it.eu/wp-content/uploads/2024/08/blog_2024.05.16_graphic_3-300x126.png 300w, https://nearshore-it.eu/wp-content/uploads/2024/08/blog_2024.05.16_graphic_3-495x208.png 495w" sizes="auto, (max-width: 762px) 100vw, 762px" /></figure></div>


<ol start="1" class="wp-block-list">
<li><strong>Testy jednostkowe</strong> – bazę testów automatycznych stanowią testy jednostkowe. Są one wykonywane za każdym razem, gdy oprogramowanie jest kompilowane i budowane.&nbsp;&nbsp;</li>
</ol>



<ol start="2" class="wp-block-list">
<li><strong>Testy integracyjne</strong> – kolejnym poziomem testów, który należy włączyć, są testy integracyjne. Są one przeprowadzane po testach jednostkowych i wykorzystują rzeczywiste dane. Testy integracyjne są ważną fazą w ciągłym testowaniu, ponieważ odpowiadają za testowanie całego systemu, a nie tylko tworzonego kodu.&nbsp;&nbsp;</li>
</ol>



<ol start="3" class="wp-block-list">
<li><strong>Testy akceptacyjne (E2E)</strong> – ostatnią fazą są testy akceptacyjne. W tej fazie wykonywane są testy przygotowane przez zespół QA w celu przetestowania systemu z punktu widzenia użytkownika. Celem tej fazy jest weryfikacja wymagań użytkownika i ich walidacja.&nbsp;</li>
</ol>



<h3 class="wp-block-heading">Kontrola kodu&nbsp;</h3>



<p>Oprócz różnych faz testowania, istnieje także faza kontroli kodu. Polega ona na sprawdzeniu kodu przy wykorzystaniu zestawu reguł wykorzystywanych do sporządzenia raportu na temat samego oprogramowania. Można ją podzielić na dwie fazy:&nbsp;&nbsp;</p>



<ol start="1" class="wp-block-list">
<li><strong>Przegląd kodu&nbsp;</strong>wykonywany przez programistę, który nie jest&nbsp; jego autorem. Przed integracją z główną gałęzią (master) kod musi zostać zatwierdzony. Członkowie zespołu sprawdzają kod i dodają komentarze, jeśli jakieś fragmenty wymagają zmian. W tym przypadku autor kodu dokonuje zmian na ich podstawie, a po skończonej pracy kod ponownie trafia do przeglądu. Jeśli nikt nie będzie miał zastrzeżeń – kod zostanie zaakceptowany i scalony z główną gałęzią.&nbsp;</li>



<li><strong>Faza statycznej analizy</strong> jest wykonywana przez odpowiednie narzędzia. Kod może zostać wtedy zweryfikowany przez pewne reguły, na przykład sprawdzające złożoność metod.&nbsp;&nbsp;</li>
</ol>



<p></p>



<h2 class="wp-block-heading">Automatyzacja i shift-left testing&nbsp;</h2>



<p>Ciągłe testowanie wykorzystuje podejścia automatyzacji do przyspieszenia testowania poprzez przyjęcie podejścia shift-left testing, które łączy etapy wytwarzania oprogramowania i zapewniania jakości. Takie podejście może obejmować zestaw przepływów pracy testów automatycznych, które można łączyć z narzędziami raportującymi i metrykami w celu otrzymania jasnego obrazu jakości oprogramowania.&nbsp;</p>



<p>Zapewnia to zespołom projektowym otrzymanie szybkiej informacji zwrotnej na temat jakości oprogramowania. Pozwala również testować na wcześniejszych etapach wytwarzania oprogramowania oraz zwiększyć pokrycie testami, eliminując wąskie gardła testowe, takie jak: dostęp do współdzielonych środowisk testowych czy oczekiwanie na stabilny interfejs użytkownika.&nbsp;</p>



<p><strong>Ciągłe testowanie niesie ze sobą szereg korzyści, takich jak:</strong>&nbsp;</p>



<p></p>



<ul class="wp-block-list">
<li>Integrowanie zespołów testowych, deweloperskich i operacyjnych na każdym etapie cyklu życia oprogramowania.&nbsp;</li>



<li>Pozwala na wdrożenie testów automatycznych w takim zakresie, jak to tylko możliwe, aby stale testować kluczowe funkcje.&nbsp;</li>



<li>Szybkie i ciągłe informacje zwrotne, które są istotne również dla biznesu.&nbsp;</li>



<li>Usunięcie wąskich gardeł w kwestii dostępności środowisk testowych, które mogą być stale dostępne.&nbsp;</li>



<li>Pozwala na stałe i aktywne zarządzanie jakością w całym etapie dostarczania oprogramowania. &nbsp;</li>
</ul>



<h3 class="wp-block-heading">Fundamenty ciągłego testowania&nbsp;</h3>



<p>Ciągłe testowanie opiera się na kombinacji określonych narzędzi i technik. Odpowiednie ich wdrożenie tworzy system, dzięki któremu znacząco można ograniczyć liczbę błędów przedostających się na środowiska rozwojowe lub produkcyjne. Większość błędów ma bardzo krótką żywotność, ponieważ są one wyłapywane przez testy. Odpowiednie zaimplementowanie tego podejścia powinno rozpoczynać się na jak najwcześniejszym etapie cyklu życia oprogramowania, aby móc je odpowiednio budować, aktualizować i (w razie potrzeby) refaktoryzować. Sama budowa i działanie zależą w głównej mierze od potrzeb projektowych – inne testy i techniki będą wykorzystywane do testowania sklepu internetowego, inne do testowania systemów w branży automotive. Lecz niezależnie od przypadku, cel pozostanie ten sam – uzyskanie jak najszybciej informacji zwrotnej w przypadku wystąpienia błędu.&nbsp;</p>



<h2 class="wp-block-heading">Projektowanie małych komponentów i usług&nbsp;</h2>



<p>Idea ciągłego testowania polega na maksymalnym zautomatyzowaniu procesów testowania i wdrażania oraz zapewnieniu, że każdy komponent aplikacji może zostać poddany testom, gdy tylko zostanie opracowany. Przykłady, które mogą ułatwić implementację tego podejścia to: projektowanie małych komponentów i usług oraz projektowanie danych testowych wykorzystywanych w ciągłym testowaniu.&nbsp;</p>



<p>Projektowanie małych komponentów i usług – nowe komponenty powinny nie tylko spełniać określone funkcje w trakcie działania programu, ale również być w pełni testowalne niezależnie od innych komponentów. Celem jest zapewnienie, że każda w pełni przetestowana usługa będzie spełniała swoje zadania zgodnie z założeniami, aby w trakcie ich łączenia i przejścia do etapu testów integracyjnych komponenty bezproblemowo współpracowały ze sobą.. Należy więc już na etapie projektowania odpowiednio przygotować architekturę i ograniczyć sprzężenie komponentów tak bardzo, jak to możliwe. W efekcie zyskamy komponenty bardziej stabilne, które zmniejsza ryzyko, że jakakolwiek zmiana dokonana w komponencie „A&#8221; spowoduje nieoczekiwaną zmianę zachowania w innych komponentach. Ograniczenie połączeń między nimi upraszcza proces testowania, rozwiązywania problemów oraz konserwacji. Dodatkowo w łatwiejszy sposób można izolować ewentualne problemy – analizie zostanie poddany konkretny komponent, bez potrzeby przeszukiwania ich grup i zależności między nimi.&nbsp;</p>



<h2 class="wp-block-heading">Projektowanie danych testowych wykorzystywanych w ciągłym testowaniu&nbsp;</h2>



<p>Posiadanie w pełni zautomatyzowanego rozwiązania do zarządzania danymi testowymi jest niezbędne do solidnego wdrożenia ciągłego testowania. Złym podejściem byłoby na przykład kopiowanie produkcyjnej bazy danych w celu utworzenia danych testowych, nie anonimizując uprzednio wrażliwych danych. Tworzenie nowych zestawów danych testowych od zera dla każdej serii testów również nie jest dobrym pomysłem ze względu na bardzo słabą efektywność, zwłaszcza gdy nie są generowane automatycznie.&nbsp;</p>



<p>Jak zatem stworzyć skuteczne rozwiązania do generowania i zarządzania danymi testowymi? Z pomocą przychodzą pewne charakterystyki, do których można zaliczyć na przykład:&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Tworzenie i generowanie danych testowych&nbsp;</strong><br>Daje możliwość tworzenia nowych, zbiorczych zestawów danych uwzględniających zależności, tak jakby pochodziły ze środowiska produkcyjnego.&nbsp;</li>



<li><strong>Możliwość pobrania pewnego podzbioru danych produkcyjnych&nbsp;</strong><br>Na podstawie określonych kryteriów, maskowania wrażliwych pól i umieszczania ich w środowisku testowym, zachowując ich integralność referencyjną. Najtrudniejsza w realizacji jest ostatnia część: wrażliwe pola muszą być zamaskowane w taki sposób, aby zachować oryginalne powiązania między danymi. Przykładowo, jeśli wartość numeru PESEL musi zostać zamaskowana i zastąpiona niepowiązaną wartością, każde odwołanie do tego numeru PESEL w bazie danych musi zostać zamaskowane tą samą wartością.&nbsp;</li>



<li><strong>Możliwość maskowania i transformacji danych&nbsp;</strong><br>Rozwiązanie powinno też zapewnić możliwość automatycznego porównania danych wstępnie zamaskowanych, aby upewnić się, że nie doszło do ich utraty i że proces maskowania nie spowodował błędów w ich integralności.&nbsp;</li>



<li><strong>Możliwość przesyłania danych&nbsp;</strong><br>Proces polegający na przesyłaniu wyodrębnionych, zamaskowanych danych na środowiska testowe, z zachowaniem integralności. Proces ten powinien obejmować funkcje dodawania, edytowania, aktualizacji i usuwania.&nbsp;</li>



<li><strong>Możliwość odświeżania danych&nbsp;</strong><br>Polega na okresowym przeglądzie i usuwaniu starych pakietów danych testowych oraz zamienianiu ich na nowy zestaw.&nbsp;</li>



<li><strong>Ekstrakcja danych i tworzenie ich podzbiorów&nbsp;</strong><br>Pozwala na tworzenie mniejszych kopii danych produkcyjnych zdefiniowanych za pomocą określonych kryteriów.&nbsp;</li>



<li><strong>„Postarzanie&#8221; danych&nbsp;</strong><br>Technika, w której dane są zmieniane w celu dopasowania ich do określonych, specyficznych warunków i wykorzystania ich w pewnych procesach (na przykład symulacji określonej godziny lub daty).&nbsp;</li>



<li><strong>Możliwość tworzenia i wyodrębniania danych testowych&nbsp;</strong></li>



<li><strong>Zarządzanie zbiorami danych&nbsp;</strong></li>



<li>Wykorzystanie narzędzi, które umożliwiają nie tylko zarządzanie wieloma zbiorami danych, ale także ich archiwizację i wersjonowanie. &nbsp;</li>
</ul>



<h2 class="wp-block-heading">Rola testów jednostkowych w ciągłym testowaniu&nbsp;</h2>



<p>Podstawę testów w podejściu ciągłego testowania, zgodnie z piramidą testów, stanowią testy jednostkowe. Są one najszybsze w wykonaniu i sprawdzają działanie oprogramowania we wczesnej fazie jego wytwarzania. Powinno ich więc być jak najwięcej (przy zachowaniu odpowiedniego stosunku liczby do jakości – nie jest prawdą, że większa liczba testów stanowi o jakości).&nbsp;&nbsp;</p>



<h3 class="wp-block-heading">Projektowanie testów jednostkowych&nbsp;</h3>



<p>Zdarza się, że testy jednostkowe są źle zaprojektowane i zamiast jednostek testują kompletne przypadki użycia (wywołanie metod, asercje, wywołanie większej liczby metod i tworzenie większej liczby asercji). Takie testy są zwykle niestabilne, a błędy wykryte w jednej części kodu mogą maskować inne błędy i utrudniać ich wykrycie. Aby temu zapobiec, należy przeanalizować takie testy, wyodrębnić z nich poszczególne, testowane funkcjonalności i asercje i rozbić je na mniejsze testy sprawdzające każdą funkcjonalność z osobna.&nbsp;</p>



<h3 class="wp-block-heading">Implementacja testów na różnych poziomach&nbsp;</h3>



<p>Testowanie bardziej złożonych ścieżek, dajmy na to przypadków użycia, powinno zostać zaimplementowane na przykład w testach akceptacyjnych. W ciągłym testowaniu można wykonywać wszystkie rodzaje testów, lecz im wyższy poziom testów, tym liczba przypadków testowych powinna być mniejsza (są one mniej stabilne, czas ich wykonywania jest dłuższy, wykrywają błędy w późniejszych etapach, przez co wydłuża się czas naprawy, a koszt rośnie).&nbsp;</p>



<p>Dotyczy to zwłaszcza testów UI (User Interface), gdy testowana jest logika biznesowa i zachowanie interfejsu użytkownika. Może tu dojść do wielu współzależnych awarii. Oddzielenie warstwy interfejsu od systemu bazowego, aby logika biznesowa mogła zostać opatrzona zaślepkami (mock) jest istotną zmianą zbliżającą nas do większej stabilności testów.&nbsp;</p>



<p>Jednym z podejść jest uruchamianie testów jednostkowych w sposób ciągły, a testów wyższych poziomów – na żądanie (nie muszą one być uruchamiane automatycznie w trakcie budowy projektu w narzędziu ciągłej integracji – zamiast tego, istnieje możliwość uruchomienia ich w sposób manualny, gdy potrzeba).&nbsp;</p>



<h3 class="wp-block-heading">Rola podejścia TDD&nbsp;</h3>



<p>Praktykowanie podejścia TDD (Test-Driven Development) w wytwarzaniu oprogramowania ułatwia zrozumienie i wdrożenie ciągłego testowania. W TDD testy tworzone są przed implementacją funkcjonalności. Najpierw tworzony jest mały test, po którym następuje implementowanie powiązanego fragmentu całej funkcjonalności. Następnie dokonuje się refaktoryzacji w celu ulepszenia kodu i wyeliminowania ewentualnych powieleń. Dzięki ciągłemu testowaniu otrzymujemy natychmiastową informację zwrotną na każdym z tych kroków. Nie tylko z tego jednego testu, który jest w danym momencie pisany, lecz ze wszystkich powiązanych testów, bez dodatkowego wysiłku i zaangażowania ze strony programisty. Dzięki temu może on skupić się w pełni na projektowaniu i pisaniu kodu, zamiast rozpraszać się koniecznością uruchamiania testów.&nbsp;</p>



<h3 class="wp-block-heading">Cel ciągłego testowania&nbsp;</h3>



<p>Zarówno w podejściu TDD, jak i w ciągłym testowaniu, celem jest jak najszybsze uzyskanie informacji zwrotnej. Pod wieloma względami naturalnym rezultatem skutecznego stosowania TDD jest dobrej jakości zestaw testów. Różnica polega na tym, że stosując ciągłe testowanie, zyskuje się dodatkowe źródła informacji zwrotnych. Stary aksjomat podejścia TDD mówi, że testy sprawdzają poprawność kodu, z kolei kod weryfikuje poprawność testów. Testy sprawdzają również projekt kodu – źle zaprojektowany kod jest trudny do przetestowania. &nbsp;</p>



<h2 class="wp-block-heading">Jakie narzędzia wykorzystywane są w procesie dostarczania oprogramowania z CI/CD?&nbsp;</h2>



<h3 class="wp-block-heading">Jenkins&nbsp;</h3>



<p>Jenkins to serwer ciągłej integracji (CI) typu open source.&nbsp; Kontroluje kilka etapów procesu dostarczania oprogramowania, takie jak testowanie, kompilacja i wdrażanie. Popularność tego narzędzia wynika między innymi z jego możliwości śledzenia i monitorowania powtarzalnych działań pojawiających się w trakcie prac nad projektem. Każda zmiana w aplikacji jest kompilowana i testowana, a w razie wykrycia błędu Jenkins ostrzeże zespół o problemach.&nbsp;</p>



<p><strong>Wdrożenie kodu na produkcję</strong>&nbsp;</p>



<p>Jednym z podstawowych zastosowań Jenkinsa jest możliwość wdrażania kodu na produkcję. Jeśli wszystkie testy opracowane dla danej funkcji lub releasu zakończą się powodzeniem, Jenkins może automatycznie opublikować kod na środowisku staging lub produkcyjnym (jest to właśnie przykład Continuous Deployment opisanego w poprzednim artykule).&nbsp;</p>



<p><strong>A</strong><strong>ut</strong><strong>o</strong><strong>matyzacja </strong><strong>w</strong><strong>orkflow</strong><strong> i różnych zadań</strong><strong></strong>&nbsp;</p>



<p>Innym przypadkiem, w którym można użyć Jenkinsa, jest m.in. automatyzacja workflow. Na przykład, gdy programista pracuje na kilku środowiskach, w pewnym momencie zajdzie konieczność instalacji lub aktualizacji pewnych komponentów na każdym z nich. Jeśli instalacja lub aktualizacja wymaga wykonania wielu kroków, przeprowadzenie jej ręcznie może skutkować pojawieniem się błędów, a dodatkowo będzie czasochłonne. Zamiast tego wszystkie kroki potrzebne do finalizacji można odpowiednio skonfigurować w Jenkinsie. Dzięki temu cały proces będzie stabilny i szybki, bo też zawsze będzie wykonywany identycznie.&nbsp;</p>



<p><strong>Konfiguracja zadań</strong>&nbsp;</p>



<p>Jenkins umożliwia tworzenie zadań (Jenkins Jobs) na różne sposoby. Konfigurację można stworzyć całkowicie przez UI, przeklikując odpowiednie opcje, lecz lepszym wyborem jest utworzenie pliku konfiguracyjnego i zdefiniowanie w nim wszystkich niezbędnych kroków. W Jenkinsie wykorzystuje się w tym celu skrypty pisane w języku Groovy. Zaletą w stosowaniu tej opcji jest dodatkowo to, że plik konfiguracyjny można przechowywać wraz z kodem dotyczącej go aplikacji. Dzięki temu mamy zapewnione wersjonowanie zmian i powstaje kopia zapasowa, przydatna w przypadku wystąpienia awarii.&nbsp;</p>



<p><strong>Rozszerzalność poprzez pluginy</strong>&nbsp;</p>



<p>Możliwości Jenkinsa można rozszerzać dzięki wielu pluginom dostępnym na stronie https://plugins.jenkins.io/. Ich liczba pozwala na dowolne skonfigurowanie serwera pod konkretne potrzeby, począwszy od zmiany wyglądu elementów interfejsu użytkownika po możliwość integracji z zewnętrznymi serwisami lub aplikacjami czy modyfikujące kroki w tworzonych jobach.<strong> </strong>&nbsp;</p>



<h3 class="wp-block-heading">GitLab&nbsp;</h3>



<p>Innym narzędziem, o którym warto wspomnieć, jest GitLab. Serwis ten nie tylko pozwala na tworzenie i przechowywanie repozytoriów kodu, ale także udostępnia narzędzia do wersjonowania oprogramowania, zarządzania zadaniami oraz procesami CI/CD. Pozwala on wszystkim członkom zespołu współpracować na wszystkich etapach projektu, upraszczając tworzenie oprogramowania.&nbsp;</p>



<p><strong>Funkcjonalności GitLaba</strong>&nbsp;</p>



<p>GitLab to internetowe repozytorium Git, które umożliwia zespołom programistów planowanie, kodowanie, testowanie, wdrażanie i monitorowanie zmian tworzonego oprogramowania w jednym miejscu. Natomiast Git to dobrze wszystkim znany system kontroli wersji.&nbsp;</p>



<p>Jedną z istotnych możliwości jest śledzenie błędów: GitLab posiada wbudowany system umożliwiający zespołom tworzenie, przypisywanie i śledzenie błędów. Zapewnia także tablicę zarządzania projektami z konfigurowalnymi przepływami pracy (workflow) w celu wizualizacji zadań i postępów.&nbsp;</p>



<p>Inną kluczową funkcjonalnością GitLaba są zintegrowane potoki CI/CD (pipelines). Dzięki temu można łatwo zautomatyzować procesy testowania, budowania i wdrażania, zapewniając dokładne testowanie zmian w kodzie przed połączeniem z główną bazą kodu i wdrożeniem w środowisku produkcyjnym.&nbsp;</p>



<p>GitLab posiada także wewnętrzny system wiki, umożliwiający zespołom tworzenie i utrzymywanie dokumentacji projektowej.&nbsp;</p>



<h2 class="wp-block-heading">Podsumowanie&nbsp;</h2>



<p>Podejście Continuous Integration wraz z Continuous Development i Continuous Testing stanowią komplementarne praktyki. Continuous Development umożliwia obserwowanie wdrażanych zmian w czasie rzeczywistym i jednocześnie eliminuje proces ręcznego śledzenia zmian. Błędy znalezione na jak najwcześniejszym etapie są najszybsze i najtańsze w naprawie.&nbsp;</p>



<p>Budowanie aplikacji wraz z przeprowadzeniem testów na lokalnym środowisku może zająć kilka minut, a ich przeprowadzenie daje pewność, że wprowadzone zmiany będą przygotowane do integracji z główną gałęzią repozytorium. Czasem zmiany mogą budzić szczególne wątpliwości –&nbsp;&nbsp; na przykład, gdy modyfikacji wymagają pliki konfiguracyjne. W takim przypadku można wykonać pełną kompilację i uruchomić wszystkie testy, aby mieć pewność, że zmiana nie spowodowała błędów w innych obszarach aplikacji, a kod jest bezpieczny i może zostać dodany do głównego repozytorium.&nbsp;</p>



<p>Ciągła integracja ma na celu identyfikowanie problemów, ale może również posłużyć jako narzędzie do zmniejszania kosztów uruchamiania testów wyższego poziomu – wykrycie błędów na etapie testów jednostkowych sprawi, że testy z pozostałych poziomów będą bardziej stabilne, co daje dodatkową pewność co do jakości.&nbsp;at the capabilities are within the connectivity management framework. At Inetum, we are a partner of Cumulocity IoT, which has a network of partners providing platform-compatible devices with substantial connectivity capabilities.</p>



<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/proces-dostarczania-oprogramowania-ci-cd/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Dostarczanie wydajnego oprogramowania: automatyzacja CI/CD </title>
		<link>https://nearshore-it.eu/pl/artykuly/automatyzacja-ci-cd/</link>
					<comments>https://nearshore-it.eu/pl/artykuly/automatyzacja-ci-cd/#respond</comments>
		
		<dc:creator><![CDATA[Mateusz Mirecki]]></dc:creator>
		<pubDate>Fri, 24 May 2024 05:28:58 +0000</pubDate>
				<category><![CDATA[Artykuły]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[DevOps]]></category>
		<guid isPermaLink="false">https://nearshore-it.eu/artykuly/automatyzacja-ci-cd/</guid>

					<description><![CDATA[Continuous Integration, Delivery and Deployment sprowadzają się do automatyzacji procesu testowania i wdrażania, minimalizacji (lub całkowitego eliminowania) potrzeby ingerencji człowieka, redukcji ryzyka wystąpienia błędów oraz ułatwienia tworzenia i wdrażania oprogramowania.]]></description>
										<content:encoded><![CDATA[
<div class="table-of-contents">
    <p class="title">Przejdź do: </p>
    <ol>
                    <li><a href="#Definicja-Continuous-Integration-(CI)-oraz-Continuous-Delivery-(CD)">1.  Definicja Continuous Integration (CI) oraz Continuous Delivery (CD)</a></li>
                    <li><a href="#Wyzwania-CI/-CD">2.  Wyzwania CI/ CD</a></li>
                    <li><a href="#Czym-jest-ciągłe-dostarczanie-i-automatyzacja-CI/CD">3.  Czym jest ciągłe dostarczanie i automatyzacja CI/CD?</a></li>
                    <li><a href="#Continuous-Delivery-(CD)-">4.  Continuous Delivery (CD) </a></li>
                    <li><a href="#Korzyści-ciągłego-dostarczania-(CD)-">5.  Korzyści ciągłego dostarczania (CD)</a></li>
                    <li><a href="#Automatyzacja-vs-manualne-wdrazanie">6.  Automatyzacja vs. manualne wdrażanie</a></li>
                    <li><a href="#Podsumowanie">7.  Podsumowanie</a></li>
            </ol>
</div>


<p><em>Continuous Integration, Delivery and Deployment</em> to praktyki rozwoju oprogramowania, które w ostatnich latach zdobyły dużą popularność. Gdybyśmy mieli je podsumować jednym słowem, brzmiałoby to: automatyzacja. Wszystkie te trzy praktyki sprowadzają się do automatyzacji procesu testowania i wdrażania, minimalizacji (lub całkowitego eliminowania) potrzeby ingerencji człowieka, redukcji ryzyka wystąpienia błędów oraz ułatwienia tworzenia i wdrażania oprogramowania do tego stopnia, że może to zrobić każdy programista w zespole. Poznaj kluczowe praktyki i korzyści w zakresie automatyzacji CI/CD.  </p>



<h2 class="wp-block-heading" id="Definicja-Continuous-Integration-(CI)-oraz-Continuous-Delivery-(CD)">Definicja Continuous Integration (CI) oraz Continuous Delivery (CD)</h2>



<h3 class="wp-block-heading">Ciągła integracja</h3>



<p>Continuous Integration, CI jest praktyką stosowaną w procesie wytwarzania oprogramowania polegającą na częstym, regularnym integrowaniu bieżących zmian w kodzie do głównego repozytorium aplikacji. Zwykle programiści włączają swoje zmiany co najmniej raz dziennie, co przy zespole składającym się z kilku lub kilkunastu osób skutkuje wieloma integracjami wykonywanymi każdego dnia. Każda integracja jest weryfikowana przez zastosowanie automatyzacji w projekcie (włączając również testy automatyczne) w celu jak najszybszego wykrycia ewentualnych błędów integrowanego kodu. Stosowanie tego podejścia prowadzi do znacznego zmniejszenia liczby problemów związanych z integracją i umożliwia szybsze tworzenie spójnego oprogramowania.</p>



<h3 class="wp-block-heading">Ciągłe dostarczanie</h3>



<p>Continuous Delivery, CD – jest praktyką inżynierii oprogramowania polegającą na regularnym wydawaniu kolejnych wersji oprogramowania w krótkich cyklach. Oznacza to, że z każdą kompilacją budowana jest nowa wersja całego tworzonego oprogramowania. Nie znaczy to jednak, że oprogramowanie jest od razu wypuszczane na środowisko produkcyjne. Nic jednak nie stoi na przeszkodzie, aby to zrobić, gdyby zaszła taka potrzeba. Ta nieznaczna różnica dotycząca automatycznego wdrażania zmian bezpośrednio na środowisku produkcyjnym odróżnia ciągłe dostarczanie od ciągłego wdrażania (Continuous Deployment) – w którym to każda kompilacja całego oprogramowania kończy się wydaniem kolejnej wersji na środowisku produkcyjnym. Zespoły developerskie dbają o to, aby nowe funkcje były dodawane w małych pakietach, dzięki czemu ewentualne wydanie nowej wersji oprogramowania może nastąpić szybko i w dowolnym momencie. W praktyce maksymalizuje to możliwość uzyskania szybkiej informacji zwrotnej na temat oprogramowania zarówno z perspektywy biznesu, jak i technicznej.</p>



<h2 class="wp-block-heading" id="Wyzwania-CI/-CD">Wyzwania CI/CD</h2>



<p>O ciągłej integracji po raz pierwszy napisał Kent Beck w swojej książce pod tytułem „Extreme Programming Explained&#8221;, wydanej po raz pierwszy w 1999 roku. Ideą CI było: jeżeli regularna integracja kodu jest dobra – dlaczego nie wykonywać jej przez cały czas? „Cały czas&#8221; oznacza: za każdym razem, gdy ktoś wprowadza zmianę w systemie kontroli wersji.</p>



<p>Problem z ciągłą integracją, dostarczaniem i wdrażaniem polega jednak na tym, że konfiguracja nie należy do najprostszych czynności i zajmuje dużo czasu, zwłaszcza jeśli zespół ma z nią do czynienia po raz pierwszy lub postanowiono wdrożyć proces do istniejącego już projektu.</p>



<p>Jednak korzyści płynące z wprowadzenia tych praktyk są warte poświęconego czasu. Przejawi się to w mniejszej liczbie błędów, ułatwieniu ich identyfikacji i naprawy, a ostatecznie w stworzeniu oprogramowania lepszej jakości.</p>



<h2 class="wp-block-heading" id="Czym-jest-ciągłe-dostarczanie-i-automatyzacja-CI/CD">Czym jest ciągłe dostarczanie i automatyzacja CI/CD?</h2>



<h3 class="wp-block-heading">Ciągła integracja (CI).</h3>



<h3 class="wp-block-heading">Kluczowe aspekty skutecznej ciągłej integracji</h3>



<p>Przyjrzyjmy się CI jeszcze bliżej. Ciągła integracja na przestrzeni ostatnich kilku lat stała się w zasadzie standardem w zwinnych metodykach wytwarzania oprogramowania. Początkowo, w połączeniu z uruchamianiem automatycznych testów jednostkowych na lokalnym środowisku programisty, miała na celu zapewnienie, że programista nie włączy kodu, który mógłby powodować błędy w aplikacji. Z biegiem czasu metoda ta ewoluowała.</p>



<p>Obecnie kompilacje uruchamiane są na serwerach ciągłej integracji, które budują projekt oraz uruchamiają zautomatyzowane testy – automatycznie, przy każdej zmianie dodanej przez programistów, lub okresowo. Wynik (w postaci raportów, logów) generowany jest po zakończeniu procesu budowania. Obecnie podejście ciągłej integracji jest wykorzystywane nie tylko w metodykach zwinnych, ale również w innych metodykach wytwarzania oprogramowania.</p>



<p>Oprócz przeprowadzania testów jednostkowych i integracyjnych można też uruchamiać testy statyczne i dynamiczne, mierzyć i profilować wydajność, tworzyć dokumentację bazującą na kodzie źródłowym oraz upraszczać manualne procesy zapewnienia jakości. W ten sposób ciągła integracja zapewnia również ciągłą kontrolę jakości oprogramowania.</p>



<p>Dobrze funkcjonująca ciągła integracja opiera się na spełnieniu pewnych warunków wstępnych, a także przestrzeganiu kilku podstawowych praktyk. Przy jej wdrażaniu należy zadbać przede wszystkim o trzy rzeczy:</p>





<ol class="wp-block-list">
<li><strong>Narzędzie kontroli wersji</strong><br>Wszystko w projekcie musi być ewidencjonowane w jednym narzędziu kontroli wersji: kod, skrypty, bazy danych, skrypty kompilacji i wdrażania oraz wszystko inne, co jest niezbędne do tworzenia, instalowania, uruchamiania i testowania aplikacji.</li>



<li><strong>Narzędzie do zautomatyzowanej kompilacji</strong><br>Należy mieć możliwość uruchomienia kompilacji za pomocą wiersza poleceń. Podstawowym narzędziem może być prosty program wiersza poleceń, który skompiluje tworzony program, a następnie uruchomi testy. Może to być też złożona kolekcja skryptów kompilacji, które wywołują się nawzajem w odpowiedniej kolejności. Niezależnie od mechanizmu, osoba lub komputer musi mieć możliwość uruchomienia kompilacji, budowania, uruchamiania testów i wdrażania w sposób zautomatyzowany za pomocą wiersza poleceń. Skrypty powinny być traktowane jak kod – muszą być testowane i stale refaktoryzowane, aby były stabilne, uporządkowane i łatwe do zrozumienia.</li>



<li><strong>Zgoda całego zespołu</strong><br>Ciągła integracja jest praktyką, a nie narzędziem. Wymaga od zespołu programistycznego dyscypliny i zaangażowania. Każdy w zespole musi często wprowadzać swoje zmiany do repozytorium i przyjąć założenie, że najważniejszym zadaniem w trakcie pracy nad projektem jest naprawa wszelkich zmian, które psują aplikację. Jeśli zespół nie będzie przestrzegał tych zasad, poprawne wdrożenie ciągłej integracji może nie być efektywne i nie doprowadzi do satysfakcjonującej poprawy jakości wytwarzania oprogramowania.</li>
</ol>



<h3 class="wp-block-heading">Zalety ciągłej integracji w porównaniu z podejściem tradycyjnym</h3>



<p>W porównaniu do tradycyjnego podejścia, gdzie zmiany wprowadzane w kodzie źródłowym są kompilowane, testowane i integrowane raz na jakiś czas (raz w tygodniu lub rzadziej), wykorzystanie podejścia ciągłej integracji zapewnia wiele korzyści:</p>



<ul class="wp-block-list">
<li>wcześniejsze wykrywanie problemów kompilacji/integracji, dzięki czemu są naprawiane w sposób ciągły, a nie w ostatniej chwili, tuż zanim główna wersja oprogramowania zostanie przygotowana do wydania, </li>



<li>zespół otrzymuje natychmiastową informację zwrotną na temat jakości, funkcjonalności oraz wpływu pisanego kodu na cały system, </li>



<li>w ramach tego procesu wykonywane są zautomatyzowane testy. Dzięki nim możliwa jest natychmiastowa kontrola poprawności architektury projektu i jakości kodu – są one wykonywane w ramach procesów kompilacji, budowania i wdrażania zmian (deployment) na różne środowiska, </li>



<li>wczesny dostęp do aktualnej wersji oprogramowania (przed oficjalnym wydaniem) do celów testowych lub demonstracyjnych. </li>
</ul>



<h3 class="wp-block-heading">Kluczowe praktyki w procesie ciągłej integracji</h3>



<p>Optymalne korzyści z procesu ciągłej integracji można uzyskać, gdy przestrzega się ustalonych w zespole procedur, co wymaga dyscypliny, jak wspomniałem wcześniej. Istnieją też sprawdzone, dobre praktyki, których przestrzeganie znacząco zwiększy sukces we wdrożeniu tego procesu. Składają się na nie poniższe aspekty: </p>





<ol class="wp-block-list">
<li><strong>Częsta integracja kodu</strong> – najważniejsza praktyka w ciągłej integracji. Kod powinno się integrować przynajmniej kilka razy dziennie. Regularne wysyłanie zmian niesie ze sobą inne korzyści – zmiany są przesyłane w mniejszych pakietach, co zmniejsza prawdopodobieństwo błędu w kompilacji, a także ułatwia poszukiwanie ewentualnych zmian (mniejsza liczba plików do przeszukiwania). To minimalizuje też prawdopodobieństwo wystąpienia konfliktów z kodem innych programistów w przypadku pracy wymagającej zmiany w wielu plikach. W przypadku awarii lokalnej stacji roboczej, która spowodowałyby utratę lokalnych zmian w kodzie – programista nie musi pisać wszystkiego od początku, lecz może zacząć od etapu zmian wprowadzonych w ostatniej integracji.</li>



<li><strong>Zarządzanie obszarem roboczym</strong> – ważne jest, aby środowisko programistyczne było starannie zarządzane – przede wszystkim zwiększa to produktywność. Deweloperzy powinni zawsze rozpoczynać nową pracę od aktualnej, działającej wersji kodu z głównej gałęzi repozytorium. Powinni móc uruchomić kompilację, testy i być w stanie wdrożyć aplikację w swoim lokalnym środowisku. Uruchamianie aplikacji w środowisku lokalnym powinno wykorzystywać te same zautomatyzowane procesy, co w serwerach ciągłej integracji.</li>



<li><strong>Kompleksowy zestaw testów automatycznych</strong> – konieczne jest posiadanie zestawu testów automatycznych, aby mieć pewność, że aplikacja działa poprawnie. Najważniejsze z punktu widzenia ciągłej integracji są testy: jednostkowe, integracyjne oraz akceptacyjne. Ich kombinacja powinna zapewnić bardzo wysoki poziom pewności co do tego, że żadna z wprowadzonych zmian nie naruszyła stabilności aplikacji.   </li>



<li><strong>Krótki proces budowania i testowania projektu </strong>– kompilacja, budowanie i wykonanie testów nie powinny trwać dłużej niż 5-10 minut. Jeśli z jakiegoś powodu proces ten zajmuje zbyt dużo czasu, mogą wystąpić problemy takie jak: 
<ul class="wp-block-list">
<li>niecierpliwość programistów – mogą oni przestać wykonywać pełną procedurę (na przykład pomijać etap testów), co będzie powodować więcej błędów kompilacji na serwerze ciągłej integracji. </li>



<li>proces ciągłej integracji może trwać tak długo, że do czasu ponownego uruchomienia kompilacji może zostać zintegrowanych wiele zmian – znalezienie tej, która powoduje błędy, może być bardzo czasochłonne. </li>



<li>rzadsza integracja zmian przez programistów z powodu czasochłonności procesu – czekanie kilku godzin na zakończenie kompilacji i testów jest stratą czasu i zasobów. </li>
</ul>
</li>
</ol>



<h2 class="wp-block-heading" id="Continuous-Delivery-(CD)-">Continuous Delivery (CD) </h2>



<p>Ciągła integracja stanowi podstawę solidnego, nowoczesnego wytwarzania oprogramowania. Jest to czynnik umożliwiający wdrożenie jeszcze bardziej zaawansowanych technik. W ciągłej integracji, gdy wszystkie testy zakończą się pomyślnie, zyskujemy pewność, że oprogramowanie działa. Jednakże – w jaki sposób upewnić się, że oprogramowanie będzie działało w środowisku docelowym? Czy będzie współpracowało z innymi aplikacjami? Wreszcie – jak dostarczyć je do użytkowników końcowych? Z pomocą przychodzi podejście ciągłego dostarczania (Continuous Delivery, CD).&nbsp;</p>



<p>W swej istocie ciągłe dostarczanie polega na minimalizowaniu czasu potrzebnego do wprowadzenia zmian w aplikacji oraz minimalizowaniu ryzyka wystąpienia problemów, które także mogą pojawić się w trakcie tego procesu. Może składać się z kilku faz, takich jak: </p>



<ul class="wp-block-list">
<li><strong>Odkrywanie</strong> – w której analizuje się pomysły, ogólne działanie, funkcjonalności – aby uzyskać szersze zrozumienie przestrzeni problemu i zastanowić się nad potencjalnymi rozwiązaniami. </li>



<li><strong>Definiowanie</strong> – gdzie formalne kryteria akceptacji i prace projektowe stanowią bazę do dalszych prac rozwojowych. </li>



<li><strong>Rozwój</strong> – w której produkt jest budowany i testowany funkcjonalnie. </li>



<li><strong>Akceptacja</strong> – w tej fazie przeprowadzane są testy akceptacyjne wysokiego poziomu i uzyskuje się potwierdzenia od akcjonariuszy. </li>



<li><strong>Wdrożenie</strong> – zmiana jest wprowadzana na produkcję. </li>



<li><strong>Weryfikacja</strong> – w ramach której, na podstawie wszelkich danych, analizuje się zmiany, aby upewnić się, że osiągnęły one zamierzony wpływ. </li>
</ul>



<p>Każda faza stanowi swego rodzaju listę kontrolną określającą, co jest potrzebne, aby zmiany szły naprzód. Czasem przywołane fazy wysokiego poziomu są podzielone na bardziej szczegółowe. Na przykład, faza rozwoju może mieć wyszczególnione podfazy:  </p>



<ul class="wp-block-list">
<li>architektury technicznej,  </li>



<li>budowania lub kompilacji,  </li>



<li>i przeglądu kodu.  </li>
</ul>



<p>Niezależnie od złożoności poszczególnych faz, zadania związane z pracą nad nimi mogą być podejmowane przez wiele osób o różnych umiejętnościach. Zadania mogą być więc wykonywane równolegle, lecz powinny zachować niezależność.&nbsp;</p>



<p>Continuous Delivery automatyzuje proces wdrażania oprogramowania na różne środowiska w projekcie. Niektóre z nich można wykorzystać do przeprowadzania różnych testów automatycznych, takich jak:  </p>



<ul class="wp-block-list">
<li>testy integracyjne,  </li>



<li>testy akceptacyjne,  </li>



<li>czy też testy niefunkcjonalne, jak na przykład testy wydajnościowe lub penetracyjne.  </li>
</ul>



<p>Nie należy również zapominać o przeprowadzeniu testów manualnych, które mogą wykryć nowe klasy defektów, których automatyczne testy zwykle nie są w stanie wychwycić. </p>



<h2 class="wp-block-heading" id="Korzyści-ciągłego-dostarczania-(CD)-">Korzyści ciągłego dostarczania (CD) </h2>



<p>Wdrożenie podejścia ciągłego dostarczania niesie wiele korzyści, do których należą:</p>



<h3 class="wp-block-heading">#1. Oszczędność czasu</h3>



<p>W średnich i dużych firmach programy oraz ich infrastruktura są zwykle tworzone i obsługiwane przez wiele oddzielnych zespołów. Każde wdrożenie nowej wersji aplikacji musi być skoordynowane między nimi. Należy ustalić między zespołami datę wprowadzenia nowej zmiany, takiej, która obu zespołom będzie odpowiadała.</p>



<p>Ponadto należy rozpowszechnić informację na temat nowej wersji (na przykład: jakie obszary aplikacji zostaną poddane zmianom, czy jest wymagana nowa konfiguracja, zmiany w integracji itp.). Dodatkowo zespoły muszą udostępnić niezbędne pliki, i tak dalej – procedury mogą się różnić w zależności od stopnia formalności i dojrzałości procesów w organizacji.</p>



<p>Generalnie wszystkie niezbędne działania z pewnością będą trwały kilka godzin, czasem nawet kilka dni. Często procesowi temu towarzyszą również przestoje spowodowane różnymi czynnikami. A ponieważ przestojów należy unikać w godzinach pracy, zdarza się, że wdrożenia odbywają się w nocy lub w weekend. Może to działać demotywująco na zespoły operacyjne odpowiedzialne za wdrożenie, a stąd już tylko krok do popełniania błędów. Wprowadzenie ciągłego wdrażania poprzez automatyzację zadań może zaoszczędzić wiele czasu i skrócić proces z kilku dni do nawet kilku minut oraz oszczędzić nerwów ludziom z zespołów operacyjnych. Dobrze skonfigurowane narzędzie pozwoli na praktycznie bezobsługowe wdrożenie, koordynowane przez jedną lub kilka osób bez potrzeby angażowania całych zespołów.</p>



<h3 class="wp-block-heading">#2. Krótsze cykle wdrożeń</h3>



<p>Firmy wykonujące wydania i wdrożenia manualnie robią to zwykle raz w tygodniu lub nawet rzadziej. Rzadkie wydania doprowadzają do przedłużających się procesów rozwoju, a w ostateczności spowolnienia czasu wprowadzenia produktu na rynek. Jeżeli na przykład oprogramowanie jest aktualizowane raz na kwartał, wprowadzenie nowej, małej funkcji lub istotnej poprawki może niepotrzebnie rozciągnąć się w czasie i spowodować odpływ klientów. Na przykład właściciel sklepu internetowego, w którym pewien etap procesu zakupowego został źle zaprojektowany (co powoduje trudności w zakupach) będzie musiał czekać 3 miesiące, zanim poprawka zostanie wdrożona. W tym czasie sklep może stracić ogromną liczbę klientów, a co za tym idzie – realne pieniądze. Automatyczne wdrażanie może całkowicie wyeliminować ten rodzaj problemów.</p>



<h3 class="wp-block-heading">#3. Krótszy czas otrzymania informacji zwrotnej (feedback)</h3>



<p>Najlepszym sposobem na uzyskanie wartościowych opinii na temat produktu jest wdrożenie go na środowisko produkcyjne, gdzie będzie ono używane przez prawdziwych użytkowników. Dzięki temu można mierzyć ich zaangażowanie w różnych częściach systemu. Użytkownicy często wyrażają również opinie na temat aplikacji i sugerują zmiany.</p>



<p>Niestety, zadanie to nie jest takie proste, gdy tworzy się na przykład narzędzia do użytku wewnętrznego w firmie. Można wtedy poprosić kilka osób, aby przetestowały je na jednym ze środowisk testowych, lecz to rodzi wyzwania. Potrzeba na to wykorzystania ich roboczogodzin, środowisko testowe musi być w pełni przygotowane i skonfigurowane z wszystkimi niezbędnymi danymi, które na końcu i tak zostaną usunięte. Jest to proces czasochłonny i skomplikowany.</p>



<p>Przy ręcznych wydaniach, co często idzie w parze z nieczęstym okresem wdrażania, cykl otrzymania feedbacku jest bardzo powolny, co jest sprzeczne z całą ideą zwinnego procesu wytwarzania oprogramowania. Komunikacja między ludźmi również nie zawsze jest idealna – praca w grupie to zawsze ryzyko nieporozumień. Zdarza się, że pierwsza implementacja funkcjonalności nie spełnia pierwotnych oczekiwań. W takiej sytuacji dyskusje (a więc informacja zwrotna) są nieuniknione. Powolne cykle wdrożeniowe prowadzą zatem do spowolnienia rozwoju aplikacji, frustrując nie tylko zespół, ale także interesariuszy. Użytkownicy docelowi, zdając sobie sprawę z czasu trwania wdrażania kolejnych aktualizacji, mogą nawet nie prosić o poprawki lub nie sugerować różnych udogodnień – prędzej przeniosą się do aplikacji konkurencyjnej, której autorzy lepiej dbają o ten aspekt. Na dłuższą metę powolne cykle wdrożeniowe przekładają się na utratę jakości aplikacji i odpływ użytkowników.</p>



<h3 class="wp-block-heading">#4. Niezawodność wydań</h3>



<p>Manualne wdrażanie zazwyczaj nie odbywa się często. To oznacza, że każde wydanie zawiera dużo zmian, co z kolei zwiększa ryzyko niepowodzenia. Gdy duże aktualizacje są źródłem zbyt wielu problemów, inżynierowie i managerowie szukają sposobów na poprawę stabilności kolejnego wydania, niejednokrotnie poprzez tworzenie kolejnych procedur i list kontrolnych.</p>



<p>Tworzy to błędne koło, ponieważ więcej procesów wymaga włożenia jeszcze większego wysiłku w kolejne wydania, a co za tym idzie – więcej czasu. Sprawia to, że cykle wydawania oprogramowania są jeszcze dłuższe, co z kolei rodzi potrzebę zmiany procedur, aby… ten czas skrócić. Sposobem na wyjście z tego błędnego koła jest automatyzacja etapów lub nawet całego procesu wydawania. Gdy więc proces ten stanie się niezawodny i szybszy, nic nie będzie stało na przeszkodzie, aby zwiększyć liczbę wydań, które jednorazowo będą zawierały mniejsze zmiany. Czas zaoszczędzony dzięki automatyzacji uwalnia zasoby, które można wykorzystać, aby jeszcze bardziej usprawnić zautomatyzowany proces wydawania.</p>



<h3 class="wp-block-heading">#5. Mniejsze pakiety ułatwiają znalezienie źródła problemu</h3>



<p>Kiedy wdrożenie spowoduje błąd w oprogramowaniu (a zawierało ono tylko jedną lub dwie nowe funkcje lub same poprawki błędów), dość łatwo można ustalić, która ze zmian stanowi źródło błędu. Duże pakiety, gdzie na jedno wydanie przypada wiele zmian w różnych częściach aplikacji, utrudniają znalezienie źródła problemów i wydłużają czas poszukiwań oraz naprawy. Ta, ze względu na wiele zmian zawartych w wydaniu (poziom skomplikowania pakietu przez różne zależności) trwa dłużej.</p>



<h3 class="wp-block-heading">#6. Swoboda architektoniczna</h3>



<p>Obecne trendy w inżynierii oprogramowania odchodzą od monolitycznych aplikacji na rzecz systemów rozproszonych, składających się z małych komponentów (mikroserwisów). Mniejsze aplikacje lub usługi są łatwiejsze w utrzymaniu, a wymagania dotyczące skalowalności wymuszają, aby działały na różnych urządzeniach, często na wielu jednocześnie. Ręczne wydawanie poszczególnych mikroserwisów, w przypadku gdy są ich setki, wydaje się być niemożliwe do przeprowadzenia w sposób bezawaryjny w satysfakcjonującym czasie. Automatyzacja wdrożeń pozwala konfigurować wydawanie aplikacji w sposób optymalny, tak, aby zapewnić niezawodność działania oprogramowania.</p>



<h3 class="wp-block-heading">#7. Zaawansowane techniki zapewnienia jakości</h3>



<p>Wyobraźmy sobie wyszukiwarkę wycieczek, której właściciel chce ulepszyć algorytm wyszukiwania. Można wdrożyć zarówno starą, jak i nową wersję silnika jednocześnie i uruchamiać zapytania na obu. Definiując przy tym odpowiednie metryki, można w prosty sposób oceniać działanie nowego algorytmu. Dzięki nim, w przypadku, gdy stary silnik będzie zwracał na przykład lepsze wyniki na niektóre zapytania – można wykorzystać te dane w celu ulepszenia nowego. Automatyczne wdrażanie nie jest samo w sobie gwarantem zapewnienia jakości, ale stanowi bazę do zastosowania zaawansowanych technik w celu jego osiągnięcia.</p>



<h2 class="wp-block-heading" id="Automatyzacja-vs-manualne-wdrazanie">Automatyzacja vs. manualne wdrażanie</h2>



<p>Główne praktyki stosowane w obu podejściach (Continuous Integration i Continuous Deployment) są jednakowe. Różnicę stanowi etap zastosowania automatyzacji wdrożenia do środowiska produkcyjnego, co obrazuje poniższy rysunek.  </p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" src="https://nearshore-it.eu/wp-content/uploads/2024/09/blog_2024.05.16_graphic_1-1.png" alt="CI/CD diagram pokazujący proces automatyczny i proces manualny" class="wp-image-14832" title="Dostarczanie wydajnego oprogramowania: automatyzacja CI/CD  38"></figure></div>


<p>Jak już wspomniałem, celem podejścia Continuous Delivery jest automatyzacja każdego etapu cyklu wdrażania do ostatniego środowiska przedprodukcyjnego, dzięki czemu zmiany można wprowadzić na docelowe środowisko w dowolnym momencie. W Continuous Deployment zmiany są dostarczane bezpośrednio na środowisko produkcyjne. Różnica to sposób wdrażania – automatyczny lub manualny.</p>



<p>Praktyka ciągłego wdrażania jest skomplikowana, procesy wykorzystywane w ciągłej integracji nie są w stanie pokryć wszystkich niezbędnych etapów koniecznych do jej poprawnego zaimplementowania w projekcie. Niezbędne jest użycie dodatkowych narzędzi, pozwalających na testowanie i kontrolowanie różnych części systemu (na przykład wydajności, gotowości do działania, weryfikacja poprawności integracji itp.).</p>



<h2 class="wp-block-heading" id="Podsumowanie">Podsumowanie</h2>



<p>Dziś bez praktyk CI/CD trudno wyobrazić sobie jakikolwiek nowoczesny projekt IT. Automatyzacja procesów ciągłej integracji i ciągłego dostarczania pozwala nam skrócić czas wdrażania zmian, wydawać oprogramowanie częściej i w sposób niezawodny. Dodatkowo szybciej uzyskujemy feedback od użytkowników. Już teraz zachęcam was do lektury drugiej części artykułu. Przyjrzę się w nim bliżej procesowi dostarczania oprogramowania z wykorzystaniem CI/CD i omówię konkretne praktyki testerskie wraz z przeglądem najlepszych narzędzi CI/CD.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nearshore-it.eu/pl/artykuly/automatyzacja-ci-cd/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
