I attended the same course; this is my answer to your question.
> @jodomofo: So what is the reason for each ABC to be the sole holder of the
> data? Why can't other ABCs store reference data? It is read only isn't it?
As I understand it, each BC is contained within a service; inside one
service a BC is only going to deal with some of the data inside that
service. (eg: bulk vs regular customers). Given that, inside a
service sharing the same data means you have some problem with your
business analysis - your BCs are not actually independent.
I would guess that you are asking about sharing the data between BCs
in different services, though, right?
Part of this is as jodomofo says, that you can't manage data integrity.
I took away, though, that the more important reason for this is this rule:
A service is the technical authority for a part of the business.
eg: Marketing is the technical authority for prices.
If you share that data with another service - they have a copy of it -
you no longer have that technical authority. Marketing can't control
how Sales use the price data they have a copy of, Sales have no hope
of knowing if their data is up to date[1].
Giving Sales a copy of that data is bad enough because it smears
responsibility for that information around multiple services, but it
gets worse: it encourages bad design in Sales, and even worse, for
Sales to start exposing price information. Now you have *two* places
that might give you a price - and who do you trust? Sales?
Marketing? Both? Neither?
I think that this problem is why Udi so strongly encouraged visual
composition rather than copying data: instead of thinking that sales
need access to the price information, visually compose them next to
each other so the sales data sits beside the price data, each pulled
from their own service.
Finally, when it comes to things like interacting with the outside
world for, eg, payment, Udi put emphasis on the IT/operations team
owning that, and being the *only* department that can query multiple
business services to get what they need.
So, instead of Sales collecting price data (owned by marketing), card
data (owned by billing) and the invoice details (owned by sales), the
payment service owned by IT/ops will collect the minimum that it
needs, when instructed, to make the external payment.
This makes integration between services a separate consideration to
the services themselves, which I think is an overall win.
Finally, to answer your latest message where you say:
> If data is read only, why do you need to ensure it's integrity? It doesn't change.
One other thing that Udi was very emphatic about through the course,
and I think rightly so, was that time is always a factor in this
design.
If that data never changes, as in, is a constant, then you probably
can have a copy in each service, but they don't need to exchange it.
It is literally unchangeable.
If, instead, you mean "never changes" in the sense of "isn't changed
by the service that has a copy", that seems like a narrow view of the
problem space to me. Once it is possible to change that you have to
go back to the question of freshness, and what business value the data
gives.
If you don't care about integrity (eg: you could replace every value
with the word "fred" instead) then why have a copy of it? If you
intend to use the data, or display it to someone, or whatever, then
you have taken on the responsibility of the other service.
eg: If Sales is showing price information, they have taken over
responsibility from Marketing for making sure the user knows how up to
date that is ... and, worse, they have taken ownership of the business
part of that. Now they have to implement all the freshness policies -
heck, all the policies - of Marketing to get that done.
If you really need that, I think that Sales and Marketing are not
separate services, and you would do better getting rid of that notion
entirely. :)
> Anyway, I'm not gonna interrogate you:) But that bit of sole ownership is really hard to get as you say. Especially in some scenarios where reference data can be stored in a ABC which is most interested in keeping it unchanged, like in an example Udi gives with user name and invoice.
One of the questions that Udi asked was: do you really sound like the
technical authority for something if you say that you can tell someone
what the authoritative, absolute value is right now, but you have no
idea what it was like yesterday?
In the case of the name on an invoice, you don't actually want "the
name on the invoice", you want "the name of customer 12 on the 30th
October, 2011, at 6:45PM" - and the service that owns the "customer
name" will be responsible for making that available even if the name
changes later.
Daniel
Footnotes:
[1] For example, if the marketing server crashes it could take a while
for it to get back, so the fact the price changed is unavailable until
that recovers.
--
♲ Made with 100 percent post-consumer electrons
I should add, Sharas, that I covered a very, very small part of what
the course did in that description. I can really recommend the whole
five days as being excellent, and well worth the time. There are lots
of other parts that also play into this picture that make it all gel
together.
Daniel
Giving Sales a copy of that data is bad enough because it smears
responsibility for that information around multiple services, but it
gets worse: it encourages bad design in Sales, and even worse, for
Sales to start exposing price information. Now you have *two* places
that might give you a price - and who do you trust? Sales?
Marketing? Both? Neither?
In the case of the name on an invoice, you don't actually want "the
name on the invoice", you want "the name of customer 12 on the 30th
October, 2011, at 6:45PM" - and the service that owns the "customer
name" will be responsible for making that available even if the name
changes later.
Daniel
Footnotes:
[1] For example, if the marketing server crashes it could take a while
for it to get back, so the fact the price changed is unavailable until
that recovers.
@Daniel: thanks for your answer.
I attended the same course; this is my answer to your question.
As I understand it, each BC is contained within a service; inside one
> @jodomofo: So what is the reason for each ABC to be the sole holder of the
> data? Why can't other ABCs store reference data? It is read only isn't it?
service a BC is only going to deal with some of the data inside that
service. (eg: bulk vs regular customers). Given that, inside a
service sharing the same data means you have some problem with your
business analysis - your BCs are not actually independent.
I would guess that you are asking about sharing the data between BCs
in different services, though, right?
Part of this is as jodomofo says, that you can't manage data integrity.
I took away, though, that the more important reason for this is this rule:
A service is the technical authority for a part of the business.
eg: Marketing is the technical authority for prices.
If you share that data with another service - they have a copy of it -
you no longer have that technical authority. Marketing can't control
how Sales use the price data they have a copy of, Sales have no hope
of knowing if their data is up to date[1].Why not set expiry date on prices and let sales know that those prices are valid for a specific interval, so sales does not have to worry about changes of prices for that period which increases autonomy of sales. Good example described in here with catalog prices.
Giving Sales a copy of that data is bad enough because it smears
responsibility for that information around multiple services, but it
gets worse: it encourages bad design in Sales, and even worse, for
Sales to start exposing price information. Now you have *two* places
that might give you a price - and who do you trust? Sales?
Marketing? Both? Neither?Marketing is entry point for prices which are broadcasted with an expiration date. Sales can display prices for that period but does not modify them. That again increases autonomy of those services.
In the case of the name on an invoice, you don't actually want "thename on the invoice", you want "the name of customer 12 on the 30thOctober, 2011, at 6:45PM" - and the service that owns the "customer
name" will be responsible for making that available even if the name
changes later.I understand that's how Udi SOA is done, but actually, in this case I need a snapshot of users name with invoice, not a knowledge that I need to get it from somewhere by date and id.
Footnotes:
[1] For example, if the marketing server crashes it could take a while
for it to get back, so the fact the price changed is unavailable until
that recovers.
That's the problem with Udis approach, to make this actually work you need to keep those ABCs highly available because they are temporaly coupled, but implicitly by a composite application.
(allocate another couple of clones of the marketing service to give higher availability).
>> (allocate another couple of clones of the marketing service to give higher availability).
>
> How do you mantain the boundaries consistent across clones?
So, this is strictly a problem inside the service, right? Obviously,
if you implement the service so it can't scale out, only scale up,
then you can wind up with terrible problems here. OTOH, you can
potentially also put in the effort as you need it: if your scale
issues come from a lack of CPU, scale out workers against a shared SQL
database. If they come from the database, change the internal store,
or scale up the DB server, or whatever.
(Also, query is less likely to hit your domain model storage database;
because you can heavily denormalize in the view model, the client is
pretty low impact, and can be pushed to a separate database if
required.)
However, if you are designing around the DDD model where you only give
atomic action inside an aggregate root, this is easier than it sounds.
You have the one place that needs to be implemented safely around
that, so it can be atomic within the AR.
This actually gets somewhat easier in the model Udi proposed, where
your saga *is* the domain model: you need to account for a race around
the events that start a saga, if it starts from more than one place,
but otherwise you just respond to events as they come in and manage
local state inside that structure.
It doesn't make handling concurrency easy, but it does make it fairly
manageable. (Also, it means that when someone messes up here you wind
up with one broken part of one service, not everything broken
everywhere, which also helps contain the damage.)
Does that make sense?
Daniel
Thanks to everyone in the thread: this is still being a big help in
forcing me to think through and explain my understanding of what Udi
proposed. Please don't mistake me for any sort of expert with real
world experience of this stuff, though. :)
On the read side, or the update side?
On the read side, just run more instances that react to events from
the bus, do their calculations, and store the data in their table.
(If you have more than one view, or a view and an augmented view, and
they are not separable by UI composition, Udi suggests just having two
tables.)
Alternately, use database replication for read, or whatever else
floats your boat. Given that the read side is, essentially, select *
from $view, this is cheap. You can also look to, eg, NoSQL database
here in many cases, because you often have view models defined around
"get data for this set of IDs", which those tools are excellent at.
On the update side? You don't have to run each view model on the same
hardware, so if one is too costly, split it off. Give it dedicated
hardware, storage, or whatever you need to make it perform adequately.
(Keep in mind that all this is inside a single BC, and each view
model updater is focused on a single, very small widget shown on
screen - eg, the price of a book, or the title of a book, rather than
an entire page.)
This allows you to focus the money the business gives you to improve
performance on explicitly the part of the system that is hurting
performance.
Oh, and remember that your view model is explicitly stale data; if it
is marginally more stale, you have to assess if there is a business
cost to that, right?
Daniel
--
Le doute n'est pas une condition agréable, mais la certitude est absurde.
My recollection is that it came up in the course, but that might have
been the general discussion since it doesn't show up in my notes.
Daniel
I would disagree with Bennie when he says " if you use the pricing service but a new system uses it so heavily it makes it runs slow. ". I cannot justify maybe breaking encapsulation and spreading logic because of possible performance issues.
To me even if it happens (a system uses it so heavily it makes it runs slow) then it is much easier to scale this service out and have 2, 3, 30 copies of it running than producing and maintaining more copies of data + more logic around these copies just because something may be slow at some point.
I find data to be a leaky abstraction. Logic tends to clump to it. Now the authority service can't change without coordinating.
If you mean the authority maintains a copy of the data closer to the heavy client, sure.
--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Given that SOA guides us away from having a given 3rd normal form entity exist in any one service, it is unlikely that the building blocks of your CQRS design will be those kinds of entities. Most 3rd normal form one-to-many and many-to-many relationships simply do not exist when doing SOA and CQRS properly.