Coding 2020-10-21

By Max Woerner Chase

For the past few days, I thought about how I want to set up serialization so that there's some assurance that the classes I care about can handle it.

Here's what I'm currently thinking of. It's pretty elaborate, but it should provide the bare minimum of verification.

Right now, my module modules look like this:

...

@attr.dataclass(frozen=True)
class FooModule:
    field: int

# ModuleProxy populates a global registry,
# such that each module only has one proxy.
class FooProxy(ModuleProxy[FooModule], FooModule):
    """Put extra validation or functionality in
    here, not relevant to the example."""

I want to make them look something like this:

...

class FooSerialized(TypedDict):
    field: int

class FooBarSerializer(Serializer):
    @dumper(name="foo", version=1)
    def __dump_foo_v1(self: FooModule) -> FooSerialized:  # type: ignore[misc]
        return {"field": self.field}

    # I haven't thought too hard about this bit.
    # Maybe it'd be like this, maybe I'll go crazier with subclassing.
    # Maybe I could go the other way and make everything a staticmethod.
    @loader(name="foo", version=1)
    @staticmethod
    def __load_foo_v1(data: FooSerialized, version: int) -> FooModule:
        return FooModule(data["field"])

@attr.dataclass(frozen=True)
class FooModule(FooBarSerializer):
    field: int

# Add the typing checks here,
# because that's the latest that still has teeth.
class FooProxy(ModuleProxy[FooModule], FooModule):
    """Same as last time."""

The verification step would basically be to make sure that, for every user-defined class that the module is defined in terms of, that class has a dumper defined in the module's base class.

Thinking about it like that, I'm inclined to go the "everything is a staticmethod" route.

Thinking over this from the top, I could make the serializer class a required class attribute rather than a subclass, which would make things cleaner.

From there, I could remove the "dumb container" class, and just work with serializer registries directly.

With a little minor fiddling, then, it shouldn't be as big of a change as I was thinking it might be.

It's late, done for now.

Good night.