Skip to main content

A collection of base classes for Domain-Driven Design (DDD) value objects and entities in Python

Project description

DDD Value Objects for Python

A comprehensive collection of base classes and specialized types for implementing Domain-Driven Design (DDD) patterns in Python. This library provides a robust foundation for building maintainable, type-safe, and self-validating domain models using Value Objects and Entities.

License: MIT Python 3.10+ Coverage

Key Features

  • Base Classes: Robust base classes for both Primitive and Composite Value Objects.
  • Immutability: Designed to be immutable, ensuring domain integrity.
  • Structural Equality: Value Objects are compared by their attributes, not by identity.
  • Self-Validation: Built-in validation for common domain types (Emails, UUIDs, URLs, etc.).
  • Strong Typing: Leverages Python generics for type safety and better IDE support.
  • Entity Support: Base class for Entities with identity-based equality.

Installation

Install using pip:

pip install ddd-value-objects

Or using uv:

uv add ddd-value-objects

Core Concepts

Value Objects

In DDD, a Value Object is an object that represents a descriptive aspect of the domain with no conceptual identity. They are defined by their attributes and are immutable. Two value objects are considered equal if all their attributes are equal.

Primitive Value Objects

Wrap single primitive types (str, int, float, bool) to give them domain meaning.

Composite Value Objects

Combine multiple values into a single domain concept (e.g., Money which consists of an amount and a currency).

Entities

Entities have a unique identity that persists over time, regardless of changes to their attributes.


Usage Examples

1. Primitive Value Objects

You can extend base classes to create domain-specific types:

from ddd_value_objects import StringValueObject, PositiveIntValueObject, InvalidArgumentError

class UserName(StringValueObject):
    pass

class UserAge(PositiveIntValueObject):
    def __init__(self, value: int):
        super().__init__(value)
        if value > 150:
            raise InvalidArgumentError(f"Age {value} is out of valid range (max 150)")

# Usage
name1 = UserName("Alice")
name2 = UserName("Alice")
age = UserAge(30)

print(name1 == name2)  # True (Structural equality)
print(name1.value)     # "Alice"

2. Specialized Value Objects

The library includes many pre-built, self-validating types:

from ddd_value_objects import (
    EmailValueObject, 
    UuidValueObject, 
    UrlValueObject, 
    PhoneNumberValueObject,
    CurrencyValueObject
)

email = EmailValueObject("user@example.com")
user_id = UuidValueObject("550e8400-e29b-41d4-a716-446655440000")
website = UrlValueObject("https://github.com")
currency = CurrencyValueObject("USD") # Validates ISO 4217 code

3. Composite Value Objects (e.g., Money)

Handle complex types that group multiple values:

from ddd_value_objects import MoneyValueObject

price = MoneyValueObject(99.99, "USD")
tax = MoneyValueObject(10.00, "USD")

# Arithmetic operations (if supported by implementation)
total = price.add(tax)

print(total.amount)   # 109.99
print(total.currency) # "USD"

4. Enum Value Objects

Restrict values to a specific set using an Enum:

from enum import Enum
from ddd_value_objects import EnumValueObject, StringValueObject, InvalidArgumentError

class UserRole(Enum):
    ADMIN = "admin"
    USER = "user"

class RoleValueObject(EnumValueObject):
    def __init__(self, value: str):
        # Define the valid options
        valid_roles = [StringValueObject(r.value) for r in UserRole]
        
        # Pass the current value as a ValueObject and the list of valid options
        super().__init__(
            StringValueObject(value), 
            valid_roles
        )

# Usage
try:
    role = RoleValueObject("admin")
    print(role.value)  # "admin"
    
    invalid_role = RoleValueObject("guest") # Raises InvalidArgumentError
except InvalidArgumentError as e:
    print(e)

5. Entities

Use the Entity base class for objects with identity:

from ddd_value_objects import Entity, UuidValueObject

class Product(Entity):
    def __init__(self, product_id: str, name: str):
        # Entity expects a string ID which it wraps in a UuidValueObject
        super().__init__(product_id)
        self.name = name

product1 = Product("550e8400-e29b-41d4-a716-446655440000", "Laptop")
product2 = Product("550e8400-e29b-41d4-a716-446655440000", "Updated Laptop Name")

print(product1 == product2) # True (Same identity/ID)

Available Value Objects

Category Classes
Primitives StringValueObject, IntValueObject, FloatValueObject, BoolValueObject
Numeric PositiveIntValueObject, PositiveFloatValueObject
Identity UuidValueObject
Network EmailValueObject, UrlValueObject, IpAddressValueObject
Communication PhoneNumberValueObject, CountryCodeValueObject (ISO 3166-1 alpha-2)
Temporal DateTimeValueObject, DateValueObject (Unix timestamps)
Financial CurrencyValueObject (ISO 4217), MoneyValueObject
Others EnumValueObject, CompositeValueObject

Development and Testing

We use uv for dependency management and pytest for testing.

Setup

# Clone the repository
git clone https://github.com/youruser/ddd-value-objects.git
cd ddd-value-objects

# Install dependencies
uv sync

Running Tests

uv run pytest

Coverage Threshold

This project maintains a minimum coverage threshold of 90%. The CI workflow will automatically fail if coverage falls below this level.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ddd_value_objects-0.1.4.tar.gz (14.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ddd_value_objects-0.1.4-py3-none-any.whl (15.7 kB view details)

Uploaded Python 3

File details

Details for the file ddd_value_objects-0.1.4.tar.gz.

File metadata

  • Download URL: ddd_value_objects-0.1.4.tar.gz
  • Upload date:
  • Size: 14.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ddd_value_objects-0.1.4.tar.gz
Algorithm Hash digest
SHA256 9500ca54de984f6cea44f7a75c1ca9a794a092895303d5bef07df5cc1b1256b1
MD5 93377ff5068ab3057f3e3c31de00620b
BLAKE2b-256 b78f063d607854d37a7e12d7226e8c42dbe0799195e877ef8ff85b85b8957d79

See more details on using hashes here.

Provenance

The following attestation bundles were made for ddd_value_objects-0.1.4.tar.gz:

Publisher: code.yml on josedejesuschavez/ddd-value-objects

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ddd_value_objects-0.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for ddd_value_objects-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 6f58ed6a3f491d9cbe60b3531950c7ebd51adb0bd7350d78919c9593dd71770e
MD5 65eaffc8345cff8cd3e77e9c7e4d4869
BLAKE2b-256 09bcdff604755047ead2cbe79d0a7fd4fa7e388663b1d0a1242169461c7f5c0c

See more details on using hashes here.

Provenance

The following attestation bundles were made for ddd_value_objects-0.1.4-py3-none-any.whl:

Publisher: code.yml on josedejesuschavez/ddd-value-objects

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page