Powrot do bloga
03 maja 2026
published

Jak AI zmieniło mój workflow jako .NET developera w ciągu 6 miesięcy

Pół roku temu pisałem testy ręcznie. Siadałem do nowego endpointu, odpalałem pusty plik testowy i zaczynałem klepać Arrange-Act-Assert od zera. Dziś robię...

Okladka: Jak AI zmieniło mój workflow jako .NET developera w ciągu 6 miesięcy

Pół roku temu pisałem testy ręcznie. Siadałem do nowego endpointu, odpalałem pusty plik testowy i zaczynałem klepać Arrange-Act-Assert od zera. Dziś robię to inaczej. Nie dlatego, że jestem lepszym programistą niż pół roku temu. Dlatego, że część mojej pracy przejął model językowy.

Ten tekst to nie jest manifest o tym, jak AI zmieni świat. To jest konkretny opis tego, co się zmieniło w mojej codziennej pracy jako .NET developer - co działa, co nie działa, i gdzie wciąż jestem niezastąpiony. Z przykładami, z narzędziami, z konkretnymi wnioskami.

Punkt wyjścia: jak wyglądał mój dzień przed AI

Pracuję jako główny programista backend w Digital TPA. Firmy z sektora outsourcingu finansowego, integracje między systemami, API, przetwarzanie danych. Klasyczny .NET Core, C#, SQL, REST API. Dużo boilerplate'u, dużo testów, sporo legacy code do utrzymania.

Typowy dzień wyglądał tak: rano pull request review, potem nowy feature - czyli kontroler, serwis, interfejs, testy, migracja. Po obiedzie jakiś bugfix w starszej części systemu. Na koniec dnia dokumentacja albo refactoring, jeśli zostało trochę energii.

Problem nie polegał na tym, że nie umiałem tego robić. Problem polegał na tym, że połowa dnia szła na rzeczy, które mógłbym wygenerować ze schematu. Pisanie kontrolera do CRUD-a po raz setny nie wymaga kreatywności. Wymaga cierpliwości. I właśnie cierpliwość jest zasobem, który się kończy.

Co AI przejęło: boilerplate w .NET

Zacznijmy od tego, co działa najlepiej. Generowanie boilerplate'u to jest use case, do którego modele językowe zostały stworzone.

Potrzebuję nowego endpointu do zarządzania kontraktami. Wcześniej: tworzę kontroler, piszę route'y, definiuję DTO, implementuję interfejs serwisu, piszę serwis, dodaję rejestrację w DI. Dwadzieścia-trzydzieści minut mechanicznej pracy. Teraz: daję Codexowi kontekst - istniejący kontroler z projektu jako wzorzec, schemat encji, konwencje nazewnictwa - i dostaję gotowy zestaw plików w czterdzieści sekund.

Kontroler z atrybutami [ApiController], [Route], poprawnym ILogger<T>, dependency injection przez konstruktor. Serwis implementujący interfejs z podstawową walidacją. DTO z odpowiednimi atrybutami walidacji. Czy to jest idealny kod? Nie. Czy wymaga review i poprawek? Tak. Ale zamiast pisać od zera, poprawiam gotowy szkielet. To jest różnica między budowaniem domu od fundamentów a remontowaniem istniejącego mieszkania.

Kluczowa rzecz: model musi znać konwencje projektu. Jeśli rzucisz mu ogólne polecenie "napisz kontroler do zarządzania kontraktami", dostaniesz generyczny kod, który nie pasuje do twojego projektu. Jeśli podrzucisz mu trzy istniejące kontrolery z twojego repo jako kontekst - dostaniesz coś, co wygląda jakby to pisał ktoś z twojego zespołu.

Testy jednostkowe: tu oszczędzam najwięcej czasu

To jest mój ulubiony use case. Pisanie testów jednostkowych w xUnit to czynność, która jest jednocześnie ważna i boleśnie powtarzalna. Mockowanie zależności, arrange-act-assert, pokrycie happy path i edge case'ów. To są setki linii kodu, które wyglądają prawie identycznie w każdym projekcie.

Daję Codexowi klasę serwisu i mówię: napisz testy xUnit z wykorzystaniem [Theory] i [InlineData], mockuj zależności przez Moq, pokryj happy path, null handling, edge case'y na granicznych wartościach. Dostaję kompletny zestaw testów w kilkadziesiąt sekund.

Przykład - mam serwis walidujący kwoty faktur. Codex generuje mi [Theory] z [InlineData] pokrywające: kwotę zerową, kwotę ujemną, kwotę przekraczającą limit, kwotę w poprawnym zakresie, kwotę z nadmiarową precyzją dziesiętną. Sam bym napisał trzy-cztery przypadki i poszedł dalej. Model wyrzuca osiem-dziesięć, w tym edge case'y, o których bym nie pomyślał - bo nie miałem na to energii po trzech godzinach klepania kodu.

