We introduced DDD concepts some time ago, in a series of articles in this
blog.
At that time, we proposed a simple way of
using mORMot types to implement DDD in your applications.
But all Domain Entitities being tied to the framework
TSQLRecord
class did appear as a limitation, breaking the
Persistence Ignorance principle, since it couples the DDD objects to
the framework implementation details.
We introduced a new mORMotDDD.pas
unit, which is able to easily create CQRS Persistence
services for any plain Delphi class (the famous PODOs -
Plain Old Delphi Objects).
No need to inherit from TSQLRecord
, or pollute your class
definition with attributes!
For instance, a TUser
class may be persisted via such a
service:
type IDomUserCommand = interface(IDomUserQuery) ['{D345854F-7337-4006-B324-5D635FBED312}'] function Add(const aAggregate: TUser): TCQRSResult; function Update(const aUpdatedAggregate: TUser): TCQRSResult; function Delete: TCQRSResult; function Commit: TCQRSResult; end;
Here, the write operations are defined in a IDomUserCommand
service, which is separated (but inherits) from IDomUserQuery
,
which is used for read operations.
Separating reads and writes is a powerful pattern also known as CQRS,
i.e. Command Query Responsibility Segregation, which we followed
when defining our persistence services.
The framework make it pretty easy to create such services for storing any kind
of class
type in any SQL or NoSQL engine, with almost no code to
write.
Last but not least, using such interface
-based services for data
persistence will allow to stub or mock the data
access layer, making unit testing straightforward: you would not fear to
write TDD code any more!
Please
refer to our updated documentation for this unique and powerful
feature.
You may take a look at the corresponding
dddDomUserTypes.pas,
dddDomUserCQRS.pas, and
dddInfraRepoUser.pas units, detailed as sample reference.
Feedback is welcome in
our forum, as usual!