Data Class: What It Costs and How to Fix It
A class that contains only fields and getters/setters with no meaningful behaviour of its own.
What It Is
A Data Class is a class that holds data but performs no operations on that data. All behaviour that uses the data lives in other classes, which reach into the Data Class to get the values they need. In languages with records or data classes as a first-class feature (Kotlin data classes, Python dataclasses, TypeScript interfaces), this is sometimes intentional and appropriate. The smell arises when the Data Class should have behaviour but developers have moved all logic to consuming classes instead, violating the 'Tell, Don't Ask' principle.
Why It Costs Money
Feature Envy cascades. When behaviour is separated from its data, every class that uses the data must reach in, extract values, perform logic, and put results back. This creates Feature Envy in every consumer and duplicates the logic.
Validation is scattered. Without behaviour, the Data Class cannot enforce its own invariants. Validation rules for the data are duplicated across every consumer, each potentially implementing them differently.
Encapsulation is broken. Clients depend on the internal structure of the Data Class. If you add, remove, or rename a field, every consumer must update.
Specific Cost Mechanisms
- ●Duplicated logic: behaviour that should be in the Data Class is scattered across consumers
- ●Validation inconsistency: different consumers validate the data differently
- ●Structural coupling: consumers depend on field names and types, not behaviour
Estimated Annual Cost
Cost per instance by team size and codebase size. Based on $120,000 average developer salary. See full methodology.
| Team Size | Small (<50k LOC) | Medium (50k-200k) | Large (200k+) |
|---|---|---|---|
| 3 devs | $1,000 | $2,400 | $4,800 |
| 5 devs | $1,600 | $4,000 | $8,000 |
| 10 devs | $2,500 | $6,000 | $8,000 |
| 20 devs | $3,200 | $8,000 | $8,000 |
How to Detect It
Specific rules and thresholds for automated detection. See full tool comparison.
Public fields, missing encapsulation
Classes with only accessor methods and no behaviour
Directly detects classes with only getters/setters
Suggests moving behaviour to data-holding classes
Refactoring Patterns
Proven techniques to eliminate this smell. See all refactoring patterns.
Move Method
Logic in consumers operates primarily on the Data Class's fields
Encapsulate Field
Public fields are accessed directly
Encapsulate Collection
The class exposes mutable collections