# Organizing Data

> Techniques that turn raw fields, magic values, arrays and type codes into objects and types that carry meaning and protect their own invariants.

- kind: category
- category: refactoring
- canonical: https://aipatterns.dev/refactoring/techniques/organizing-data
- inspired-by: https://refactoring.guru/refactoring/techniques/organizing-data

## What these techniques solve

Data that is only strings, numbers and loose arrays spreads its rules everywhere. Every caller re-validates an email, remembers that index `2` is the currency, or checks `type === 3`. These techniques give data a proper home: small value objects, encapsulated fields and collections, named constants, and real types in place of codes.

**Make illegal states hard to represent and put the rules for a value next to the value.**

## Members

- [Self Encapsulate Field](https://aipatterns.dev/refactoring/techniques/self-encapsulate-field.md): access a field through getters and setters even inside its own class.
- [Replace Data Value with Object](https://aipatterns.dev/refactoring/techniques/replace-data-value-with-object.md): turn a primitive with behavior attached to it into a small class.
- [Change Value to Reference](https://aipatterns.dev/refactoring/techniques/change-value-to-reference.md): replace many equal copies of an entity with one shared instance.
- [Change Reference to Value](https://aipatterns.dev/refactoring/techniques/change-reference-to-value.md): turn a small, rarely changing reference object into an immutable value.
- [Replace Array with Object](https://aipatterns.dev/refactoring/techniques/replace-array-with-object.md): replace an array whose positions mean different things with an object with named fields.
- [Duplicate Observed Data](https://aipatterns.dev/refactoring/techniques/duplicate-observed-data.md): move domain data out of a UI class and keep the two in sync.
- [Change Unidirectional Association to Bidirectional](https://aipatterns.dev/refactoring/techniques/change-unidirectional-association-to-bidirectional.md): add a back-reference when both sides need to navigate to each other.
- [Change Bidirectional Association to Unidirectional](https://aipatterns.dev/refactoring/techniques/change-bidirectional-association-to-unidirectional.md): drop a back-reference that one side no longer needs.
- [Replace Magic Number with Symbolic Constant](https://aipatterns.dev/refactoring/techniques/replace-magic-number-with-symbolic-constant.md): give an unexplained literal a name.
- [Encapsulate Field](https://aipatterns.dev/refactoring/techniques/encapsulate-field.md): make a public field private and add accessors.
- [Encapsulate Collection](https://aipatterns.dev/refactoring/techniques/encapsulate-collection.md): return a read-only view of a collection and provide add and remove methods.
- [Replace Type Code with Class](https://aipatterns.dev/refactoring/techniques/replace-type-code-with-class.md): replace a code that doesn't affect behavior with a dedicated type or enum.
- [Replace Type Code with Subclasses](https://aipatterns.dev/refactoring/techniques/replace-type-code-with-subclasses.md): replace a fixed code that drives behavior with one subclass per value.
- [Replace Type Code with State/Strategy](https://aipatterns.dev/refactoring/techniques/replace-type-code-with-state-strategy.md): replace a code that drives behavior and changes at runtime with a state or strategy object.
- [Replace Subclass with Fields](https://aipatterns.dev/refactoring/techniques/replace-subclass-with-fields.md): collapse subclasses that differ only in constant values into fields.

## How to choose within this category

- **A primitive carries rules (format, range, unit):** [Replace Data Value with Object](https://aipatterns.dev/refactoring/techniques/replace-data-value-with-object.md). In TypeScript, a branded type or a small class works; in Python, a frozen dataclass; in Java, a record.
- **Positions in an array or tuple mean different things:** [Replace Array with Object](https://aipatterns.dev/refactoring/techniques/replace-array-with-object.md).
- **A literal like `86400` or `0.2` appears in logic:** [Replace Magic Number with Symbolic Constant](https://aipatterns.dev/refactoring/techniques/replace-magic-number-with-symbolic-constant.md).
- **Outside code writes fields or mutates a list directly:** [Encapsulate Field](https://aipatterns.dev/refactoring/techniques/encapsulate-field.md) and [Encapsulate Collection](https://aipatterns.dev/refactoring/techniques/encapsulate-collection.md). Language properties (C#, Kotlin, Python `@property`, TypeScript `get`) let you add the accessor later without breaking callers, so don't add boilerplate getters up front.
- **Type codes:** ask two questions. Does the code change behavior? If not, use [Replace Type Code with Class](https://aipatterns.dev/refactoring/techniques/replace-type-code-with-class.md); a language enum or string-literal union is often enough. Does the code change after creation? If not, use [Replace Type Code with Subclasses](https://aipatterns.dev/refactoring/techniques/replace-type-code-with-subclasses.md); if it does, use [Replace Type Code with State/Strategy](https://aipatterns.dev/refactoring/techniques/replace-type-code-with-state-strategy.md). If subclasses exist only to return different constants, reverse it with [Replace Subclass with Fields](https://aipatterns.dev/refactoring/techniques/replace-subclass-with-fields.md).
- **Identity questions:** the same customer loaded twice and updated in one place calls for [Change Value to Reference](https://aipatterns.dev/refactoring/techniques/change-value-to-reference.md). A small object that would be safer immutable calls for [Change Reference to Value](https://aipatterns.dev/refactoring/techniques/change-reference-to-value.md).
- **Associations:** add a back-reference only when navigation is needed in both directions, since it doubles the bookkeeping. Remove it as soon as it isn't.
- **Domain data trapped in a UI component:** [Duplicate Observed Data](https://aipatterns.dev/refactoring/techniques/duplicate-observed-data.md). Modern UI frameworks with a separate state store often give you this split for free.
- **Subclasses or lazy-loading need to intercept field access:** [Self Encapsulate Field](https://aipatterns.dev/refactoring/techniques/self-encapsulate-field.md). Skip it otherwise.