Czy każdy wygenerowany test jest poprawny? Nie. Czasem model źle zakłada zachowanie na granicy, czasem mockuje coś, co powinno być prawdziwą implementacją. Ale poprawienie dwóch testów z dziesięciu to nie to samo co pisanie dziesięciu od zera.

Refactoring legacy: analiza zależności z AI

Tu sprawa jest ciekawsza. Legacy code to nie jest problem, który rozwiążesz jednym promptem. Ale AI bardzo dobrze sprawdza się jako narzędzie do analizy - zanim zaczniesz refaktorować.

Mam kawałek systemu napisany trzy lata temu. Klasa z osiemnastu metodami, dwadzieścia zależności w konstruktorze, pięć warstw ifów. Zanim dotknę jednej linijki, potrzebuję zrozumieć graf zależności - kto wywołuje tę klasę, co się stanie jak zmienię sygnaturę metody, które testy pokrywają który fragment.

Tu wchodzi Claude Code. Daję mu plik, proszę o analizę: ile odpowiedzialności ma ta klasa, jakie wzorce łamie, jak bym mógł ją podzielić zgodnie z Single Responsibility. Dostaję raport z propozycją podziału na trzy mniejsze serwisy, z listą metod do przeniesienia i sugestią nowych interfejsów.

Czy mogę bezrefleksyjnie zastosować tę propozycję? Oczywiście, że nie. Ale mam punkt wyjścia do rozmowy z kodem. Zamiast gapić się na osiemset linii i zastanawiać się od czego zacząć - mam plan, który mogę krytycznie ocenić i dostosować.

Gdzie AI zawodzi: logika domenowa

Teraz czas na zimny prysznic. Bo gdybym tu napisał tylko o sukcesach, ten tekst byłby reklamą, nie relacją.

AI nie radzi sobie z logiką domenową. I nie mówię o tym, że jest słabe - mówię o tym, że tutaj generuje kod, który wygląda poprawnie, a jest biznesowo błędny.

Pracuję z integracjami systemów finansowych. Są tam reguły, które wynikają z przepisów, z umów między firmami, z wewnętrznych polityk klienta. Nie są nigdzie opisane w jednym miejscu. Siedzą w głowach ludzi, w mailach sprzed dwóch lat, w komentarzach w kodzie pisanych przez kogoś, kto już tu nie pracuje.

Próbowałem poprosić AI o zaimplementowanie logiki rozliczania transakcji międzyfirmowych. Wynik wyglądał profesjonalnie - clean code, poprawna struktura, nawet komentarze były sensowne. Problem: model zakładał standardowy przepływ, a nasz klient ma niestandardowy schemat z wyjątkiem na trzech typach transakcji, o którym wie dwóch ludzi w firmie. Żaden model tego nie wyczyta z kodu, bo tego nie ma w kodzie.

Podobnie z maszynami stanów. Mam workflow zatwierdzania dokumentów - dokument przechodzi przez pięć stanów, ale przejścia między nimi zależą od typu dokumentu, roli użytkownika i flag konfiguracyjnych. Dałem AI specyfikację i poprosiłem o implementację. Dostałem elegancki pattern state machine, który obsługiwał cztery z pięciu stanów poprawnie. Piąty - ten z niestandardowym cofnięciem do stanu drugiego tylko dla jednego typu dokumentu - został pominięty. Bo model zoptymalizował pod czystość kodu zamiast pod kompletność biznesową.

Wniosek: im bardziej logika zależy od kontekstu biznesowego, który nie jest jawnie opisany w kodzie, tym mniej AI jest w stanie pomóc. Boilerplate - tak. Domain logic - to wciąż moja robota.

Porównanie narzędzi: Codex vs Claude Code vs Cursor

Używam trzech narzędzi i każde ma inną niszę.

Codex sprawdza się najlepiej do generowania kodu z jasną strukturą. Kontrolery, serwisy, testy, migracje. Dajesz mu wzorzec i specyfikację, dostajesz implementację. Jest szybki, dobrze trzyma konwencje projektu, i radzi sobie z dużymi plikami. To jest mój koń roboczy do boilerplate'u.

Claude Code wygrywa w analizie i refactoringu. Kiedy potrzebuję zrozumieć legacy code, zaplanować podział modułu, przeanalizować graf zależności albo przedyskutować architekturę - tu jest najsilniejszy. Prowadzenie dłuższej rozmowy o kodzie, iterowanie nad rozwiązaniem, zadawanie pytań zwrotnych - to jest jego mocna strona. Używam go też do review kodu, kiedy chcę drugą opinię przed pushem.

Cursor jest najlepszy do pracy w IDE. Podpowiedzi inline, autouzupełnianie, szybkie edycje w kontekście otwartego pliku. Kiedy piszę kod i potrzebuję dokończyć metodę albo wygenerować implementację interfejsu na podstawie sygnatury - Cursor jest najszybszy, bo nie muszę zmieniać kontekstu.

Nie używam jednego narzędzia do wszystkiego. To jak pytanie, czy lepszy jest młotek czy śrubokręt - zależy, co montujesz.

