Przez ostatnie 2 lata oddałem AI setki zadań programistycznych. Część z nich oszczędza mi dziś kilka godzin tygodniowo. Ale kilka razy prawie skończyło się to katastrofą - raz o mały włos nie wdrożyłem na produkcję migracji, która kasowała dane klientów. Dlatego uważam, że pytanie "czy używać AI w programowaniu?" jest dziś źle postawione. Dobre pytanie brzmi: które zadania oddawać AI, a których nie.
Od razu jedno zastrzeżenie: to nie jest tekst w stylu "AI jest złe" ani "AI zastąpi programistów". To tekst o delegowaniu. Bo właśnie umiejętność delegowania odróżnia dziś programistę, który dowozi 2 razy szybciej, od takiego, który 2 razy szybciej produkuje bugi.
W tym artykule dostaniesz konkretną listę: 5 zadań, których nigdy nie oddaję AI, i 5, które oddaję zawsze - wszystko na przykładach z projektów C# i .NET, z promptami i fragmentami kodu. Do tego 2 rzeczy ekstra: prostą zasadę 2 pytań, dzięki której sam podejmiesz taką decyzję dla każdego zadania, które wpadnie Ci na biurko, oraz checklistę przed merge do wydrukowania i powieszenia nad monitorem. Bez filozofowania, sama praktyka.
Część 1: czego nigdy nie oddaję AI
Zaczynamy od zakazów. Zanim przejdę do konkretów, zapamiętaj jedno zdanie, bo wróci jeszcze na końcu: nie chodzi o to, że AI jest słabe. Chodzi o to, że koszt błędu jest za wysoki.
Każde z 5 poniższych zadań łączy to samo: pomyłka jest droga, trudna do wykrycia albo niemożliwa do cofnięcia. Co nie znaczy, że AI nie ma tu nic do roboty - w każdym z tych obszarów go używam. Tylko nigdy w roli autora finalnej decyzji czy finalnego kodu.
Nigdy #1: decyzje architektoniczne
Monolit czy mikroserwisy? EF Core czy Dapper? Modular monolith czy osobne serwisy? AI odpowie Ci na każde z tych pytań - pewnie siebie i z ładną listą zalet. Problem w tym, że AI nie zna Twojego kontekstu. Nie wie, że w zespole jest 3 developerów, deadline wypada za 2 miesiące, a doświadczenie z Kubernetesem wynosi zero.
Najlepsze praktyki z internetu to nie najlepsza decyzja dla Ciebie. Model podpowiada to, co najczęściej widział, czyli "najlepsze praktyki z internetu". A najlepsza praktyka z bloga Netflixa bywa najgorszą możliwą decyzją dla 3-osobowego zespołu. Zapytaj AI o mikroserwisy w takim zespole, a usłyszysz "świetny pomysł!". Rzeczywistość: 6 miesięcy bólu.
Koszt złej decyzji rośnie z każdym miesiącem. I rzecz najważniejsza: złą architekturę odkrywasz po pół roku, a naprawiasz przez rok. Tego nie cofniesz skrótem Ctrl+Z. Im dłużej projekt rośnie na złych fundamentach, tym drożej je wymienić.
Jak to robię: AI jako sparingpartner. Czy to znaczy, że AI jest tu bezużyteczne? Nie. Traktuję je jak sparingpartnera, który pomaga mi zobaczyć słabe punkty. Piszę na przykład:
"Rozważam opcję A i B. Wymień ryzyka każdej z nich i zadaj mi pytania, których nie wziąłem pod uwagę."
To działa genialnie. Im więcej kontekstu dasz (wielkość zespołu, termin, doświadczenie), tym lepsze pytania dostaniesz. Ale całej wiedzy o ludziach, budżecie i historii firmy i tak nie zmieścisz w prompcie. Dlatego decyzję podejmuję ja. Bo to ja będę z nią żył.
Nigdy #2: kod bezpieczeństwa
Autoryzacja, płatności, dane osobowe. Tutaj błąd to nie jest bug, który poprawisz w następnym sprincie. To wyciek danych, RODO i bardzo nieprzyjemne rozmowy.
Działa w happy path, ma subtelne luki. AI generuje kod, który wygląda dobrze i działa, gdy wszystko idzie zgodnie z planem, ale potrafi mieć luki niewidoczne na pierwszy rzut oka. Modele bywają też uczone na starych, dziurawych przykładach z internetu - i chętnie je powielają. Klasyk: prosisz o hashowanie haseł w C# i dostajesz coś takiego:
/* Źle: kompiluje się, działa... i jest podatne */
using var sha = SHA256.Create();
var hash = Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(haslo)));Kompiluje się? Tak. Działa? Tak. Jest bezpieczne? Absolutnie nie. SHA256 to szybka funkcja skrótu ogólnego przeznaczenia, a tu dodatkowo bez soli - te same hasła dają te same hashe, a wykradzioną bazę da się łamać siłowo bardzo szybko. Do haseł używa się funkcji celowo wolnych, z solą. W .NET masz to gotowe w ASP.NET Core Identity (alternatywnie: Argon2):
/* Dobrze: PasswordHasher z ASP.NET Core Identity (sól i wiele iteracji w standardzie) */
var hasher = new PasswordHasher<Uzytkownik>();
var hash = hasher.HashPassword(uzytkownik, haslo);
/* weryfikacja przy logowaniu */
var wynik = hasher.VerifyHashedPassword(uzytkownik, hash, podaneHaslo);
if (wynik == PasswordVerificationResult.Failed)
{
return Unauthorized();
}Tylko skąd masz wiedzieć, że wersja z SHA256 jest zła, jeśli ufasz AI w ciemno?
Jak to robię: sprawdzone biblioteki i review człowieka. Moja zasada jest prosta: w security nie piszę własnych rozwiązań i nie pozwalam pisać ich AI. Sprawdzone biblioteki (ASP.NET Core Identity), gotowe bramki płatności, a każdą linię, która dotyka bezpieczeństwa, czyta człowiek. Zawsze. AI może mi wytłumaczyć, jak działa OAuth. Ale nie napisze finalnej implementacji.
Nigdy #3: operacje na produkcyjnej bazie
Migracje, UPDATE-y, DELETE-y - czyli wszystko, co dotyka produkcyjnej bazy danych i czego nie da się cofnąć Ctrl+Z. Jedna wygenerowana linia SQL potrafi skasować dane klientów.
AI nie zna historii Twojej bazy. AI nie wie, że kolumna OldStatus - która wygląda na martwą - karmi raport, z którego co miesiąc korzysta księgowość. Poprosisz o "posprzątanie" encji, a w wygenerowanej migracji pojawi się DropColumn bez mrugnięcia okiem:
public partial class UporzadkujZamowienia : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
/* "martwa" kolumna, z której co miesiąc korzysta raport księgowości */
migrationBuilder.DropColumn(
name: "OldStatus",
table: "Orders");
}
}EF Core co prawda ostrzega przy dotnet ef migrations add, że operacja może spowodować utratę danych, ale to jedna linijka w terminalu, którą łatwo przegapić. A AI i tak nie wie, że akurat ta kolumna jest komuś potrzebna. Albo inny klasyk: UPDATE bez WHERE. Brzmi jak suchar, dopóki nie zobaczysz tego w wygenerowanym skrypcie na własne oczy.
Jak to robię: szkic, skrypt, backup, kopia, produkcja. AI może napisać szkic migracji, jasne. Ale potem zawsze idę tą samą ścieżką:
1. Generuję pełny skrypt SQL.
2. Czytam każdą linię.
3. Robię backup.
4. Odpalam skrypt najpierw na kopii bazy.
5. Dopiero potem produkcja.
W EF Core skrypt SQL wygenerujesz jednym poleceniem:
dotnet ef migrations add UporzadkujZamowienia
dotnet ef migrations script OstatniaMigracjaNaProdukcji --idempotent --output migracja.sqlPodajesz nazwę migracji, która jest już na produkcji, a EF Core generuje SQL ze wszystkimi zmianami od tego miejsca. Opcja --idempotent sprawia, że skrypt sam sprawdza, które migracje zostały już zastosowane. Taki plik czytasz linijka po linijce - i to w nim zobaczysz DROP COLUMN, zanim zobaczy go produkcja.
Nudne? Bardzo. Ale nuda na produkcji to dokładnie to, czego chcesz.
Nigdy #4: nauka fundamentów
To szczególnie ważne, jeśli dopiero wchodzisz do branży. Jeśli AI pisze za Ciebie kod, którego nie rozumiesz, to nie masz asystenta. Masz dług. I spłacisz go w najgorszym możliwym momencie: na rozmowie kwalifikacyjnej, kiedy ktoś poprosi Cię o wyjaśnienie "Twojego" kodu. Albo o 3:00 w nocy, kiedy produkcja leży, a AI proponuje już 5. z rzędu "rozwiązanie", które nie działa. Junior z AI potrafi wyprodukować 500 linii dziennie i nie mieć pojęcia, czemu aplikacja nie działa.
Bez modelu mentalnego nie ocenisz kodu od AI. async/await, LINQ i odroczone wykonanie, typy referencyjne kontra wartościowe - to musisz przeżyć sam, na własnych błędach. Przykład? Ten kod wygląda zupełnie niewinnie:
var noweZamowienia = db.Zamowienia.Where(z => z.Status == Status.Nowe); /* nic się jeszcze nie wykonało */
var liczba = noweZamowienia.Count(); /* zapytanie nr 1 do bazy */
var lista = noweZamowienia.ToList(); /* zapytanie nr 2 do bazy */Jeśli nie rozumiesz odroczonego wykonania, nie zauważysz, że kod od AI odpytuje bazę 2 razy (a w pętli - przy każdej iteracji). Bez takiego modelu mentalnego nie jesteś w stanie ocenić, czy kod od AI jest dobry. A umiejętność oceny cudzego kodu to dziś najważniejsza umiejętność programisty. Ważniejsza niż pisanie.
Jak to robię: odwróć role. Uwaga - nie mówię "nie używaj AI do nauki". Mówię: odwróć role. AI jako nauczyciel to genialna sprawa:
"Wytłumacz mi, jak działa odroczone wykonanie w LINQ. Potem daj mi zadanie, sprawdź moje rozwiązanie i dopytuj, aż będziesz pewien, że to rozumiem."
Natomiast AI jako autor Twoich ćwiczeń to droga donikąd.
Nigdy #5: finalny code review
Ostatnia para oczu przed merge to zawsze człowiek. Powody są 2.
Odpowiedzialności nie da się delegować. Jak coś wybuchnie na produkcji, na retro nikt nie przyjmie tłumaczenia "tak mi wygenerowało AI". Ty kliknąłeś merge - Twój kod. Koniec tematu.
AI recenzujące kod od AI przepuszcza własne błędy. Kod się kompiluje, testy świecą na zielono, a logika robi coś subtelnie innego niż wymaganie. Mój ulubiony klasyk:
/* Źle: wynik zależy od strefy czasowej maszyny, na której działa kod */
var dzisiaj = DateTime.Now.Date;
/* Dobrze: w logice i w bazie trzymaj UTC, na czas lokalny konwertuj dopiero przy wyświetlaniu */
var teraz = DateTime.UtcNow;Na Twojej maszynie wszystko gra. Na serwerze w innej strefie czasowej - już nie. Taki błąd przechodzi przez kompilator, przez testy i często też przez review zrobione przez model, który popełnia dokładnie ten sam błąd.
Jak to robię: AI robi pierwsze review, ja ostatnie. Zanim sam usiądę do kodu, daję AI prompt w stylu:
"Znajdź w tym kodzie bugi, edge case'y i problemy wydajnościowe."
To wyłapuje naprawdę sporo. Ale ostatnie review jest moje. Zawsze.
Część 2: co oddaję AI zawsze
To była lista zakazów. Teraz druga strona medalu: 5 zadań, które oddaję AI zawsze, bez wahania. Tu robią się prawdziwe oszczędności czasu.
Zwróć uwagę, co je łączy: wynik łatwo sprawdzić, a pomyłka kosztuje niewiele. Za chwilę zamienię to w prostą zasadę, dzięki której sam zdecydujesz o każdym innym zadaniu.
Zawsze #1: boilerplate
DTO, mapowania, rejestracje w DI, bindowanie konfiguracji, klasy z JSON-a. Zero myślenia, 100% klepania. To idealne zadanie dla AI z 3 powodów: wynik widzisz od razu, błąd wyłapiesz na oko, a koszt pomyłki jest bliski zeru. Oszczędność? Godziny tygodniowo.
JSON na rekordy C# w 20 sekund. Mój ulubiony trik: wklejam JSON-a z odpowiedzi API i piszę:
"Zamień ten JSON na rekordy C# z atrybutami System.Text.Json."
20 sekund zamiast 20 minut. Wynik wygląda mniej więcej tak:
public record OrderResponse(
[property: JsonPropertyName("order_id")] int OrderId,
[property: JsonPropertyName("customer_name")] string CustomerName,
[property: JsonPropertyName("created_at")] DateTimeOffset CreatedAt,
[property: JsonPropertyName("items")] List<OrderItem> Items);
public record OrderItem(
[property: JsonPropertyName("sku")] string Sku,
[property: JsonPropertyName("quantity")] int Quantity,
[property: JsonPropertyName("unit_price")] decimal UnitPrice);Pro tip: DTO z ręcznym mapowaniem. Teraz rada, za którą część programistów mnie zhejtuje: wklej encję i poproś o DTO plus ręczne mapowanie. Tak, ręczne. Od kiedy AI pisze mapowania w sekundę, AutoMapper w większości projektów stracił rację bytu - a debugowanie ręcznego mapowania jest 100 razy prostsze:
public static class ZamowienieMapowanie
{
public static ZamowienieDto ToDto(this Zamowienie zamowienie) => new(
zamowienie.Id,
zamowienie.Numer,
zamowienie.Klient.Nazwa,
zamowienie.Pozycje.Sum(p => p.Cena * p.Ilosc));
}Wszystko widać czarno na białym: możesz postawić breakpoint, sprawdzić "Find All References", a gdy ktoś zmieni nazwę właściwości w encji, dostaniesz błąd kompilacji, a nie puste pole w odpowiedzi API na produkcji.
Zawsze #2: szkice testów jednostkowych
AI jest zaskakująco dobre w wymyślaniu edge case'ów, o których zapominasz w piątek o 17:00: null, pusty string, polskie znaki, wartości ujemne, kolekcja z 1 elementem. Piszę:
"Napisz testy xUnit dla tego walidatora. Uwzględnij przypadki brzegowe: null, pusty string, polskie znaki, wartości ujemne."
i w minutę dostaję szkielet z sensownymi nazwami i strukturą Arrange-Act-Assert.
Uwaga: zielony test to nie dowód poprawności. Jedno wielkie ALE, i to jest ważne: AI potrafi napisać test, który przechodzi, ale niczego nie sprawdza. Na przykład taki (walidator w FluentValidation):
[Fact]
public void Validate_PustyEmail_ZwracaBlad()
{
var walidator = new RejestracjaWalidator();
var wynik = walidator.Validate(new Rejestracja { Email = "" });
Assert.NotNull(wynik); /* zawsze zielony - niczego nie sprawdza */
}Ten test będzie zielony niezależnie od tego, czy walidator działa. Logikę sprawdzają dopiero porządne asercje:
Assert.False(wynik.IsValid);
Assert.Contains(wynik.Errors, e => e.PropertyName == nameof(Rejestracja.Email));Dlatego czytam każdą asercję. Mimo to i tak wychodzi 3 razy szybciej, niż gdybym pisał wszystko sam. A pokrycie testami w projekcie w końcu realnie rośnie - bo pisanie testów przestało boleć.
Zawsze #3: regex, LINQ i SQL
To zadania typu "wejście - wyjście": banalnie łatwo je zweryfikować, a koszmarnie nudno pamiętać składnię. Nikt normalny nie pamięta, jak się pisze lookahead w regexie. I nie musi.
Zawsze proś o przykłady testowe. Cały trik tkwi w tym, jak formułujesz prośbę:
"Napisz regex do polskiego kodu pocztowego. Dodaj 5 przykładów, które przechodzą, i 5, które nie przechodzą."
Te przykłady to klucz - dzięki nim weryfikacja zajmuje 10 sekund:
var kodPocztowy = new Regex(@"^[0-9]{2}-[0-9]{3}$");
/* przechodzą: 00-950, 31-042, 80-180, 61-001, 99-999 */
/* nie przechodzą: 00950, 0-950, 00-95, 00-9500, ab-123 */Przy okazji drobiazg, który dobrze pokazuje, po co jest weryfikacja: w .NET \d dopasowuje każdą cyfrę Unicode, a nie tylko 0-9 (np. także cyfry arabsko-indyjskie). Dlatego w walidacji bezpieczniej użyć [0-9] - i warto, żeby taki przypadek trafił na listę przykładów, które nie przechodzą.
LINQ i SQL działają tak samo. Wieloetapowe GroupBy z projekcją, nad którym kiedyś siedziałem pół godziny, AI wypluwa od ręki. Podobnie window functions w SQL. Ja tylko puszczam zapytanie na danych testowych i sprawdzam wynik.
Zawsze #4: wyjaśnianie cudzego kodu
Dostajesz projekt legacy: metoda na 400 linii, zero komentarzy, autor od 3 lat nie pracuje w firmie. Kiedyś: 2 dni czytania z notesem. Dziś:
"Wyjaśnij krok po kroku, co robi ta metoda, gdzie może rzucić wyjątkiem i co byś tu zrefaktorował."
5 minut i mam mapę terenu. AI przeczyta 500 linii szybciej niż Ty 50.
Ryzyko praktycznie zerowe. Nawet jeśli AI pomyli się w 10% - a czasem się myli - to i tak startuję z zupełnie innego poziomu. A ryzyko? Praktycznie zero, bo niczego nie wdrażam, tylko czytam.
Kryptyczne błędy i migracje bibliotek. To samo działa na kryptyczne błędy MSBuild, konflikty NuGetów i stack trace'y na 3 ekrany. AI tłumaczy z "kompilatorowego" na ludzki lepiej niż niejedna dokumentacja. Bonus: migracje bibliotek, np. z Newtonsoft.Json na System.Text.Json. AI zna odpowiedniki 1:1, np. [JsonProperty] → [JsonPropertyName] czy JsonConvert.SerializeObject → JsonSerializer.Serialize.
Zawsze #5: dokumentacja
XML doc do publicznych metod, README, opisy pull requestów, komunikaty commitów. Umówmy się - nikt tego nie lubi pisać. I dlatego zwykle... nikt tego nie pisze.
A AI robi to dobrze i szybko. Co najważniejsze: błąd w dokumentacji nie położy Ci produkcji, a review to 30 sekund czytania. Prompty są banalne:
"Wygeneruj XML doc dla publicznych metod tej klasy."
"Napisz opis PR na podstawie tego diffa."
Efekt jest taki, że dokumentacja w projekcie w końcu istnieje. Twój zespół - i Ty sam za pół roku - będziecie wdzięczni.
Jak decydować samemu? Zasada 2 pytań
Listy listami, ale projekty są różne i codziennie wpadają zadania spoza tej dziesiątki. Jak decydować samemu? Zadaję sobie 2 pytania.
Pytanie 1: ile kosztuje błąd? Jeśli AI się pomyli, to poprawiam literówkę w DTO - czy odzyskuję dane klientów z backupu?
Pytanie 2: ile kontekstu potrzeba? Czy cały kontekst zadania mieści się w prompcie - jak przy regexie? Czy siedzi w głowach ludzi, w historii firmy i w budżecie - jak przy architekturze?
Z odpowiedzi wychodzi prosty werdykt:
• Deleguj: tani błąd i pełny kontekst w prompcie. Tak jest przy boilerplate, testach, regexach i dokumentacji.
• Zostaw u siebie: drogi błąd albo kontekst rozproszony po ludziach. Tak jest przy architekturze, security i operacjach na produkcji.
Te 2 pytania załatwiają 90% przypadków. A jeśli masz z tego artykułu zapamiętać tylko jedno zdanie, niech to będzie to:
"AI to genialny junior z fotograficzną pamięcią. Deleguj mu zadania jak juniorowi. I rób mu code review - jak juniorowi."
Checklista: zanim zmergujesz kod od AI
Na koniec obiecana checklista. 5 punktów do sprawdzenia, zanim zmergujesz kod wygenerowany przez AI:
1. Rozumiem każdą linię. Jak nie rozumiem - pytam AI tak długo, aż zrozumiem. To swoją drogą świetna nauka.
2. Przeczytałem testy. Sprawdzają logikę, a nie tylko świecą na zielono.
3. Sprawdziłem edge case'y. Null, pusta kolekcja, daty i strefy czasowe. I nasz polski klasyk: kultura pl-PL i przecinek w liczbach - double.Parse potrafi zaskoczyć, jeśli serwer ma inne ustawienia regionalne niż Twój laptop (przykład niżej).
4. Paczki i API naprawdę istnieją. AI potrafi wymyślić NuGeta, którego nie ma, albo użyć metody sprzed 5 wersji frameworka.
5. Wejście jest walidowane, sekretów brak. Dane wejściowe są walidowane, a żaden connection string ani klucz API nie wylądował w kodzie.
Przykład do punktu 3:
var tekst = "12,5";
/* Laptop z pl-PL: 12,5. Serwer z en-US: 125 (przecinek to tam separator tysięcy) */
var kwota = double.Parse(tekst);
/* Kultura podana jawnie - wynik nie zależy od ustawień serwera */
var kwotaPewna = double.Parse(tekst, CultureInfo.GetCultureInfo("pl-PL"));Zrób sobie screenshot tej listy albo ją wydrukuj i powieś nad biurkiem. Podziękujesz mi za pół roku.
Ściąga: nigdy vs zawsze
Cała lista w jednym miejscu - razem z tym, jak w praktyce wygląda rola AI i weryfikacja:
| Nigdy nie oddaję AI | Oddaję AI zawsze |
| Decyzje architektoniczne - AI wymienia ryzyka i zadaje pytania, decyzja jest moja | Boilerplate - DTO, mapowania, DI, konfiguracja; błąd widać na oko |
| Kod bezpieczeństwa - sprawdzone biblioteki i review człowieka; AI najwyżej tłumaczy | Szkice testów jednostkowych - edge case'y od AI, ja czytam każdą asercję |
| Operacje na produkcyjnej bazie - AI pisze szkic, ja: skrypt SQL, backup, test na kopii | Regex, LINQ i SQL - zawsze razem z przykładami testowymi |
| Nauka fundamentów - AI jako nauczyciel, nie autor Twoich ćwiczeń | Wyjaśnianie cudzego kodu - tylko czytam, niczego nie wdrażam |
| Finalny code review - AI robi pierwsze review, ja ostatnie | Dokumentacja - XML doc, README, opisy PR; review w 30 sekund |
Podsumowanie
Najważniejsze rzeczy w pigułce:
• Nigdy nie oddaję AI: decyzji architektonicznych, kodu bezpieczeństwa, operacji na produkcyjnej bazie, nauki fundamentów i finalnego code review - bo koszt błędu jest za wysoki.
• Oddaję AI zawsze: boilerplate, szkice testów, regex/LINQ/SQL, wyjaśnianie cudzego kodu i dokumentację - bo wynik łatwo sprawdzić, a pomyłka jest tania.
• Zasada 2 pytań: ile kosztuje błąd i ile kontekstu potrzeba. Tani błąd i pełny kontekst - deleguj. W przeciwnym razie zostaw u siebie.
• Checklista przed merge: rozumiem każdą linię, czytam testy, sprawdzam edge case'y, weryfikuję paczki i API, pilnuję walidacji i sekretów.
I jedna rzecz na koniec. AI nie zabiera pracy programistom, którzy myślą. Zabiera klepanie. Cała wartość przesuwa się w stronę decyzji, kontekstu i odpowiedzialności - czyli dokładnie tych 5 rzeczy z pierwszej listy. I to jest dla nas dobra wiadomość.
Jeśli chcesz od razu przełożyć listę "zawsze" na praktykę, mam coś dla Ciebie. Przygotowałem darmowy PDF: 25 gotowych promptów AI dla programistów C#/.NET. W środku: refaktoryzacja, testy jednostkowe, debugowanie, code review oraz praca z legacy i dokumentacją, a do tego 3 zasady pracy z AI. Prompty działają w Claude Code, Copilocie i Cursorze - kopiujesz, wklejasz i widzisz różnicę w 5 minut. Każdy ma krótką wskazówkę, czemu jest tak zbudowany, żebyś umiał pisać własne, a nie tylko kopiować moje.
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 - newsy ze świata .NET i AI z moim komentarzem, rzeczy, które właśnie testuję, i rabaty na moje kursy, których nie znajdziesz nigdzie indziej. Zero spamu - wypisujesz się jednym kliknięciem.
Powodzenia w delegowaniu - i w code review :)