Rickard Öberg | 1 May 03:39
Picon
Gravatar

Re: Applying CQS: versioning

Udi Dahan wrote:
>>  could that be done by creating one of those commands and putting it on 
> a queue
> 
> Yes. The only thing you'd want to be careful about is that the sending 
> of the message is done in the same transactional context as the 
> processing of the original command. That way you avoid difficult global 
> inconsistency problems under failure conditions.

The simplest way to do that in Qi4j is to add the sending as a line in 
the UoW log. Then it becomes just a part of normal processing, rather 
than something "outside". The read snapshot persistence would ignore the 
line, but a command invoker would use it.

/Rickard

------------------------------------

Jørn Wildt | 1 May 09:31
Picon
Favicon
Gravatar

Re: Applying CQS: versioning

--- In domaindrivendesign <at> yahoogroups.com, "Udi Dahan" <thesoftwaresimplist@...> wrote:
> Is that at all helpful?

Yes, thanks, that was very helpfull.

> When adding some publish-subscribe to the solution domain, we can
> drastically decrease the period of time where users aren't seeing the
> results of other users actions

The only thing I am ignorant of is the publish-subscribe technique you mention - can you refer to some
reference text about it (on the web)? Thanks.

/Jørn

------------------------------------

Jørn Wildt | 1 May 09:34
Picon
Favicon
Gravatar

Re: Applying CQS: versioning

--- In domaindrivendesign <at> yahoogroups.com, Carfield Yim <carfield@...> wrote:
> We can get the last update time when view the record. For the
> UpdateTextFieldXOnRecord, we submit back the last update time. If the last
> update time is difference from the respository, we reject this update, is
> that sound ok to you?

Certainly okay. But it is not different from using a version number, which is what I was asking about :-)

/Jørn

------------------------------------

Jørn Wildt | 1 May 09:50
Picon
Favicon
Gravatar

Re: Applying CQS: versioning

--- In domaindrivendesign <at> yahoogroups.com, Jørn Wildt <jw@...> wrote:
> The only thing I am ignorant of is the publish-subscribe technique you mention - can you refer to some
reference text about it (on the web)? Thanks.

Well, I just found your blog: http://www.udidahan.com/2008/08/11/command-query-separation-and-soa/

Thanks for a well written introduction.

/Jørn

------------------------------------

ryzamm | 1 May 13:35
Picon
Favicon

Any CQS demo/ example project

Hi i'm very interested to know more about CQS but still having difficulty to understand the advantage of it.
I just wondering if there any good example on how to implement CQS in DDD. 

------------------------------------

Udi Dahan | 1 May 13:56
Picon

RE: Re: Applying CQS: versioning

xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:p="urn:schemas-microsoft-com:office:powerpoint" xmlns:a="urn:schemas-microsoft-com:office:access" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns:b="urn:schemas-microsoft-com:office:publisher" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:odc="urn:schemas-microsoft-com:office:odc" xmlns:oa="urn:schemas-microsoft-com:office:activation" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:q="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtc="http://microsoft.com/officenet/conferencing" xmlns:D="DAV:" xmlns:Repl="http://schemas.microsoft.com/repl/" xmlns:mt="http://schemas.microsoft.com/sharepoint/soap/meetings/" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:ppda="http://www.passport.com/NameSpace.xsd" xmlns:ois="http://schemas.microsoft.com/sharepoint/soap/ois/" xmlns:dir="http://schemas.microsoft.com/sharepoint/soap/directory/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:dsp="http://schemas.microsoft.com/sharepoint/dsp" xmlns:udc="http://schemas.microsoft.com/data/udc" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sub="http://schemas.microsoft.com/sharepoint/soap/2002/1/alerts/" xmlns:ec="http://www.w3.org/2001/04/xmlenc#" xmlns:sp="http://schemas.microsoft.com/sharepoint/" xmlns:sps="http://schemas.microsoft.com/sharepoint/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:udcs="http://schemas.microsoft.com/data/udc/soap" xmlns:udcxf="http://schemas.microsoft.com/data/udc/xmlfile" xmlns:udcp2p="http://schemas.microsoft.com/data/udc/parttopart" xmlns:wf="http://schemas.microsoft.com/sharepoint/soap/workflow/" xmlns:dsss="http://schemas.microsoft.com/office/2006/digsig-setup" xmlns:dssi="http://schemas.microsoft.com/office/2006/digsig" xmlns:mdssi="http://schemas.openxmlformats.org/package/2006/digital-signature" xmlns:mver="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns:mrels="http://schemas.openxmlformats.org/package/2006/relationships" xmlns:spwp="http://microsoft.com/sharepoint/webpartpages" xmlns:ex12t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:ex12m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:pptsl="http://schemas.microsoft.com/sharepoint/soap/SlideLibrary/" xmlns:spsl="http://microsoft.com/webservices/SharePointPortalServer/PublishedLinksService" xmlns:Z="urn:schemas-microsoft-com:" xmlns:st="" xmlns="http://www.w3.org/TR/REC-html40">



