alexpovel / effective-typestate

A presentation on the type-state pattern (as popular in the Rust ecosystem), in the style of "Effective C++/Rust" (loosely coupled showcases), with examples in Python (easiest to read). Link below contains compiled presentation
https://alexpovel.github.io/effective-typestate/
MIT License
2 stars 0 forks source link

Add topic: newtype pattern #1

Closed alexpovel closed 4 months ago

alexpovel commented 6 months ago

Newtype pattern

I've never seen it mentioned in the Python, C#, and other communities. Seems confined to Rust and other ML languages. So let's highlight it a bit more.

Premise/Use case

Imagine you have a database with a bunch of tables, and a bunch of indices. Your index columns are all integers, or UUIDv4s. Doesn't matter. So all your indices are all the same type! Woops! You might have code such as:

def get_products(costumer: uuid.UUID, order: uuid.UUID) -> Product:
    pass # Some database query

get_products(order_id, customer_id)  # 💥

This of course type checks. It throws us back into a "time before type-state", which were bad times! So in Rust, we could trivially wrap this:

struct CustomerId(Uuid);
struct OrderId(Uuid);

yielding two new types. In Python, it's a bit stupider, but I'd say creating a wrapper class, even though it seems verbose, is totally worth it:

@dataclass
class CustomerId:
    _inner: uuid.UUID

@dataclass
class OrderId:
    _inner: uuid.UUID

a bit uglier, but works and gets the desired effect. Otherwise, maybe CustomerId = tuple[uuid.UUID] works? Not tested yet; would be equivalent to the tuple struct-based newtype from Rust.

alexpovel commented 4 months ago

Done in e3bece4