Skip to main content
SEMastery
Fundamentalsbeginner

40 Lessons I Learned in 12 Years as a .NET Developer

Forty honest, beginner-friendly lessons from 12 years of .NET work, covering C#, EF Core, testing, deployment, teamwork, and a calm career.

11 min readUpdated October 9, 2025

A quick story before the lessons

Imagine you are learning to cook in your home kitchen. On day one you burn the rice. You add too much salt. You cut your finger a little. But you keep cooking. After a few years, you do not even look at the recipe. Your hands just know.

Writing software is the same. Nobody is born knowing it. You learn by making small mistakes, again and again, until the mistakes become wisdom.

I have spent twelve years writing .NET code. I started scared and confused. I am still learning today. Below are forty lessons I wish someone had handed me on my first day. They are simple. They are honest. And a careful twelve-year-old can follow most of them.

Let me show you how a small daily habit grows into real skill.

Small daily steps slowly turn a beginner into a calm, skilled engineer.

Lessons about code (the C# itself)

1. Names matter more than you think. A variable called d tells nobody anything. daysUntilExpiry tells the whole story. Good names are free documentation.

2. Small methods are easier to trust. If a method does not fit on your screen, it is probably doing two jobs. Split it.

3. null is the source of most bugs. Turn on nullable reference types. The compiler will warn you before your users do.

#nullable enable
 
// The compiler now warns you here, because GetName might return null.
string? name = user.GetName();
Console.WriteLine(name.Length); // warning: possible null
 
// Safer:
Console.WriteLine(name?.Length ?? 0);

4. Prefer var only when the type is obvious. var total = 0; is fine. var x = Process(); hides too much.

5. Learn LINQ early, but read what it does. LINQ is lovely. It can also hide slow loops. Know when a query touches the database and when it runs in memory.

6. Records are great for data that does not change. They give you equality and a clean shape for free.

7. Use new C# features, but do not chase every one. C# 14 added field-backed properties and nicer extension members. They are useful. Still, a clear if statement beats a clever one-liner you cannot read next month.

8. async all the way, or not at all. Mixing blocking calls like .Result with async code causes deadlocks. Pick one path.

9. Exceptions are for the unexpected. Do not use them for normal flow, like "user not found." That is slow and confusing.

10. Delete dead code. If it is commented out, your git history already keeps it. Remove it.

Here is how a single request flows through a typical .NET app. Knowing this map makes debugging far calmer.

The path of one HTTP request through a normal ASP.NET Core application.

Lessons about data and EF Core

11. The database is usually the slow part. Most "my app is slow" problems are really "my query is slow."

12. Beware the N+1 query. Looping over a list and hitting the database each time is a classic trap. Load what you need in one go.

// ❌ N+1: one query for orders, then one query per order for its customer
var orders = await db.Orders.ToListAsync();
foreach (var o in orders)
    Console.WriteLine(o.Customer.Name); // hidden query each loop!
 
// ✅ One query that brings the customer along
var orders = await db.Orders
    .Include(o => o.Customer)
    .ToListAsync();

13. Use AsNoTracking() for read-only data. If you are only showing data, you do not need EF Core to watch it for changes. It is faster.

14. Never trust user input near SQL. Use parameters. EF Core does this for you, so do not glue raw strings together.

15. Migrations are your friend, but review them. Always open the generated migration and read it before running it on real data.

16. Back up before you change production data. This lesson cost me a long, scary night once. Learn it the cheap way.

Here is a simple table of EF Core habits and why they help.

HabitWhy it helps
AsNoTracking() on readsLess memory, faster queries
Include() for related dataAvoids N+1 queries
Review migrationsCatches accidental data loss
Index your filter columnsDatabase finds rows quickly
Avoid SELECT * patternsMove less data over the wire

Lessons about testing

17. A test you trust lets you sleep. When tests pass, you can change code without fear.

18. Test behavior, not the inside. Check what the method returns, not which private field it set.

19. Start with the simple cases. Empty list. Null input. Zero. Bugs love these corners.

[Fact]
public void Discount_Is_Zero_When_Cart_Is_Empty()
{
    var cart = new Cart(); // no items
    var discount = cart.CalculateDiscount();
    Assert.Equal(0m, discount);
}

20. Slow tests get skipped. If the suite takes ten minutes, people stop running it. Keep most tests fast.

21. One assert idea per test. A test should fail for one clear reason.

22. Do not test the framework. You do not need to test that EF Core saves a row. Trust the tools. Test your own logic.

Lessons about building and shipping

This is the part beginners fear most. Let me lay out a calm release flow.

A Safe Release Flow

Code
Pull Request
CI Tests
Staging
Production

Steps

1

Code

Write on a branch, not on main

2

Pull Request

A teammate reviews your change

3

CI Tests

The build runs all tests automatically

4

Staging

Try it in a safe copy of production

5

Production

Release in small, reversible steps

Each step catches problems earlier, when they are cheap to fix.

23. Automate the build. If shipping needs ten manual steps, one will be forgotten. Let a pipeline do it.

24. Small releases are safer than big ones. A tiny change is easy to undo. A giant change is a guessing game when it breaks.

25. Always have a way back. Know how to roll back before you roll forward.

26. Read your logs. Good logging is like leaving footprints. When something breaks at 2 a.m., footprints save you.

27. Configuration does not belong in code. Keep secrets and settings outside the source. Never commit a password.

28. Measure before you optimize. "I think this is slow" is a guess. A profiler gives you the truth. Fix the real hot spot, not the imagined one.

Here is how problems get cheaper to fix the earlier you catch them.

Cost of a Bug Over Time

While Typing
In Review
In Tests
In Production

Steps

1

While Typing

Almost free; the compiler tells you

2

In Review

Cheap; a teammate spots it

3

In Tests

Still cheap; caught before users

4

In Production

Expensive; users and trust are hurt

The same bug costs more the further it travels toward your users.

Lessons about tools and the ecosystem

29. Stay on supported versions. .NET 10 is the current LTS release with three years of support. Old, unsupported versions stop getting security fixes. Plan upgrades early, not in a panic.

30. Pick libraries carefully. A library is a long-term marriage, not a quick chat.

31. Watch the license, not just the features. Some popular tools changed their rules. For example, MediatR and MassTransit are now commercially licensed for many uses. They are still good, but check the cost and terms before you depend on them in a big project.

32. You do not need a library for everything. Sometimes ten lines of your own code beats a heavy dependency you must keep updated.

33. Learn your debugger. Breakpoints, stepping, and watching variables will teach you more than a hundred print statements.

34. The docs are usually right. Microsoft Learn is free and accurate. Read it before searching random blogs.

Here is a comparison of a few choices you will make often.

ChoiceGood whenBe careful when
A big libraryIt solves a hard, common problemIts license or size grows costly
Your own codeThe task is small and specificIt becomes complex and untested
Newest .NET versionYou want speed and new featuresYou are mid-project and stable
MicroservicesTeams and scale are largeYour app is still small and simple

Lessons about people and yourself

This is the half nobody tells beginners. Software is built by humans.

35. Ask questions early. Being stuck quietly for a day helps no one. A good question is a sign of strength, not weakness.

36. Code review is a gift, not an attack. When a teammate marks up your code, they are protecting the product and teaching you. Say thank you.

37. Write for the next person. The next person reading your code might be you, six months from now, tired and forgetful. Be kind to that person.

38. Rest is part of the work. Tired brains write buggy code. A walk often solves the problem a long night could not.

39. You will never know everything, and that is fine. Twelve years in, I still Google basic things. The goal is not to memorize. The goal is to know how to find out.

40. Be patient with yourself. Every expert was once a beginner who burned the rice. Keep cooking.

Let me show how these soft skills and hard skills grow together over a career.

A healthy career grows both technical skill and people skill at the same time.

How a beginner should use this list

You do not need to apply all forty lessons today. That would be too much, like trying to learn every spice on the first day of cooking.

Pick three. Maybe lesson 3 (turn on nullable), lesson 12 (avoid N+1), and lesson 35 (ask questions early). Practice those for a month. Then come back and pick three more.

Skill is not a single jump. It is many small steps, repeated with care. The compiler will catch you. Your tests will protect you. Your teammates will guide you. And one day you will look back and realize your hands just know.

Quick recap

  • Software skill grows from many small mistakes, like learning to cook.
  • Clear names, small methods, and async discipline make code easy to trust.
  • The database is often the slow part; watch out for the N+1 query.
  • Tests you trust let you change code without fear, so keep them fast.
  • Automate your build, ship small, and always keep a way to roll back.
  • Stay on supported versions like .NET 10 LTS, and check library licenses (note: MediatR and MassTransit are now commercially licensed).
  • People skills matter as much as code: ask early, welcome reviews, and rest.
  • Be patient. Pick three lessons, practice, then pick three more.

References and further reading

Related Posts