What Is Immutability?

An object is immutable if its state never changes after it is created.
All of its fields are set during construction and stay the same for the entire lifetime of the object.

Important points:

  • You never modify an immutable object in place.

  • If you need a “changed” version, you create a new object with the new values.

  • Methods that look like “updates” actually return a new object instead of editing the old one.

This is the opposite of mutable objects, where fields can be changed by setters or other methods after construction.

Why Immutability Matters in LLD

Immutability is especially useful for value‑like objects and shared data in designs.

Benefits:

  • Easier reasoning

    • If an object cannot change, you know that once it’s created, its state is fixed.

    • There are no surprises from hidden modifications in other parts of the code.

  • Inherently thread‑safe

    • Multiple threads can read the same immutable object without any locks, because nobody can modify it.

  • Good for value objects

    • Concepts like money amounts, time ranges, and configuration options often behave like values, not entities with a lifecycle.

    • Treating them as immutable avoids many bugs.

  • Safer as keys in maps/sets

    • If something is used as a key in a HashMap or set, changing it after insertion can break lookups.

    • Immutability prevents that scenario.

In Low Level Design, immutability is a design choice that can simplify parts of your system where values are passed around but should not be changed.

Mutable vs Immutable: Simple Comparison

Take a simple Point representation of a 2D coordinate.

Mutable version


Here:

  • The point’s coordinates can change over time via setX and setY.

  • Different parts of the code might hold references to the same object and see different values at different times.

Immutable version (concept)

  • No setters.

  • Fields are set once in the constructor.

  • Any change returns a new Point.

This style is explained next in C++ terms.

How to Design an Immutable Class in C++

C++ does not have a special “immutable” keyword, but you can design immutability by following a few rules.

Typical rules:

  1. Make data members private

    • Do not expose them directly.

  2. Initialize all data in the constructor

    • After construction, the object is fully defined.

  3. Do not provide setters

    • No methods that modify internal fields.

  4. Return new objects for “changes.”

    • Operations that conceptually change the value return a new instance.

  5. Be careful with the mutable member.s

    • If a field is itself a mutable object (like a vector), avoid exposing it directly; copy when needed.

Example: Immutable Money Value

Consider a simple Money value object representing an amount and currency.


Usage:


Notice:

  • m1, m2, m3They m4 are all separate objects.

  • None of them changes after they are created.

  • The methods subtract return new Money instances.

This is a typical immutable “value object” that works very well in LLD and domain modeling.

Example: Immutable Time Range

Another place immutability fits naturally is a time range, for example, a booking period.


Usage:


Again:

  • morning never changes. Returnss a new range instead of mutating the existing one.

Where Immutability Fits in LLD

You do not want every class to be immutable.
Immutability is mainly useful for:

  • Value‑like objects

    • Amounts of money, distances, dates, time ranges, coordinates, and configuration values.

  • Shared read‑only configuration

    • Application settings that are loaded once and then used everywhere without modification.

  • Keys in maps/sets

    • Objects used as keys in std::unordered_map, std::map, or std::set should ideally not change after insertion.

In contrast, many “entity” objects in LLD (like User, Order, Booking) naturally have a lifecycle and change over time, so they are usually mutable.

A common pattern is:

  • Use immutable value objects inside mutable entities.

    • Example: Order is mutable, but it contains an immutable Money or TimeRange.

Pros and Cons of Immutability

Advantages

  • Safety and predictability

    • Once created, the object cannot be accidentally changed from some other part of the code.

  • Simpler reasoning and testing

    • Many tests become “input → output” checks, because no side effects change the internal state across calls.

  • Thread safety

    • Multiple threads can safely share an immutable object.

  • Good fit for functional style

    • Encourages writing functions without side effects, which is easier to reason about.

Trade‑offs

  • More object creation

    • Each “update” creates a new object, which can mean more allocations.

  • Sometimes inconvenient

    • For large, complex objects that change frequently, copying a new one each time can be heavy.

Because of this, immutability is usually applied where the object is small and value‑like, not to every class in the system.

Practical Design Tips for Immutability

When designing an immutable class in your LLD:

  • Keep the class focused and value‑like.

  • Make all fields private; only read them through getters.

  • Do not provide setters or any methods that modify fields in place.

  • Let “update” methods return new objects with modified values.

  • If you hold mutable fields internally (like std::vector), avoid returning them directly; consider returning copies or read‑only views.

And when deciding whether to make something immutable:

  • Prefer immutability for values and shared data.

  • Prefer mutability for entities with identity and lifecycle (like orders, bookings, users in a system).

Summary

Immutability means that an object’s state never changes after it is created.
Instead of mutating fields, methods return new objects when something needs to change.

You saw:

  • The difference between mutable and immutable objects.

  • Why immutability improves safety, reasoning, and thread‑safety for value‑like objects.

  • How to design immutable classes in C++ by hiding fields, avoiding setters, and returning new instances from “update” operations.

  • Practical examples with an immutable Money and an immutable TimeRange.

  • Where immutability fits naturally in Low Level Design and what trade‑offs to consider.