Skip to main content
added 95 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16

Here Reader/Writer are essentially dicts that map types to concrete read/write methods.

Here Reader/Writer are essentially dicts that map types to concrete read/write methods.

added 53 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
  1. Reader/Writer is simply aware of all the classes it needs to work with (which is ok for small number of classes) and implements the mechanism internally.
  2. You add a magic method on each class that converts it to well-understood, (de)serializable format, e.g. into a dict, list, string or number, etc. And then Reader/Writer only works with those basic types. This is the simplest solution, but incurs a non-trivial overhead if those objects are big. And is a leaky abstraction, although not a big leak.
  1. Reader/Writer is simply aware of all the classes it needs to work with (which is ok for small number of classes) and implements the mechanism internally.
  2. You add a magic method on each class that converts it to well-understood, (de)serializable format, e.g. into a dict, list, string or number, etc. And then Reader/Writer only works with those basic types. This is the simplest solution, but incurs a non-trivial overhead if those objects are big.
  1. Reader/Writer is simply aware of all the classes it needs to work with (which is ok for small number of classes) and implements the mechanism internally.
  2. You add a magic method on each class that converts it to well-understood, (de)serializable format, e.g. into a dict, list, string or number, etc. And then Reader/Writer only works with those basic types. This is the simplest solution, but incurs a non-trivial overhead if those objects are big. And is a leaky abstraction, although not a big leak.
added 79 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
# IReader/IWriter are common interfaces defined by you
# which BarReader and FooWriter implement

def read_my_class_read_my_class(reader: IReader, input_stream: BinaryIO) -> MyClass:
   # implement deserialization

BarReader.register(MyClass, read_my_class_read_my_class)

def write_my_class_write_my_class(writer: IWriter, output_stream: BinaryIO, instance: MyClass):
   # implement serialization

FooWriter.register(MyClass, write_my_class_write_my_class)

# Note: "register" can and should be a generic method.

In a more sophisticated context you can even use a visitor pattern1 on dataclasses. Of course you need a common interface for all Readers and all Writers (likely with generic read/write methods). Note that you need to pass IReader/IWriter in case of recursive (de)serialization.

The keywordkeywords here isare: separation of concerns. And depend on abstract interfaces instead of concrete classes.


1 It's a shame that you cannot extend existing Python classes in a clean, simple, safe and non-hacky way, like in Rust.

# IReader/IWriter are common interfaces defined by you
# which BarReader and FooWriter implement

def read_my_class(reader: IReader, input_stream: BinaryIO) -> MyClass:
   # implement deserialization

BarReader.register(MyClass, read_my_class)

def write_my_class(writer: IWriter, output_stream: BinaryIO, instance: MyClass):
   # implement serialization

FooWriter.register(MyClass, write_my_class)

# Note: "register" can and should be a generic method.

In a more sophisticated context you can even use a visitor pattern on dataclasses. Of course you need a common interface for all Readers and all Writers (likely with generic read/write methods). Note that you need to pass IReader/IWriter in case of recursive (de)serialization.

The keyword here is: separation of concerns.

# IReader/IWriter are common interfaces defined by you
# which BarReader and FooWriter implement

def _read_my_class(reader: IReader, input_stream: BinaryIO) -> MyClass:
   # implement deserialization

BarReader.register(MyClass, _read_my_class)

def _write_my_class(writer: IWriter, output_stream: BinaryIO, instance: MyClass):
   # implement serialization

FooWriter.register(MyClass, _write_my_class)

# Note: "register" can and should be a generic method.

In a more sophisticated context you can even use a visitor pattern1 on dataclasses. Of course you need a common interface for all Readers and all Writers (likely with generic read/write methods). Note that you need to pass IReader/IWriter in case of recursive (de)serialization.

The keywords here are: separation of concerns. And depend on abstract interfaces instead of concrete classes.


1 It's a shame that you cannot extend existing Python classes in a clean, simple, safe and non-hacky way, like in Rust.

added 79 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
Loading
added 79 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
Loading
added 177 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
Loading
added 299 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
Loading
added 152 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
Loading
added 162 characters in body
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
Loading
Source Link
freakish
  • 3.1k
  • 1
  • 11
  • 16
Loading