Vernon,

 

> 1. Are you using Event Sourcing as Greg does for this scenario?

 

Sometimes.

 

> Isn't it really a matter of "all updates win"

 

Not when it exposes conditions to users who don't know how to handle them.

 

> how would you actually deal with preventing the whole entity overwrite scenario?

 

This is what tasks are about. In a transaction, get the object from the DB (under repeatable read or higher) which locks the entity, call a method on it, it changes the relevant parts of its state, commit. All tasks on that entity are serialized (performed in order) due to the locking. Since each task gets the entity as it is in the DB and performs its changes on top of that, it doesn't overwrite the whole entity.

 

> this is a perfect place where Rickard's mixins/traits would apply

 

I see that as relatively orthogonal (but valuable nonetheless).

 

> what does pub-sub accomplish

 

Let me put it this way, if you knew that some other just did X to the entity you're looking at, would that affect your decision to do X to that same entity? Often, yes. Pub/sub is a mechanism which allows us to push these notifications to users (implementation depending on our client technology).

 

> Are you discussing users working in other BCs

 

Not so much, since we don't often see users in different BCs collaborating that way. Also, business tasks performed in one BC usually are not performed in other BCs - only one BC can accept an order, another bill the customer, another ship the product, etc.

 

Does that make sense?

 

-- Udi Dahan

 

From: domaindrivendesign <at> yahoogroups.com [mailto:domaindrivendesign <at> yahoogroups.com] On Behalf Of vvernon_shiftmethod
Sent: Thursday, April 30, 2009 7:24 PM
To: domaindrivendesign <at> yahoogroups.com
Subject: [domaindrivendesign] Re: Applying CQS: versioning

 




Udi,

I have a couple of follow-up questions and observations:

1. Are you using Event Sourcing as Greg does for this scenario? If so, then "last update wins" isn't really relevant, right? Isn't it really a matter of "all updates win" as long as I can reconstruct history upon dispute by applying the various Event Sourcing pattern strategies.

2. If you are not using Event Sourcing, then how would you actually deal with preventing the whole entity overwrite scenario? Do you break up entities into finer granularity as reflected in use case flows, which prevents different field changes from overwriting non-changed fields? IMO, it seems that this is a perfect place where Rickard's mixins/traits would apply. Thoughts?

3. Can you please elaborate why the following is true?

> When adding some publish-subscribe to the solution domain,
> we can drastically decrease the period of time where users
> aren't seeing the results of other users actions, which
> (in the problem domain) decreases the chance of those users
> performing the same task on the same entity at the
> same time.

In more detail, what does pub-sub accomplish in real terms that allows other users to see the effects of out-of-band changes? Are you discussing users working in other BCs?

Thanks!

Vaughn Vernon

