structuring what lives where became easier, naming things became systematic and consistent, and writing unit tests became simple.
structuring what lives where became easier, naming things became systematic and consistent, and writing unit tests became simple.
It makes for great APIs (dot-chaining from one type to another), well-defined types (parse, don’t validate) and keeps the code associated with the type.
class Profile:
...
class User:
@classmethod
def from_profile(cls, profile: Profile) -> 'User':
...
def to_profile(self) -> Profile:
...
...are about all the methods I need in my data records. Three simple rules though:1. Keep isomorphisms to one class only: Don't put two def to_${OTHER_MODEL_NAME} in each class, instead (like you said) create one static mapping (@classmethod) and one instance mapping
2. Add a mapping to the one class that feels more generalized out of the two: A more generalized data model will probably be used a lot more throughout the application
3. The creation of instances should be pure: If a mapping has side effects and needs to await something then it isn't just a mapping - first resolve all necessary dependencies, then do the mapping
Frontend, backend, databases, services, reports, whatever - ETL.
In that context, the types and transformations between types are the most important feature. (Everything is actually Category Theory)
To me, looking at it as "functional" approach instead (data in, operate over that data, data out) is cognitively simpler.
I guess with general computers everything we do is basically defining nested specific computers. That's, I think, the insight behind SmallTalk and the original concept of objects it used: the objects were supposed to represent computers and the message passing was an abstract network layer.