Wyobraź sobie pojedynek. W lewym narożniku junior: rok doświadczenia, ale w zestawie GitHub Copilot, Claude i ChatGPT. W prawym narożniku senior: 10 lat w .NET i zero AI, bo - jak sam mówi - "sam napiszę lepiej". Pytanie brzmi: kto dowozi więcej?
Na ten temat krążą w sieci 2 skrajne opinie. Według jednych AI zrównało juniorów z seniorami i doświadczenie przestało mieć znaczenie. Według drugich AI produkuje głównie kod, który ktoś potem musi sprzątać. Obie strony łączy zwykle jedno: opinia zamiast liczb. A odpowiedź wcale nie musi brzmieć "to zależy" - da się ją całkiem konkretnie rozpisać.
W tym artykule zestawię dane z badań (w tym z jednego, które mocno ostudziło entuzjazm wokół AI), rozegram 3 rundy na zadaniach prosto z życia projektów .NET i pokażę kod w C#, który wygląda świetnie, przechodzi code review... i kładzie produkcję. Na końcu dostaniesz konkretny plan działania - inny, jeśli jesteś juniorem, i inny, jeśli jesteś seniorem.
Na czym się opieram: randomizowane badanie METR (2025), eksperyment GitHuba z Copilotem, raporty Google DORA (2024 i 2025), analizy GitClear i CodeRabbit oraz badanie Stanford Digital Economy Lab (2025) o zatrudnieniu młodych pracowników. Część tych danych przemawia za AI, część przeciw - i właśnie dlatego warto zobaczyć je razem.
Zasady pojedynku: co właściwie znaczy "dowozić"?
Najpierw zawodnicy:
• Junior z AI. Rok doświadczenia, pełen dostęp do asystentów AI. Generuje kod szybko, ale weryfikuje go słabo - bo jeszcze nie wie, na co patrzeć.
• Senior bez AI. 10 lat w .NET, żadnych asystentów. Pisze wolniej, ale wie, dlaczego pisze to, co pisze.
Rozegramy 3 rundy: prosty feature, bug na produkcji i zmianę w starym systemie. To nie jest laboratoryjny pomiar, tylko typowe sytuacje z projektów, więc czasy w rundach traktuj jako poglądowe. Twarde liczby z badań omówię osobno, zanim wejdziemy na ring.
I najważniejsza rzecz, zanim zaczniemy: "dowozić" nie znaczy "wygenerować dużo kodu". Dowozić znaczy: działa na produkcji i da się to utrzymać za pół roku. To jest kryterium, według którego oceniam każdą rundę.
Badanie METR: czuli, że są szybsi. Byli wolniejsi
W temacie AI każdy ma opinię, a mało kto ma liczby. Dlatego zacznijmy od badania, jakich w tej dziedzinie jest naprawdę niewiele.
Organizacja METR przeprowadziła w 2025 roku prawdziwy, randomizowany eksperyment: 16 doświadczonych programistów open source i 246 realnych zadań z ich własnych projektów. Każde zadanie losowo przydzielano do puli "z AI" albo "bez AI" i mierzono czas pracy. Uczestnicy korzystali głównie z Cursora z modelami Claude 3.5/3.7 Sonnet, czyli z narzędzi z początku 2025 roku.
Wyniki wyglądały tak:
• przed badaniem programiści przewidywali, że AI przyspieszy ich o ok. 24%,
• po badaniu ocenili, że z AI byli ok. 20% szybsi,
• pomiar pokazał, że z AI byli o 19% wolniejsi.
Przeczytaj to jeszcze raz, bo to jest szalone: czuli, że są szybsi. Byli wolniejsi.
Dla jasności - to jedno badanie i konkretne warunki: doświadczeni ludzie w projektach, które znali na wylot. Nie warto go generalizować w nieskończoność. Ale jeden wniosek jest złoty i przyda się przez resztę artykułu: Twoje odczucie tempa jest bezwartościowe. Licz efekty, nie wrażenia.
Co jeszcze mówią liczby? Druga strona medalu
Żeby było uczciwie, spójrzmy też na dane, które przemawiają za AI - i na te, które pokazują jego koszty.
GitHub: 55% szybciej. W kontrolowanym eksperymencie GitHuba programiści z Copilotem skończyli zadanie (implementację serwera HTTP w JavaScripcie) o 55% szybciej niż grupa bez Copilota. Tylko że zadanie było proste i pisane od zera. Czyli dokładnie tam, gdzie AI błyszczy najbardziej.
Google DORA: szybciej, ale mniej stabilnie. Raport DORA z 2024 roku pokazał, że każde 25% więcej adopcji AI w zespole to średnio 7,2% mniej stabilne wdrożenia. Piszemy szybciej, psujemy częściej.
GitClear: sprzątanie znika. GitClear przeanalizował 211 milionów linii kodu. Udział refaktoryzacji (GitClear mierzy ją jako kod przenoszony w ramach porządkowania) spadł między 2020 a 2024 rokiem z 24% do 9,5%. Kopiuj-wklej rośnie, sprzątanie znika.
Złóżmy to w całość: AI realnie przyspiesza pisanie kodu. Ale między "napisane" a "dowiezione" jest przepaść. I właśnie tę przepaść widać w kolejnych rundach pojedynku.
Runda 1: prosty feature ze sprintu
Klasyk z każdego sprintu: endpoint CRUD do notatek w ASP.NET Core, walidacja i testy jednostkowe.
Junior z AI opisuje zadanie, a AI generuje kontroler, DTO, walidację, a nawet testy. Junior klika, sprawdza, poprawia 2 rzeczy. Po 1,5 godziny pull request czeka na review - jeszcze przed lunchem.
Senior pisze wszystko sam. Solidnie, czysto... w 3 godziny.
Obie wersje działają. Punkt dla juniora.
I to jest w pełni uczciwy punkt. W prostych, dobrze opisanych zadaniach AI po prostu świeci: boilerplate, CRUD-y, mapowania, testy do istniejącego kodu. Tu nie ma dyskusji - kto to neguje, ten nie próbował.
Runda 2: bug na produkcji
Objaw: co kilka dni API przestaje odpowiadać. Restart pomaga... na kilka dni. W logach od czasu do czasu pojawia się SocketException. Klasyczny horror.
Junior wkleja stack trace do AI i dostaje 5 propozycji: zwiększ timeout, dodaj retry, zmień ustawienia puli wątków, przeskaluj pody... Wdraża je po kolei. Każda poprawka coś zmienia, żadna nie naprawia. Mijają 2 dni.
Senior zaczyna od pytania: "co się ostatnio zmieniło w kodzie?". Przegląda commity, patrzy w metryki, widzi rosnącą liczbę otwartych połączeń... i już wie. Bo ten wzorzec już kiedyś przeżył. 2 godziny.
Punkt dla seniora. Debugowanie to nie generowanie kodu, tylko stawianie hipotez i ich eliminowanie. A do dobrych hipotez potrzebujesz kontekstu, którego AI nie ma.
Co to był za bug? Warto go zobaczyć, bo to kod, który AI generuje nagminnie.
Kod od AI, który kładzie produkcję: new HttpClient()
Spójrz na tę metodę. Pobiera kurs waluty z API NBP:
public async Task<decimal> PobierzKursAsync(string kodWaluty)
{
using var client = new HttpClient();
var odpowiedz = await client.GetFromJsonAsync<KursNbp>(
$"https://api.nbp.pl/api/exchangerates/rates/a/{kodWaluty}/?format=json");
return odpowiedz!.Rates[0].Mid;
}
/* model odpowiedzi API NBP */
public record KursNbp(string Code, List<KursNbpPozycja> Rates);
public record KursNbpPozycja(DateOnly EffectiveDate, decimal Mid);Kompiluje się. Testy przechodzą. Na code review dostaje "LGTM". Junior by to przepuścił. Szczerze? Większość ludzi by to przepuściła.
Zanim przeczytasz dalej, poszukaj problemu. Serio, zatrzymaj się na chwilę.
No dobra. Problem siedzi w linijce using var client = new HttpClient();. Przy każdym wywołaniu metody tworzymy nowego klienta HTTP i zaraz go wyrzucamy.
"No i co z tego? Przecież jest using, wszystko się zwalnia." No właśnie... nie do końca.
Bomba z opóźnionym zapłonem. Mechanizm jest taki: każdy nowy HttpClient otwiera nowe połączenie TCP. Kiedy metoda kończy pracę i klient jest zwalniany, socket nie znika od razu - ląduje w stanie TIME_WAIT i jeszcze przez jakiś czas (zależnie od systemu - od kilkudziesięciu sekund do kilku minut) zajmuje port.
Przy małym ruchu nic się nie dzieje. Przy dużym sockety przybywają szybciej, niż system je sprząta. Wolne porty się kończą i... SocketException. Produkcja leży.
Najgorsze w tym bugu jest to, że lokalnie go nie zobaczysz. Kilka requestów na krzyż to za mało, żeby cokolwiek się zapchało.
Fix. Banalny: IHttpClientFactory albo 1 współdzielony HttpClient na całą aplikację. W ASP.NET Core najwygodniej zarejestrować typowanego klienta:
/* Program.cs - rejestracja typowanego klienta */
builder.Services.AddHttpClient<KursyNbpService>(client =>
{
client.BaseAddress = new Uri("https://api.nbp.pl/api/");
});
/* serwis dostaje HttpClient z fabryki, zamiast tworzyć go sam */
public class KursyNbpService(HttpClient client)
{
public async Task<decimal> PobierzKursAsync(string kodWaluty)
{
var odpowiedz = await client.GetFromJsonAsync<KursNbp>(
$"exchangerates/rates/a/{kodWaluty}/?format=json");
return odpowiedz!.Rates[0].Mid;
}
}Fabryka zarządza pulą handlerów i połączeń, więc połączenia są ponownie wykorzystywane, zamiast powstawać przy każdym wywołaniu. Jedna uwaga: typowany klient jest rejestrowany jako transient, więc nie wstrzykuj go do serwisu typu singleton - wtedy tracisz to, co daje fabryka.
Jeśli wolisz 1 współdzielony klient (np. w aplikacji konsolowej, bez kontenera DI), ustaw mu czas życia połączeń, żeby aplikacja reagowała na zmiany DNS:
private static readonly HttpClient Client = new(new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(15) /* okresowo odświeża połączenia, np. po zmianie DNS */
});Tylko że żeby ten fix zastosować, musisz wiedzieć, że problem w ogóle istnieje. Senior wie, bo to przeżył. Junior nie wie nawet, o co zapytać. I to jest cała różnica między nimi w jednym zdaniu.
4 inne miny, które AI chętnie wstawia do kodu C#
HttpClient to nie jedyna taka pułapka. Szybka seria:
• DateTime.Now w logice biznesowej. Bug wyjdzie przy zmianie czasu albo u klienta z innej strefy czasowej. Używaj DateTime.UtcNow (a od .NET 8 warto sięgnąć po TimeProvider, który dodatkowo ułatwia testowanie).
• .Result i .Wait() na taskach. Blokowanie wątków to klasyczna droga do deadlocka w aplikacjach desktopowych i starym ASP.NET, a w ASP.NET Core - do zagłodzenia puli wątków pod obciążeniem.
• Pusty catch (Exception). Błąd znika bez śladu. Powodzenia w debugowaniu za pół roku.
• async void poza event handlerami. Wywołujący nie złapie wyjątku, a nieobsłużony wyjątek potrafi położyć cały proces.
W kodzie wygląda to tak:
/* Miny */
var dataZamowienia = DateTime.Now;
var kurs = PobierzKursAsync("USD").Result;
try
{
ZapiszZamowienie(zamowienie);
}
catch (Exception) { }
public async void WyslijPotwierdzenie(Zamowienie zamowienie) { /* ... */ }
/* Bezpieczniej */
var dataZamowienia = timeProvider.GetUtcNow(); /* albo DateTime.UtcNow */
var kurs = await PobierzKursAsync("USD");
try
{
ZapiszZamowienie(zamowienie);
}
catch (Exception ex)
{
logger.LogError(ex, "Nie udało się zapisać zamówienia {Id}", zamowienie.Id);
throw;
}
public async Task WyslijPotwierdzenieAsync(Zamowienie zamowienie) { /* ... */ }Zwróć uwagę na wspólny mianownik: każda z tych rzeczy się kompiluje, przechodzi testy i wygląda porządnie.
Swoją drogą - raport CodeRabbit policzył, że pull requesty pisane z AI mają średnio 1,7 raza więcej problemów niż te pisane przez ludzi. Zasada jest więc prosta: kod od AI czytasz jak kod od juniora. Uważnie.
Runda 3: zmiana w starym systemie
Runda finałowa. Stary system: 8 lat, 200 tysięcy linii kodu, dokumentacji brak. Zadanie: dodać system rabatów do modułu zamówień.
Junior z AI. Model nie ogarnia całego systemu, bo kończy mu się okno kontekstu. Kod powstaje szybko, wygląda dobrze, testy przechodzą... A tydzień po wdrożeniu okazuje się, że rabaty rozjechały raporty finansowe i integrację z magazynem - bo z tego kawałka kodu korzystały jeszcze 2 inne moduły. Bilans: 3 dni pracy plus tydzień gaszenia pożarów.
Senior wie, kto używa tego kodu, bo sam go kiedyś ruszał. Robi zmianę bezpiecznie i dopisuje testy regresji. 2 dni. Nic nie pęka.
Punkt dla seniora. I zapamiętaj to zdanie: AI ma okno kontekstu. Senior ma lata kontekstu.
Tablica wyników: 2 do 3 dla seniora... z haczykiem
Podliczmy. Do 3 rund dorzucam 2 sytuacje, które zna każdy zespół: prototyp "na wczoraj" i utrzymanie kodu po pół roku.
| Sytuacja | Kto dowozi więcej |
| Prosty feature ze sprintu | junior z AI |
| Prototyp "na wczoraj" | junior z AI |
| Bug na produkcji | senior |
| Zmiana w starym systemie | senior |
| Utrzymanie kodu po pół roku | senior |
2 do 3. Senior dowozi więcej.
Tylko że to porównanie ma haczyk. I ten haczyk jest najważniejszą częścią całego artykułu.
"Dowozić" to nie "pisać kod". Zobacz, z czego naprawdę składa się dostarczenie funkcji:
1. Zrozumieć problem.
2. Wybrać rozwiązanie.
3. Napisać kod.
4. Zweryfikować go.
5. Utrzymywać go.
AI dramatycznie przyspiesza 1 etap: pisanie. A prawdziwe wąskie gardło prawie nigdy tam nie siedzi. Siedzi w decyzjach i w weryfikacji. Kod piszesz raz. Czytasz i utrzymujesz go latami.
AI nie dodaje umiejętności. AI je mnoży
I tu dochodzimy do sedna. Raport DORA z 2025 roku nazywa to wprost: AI jest przede wszystkim wzmacniaczem. Nie dodaje umiejętności - mnoży te, które już masz.
Zobacz to na prostym, umownym rachunku: umiejętności w skali 0-10, a AI jako mnożnik ×3.
| Kto | Umiejętności | Mnożnik AI | Efekt |
| Junior z AI | 2 | ×3 | 6 |
| Senior bez AI | 8 | ×1 | 8 |
| Senior z AI | 8 | ×3 | 24 |
| Junior bez fundamentów z AI | 0 | ×3 | 0 |
Junior z mnożnikiem daje 6. Senior bez mnożnika daje 8 - i dlatego wygrał nasz pojedynek. Ale senior z AI daje 24. Inna liga.
I ostatni wiersz, najważniejszy: 0 razy 3 to dalej 0. Jeśli nie umiesz ocenić kodu, AI tylko przyspiesza produkcję rzeczy, których nie rozumiesz.
Widać to zresztą w danych. GitClear porównał programistów rok do roku: power userzy AI zwiększyli output o 81%, a osoby nieużywające AI - praktycznie wcale. Jest jednak haczyk: ci power userzy już rok wcześniej byli najlepsi. AI wzmocniło najlepszych. Nie stworzyło ich.
Werdykt: kto naprawdę wygrywa?
• Krótki sprint i proste zadania: junior z AI potrafi dowieźć więcej - i nie ma co udawać, że jest inaczej.
• Duży system i długi horyzont: senior bez AI.
• Prawdziwy zwycięzca rynku: senior z AI. I w tę stronę toczy się cała gra.
Jest też najsłabsza pozycja w tej układance: junior bez fundamentów, który klika Accept, Accept, Accept. Mówię to bez złośliwości. Badacze ze Stanford Digital Economy Lab policzyli na danych z USA, że zatrudnienie najmłodszych pracowników (22-25 lat) w zawodach najbardziej wystawionych na AI - a programowanie jest jednym z nich - spadło relatywnie o ok. 13%, podczas gdy zatrudnienie bardziej doświadczonych osób w tych samych zawodach jest stabilne. Rynek już głosuje.
Dobra wiadomość? Na swoją pozycję w tym równaniu masz pełny wpływ. Poniżej konkretny plan - najpierw dla juniorów, potem dla seniorów.
Jesteś juniorem? 5 zasad pracy z AI
1. Najpierw 15 minut sam, dopiero potem AI. Inaczej nie budujesz mięśnia rozwiązywania problemów - a to on Cię kiedyś wyżywi.
2. Nie commituj linijki, której nie umiesz wytłumaczyć. Ani jednej. Tak, to boli. Tak, to spowalnia. I właśnie dlatego działa.
3. Pytaj AI "dlaczego?" i "co tu może pęknąć na produkcji?", a nie tylko "napisz mi". Z generatora zrób sobie mentora dostępnego 24 godziny na dobę. To przewaga, jakiej nie miało żadne wcześniejsze pokolenie juniorów.
4. Odwróć role - każ AI robić review Twojego kodu. Napisz sam, wrzuć i poproś o brutalną ocenę, np.: "Zrób surowe code review tego kodu. Wskaż, co może się wysypać na produkcji pod dużym ruchem, i wyjaśnij dlaczego." To najszybsza pętla nauki, jaką znam.
5. Fundamenty bez dróg na skróty: async/await, LINQ, SQL, HTTP, zarządzanie pamięcią. Bo to one są Twoją liczbą w mnożeniu z tabeli powyżej. Bug z HttpClientem z rundy 2 to dobry przykład: żeby go wyłapać, wystarczyło rozumieć, jak działają HTTP i połączenia TCP.
Jesteś seniorem? Nie odpadnij z gry
Wiem, co myślisz: "AI pisze gorszy kod ode mnie". Prawda. Junior w Twoim zespole też - a mimo to mu delegujesz. Bo tylko tak skalujesz swoją robotę.
Traktuj AI dokładnie tak samo:
• Deleguj rzeczy, które umiesz zrobić, ale które kradną Ci czas: boilerplate, testy, migracje, dokumentację.
• Zostaw sobie to, w czym jesteś niezastąpiony: architekturę, code review i decyzje.
Twoje doświadczenie to dokładnie ten element, którego AI brakuje. To dzięki niemu wyłapiesz new HttpClient() w wygenerowanym kodzie w kilka sekund, zamiast szukać go 2 dni na produkcji.
I jedno zdanie na trzeźwo: senior z AI to już nie przewaga konkurencyjna. To nowy standard rynku. Pytanie nie brzmi "czy", tylko "jak szybko".
Podsumowanie
Kto dowozi więcej? W prostych zadaniach junior z AI, w dużych systemach i na długim dystansie - senior. Ale z całego porównania warto zapamiętać 3 rzeczy:
• AI mnoży umiejętności, nie dodaje ich. A 0 razy cokolwiek to 0.
• Dowozić to nie generować. O dowiezieniu decydują weryfikacja i utrzymanie, a nie tempo pisania.
• Fundamenty ORAZ AI. Nie "albo-albo".
Jeśli chcesz, żeby AI było u Ciebie mnożnikiem, a nie generatorem problemów, mam coś, co Ci w tym pomoże. Przygotowałem darmowy PDF: 25 promptów AI dla programistów C#/.NET. 5 obszarów po 5 promptów: refaktoryzacja, testy jednostkowe, debugowanie, code review i legacy. Każdy prompt przetestowałem na prawdziwym kodzie - kopiujesz, wklejasz, podmieniasz nazwy i widzisz różnicę w 5 minut.
Pamiętasz rundę 2, w której AI strzelało poprawkami na ślepo? W PDF-ie jest prompt, który rozwiązuje dokładnie ten problem: każe AI najpierw napisać test odtwarzający buga, a dopiero potem go naprawiać. Takich promptów jest tam 25.
Odbierzesz go tutaj: modestprogrammer.pl/25-promptow. Zostawiasz maila i PDF przychodzi od razu. Przy okazji dołączasz do społeczności ponad 10 000 programistów .NET: raz w tygodniu jeden konkretny mail o .NET i AI, bez lania wody, plus rabaty na moje kursy, których nigdzie indziej nie publikuję. Zero spamu - wypisujesz się jednym kliknięciem.
Powodzenia - i niech AI mnoży u Ciebie coś więcej niż zero :)