Best practices for serialization of DDD aggregates

According to DDD domain logic should not be polluted with technical concerns like serialization, object-relational mapping, etc.

So how do you serialize or map the aggregates’ state without publicly exposing it via getters and setters? I have seen lots of examples for e.g. repository implementations, but practically all of them relied on public accessors on the entities and value objects for mapping.

We could use reflection to avoid public accessors, but IMO these domain objects would still implicitly be dependent on the serialization concern. E.g. you couldn’t rename or remove a private field without tweaking your serialization/mapping configuration. So you have to consider serialization where you should instead be focussing on domain logic.

So what’s the best compromise to follow here? Live with public accessors, but avoid using them for anything else but mapping code? Or did I just miss something obvious?

I’m explicitly interested in serializing the state of DDD domain objects (aggregates consisting of entities and value objects). This is NOT about serialization in general or transcation script scenarios where stateless services operate on simple data container objects.

Kinds of objects

For purposes of our discussion, let’s separate our objects into three different kinds:

Business Domain logic

These are the objects that get work done. They move money from one checking account to another, fulfill orders, and all of the other actions that we expect business software to take.

Domain logic objects normally do not require accessors (getters and setters). Rather, you create the object by handing it dependencies through a constructor, and then manipulate the object through methods (tell, don’t ask).

Data Transfer Objects

Data Transfer Objects are pure state; they don’t contain any business logic. They will always have accessors. They may or may not have setters, depending on whether or not you’re writing them in an immutable fashion. You will either set your fields in the constructor and their values will not change for the lifetime of the object, or your accessors will be read/write. In practice, these objects are typically mutable, so that a user can edit them.

View Model objects

View Model objects contain a displayable/editable data representation. They may contain business logic, usually confined to data validation. An example of a View Model object might be an InvoiceViewModel, containing a Customer object, an Invoice Header object, and Invoice Line Items. View Model objects always contain accessors.

So the only kind of object that will be “pure” in the sense that it doesn’t contain field accessors will be the Domain Logic object. Serializing such an object saves its current “computational state,” so that it can be retrieved later to complete processing. View Models and DTO’s can be freely serialized, but in practice their data is normally saved to a database.

Serialization, dependencies and coupling

While it is true that serialization creates dependencies, in the sense that you have to deserialize to a compatible object, it does not necessarily follow that you have to change your serialization configuration. Good serialization mechanisms are general purpose; they don’t care if you change the name of a property or member, so long as it can still map values to members. In practice, this only means that you must re-serialize the object instance to make the serialization representation (xml, json, whatever) compatible with your new object; no configuration changes to the serializer should be necessary.

It is true that objects should not be concerned with how they are serialized. You’ve already described one way such concerns can be decoupled from the domain classes: reflection. But the serializer should be concerned about how it serializes and deserializes objects; that, after all, is its function. The way you keep your objects decoupled from your serialization process is to make serialization a general-purpose function, able to work across all object types.

One of the things people get confused about is that decoupling has to occur in both directions. It does not; it only has to work in one direction. In practice, you can never decouple completely; there is always some coupling. The goal of loose coupling is to make code maintenance easier, not to remove all dependencies.

8

The underlying purpose of serialization is to ensure that data produced by one system is able to be consumed by one or more compatible systems.

The easiest and most robust approach to serialization is to translate the data into a type agnostic format that maintains the structure in a simple and easy-to-consume format. For instance the most ubiquitous serialization formats (ie JSON, XML) use a well-defined text-based format. Text is simple to produce, transmit, and consume.

There are 2 reasons why using one of these formats may not be ideal.

  1. Efficiency

    There is an inherent cost involved in translating all of the data into their text-based equivalents. Data types wouldn’t exist if text was the most efficient way to express all the different forms of data. In addition, the structure of these formats is not ideal for retrieving subsets of data asynchronously or in parts.

    For instance, XML and JSON assume that the data being used will be written and read from start to finish. For processing very large data sets where memory is scarce, the system consuming the data may require the ability to process the data in parts. In that case, a special purpose serialization/deserialization implementation may be required to handle the data.

  2. Precision

    The casting required to serialize/deserialize the data from it’s intended type to data agnostic type result in a loss of precision.

One could argue that producing a binary representation of the objects and data is clearly the most efficient and accurate solution. The major drawback is that the implementation of all systems that both consume and produce data need to remain compatible. It’s a simple constraint in theory but it’s a nightmare to maintain in practice as production systems tend to change/evolve over time.

With that said. Decoupling serialization/deserialization from the domain-specific details makes sense as a general rule because general purpose formats are more robust, better supported across diverse systems, and require little-to-no increased maintenance overhead to use.

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Best practices for serialization of DDD aggregates

