Skip to content
Katabench
Try free

Free C# design-principles practice in the browser

C# SOLID principles exercises that grade the design

Refactor working C# until the code is easier to change for a reason you can prove. Behavior tests protect the feature while 244 executable rules grade abstractions, immutability, interfaces, dependencies, and pattern structure across 28 focused exercises.

All exercises are available on every plan. No project setup or local SDK.

design exercises
28
executable rules
244
available free
28/28

Beyond naming the acronym

Make the principle survive a workaround

Reading that high-level code should depend on abstractions is easy. The useful judgment is recognizing when an interface still leaks a vendor DTO, a class accepts the interface but constructs the concrete anyway, or a service locator merely moves behind a readonly field.

Each kata starts with working code and one plausible design failure. You refactor several files, keep 122 catalog behavior tests green, and satisfy authored rules that inspect the submitted type structure. A cosmetic rename cannot clear a dependency rule.

Start with the dependency inversion guide or the value-object guide, then turn the idea into a graded refactor.

Your refactor

IPricingStrategy.cs

PricingCalculator.cs

CompositionRoot.cs

Working code is supplied. You change the design without changing the behavior.

Behavior suite

The feature still calculates every price correctly

PASS

Executable design rules

depends on abstraction

PricingCalculator → IPricingStrategy

✓ HOLDS

no concrete dependency

PricingCalculator ↛ PremiumPricing

✓ HOLDS

sealed policy owner

PricingCalculator is sealed

✓ HOLDS
Tests protect what the code does. Structural rules prove the submitted design has the intended shape.

Four object-design skill families

Practice the pressure that makes each principle useful

The exercises are organized by the design decision they force, not by flashcard letters. That keeps Result models, honest capability contracts, Observer, Strategy, Decorator, value objects, and SOLID principles attached to the problems they actually solve.

Encapsulation, explicit outcomes, and invariants

9 exercises

Make state ownership, resource lifetimes, and expected outcomes explicit, close mutation leaks, keep snapshots opaque, and encode invariants in types instead of relying on callers to behave.

Single responsibility, dependency inversion, and clean ports

6 exercises

Split a class along its reasons to change, depend on abstractions owned by the policy side, remove the ones nothing varies behind, expose hidden dependencies, and keep vendor types outside application-facing contracts.

Substitutability, interface segregation, and low coupling

4 exercises

Keep subtype contracts honest, shrink roles to what each consumer actually needs, separate queries from commands, and replace long object-navigation chains with intention-revealing boundaries.

Composition and behavioral patterns

9 exercises

Use observers, policies, strategies, null objects, decorators, composites, state objects, undoable commands, and visitors where fixed collaborators, inheritance, switches, type tests, nullable branches, boolean flags, and tagged trees resist change.

28 free C# SOLID and design-pattern exercises

Refactor every design in the browser

Start with one concrete dependency or train wreck, then move into explicit outcomes, honest subtype contracts, value objects, composition, Observer, Strategy, Null Object, and Decorator. Every card opens the actual kata.

9 focused refactors

Encapsulation, explicit outcomes, and invariants

  1. Medium 4 tests + 10 rules

    History Keeps a Checkpoint, Not Editor Internals

    Give history immutable checkpoints it can restore repeatedly without seeing the editor's internals.

    Refactor this design →
  2. Medium 3 tests + 5 rules

    Freeze the Money

    Turn a mutable Money-shaped DTO into a structurally immutable value object.

    Refactor this design →
  3. Medium 6 tests + 4 rules

    An OrderId Is Not a CustomerId

    Give order and customer identifiers their own always-valid value types so a swapped argument stops compiling.

    Refactor this design →
  4. Medium 3 tests + 3 rules

    Kill the Global Counter

    Give mutable state one explicit owner and remove a process-wide static coupling.

    Refactor this design →
  5. Medium 5 tests + 10 rules

    Make Failure a Result

    Replace a hidden throw/catch protocol with one sealed, immutable enrollment outcome.

    Refactor this design →
  6. Medium 6 tests + 13 rules

    Make Illegal States Unrepresentable

    Model each parcel stage as an immutable type that carries only its own data and legal moves.

    Refactor this design →
  7. Hard 3 tests + 6 rules

    Make It a Value Object

    Freeze a two-phase Reservation and stop its guest collection escaping through the API.

    Refactor this design →
  8. Medium 4 tests + 9 rules

    Own the Lease Until the Work Ends

    Acquire and deterministically dispose a lease in one scope, exception paths included, from any lease factory.

    Refactor this design →
  9. Hard 3 tests + 4 rules

    Seal the Aggregate

    Protect an Order invariant by sealing mutation paths and its backing collection.

    Refactor this design →

6 focused refactors

Single responsibility, dependency inversion, and clean ports

  1. Easy 3 tests + 5 rules

    Ask for the Interface

    Replace a hidden concrete dependency with an explicit abstraction-owned constructor seam.

    Refactor this design →
  2. Medium 7 tests + 7 rules

    Four Layers for One Formula

    Remove the abstractions nothing varies behind and keep the one that does, without changing a single report card.

    Refactor this design →
  3. Hard 3 tests + 5 rules

    The Leaky Payment Port

    Build a vendor-neutral payment port instead of leaking Stripe types through an interface.

    Refactor this design →
  4. Medium 5 tests + 13 rules

    One Reason to Change

    Split a payment importer so statement parsing, storage, and summary wording each change in one place.

    Refactor this design →
  5. Hard 3 tests + 4 rules

    Program to the Abstraction

    Make every payment method a conventionally named drop-in over one real abstraction.

    Refactor this design →
  6. Medium 4 tests + 5 rules

    Retire the Service Locator

    Expose a quote calculator's hidden global dependency through constructor injection.

    Refactor this design →