"Ekonomia uwagi" - oszczędzam energię, nie tylko czas

Tu jest rzecz, o której mało kto mówi. Metryki oszczędności czasu - "zaoszczędziłem 40 minut na testach" - to tylko połowa historii. Ważniejsza jest ekonomia uwagi.

Programowanie to praca umysłowa, a energia mentalna jest ograniczona. Mam jej określoną pulę na dzień. Mogę ją wydać na pisanie boilerplate'u albo na projektowanie architektury. Mogę ją wydać na klepanie testów albo na myślenie o edge case'ach w logice domenowej. Mogę ją wydać na formatowanie kodu albo na rozmowę z klientem o wymaganiach.

AI przejmuje te zadania, które zużywają energię mentalną, ale nie wymagają kreatywności. I dzięki temu o czternastej, kiedy wcześniej byłem już wypalony po dniu mechanicznej roboty, teraz mam jeszcze paliwo na rzeczy, które naprawdę wymagają mojej głowy.

To nie jest kwestia lenistwa. To jest kwestia alokacji ograniczonego zasobu. Programista, który do szesnastej pisze boilerplate, a od szesnastej próbuje zaprojektować architekturę nowego modułu - nie zaprojektuje jej dobrze. Nie dlatego, że nie umie. Dlatego, że nie ma już na to mentalnego budżetu.

Jak zmienił się mój typowy dzień

Przed AI: rano review, potem trzy godziny implementacji (z czego połowa to boilerplate), po obiedzie bugfix, na koniec dnia refactoring jeśli starczył zapas energii (zwykle nie starczył).

Teraz: rano review (z AI jako drugą parą oczu), potem implementacja gdzie boilerplate generuję w minuty a nie godziny, po obiedzie mam jeszcze energię na refactoring i planowanie architektury. Bugfixy wciąż robię sam, ale AI pomaga w diagnozie - analiza stack trace'ów, sugestie przyczyn, wyszukiwanie podobnych wzorców w codebase.

Szacuję, że na czystej implementacji oszczędzam jakieś trzydzieści-czterdzieści procent czasu. Ale prawdziwy zysk jest w tym, że na koniec dnia mam jeszcze głowę do myślenia. I to przekłada się na jakość decyzji architektonicznych, które są warte więcej niż dwadzieścia kontrolerów.

Czego się nauczyłem po sześciu miesiącach

Kilka rzeczy, które wiem teraz, a nie wiedziałem na początku.

Po pierwsze - kontekst jest wszystkim. AI bez kontekstu projektu generuje generyczny kod. AI z trzema plikami referencyjnymi z twojego repo generuje kod, który pasuje. Inwestycja w dobre promptowanie się zwraca, ale jeszcze bardziej zwraca się podawanie konkretnych plików z projektu jako wzorców.

Po drugie - review wygenerowanego kodu to nie jest opcja. To jest obowiązek. Widziałem sytuacje, w których wygenerowany test przechodził na zielono, ale testował coś innego niż zamierzone Wyglądał dobrze, kompilował się, assertions nie rzucały wyjątków - ale logicznie sprawdzał nie to, co trzeba. Bez uważnego review taki test daje fałszywe poczucie bezpieczeństwa.

Po trzecie - nie próbuj zastąpić AI myślenia o domenie. To jest strata czasu i potencjalne źródło bugów, które trudno znaleźć, bo wygenerowany kod wygląda poprawnie.

Po czwarte - narzędzia się zmieniają szybciej niż zdążysz je opanować. Sześć miesięcy temu Codex działał inaczej niż dziś. Za pół roku pewnie będę pisał kolejny tekst o tym, jak znowu zmienił się mój workflow. Adaptacja jest ważniejsza niż perfekcja w jednym narzędziu.

Kto zostaje za klawiaturą

Podsumowując: AI przejęło klepanie. Generowanie boilerplate'u, pisanie testów jednostkowych, analizę zależności w legacy code, formatowanie i wstępny scaffolding. To wszystko robi szybciej i bez narzekania.

Po mojej stronie zostały decyzje. Architektura systemu. Logika domenowa. Rozumienie kontekstu biznesowego. Review tego, co wypluwa model. I przede wszystkim - wiedzieć, kiedy AI się myli, a wynik wygląda jakby się nie mylił.

Developer, który umie korzystać z AI, nie jest zagrożeniem dla developerów, którzy nie umieją. Jest zagrożeniem dla tych, którzy myślą, że boilerplate to jest ta wartościowa część ich pracy.

Maciej Woźniczka - .NET developer, backend w Digital TPA, integracje API i AI w DBA Finanse. Prowadzę firmę Deadline, gdzie buduję MVP i PoC z wykorzystaniem AI-augmented development. Jeśli szukasz kogoś, kto połączy backend, integracje systemów finansowych i narzędzia AI w działający produkt - odezwij się przez LinkedIn albo stronę.