00:00:00
hey everybody it's Derek Martin from Cod
00:00:01
opinion.com data transfer objects also
00:00:04
known as dto are like many things that
00:00:06
get overused used incorrectly or Worse
00:00:10
used in places where you don't even have
00:00:12
the problem that they solve specifically
00:00:15
when you're mapping between layers and
00:00:17
tiers so what are data transfer objects
00:00:20
really for and when should you use them
00:00:22
so let's start where I think people
00:00:24
misuse or misunderstand etos and where
00:00:26
things go wrong so let's say we have a
00:00:28
tier or a layer this could be something
00:00:30
that gets serialized on the way out or
00:00:32
it's in memory doesn't really matter at
00:00:34
some point we're going to hit some type
00:00:36
of data access we hit our database and
00:00:39
if this is the case of an orm something
00:00:40
in net like Entity framework you're
00:00:42
thinking about retrieving an entity and
00:00:44
at this point you could return that
00:00:46
entity it could be serialized back out
00:00:49
to another tier or if it was in process
00:00:51
in memory to another layer but that word
00:00:53
entity can get people confused and lead
00:00:55
them down the wrong path with dto but
00:00:57
before I get to that I'd like to thank
00:00:58
event store for sponsoring this video
00:01:00
event store DB is a new category of
00:01:02
operational database f for event
00:01:04
sourcing cqrs and event driven
00:01:06
microservices for more event stb check
00:01:08
out the link in the description this is
00:01:10
the first step of confusion because
00:01:12
people are either thinking about two
00:01:13
distinct things differently or kind of
00:01:16
some weird merged idea when you say
00:01:18
entity people are either thinking about
00:01:20
in the orm sense possibly about an
00:01:23
entity that really is just a data model
00:01:26
it's just the backing data model to your
00:01:28
table that you're mapping with your aura
00:01:30
M some other people are going to be
00:01:31
thinking about domain model in the
00:01:34
domain German design sense and thinking
00:01:35
of about entity related to behaviors and
00:01:38
the data in either situation what ends
00:01:41
up happening is people then don't want
00:01:43
to expose that data model entity or that
00:01:47
domain model entity and this is why they
00:01:49
end up introducing some type of dto so
00:01:52
we got our entity however you want to
00:01:54
think of that and then you're mapping
00:01:56
that to some dto and that's ultimately
00:01:59
when it ends up getting di down possibly
00:02:01
serialized to the other tier or just in
00:02:03
memory to another layer so the reasoning
00:02:05
which is valid in context we'll get more
00:02:07
to this is that what you're saying is
00:02:09
you don't want to expose the underlying
00:02:11
data model what is ultimately your
00:02:13
database schema or if you're thinking of
00:02:16
the entity in the domain sense that you
00:02:17
don't want to expose your underlying
00:02:19
domain directly to the caller rather you
00:02:22
want to do some translation mapping and
00:02:24
then send that back to the client now
00:02:26
I'm going to push back give a little bit
00:02:27
of food for thought and play Devil's
00:02:29
Advocate hopefully make some people
00:02:31
think about the Dogma around this why
00:02:33
can you not return that underlying data
00:02:35
model from your orm or entity however
00:02:38
you view that why did you need to map it
00:02:41
to a dto speaking of Dogma let's give
00:02:43
the example of an HTP API which I think
00:02:46
is a great illustration of this Dogma so
00:02:49
we have an HP API that often times in my
00:02:52
prior example our entity and the dto we
00:02:55
are creating that we are returning are
00:02:57
almost always in my experience people
00:02:59
are creating as a one to one they're
00:03:02
identical and this is somewhat of reason
00:03:04
why is that you see all this related to
00:03:07
how you build an HP API all the
00:03:10
tutorials about rest which this is not
00:03:13
at all but you'll get claims that this
00:03:14
is is we're usually end up mapping kind
00:03:18
of crud and behavior around databases to
00:03:21
HTP so we got a get is a select a post
00:03:25
is an insert a put is an update a patch
00:03:27
is a partial update and a delete is a
00:03:29
delete so what you might end up is kind
00:03:32
of this bike shedding around URI driven
00:03:35
driven development around method so if I
00:03:37
want to basically read for example let's
00:03:40
talk about uh shipping and shipping
00:03:42
packages deliveries that type of thing
00:03:45
so if I want to get a shipment I call a
00:03:47
get with a shipment and some ID a part
00:03:49
of that URI if I want to create a
00:03:51
shipment I'm posting to/ shipment same
00:03:54
thing for put if for updating patch the
00:03:57
same thing and delete to delete a
00:03:59
shipment I call these entity Services
00:04:01
really what they are is mapping HTTP
00:04:04
using Json to a database table just
00:04:07
using regular crud operations create
00:04:09
read update delete there's nothing
00:04:11
inherently wrong with this but it does
00:04:13
force you down a certain path and that
00:04:15
path that's forcing you down thinking
00:04:17
that you need to do crud operations on
00:04:18
database records a resource how you're
00:04:21
building a URI it does not have to be a
00:04:24
database record it can be anything you
00:04:26
want it to be to illustrate this if
00:04:28
you're using service side rendering
00:04:30
you'd be doing things a lot differently
00:04:32
and we kind of lose sight of that if I
00:04:34
was doing server side rendering I'd be
00:04:36
getting all the data and I'd be doing
00:04:38
some type of composition to put it all
00:04:40
together so I can produce my view my
00:04:42
HTML I have my shipment number when the
00:04:45
shipment was started the status but I
00:04:48
also have something like the customer
00:04:50
this isn't directly I may have some
00:04:52
reference to the customer but the table
00:04:54
the actual entity underlying doesn't
00:04:56
have the customer directly I have to do
00:04:58
that composition as well as here I'm
00:05:00
illustrating I have a couple different
00:05:02
forms that I can do the arrive when the
00:05:04
shipment needs to be picked up um by the
00:05:06
driver and the the vehicle as well as
00:05:08
being able to cancel that shipment but
00:05:10
if you're using entity services and
00:05:12
purely thinking about database records
00:05:14
this is something you would return just
00:05:16
the shipment ID the started date time
00:05:18
the status not the customer information
00:05:20
with the name like in my other HTML view
00:05:22
but rather just the customer ID cuz you
00:05:24
haven't done that composition nor am I
00:05:26
illustrating any of the actions you can
00:05:28
perform like the arrived the cancel so
00:05:30
what does this have to do with dto
00:05:32
everything in my opinion cuz there's two
00:05:34
primary benefits the first is managing
00:05:37
coupling the second is composition so if
00:05:41
you're not doing any composition at all
00:05:43
and your database record Maps almost
00:05:45
identically to your dto and
00:05:48
unfortunately worse if you have more dto
00:05:50
that you need to keep mapping all along
00:05:52
the way that means that when you make
00:05:54
changes you're making changes through
00:05:56
all these different layers to all these
00:05:58
different dto and they serve no value
00:06:01
the only value they might serve is the
00:06:04
argument is well if I make a change to
00:06:06
underlying data schema then I don't have
00:06:09
to do it everywhere that's fair but
00:06:11
you're creating all this work and all
00:06:13
these dto when you don't even have that
00:06:15
problem yet which relates to managing
00:06:18
coupling if you're managing the coupling
00:06:20
to your underlying data model and
00:06:22
tightly controlling how that's being
00:06:24
used if you do need to change it you're
00:06:28
not in a world of hurt don't create work
00:06:30
for yourself ahead of time just in case
00:06:33
it's about giving yourself options and
00:06:35
not creating a bunch of work for just in
00:06:37
case that can hinder you in future
00:06:40
development so if we're talking about
00:06:41
cqrs as the example we have a query and
00:06:44
what it is is a special way of doing
00:06:46
that data composition to return data
00:06:50
specifically for that use case that
00:06:52
particular query our commands are
00:06:54
exactly the same thing but for use cases
00:06:57
of providing some type of intent of we
00:06:59
want to invoke something we want to
00:07:00
perform some type of action it doesn't
00:07:03
need to be a different database that
00:07:04
these are using doesn't need to be a
00:07:06
different schema when people say they're
00:07:08
different models they're talking about
00:07:09
the queries and the commands themselves
00:07:11
and how you actually they're performed
00:07:13
and what they're underlying doing
00:07:15
doesn't mean that they're using a
00:07:16
different database in the example what I
00:07:18
was illustrating earlier if you're
00:07:20
talking about just strictly thinking
00:07:22
about database records and I wanted to
00:07:24
perform like the cancel of a shipment
00:07:26
what would I call the delete or when I
00:07:28
did the arve at the the pickup where
00:07:31
that happened what am I doing a put like
00:07:33
a patch a partial put to update the data
00:07:36
no you want to be specific about the
00:07:38
actions the tasks that you're performing
00:07:41
and queries being specialized on doing
00:07:43
that data composition so with cqrs our
00:07:45
query our response is really our dto it
00:07:48
contains all that data composition so if
00:07:51
we're doing server side rendering on the
00:07:52
query response might be our HTML but if
00:07:54
we had an HTTP API it's exactly the same
00:07:58
thing just a different rep presentation
00:08:00
because we've done all that composition
00:08:02
we have our shipment with all the
00:08:03
standard information but I'm also
00:08:05
including the customer information as
00:08:08
well as the same thing as in the HTML
00:08:10
I'm providing what the actions are that
00:08:11
we can cancel our shipment and do the
00:08:13
arrive this is the value of the dto is
00:08:16
in our composition so a way of thinking
00:08:18
about this whether it be your API or
00:08:20
whether you're using events or messages
00:08:22
with an Aventure of an architecture or
00:08:24
messages within a queue it's the same
00:08:26
thing you want to be thinking about data
00:08:28
on the inside and data on the outside if
00:08:31
it's inside it's internal it's private
00:08:34
to you you don't want to you want to be
00:08:36
able to evolve it and change it without
00:08:38
affecting external consumers and if it's
00:08:41
external you want to be thinking of it
00:08:43
as public as a contract because you're
00:08:44
going to likely version it differently
00:08:46
and this goes back to the very beginning
00:08:48
of the video where I kind of push back
00:08:49
food for thought and asked the question
00:08:51
do we really need to create that dto can
00:08:53
we not just return that entity the
00:08:56
answer really lies in what's the context
00:08:59
do do we own who is calling that that
00:09:01
consumer can we manage the coupling if
00:09:03
we do expose it if I find usages on that
00:09:07
data model that entity is it two or is
00:09:09
it 50 well if it's two we've been
00:09:11
managing it pretty well if it's 50 maybe
00:09:14
not another way I've been thinking about
00:09:15
it is don't allow externals that you
00:09:18
don't control to couple to internals
00:09:20
that you do control an easy example of
00:09:23
this is just your database it's internal
00:09:25
it's private to you it's your
00:09:26
implementation detail you don't expose
00:09:28
that to some random third party but
00:09:30
another layer within your application
00:09:32
that you control isn't a random third
00:09:35
party you manage it you can decide
00:09:37
whether you want a couple to a dto
00:09:40
because that's what you want to
00:09:41
interface with or whether you can
00:09:43
actually manage and use that underlying
00:09:45
data structure data model whatever it is
00:09:48
do you have 50 references to it or do
00:09:51
you have two don't create random dto
00:09:54
that are a onetoone mapping that
00:09:56
ultimately just are still exposing
00:09:58
whatever it is that you're trying to
00:10:00
hide for no reason dto have utility for
00:10:04
dealing with things like composition and
00:10:06
for managing coupling use them
00:10:08
appropriately and as always get in the
00:10:10
comments cuz I know you have some horror
00:10:12
stories about layers upon layers where
00:10:15
there's mappings upon mappings of
00:10:17
seemingly the exact same object so get
00:10:20
in the comments and let me know your
00:10:21
horror stories and if you want to join
00:10:23
my channel the links in the description
00:10:25
you can get access to a private Discord
00:10:26
server where we can chat with other
00:10:28
software developers about top of like
00:10:29
this around software architecture design
00:10:31
links in the description on how to join
00:10:33
if you found this video helpful please
00:10:34
give a thumbs up if you have any other
00:10:35
thoughts or questions make sure to get
00:10:37
in the comments and please subscribe for
00:10:39
more videos on software architecture and
00:10:40
design thanks