--- In domaindrivendesign <at> yahoogroups.com, "Udi Dahan" <thesoftwaresimplist <at> ...> wrote:
>
> Jørn,
>
>
>
> If multiple users perform the same task, then if the business requirement is
> NOT last one wins, we may go with a versioning solution.
>
>
>
> However, the command you described (UpdateTextFieldXOnRecord) is really just
> a different implementation of the same core entity-based user interaction
> model. In other words, it's not a task in the business sense - it's not what
> users use the system *for*.
>
>
>
> While there are some contexts where multiple users may be performing the
> same task on the same entity at the same time, it isn't *that* common (since
> many businesses don't work that way).
>
>
>
> The reason we get into these concurrency issues with entity-based
> interaction models is that we send entire entities around, leading to issues
> around fields changed by one user overwritten by another user who hadn't
> changed those fields (as your example showed):
>
>
>
> Bob: Read A, B
>
> Rob: Read A, B
>
> Bob: Write C, B
>
> Rob: Write A, D (A overwrote C)
>
>
>
> While with task-based interactions we'd see:
>
>
>
> Bob: Read A, B
>
> Rob: Read A, B
>
> Bob: Task 1 (Make field 1 = C) Result: C, B
>
> Rob: Task 2 (make field 2 = D) Result: C, D - nothing overwritten.
>
>
>
> So, while tasks don't directly solve the problem of multiple users
> overwriting each others' work when performing the same tasks on the same
> entities, they mitigate much of it at the level of the problem domain.
>
>
>
> When adding some publish-subscribe to the solution domain, we can
> drastically decrease the period of time where users aren't seeing the
> results of other users actions, which (in the problem domain) decreases the
> chance of those users performing the same task on the same entity at the
> same time. Interestingly enough, when 2 users are performing the same task
> on the same entity at the same time, it's often for the *same reason* as in
> the case where they both go to fix the same problem they noticed at the same
> time. In that case, last one wins has the same business effect.
>
>
>
> I find it worthwhile asking questions about the applicability of this
> approach in every project I work on. Even if the answer is that it isn't
> applicable, the thought processes we go through in the analysis often
> surface interesting insights into the domain (especially around inter-user
> collaboration).
>
>
>
> Is that at all helpful?
>
>
>
> -- Udi Dahan
>
>
>
> From: domaindrivendesign <at> yahoogroups.com
> [mailto:domaindrivendesign <at> yahoogroups.com] On Behalf Of Jørn Wildt
> Sent: Thursday, April 30, 2009 4:44 PM
> To: domaindrivendesign <at> yahoogroups.com
> Subject: [domaindrivendesign] Re: Applying CQS: versioning
>
>
>
>
>
>
>
>
> <thesoftwaresimplist <at> > wrote:
> > What this means is that the command is performed on the data as is in the
> > database, possibly after multiple modifications by other users.
> >
> > The validity of performing the action is not predicated on if the data was
> > changed by other users, but rather by business rules
>
> Could you please explain what would happen in the following, rather simple,
> scenario without versioning (repeating myself a bit, sorry)?
>
> 1) User A views a record (maybe complete AR)
>
> 2) User B views the same record (maybe complete AR)
>
> 3) User A submits a command "UpdateTextFieldXOnRecord" - changing for
> instance the title to something.
>
> 4) User B submits an identical command (with some other text)
>
> What kind of bussiness rule could protect user B from overwriting user A's
> changes without any notification?
>
> Thanks, Jørn
>



__._,_.___


Your email settings: Individual Email|Traditional
Change settings via the Web (Yahoo! ID required)
Change settings via email: Switch delivery to Daily Digest | Switch to Fully Featured
Visit Your Group | Yahoo! Groups Terms of Use | Unsubscribe

__,_._,___
Jørn Wildt | 1 May 14:19
Picon
Favicon
Gravatar

Re: Applying CQS: versioning

--- In domaindrivendesign <at> yahoogroups.com, "Udi Dahan" <thesoftwaresimplist@...> wrote:
> > how would you actually deal with preventing the whole entity overwrite scenario?
> 
> This is what tasks are about. In a transaction, get the object from the DB
> (under repeatable read or higher) which locks the entity, call a method on
> it, it changes the relevant parts of its state, commit. 

I guess the "changes the relevant parts" element is the *key* feature here? 