According to DDD domain logic should not be polluted with technical concerns like serialization, object-relational mapping, etc.

So how do you serialize or map the aggregates’ state without publicly exposing it via getters and setters? I have seen lots of examples for e.g. repository implementations, but practically all of them relied on public accessors on the entities and value objects for mapping.

We could use reflection to avoid public accessors, but IMO these domain objects would still implicitly be dependent on the serialization concern. E.g. you couldn’t rename or remove a private field without tweaking your serialization/mapping configuration. So you have to consider serialization where you should instead be focussing on domain logic.

So what’s the best compromise to follow here? Live with public accessors, but avoid using them for anything else but mapping code? Or did I just miss something obvious?

I’m explicitly interested in serializing the state of DDD domain objects (aggregates consisting of entities and value objects). This is NOT about serialization in general or transcation script scenarios where stateless services operate on simple data container objects.

Kinds of objects

For purposes of our discussion, let’s separate our objects into three different kinds:

Business Domain logic

These are the objects that get work done. They move money from one checking account to another, fulfill orders, and all of the other actions that we expect business software to take.

Domain logic objects normally do not require accessors (getters and setters). Rather, you create the object by handing it dependencies through a constructor, and then manipulate the object through methods (tell, don’t ask).

Data Transfer Objects

Data Transfer Objects are pure state; they don’t contain any business logic. They will always have accessors. They may or may not have setters, depending on whether or not you’re writing them in an immutable fashion. You will either set your fields in the constructor and their values will not change for the lifetime of the object, or your accessors will be read/write. In practice, these objects are typically mutable, so that a user can edit them.

View Model objects

View Model objects contain a displayable/editable data representation. They may contain business logic, usually confined to data validation. An example of a View Model object might be an InvoiceViewModel, containing a Customer object, an Invoice Header object, and Invoice Line Items. View Model objects always contain accessors.

So the only kind of object that will be “pure” in the sense that it doesn’t contain field accessors will be the Domain Logic object. Serializing such an object saves its current “computational state,” so that it can be retrieved later to complete processing. View Models and DTO’s can be freely serialized, but in practice their data is normally saved to a database.

Serialization, dependencies and coupling

While it is true that serialization creates dependencies, in the sense that you have to deserialize to a compatible object, it does not necessarily follow that you have to change your serialization configuration. Good serialization mechanisms are general purpose; they don’t care if you change the name of a property or member, so long as it can still map values to members. In practice, this only means that you must re-serialize the object instance to make the serialization representation (xml, json, whatever) compatible with your new object; no configuration changes to the serializer should be necessary.

It is true that objects should not be concerned with how they are serialized. You’ve already described one way such concerns can be decoupled from the domain classes: reflection. But the serializer should be concerned about how it serializes and deserializes objects; that, after all, is its function. The way you keep your objects decoupled from your serialization process is to make serialization a general-purpose function, able to work across all object types.

One of the things people get confused about is that decoupling has to occur in both directions. It does not; it only has to work in one direction. In practice, you can never decouple completely; there is always some coupling. The goal of loose coupling is to make code maintenance easier, not to remove all dependencies.

8

The underlying purpose of serialization is to ensure that data produced by one system is able to be consumed by one or more compatible systems.

The easiest and most robust approach to serialization is to translate the data into a type agnostic format that maintains the structure in a simple and easy-to-consume format. For instance the most ubiquitous serialization formats (ie JSON, XML) use a well-defined text-based format. Text is simple to produce, transmit, and consume.

There are 2 reasons why using one of these formats may not be ideal.

  1. Efficiency

    There is an inherent cost involved in translating all of the data into their text-based equivalents. Data types wouldn’t exist if text was the most efficient way to express all the different forms of data. In addition, the structure of these formats is not ideal for retrieving subsets of data asynchronously or in parts.

    For instance, XML and JSON assume that the data being used will be written and read from start to finish. For processing very large data sets where memory is scarce, the system consuming the data may require the ability to process the data in parts. In that case, a special purpose serialization/deserialization implementation may be required to handle the data.

  2. Precision

    The casting required to serialize/deserialize the data from it’s intended type to data agnostic type result in a loss of precision.

One could argue that producing a binary representation of the objects and data is clearly the most efficient and accurate solution. The major drawback is that the implementation of all systems that both consume and produce data need to remain compatible. It’s a simple constraint in theory but it’s a nightmare to maintain in practice as production systems tend to change/evolve over time.

With that said. Decoupling serialization/deserialization from the domain-specific details makes sense as a general rule because general purpose formats are more robust, better supported across diverse systems, and require little-to-no increased maintenance overhead to use.

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật