Dataslope logoDataslope

Writing Maintainable Software

Code is read far more often than it is written — habits that make programs a pleasure to come back to

Most professional software engineering isn't writing brand-new code. It's changing code that someone (often a past version of yourself) wrote months or years ago. The code that's easy to come back to and change without breaking is maintainable code.

This chapter isn't about C# features. It's about the small habits that compound over a career.

The first audience for your code is the next person

Including future-you, six months from now, who's forgotten everything. Write for that person. They're tired, they're in a hurry, and they want to understand your code in five minutes, not fifty.

Three concrete consequences:

  1. Names matter more than cleverness. A clear name is worth ten comments.
  2. Small things beat big things. Small classes, small methods, small files.
  3. Boring is good. Surprising code is hard to maintain, even when it's correct.

Naming

Compare:

Code Block
C# 13
Code Block
C# 13

Both produce the same number. Only one tells you what's happening at the call site. The C# community has well-trodden naming conventions:

ThingConventionExample
Class, struct, recordPascalCaseBankAccount
Public method, propertyPascalCaseDeposit, Balance
Local variablecamelCasetotalAmount
ParametercamelCaseaccountId
Private field_camelCase (common)_balance
InterfaceIPascalCaseIDisposable
ConstantPascalCaseMaxRetries

Following the conventions sounds trivial but pays off the moment someone else reads your code: they immediately know what kind of thing each identifier is.

Methods that do one thing

We saw this in the methods chapter; it's worth repeating because it's the single biggest readability lever.

Code Block
C# 13
Code Block
C# 13

The second version is slightly longer but each piece is independently nameable and testable.

Don't repeat yourself (DRY)

Duplicated code is duplicated bugs. The moment a piece of logic appears twice and starts diverging, extract it into a method or a class.

But DRY is a guideline, not a religion. Two pieces of code that look the same today but model different concepts may need to diverge tomorrow. Be pragmatic.

Comments: explain why, not what

Code Block
C# 13

A good comment answers a question the code can't: why this particular value, why this particular order, why this seemingly-odd branch exists. The code already shows what.

Cyclomatic complexity, in plain words

Every if, switch, loop, &&, or || adds a new path through a method. The more paths, the harder it is to think about all the cases. Methods with one or two branches are easy; methods with fifteen are nightmares.

If a method has more than ~10 decision points, that's a sign to refactor — usually by extracting smaller methods or replacing nested conditionals with polymorphism.

Mutable state is a tax

Every variable that can change makes a program harder to reason about. Where you can:

  • Prefer readonly fields and get-only properties.
  • Prefer returning new values to mutating existing ones.
  • Prefer immutable types like record for "value-shaped" data.
Code Block
C# 13

record types give you value-style equality and the with expression for non-destructive updates. They are excellent for data carriers in modern C#.

A maintenance-friendly project ages well

A useful self-test, six months in:

  1. Can you understand what each file is for from its name?
  2. Can you read any single method in under a minute?
  3. Are tests present, and do they tell you what the code is for?
  4. When a change is needed, is the change localized?

If yes to all four, the project is in good shape. If not, you've just found your refactoring targets.

Small habits, big payoff

A short, rotating set of habits that compound massively:

  • Run tests on every change. Don't accumulate weeks of red.
  • Commit small. A commit per logical change beats giant blobs.
  • Format consistently. Pick a style and stick to it.
  • Delete code aggressively. Dead code rots.
  • Refactor with the change. Don't promise to "clean it up later."

Test your understanding

QuestionSelect one

Why does code readability matter so much?

The compiler runs unreadable code more slowly

Readability is required by the language spec

Code is read far more often than it is written; readable code is cheaper to maintain and less likely to harbor bugs

Readable code uses less memory

QuestionSelect one

Which is the best comment to attach to a line of code?

A restatement of what the code does in English

The author's initials and the current date

An explanation of why the code is the way it is — context the code itself can't capture

Nothing — comments should always be removed

On this page