{
    "slug": "primitive_obsession",
    "term": "Primitive Obsession",
    "category": "quality",
    "difficulty": "intermediate",
    "short": "Using raw strings, ints, and arrays to represent domain concepts instead of small dedicated value objects.",
    "long": "Primitive obsession is using primitive types (string, int, bool, array) for concepts that deserve their own class — e.g. representing a phone number as a plain string, a money amount as a float, or a coordinate pair as two separate variables. Primitives have no domain validation, no domain-specific methods, and no documentation of their meaning. Introducing small value objects (PhoneNumber, Money, Coordinate) gives the type a name, centralises validation, and makes illegal states unrepresentable.",
    "aliases": [
        "primitive overuse",
        "stringly typed",
        "value type smell"
    ],
    "tags": [
        "code-smell",
        "oop",
        "refactoring",
        "type-safety"
    ],
    "misconception": "Using primitives for everything is simpler than creating wrapper classes. A string for an email address cannot enforce format, a float for money cannot prevent rounding errors, and an int for a user ID can be accidentally passed where a product ID is expected — value objects eliminate these classes of bugs.",
    "why_it_matters": "Using raw strings and integers for domain concepts (email, money, coordinates) means validation and behaviour are scattered everywhere — wrapping them in value objects centralises rules and makes types self-documenting.",
    "common_mistakes": [
        "Passing $email as a string everywhere instead of an Email value object that validates on construction.",
        "Using int for money — floating point errors and currency handling belong in a Money class.",
        "Not noticing when a cluster of primitives always travels together — that is a data clump and a value object candidate.",
        "Creating value objects without making them immutable — a mutable Email can change to invalid state after construction."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "code_smell",
        "long_parameter_list"
    ],
    "prerequisites": [
        "value_object",
        "type_declarations",
        "ddd_value_objects"
    ],
    "refs": [
        "https://refactoring.guru/smells/primitive-obsession"
    ],
    "bad_code": "function registerUser(string $email, string $role, int $age): void {\n    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {\n        throw new \\InvalidArgumentException('Bad email');\n    }\n    // $email, $role, $age scattered everywhere as raw strings/ints\n}",
    "good_code": "readonly class Email {\n    public function __construct(public string $value) {\n        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {\n            throw new \\InvalidArgumentException(\"Invalid email: $value\");\n        }\n    }\n}\n\nfunction registerUser(Email $email, Role $role, Age $age): void {\n    // types carry their own validation — impossible to pass invalid data\n}",
    "quick_fix": "Replace a cluster of related primitives (string $email, string $currency, int $amount) with a Value Object that encapsulates validation and behaviour",
    "severity": "low",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/primitive_obsession",
        "html_url": "https://codeclaritylab.com/glossary/primitive_obsession",
        "json_url": "https://codeclaritylab.com/glossary/primitive_obsession.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Primitive Obsession](https://codeclaritylab.com/glossary/primitive_obsession) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/primitive_obsession"
            }
        }
    }
}