4 focused refactors

Substitutability, interface segregation, and low coupling

  1. Hard 5 tests + 18 rules

    Make the Membership Contract Honest

    Split shared membership identity from renewal so lifetime members inherit no lying method.

    Refactor this design →
  2. Easy 4 tests + 7 rules

    A Preview Must Not Consume Work

    Hand queue observers a read-only preview and keep consumption behind an explicit command.

    Refactor this design →
  3. Medium 3 tests + 8 rules

    Shrink the Machine Interface

    Split a fat machine contract so printers and consumers depend only on roles they use.

    Refactor this design →
  4. Easy 3 tests + 5 rules

    Stop the Train Wreck

    Replace a multi-object navigation chain with one intention-revealing neighbor call.

    Refactor this design →

9 focused refactors

Composition and behavioral patterns

  1. Hard 6 tests + 23 rules

    A Rule Tree Can Contain Any Rule

    Replace a tagged-tree evaluator with recursive rule objects that keep child order and short-circuit behavior.

    Refactor this design →
  2. Hard 6 tests + 11 rules

    Compose the Fees

    Flatten a fee hierarchy into a sealed account composed with interchangeable policies.

    Refactor this design →
  3. Hard 5 tests + 10 rules

    Notify Every Observer

    Broadcast build completion through an open observer collection and prove every subscriber runs.

    Refactor this design →
  4. Medium 3 tests + 5 rules

    Null Object: No Branching

    Replace repeated null checks with a substitutable NoDiscount supplied at composition.

    Refactor this design →
  5. Hard 5 tests + 5 rules

    Strategy Over the Switch

    Move plan-specific pricing behind strategies chosen outside the calculator.

    Refactor this design →
  6. Hard 4 tests + 14 rules

    Adopt the State That Comes Back

    Move lifecycle decisions into state objects and adopt every successor they return across a whole sequence.

    Refactor this design →
  7. Medium 6 tests + 11 rules

    Undo What Actually Happened

    Turn stock adjustments into commands that undo what really happened behind a history that knows no stock.

    Refactor this design →
  8. Hard 5 tests + 10 rules

    Visit Every Invoice Line

    Replace type switches and their silent defaults with visitors, so a new invoice line kind fails to compile.

    Refactor this design →
  9. Hard 5 tests + 14 rules

    Wrap It, Don't Flag It

    Replace multiplying boolean branches with stackable decorators over one announcer role.

    Refactor this design →

The design-practice loop

Preserve the feature, change the reason it is easy to extend

01

Find the design pressure

Read working C# with one specific rigidity: a concrete dependency, fat interface, mutation leak, switch, flag, or global hiding the real seam.

02

Refactor the shape

Edit the multi-file project in the browser. Introduce the smallest abstraction, policy, wrapper, or invariant boundary that resolves the pressure.

03

Prove behavior and design

Submit against behavior tests and executable structural rules. The feature must still work, and the dependency or type shape must genuinely change.

The structural verdict is separate from correctness. Read how Katabench grades design rules and why a compiling implementation can still be the wrong shape.

C# SOLID principles exercise FAQ

Before you move the first dependency

What are C# SOLID principles exercises?

They are small working C# systems with one design pressure already present. Instead of answering a quiz about an acronym, you refactor the code and receive separate verdicts for preserved behavior and structural design rules such as abstraction use, interface segregation, immutability, sealing, and dependency direction.

Do these exercises cover all five SOLID principles?

The strongest direct coverage is Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion, and one exercise splits a class along its reasons to change for Single Responsibility. Related exercises train state ownership, explicit outcomes, composition over inheritance, encapsulation, and value objects. It is a focused practice catalog, not a five-chapter theory course that forces every kata under one letter.

Which C# design patterns can I practice?

The catalog includes Strategy, Decorator, Observer, Composite, State, Memento, Command with undo, Visitor, Null Object, Value Object, strongly typed identifiers, one type per lifecycle stage, explicit Result models, command-query separation, composition roots, constructor injection, anti-corruption ports, composition over inheritance, and removing speculative abstractions. Each pattern appears as a response to a concrete design problem rather than an isolated template to copy.

Are all 28 design-principles exercises free?

Yes. The complete Design Principles track is currently available on all plans. Daily graded-submission limits still depend on your plan, but none of these exercises is locked behind a specialized-track entitlement.

Do I need Visual Studio or the .NET SDK installed?

No. The multi-file editor, compiler, behavior tests, and design-rule grader run from the browser in disposable server-side sandboxes.

How are design-principles exercises different from architecture exercises?

Design-principles exercises focus on the internal shape and collaborators of a few types: immutability, interfaces, roles, dependencies, and patterns. Architecture exercises operate at the larger namespace, layer, module, and dependency-graph level.

Looking for broader practice? Browse all C# coding challenges across algorithms, data access, refactoring, architecture, security, testing, and design.

Make one dependency prove the principle

Start with Ask for the Interface: working notification code, one hidden concrete dependency, and five structural rules that reject the cosmetic fixes.

Try dependency inversion free

Get new puzzles and .NET tips in your inbox

A short note when fresh kata land, plus the C# and performance tricks behind the grading. No spam, unsubscribe anytime.