Assume a record with for instance two fields "Title" and "Age". One task would say "Set Title=Xxx" and
another task would say "Set Age=Yyy" Both can be serialized and executed one by one without overwriting
previous work. 

As you said earlier - you don't pass the whole entity around, you pass much more finegrained information
around - such as the above field-specific updates.

Correct?

The next question is then: do you apply versioning on *each* field? I guess not and assume this is a place
where the pragmatic solution is "well, this happens so seldom that we ignore the problem (you can find the
old value in the log anyway)". Right?

/Jørn

------------------------------------

Udi Dahan | 1 May 15:15
Picon

RE: Re: Applying CQS: versioning

xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:p="urn:schemas-microsoft-com:office:powerpoint" xmlns:a="urn:schemas-microsoft-com:office:access" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns:b="urn:schemas-microsoft-com:office:publisher" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:odc="urn:schemas-microsoft-com:office:odc" xmlns:oa="urn:schemas-microsoft-com:office:activation" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:q="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rtc="http://microsoft.com/officenet/conferencing" xmlns:D="DAV:" xmlns:Repl="http://schemas.microsoft.com/repl/" xmlns:mt="http://schemas.microsoft.com/sharepoint/soap/meetings/" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:ppda="http://www.passport.com/NameSpace.xsd" xmlns:ois="http://schemas.microsoft.com/sharepoint/soap/ois/" xmlns:dir="http://schemas.microsoft.com/sharepoint/soap/directory/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:dsp="http://schemas.microsoft.com/sharepoint/dsp" xmlns:udc="http://schemas.microsoft.com/data/udc" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sub="http://schemas.microsoft.com/sharepoint/soap/2002/1/alerts/" xmlns:ec="http://www.w3.org/2001/04/xmlenc#" xmlns:sp="http://schemas.microsoft.com/sharepoint/" xmlns:sps="http://schemas.microsoft.com/sharepoint/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:udcs="http://schemas.microsoft.com/data/udc/soap" xmlns:udcxf="http://schemas.microsoft.com/data/udc/xmlfile" xmlns:udcp2p="http://schemas.microsoft.com/data/udc/parttopart" xmlns:wf="http://schemas.microsoft.com/sharepoint/soap/workflow/" xmlns:dsss="http://schemas.microsoft.com/office/2006/digsig-setup" xmlns:dssi="http://schemas.microsoft.com/office/2006/digsig" xmlns:mdssi="http://schemas.openxmlformats.org/package/2006/digital-signature" xmlns:mver="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns:mrels="http://schemas.openxmlformats.org/package/2006/relationships" xmlns:spwp="http://microsoft.com/sharepoint/webpartpages" xmlns:ex12t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:ex12m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:pptsl="http://schemas.microsoft.com/sharepoint/soap/SlideLibrary/" xmlns:spsl="http://microsoft.com/webservices/SharePointPortalServer/PublishedLinksService" xmlns:Z="urn:schemas-microsoft-com:" xmlns:st="" xmlns="http://www.w3.org/TR/REC-html40">



Jørn,

 

You've got it right.

 

The only thing is that while it may decrease the need for versioning, there are contexts where we may still need it.

In those cases, we'd still version the entity - not the field.

 

-- Udi Dahan

 

From: domaindrivendesign <at> yahoogroups.com [mailto:domaindrivendesign <at> yahoogroups.com] On Behalf Of Jørn Wildt
Sent: Friday, May 01, 2009 3:19 PM
To: domaindrivendesign <at> yahoogroups.com
Subject: [domaindrivendesign] Re: Applying CQS: versioning

 




--- In domaindrivendesign <at> yahoogroups.com, "Udi Dahan" <thesoftwaresimplist <at> ...> wrote:
> > how would you actually deal with preventing the whole entity overwrite scenario?
>
> This is what tasks are about. In a transaction, get the object from the DB
> (under repeatable read or higher) which locks the entity, call a method on
> it, it changes the relevant parts of its state, commit.

I guess the "changes the relevant parts" element is the *key* feature here?

Assume a record with for instance two fields "Title" and "Age". One task would say "Set Title=Xxx" and another task would say "Set Age=Yyy" Both can be serialized and executed one by one without overwriting previous work.

As you said earlier - you don't pass the whole entity around, you pass much more finegrained information around - such as the above field-specific updates.

Correct?

The next question is then: do you apply versioning on *each* field? I guess not and assume this is a place where the pragmatic solution is "well, this happens so seldom that we ignore the problem (you can find the old value in the log anyway)". Right?

/Jørn



__._,_.___


Your email settings: Individual Email|Traditional
Change settings via the Web (Yahoo! ID required)
Change settings via email: Switch delivery to Daily Digest | Switch to Fully Featured
Visit Your Group | Yahoo! Groups Terms of Use | Unsubscribe

__,_._,___
Greg Young | 1 May 15:26
Picon
Gravatar

Re: Re: Applying CQS: versioning

The versioning is on the entity but if you are building from commands
and you have a version number you can solve conflicts quite easily in
cases like the one defined here by making the version number the
number (of the commands used to build the object at that state). Then
you can create an interface on your commands for

IConflictWith : IMesssage
    ConflictsWith(IMessage other)

Then when you are in a state where you have a bad version number you
go from the version number to the last command and call conflicts with
on all the commands that you are trying to apply. In the case that you
gave of Title and Age you would have 2 different commands that do not
conflict with each other so you would end up being able to
automatically merge after the version conflict.

HTH

Greg

On Fri, May 1, 2009 at 9:15 AM, Udi Dahan <thesoftwaresimplist <at> gmail.com> wrote:
>
>
> Jørn,
>
>
>
> You've got it right.
>
>
>
> The only thing is that while it may decrease the need for versioning, there
> are contexts where we may still need it.
>
> In those cases, we'd still version the entity - not the field.
>
>
>
> -- Udi Dahan
>
>
>
> From: domaindrivendesign <at> yahoogroups.com
> [mailto:domaindrivendesign <at> yahoogroups.com] On Behalf Of Jørn Wildt
> Sent: Friday, May 01, 2009 3:19 PM
> To: domaindrivendesign <at> yahoogroups.com
> Subject: [domaindrivendesign] Re: Applying CQS: versioning
>
>
>
>
> --- In domaindrivendesign <at> yahoogroups.com, "Udi Dahan"
> <thesoftwaresimplist@...> wrote:
>> > how would you actually deal with preventing the whole entity overwrite
>> > scenario?
>>
>> This is what tasks are about. In a transaction, get the object from the DB
>> (under repeatable read or higher) which locks the entity, call a method on
>> it, it changes the relevant parts of its state, commit.
>
> I guess the "changes the relevant parts" element is the *key* feature here?
>
> Assume a record with for instance two fields "Title" and "Age". One task
> would say "Set Title=Xxx" and another task would say "Set Age=Yyy" Both can
> be serialized and executed one by one without overwriting previous work.
>
> As you said earlier - you don't pass the whole entity around, you pass much
> more finegrained information around - such as the above field-specific
> updates.
>
> Correct?
>
> The next question is then: do you apply versioning on *each* field? I guess
> not and assume this is a place where the pragmatic solution is "well, this
> happens so seldom that we ignore the problem (you can find the old value in
> the log anyway)". Right?
>
> /Jørn
>
> 

--

-- 
It is the mark of an educated mind to be able to entertain a thought
without accepting it.

------------------------------------

Jørn Wildt | 1 May 15:37
Picon
Favicon
Gravatar

Re: Applying CQS: versioning

--- In domaindrivendesign <at> yahoogroups.com, Greg Young <gregoryyoung1@...> wrote:
> you can create an interface on your commands for
> 
> IConflictWith : IMesssage
>     ConflictsWith(IMessage other)
> 
> Then when you are in a state where you have a bad version number you
> go from the version number to the last command and call conflicts with
> on all the commands that you are trying to apply. 

That's a neat trick :-) Thanks.

/Jørn

------------------------------------


Gmane