Skip to search.

Breaking News Visit Yahoo! News for the latest.

×Close this window

domaindrivendesign · Domain-Driven Design

The Yahoo! Groups Product Blog

Check it out!

Group Information

  • Members: 4073
  • Category: Software
  • Founded: Sep 27, 2002
  • Language: English
? Already a member? Sign in to Yahoo!

Yahoo! Groups Tips

Did you know...
Real people. Real stories. See how Yahoo! Groups impacts members worldwide.

Messages

Advanced
Messages Help
Messages 8410 - 8439 of 24071   Oldest  |  < Older  |  Newer >  |  Newest
Messages: Show Message Summaries Sort by Date ^  
#8410 From: "Jonathan Harley" <jdharley@...>
Date: Sun Sep 28, 2008 7:47 pm
Subject: Re: Re: Repositories for lookups
agilista
Send Email Send Email
 
Okay.  If you are referring to the maintenance of value objects then,
for the purpose of maintenance, do we temporarily treat the value
objects (in any other context) as entities?  I think this a reasonable
variation, and not incorrect given the context.

Context is everything.

On Sun, Sep 28, 2008 at 12:39 PM, ryzamm <ryzamm@...> wrote:
> I think we need to separate Value Object to 2 types. One is initial
> list value object and another one is runtime value object (i'm not
> sure the term is correct or not).
>
> Let's take initial list value object concept. Initial list value
> object is like a data to represent in lookup/dropdownlist, for example
> country. We need to create a value object for all valid country in the
> world
> 1. United State
> 2. China
> 3. Russia
> 4. ...
>
> So the question comes to whom the managing responsibility should we
> put? Do we need to have GenericAdmin repository or GenericValueObject
> repository for maintenance?
>
> Another type of value object is a runtime value object meaning that we
> only create new instance when needed. For example Person entity and
> Address value object. Normally we don't put address in dropdownlist
> for client to select the address . Person A have reference to AddressA
> and then PersonB join to live in the same address, if we want to add
> PersonB address, we should check if the value we add already exist or
> not if yes we just make a reference AddressA to PersonB but if Person
> B live next to PersonA, so when we check the address value no value
> equality exist then we will create a new instance of AddressB and set
> a reference for PersonB.I think for the second type quite clear the
> saving value object will be responsible by the entity who use that
> value object. Type 1 still not clear to me
>
> --- In domaindrivendesign@yahoogroups.com, "Jonathan Harley"
>
> <jdharley@...> wrote:
>>
>> The class that uses the value object stores its reference via the
>> repository for the using object.
>>
>> On Sat, Sep 27, 2008 at 7:53 AM, ryzamm <ryzamm@...> wrote:
>> > How about if i want to stick that State is a Value Object and i
> want
>> > to store it to the State table itself. So when it comes to save
> into
>> > the database who will take this responsibility? If i have Person
>> > entity which is contain State Value Object does Person Repository
> do
>> > the saving of State value? How about if i have more than one
> aggregate
>> > entity refer to the same State value?
>> >
>> > Thanks
>> >
>> >
>>
>>
>>
>> --
>> A long habit of not thinking a thing wrong, gives it a superficial
>> appearance of being right, and raises at first a formidable outcry
> in
>> defense of custom.
>> -Thomas Paine
>>
>
>



--
A long habit of not thinking a thing wrong, gives it a superficial
appearance of being right, and raises at first a formidable outcry in
defense of custom.
-Thomas Paine

#8411 From: "billhamaker" <BillHamaker@...>
Date: Mon Sep 29, 2008 2:08 pm
Subject: Re: Customizing a domain model
billhamaker
Send Email Send Email
 
Forgetting the implementation details for the moment to do it in a
sophisticated way what you need is to have a "metadata" component of
your domain model.  If the user has to be able to add attributes to
entity types then you will need an object "entity type" in your
metadata model and will methods like 'add attribute".   If the user
has to be able to add fields to screens then you will the screens
will have to be objects in the metadata model.  The you will need to
figure out what sort of user interface to use that allows the user to
update the metadata.

There are many details to work out and it all depends on the level of
sophistication your requirements and budget allow for.    If you
customization requirements are limited a shortcut frequently used is
just to build in a few user defined fields into your database "e.g.
userfield1, userfield2, etc". and then just let the user have the
ability to change field labels.

As far as storing the data is concerned a lot depends on what the
user needs to do with the data outside of your application.  They may
require a particular structure to make it easy to your data with
legacy applications.    If they don't need to access the data outside
your applications API then XML is an elegant to way to store user
defined fields but there are many other choices.

Bill



--- In domaindrivendesign@yahoogroups.com, Jørn Wildt <jw@...> wrote:
>
> Does anyone have experience with customization of domain models
(and, well, hmmm, entire applications)? I know "customization" is
quite a broad term, so let me give an example: our customer wants to
be able to extend the system we deliver. He wants to be able to add
new customer-specific properties to some of the core entities, and he
wants them to show up in the UI (but not necessarily automatically).
For instance, the entity Person could be extended with a new
enumerated property "HairColor" which we haven't added to the system
initially. The customer does not have write access to the application
code, but he may freely depend on calling it from other applications.
>
> We are using C#, NHibernate and Inversion of Control to model,
persist and instantiate our bussiness objects, services and
repositories.
>
> In a system where only DataRows and DataTables are used, we can
easily add extra columns without recompiling the code: just make sure
to "select * from..." and all columns in the DB will be passed
automatically to the UI (please ignore the perfomance problems with
this).
>
> But when we have hardwired Person as a class with N properties, how
should the customer then extend it? How does a domain model handle
that kind of feature request?
>
> One solution is to let the customer inherit from Person to
CustomPerson, extend it with the custom properties, and then inject
new NHibernate mapping files and use IoC in configuration files to
make sure all instances of IPerson are mapped to CustomPerson. But
that is quite a lot more complex than simply adding a new field to
the database - and requires the customer to be quite proficient with
that setup.
>
> Another solution is to store custom properties in a separate
CustomPerson table and then do a "select *" from that table everytime
we fetch a Person. The returned columns can then be added to the
object Person as a referenced DataRow.
>
> Other ideas?
>
> Regards, Jørn Wildt
>

#8412 From: "Peter Morris" <mrpmorris@...>
Date: Fri Oct 3, 2008 7:31 am
Subject: Re: Broken Business Rules vs Broken Validation
mrpmorris
Send Email Send Email
 
In this kind of scenario I usually have a state machine on the class.
  Simple states would do

Creating,
Live

Some constraints are added if the state == Creating (Name required,
Name must be unique, etc), additional constraints are added if the
state == Live.


Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com

#8413 From: "Peter Morris" <mrpmorris@...>
Date: Fri Oct 3, 2008 7:36 am
Subject: Re: Cascades across aggregates
mrpmorris
Send Email Send Email
 
My rule is simple.

"Can the child exist without the parent?"

[Order] (Order) 1---* (Lines) [OrderLine]

If you delete the Order then its lines should also be deleted, it
makes no sense to have lines exist without an order.


[Country] (CountryOfResidence) 1--* (Residents) [Person]

Here I would use aggregation (prohibit delete) because deleting a
country should not delete lots of people, you would obviously be
deleting a country entered in error or something so you would want the
delete to fail if someone had assigned residents to it.


Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com

#8414 From: "Peter Morris" <mrpmorris@...>
Date: Fri Oct 3, 2008 7:53 am
Subject: Re: Is access control part of the domain?
mrpmorris
Send Email Send Email
 
For me there are two types of "Can I" on an object

01: Is it logical for this object to perform this task based on its state.
02: Is it permissible for the current user to perform this task.

The framework I use abstracts all of its services and provides access
via a service provider pattern.  I find this useful for many reasons
that I wont go into because I tend to talk too much :-) but one of the
advantages is that it allows you to register your own services.

Coincidentally I blogged about unit testing security only a few days ago.
http://mrpmorris.blogspot.com/2008/09/unit-testing-security.html


Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com

#8415 From: "Eben Roux" <eben@...>
Date: Fri Oct 3, 2008 8:26 am
Subject: Re: Customizing a domain model
eben_roux
Send Email Send Email
 
Hello Jørn,

This is a typical "have your cake and eat it" scenario that customers
think they'll need.  It ends up being utterly dumb data and as soon as
your system (er... domain) requires knowledge of it in any way, manner,
or form, then it absolutely has to move into the domain.  This
typically happens when business rules enter the fray.

If, however, you can treat treat the data as dumb I would create a sub-
domain (is this right?).  I don't know if your core domain even need be
aware of this.  Your front end sure would.

So you have a Person.  Now your generic mechanism doesn't care what the
data belongs to.  It simply contains the ID (guid is nice, heh?), the
type (or type name) --- Hair Colour, etc. --- and the value.  This can
then be managed totally separate from your core domain without
resorting to the likes of "select *".

Regards,
Eben

#8416 From: "Paul Batum" <paul.batum@...>
Date: Fri Oct 3, 2008 1:23 pm
Subject: Re: Re: Cascades across aggregates
paul.batum
Send Email Send Email
 
I don't think I follow your point, you say you would "use aggregation (prohibit delete)", but in your example its obvious that Person does not sit inside the Country aggregate.
When I used the term aggregate I was talking about the concept that Evans describes in DDD, as in aggregates with an identified root, not the broader definition of the word aggregate.

On Fri, Oct 3, 2008 at 8:36 AM, Peter Morris <mrpmorris@...> wrote:

My rule is simple.

"Can the child exist without the parent?"

[Order] (Order) 1---* (Lines) [OrderLine]

If you delete the Order then its lines should also be deleted, it
makes no sense to have lines exist without an order.

[Country] (CountryOfResidence) 1--* (Residents) [Person]

Here I would use aggregation (prohibit delete) because deleting a
country should not delete lots of people, you would obviously be
deleting a country entered in error or something so you would want the
delete to fail if someone had assigned residents to it.

Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com



#8417 From: "Paul Batum" <paul.batum@...>
Date: Fri Oct 3, 2008 1:29 pm
Subject: Re: Re: Cascades across aggregates
paul.batum
Send Email Send Email
 
Just as a follow up, thinking about it a bit more, it doesn't really make sense to cascade deletes across aggregate boundaries because you may be breaking referential integrity. When I asked my original question I was really more interested in hearing thoughts about cascading saves. And I still am! I got a useful answer from Bert but was hoping to get more opinions.

On Fri, Oct 3, 2008 at 2:23 PM, Paul Batum <paul.batum@...> wrote:
I don't think I follow your point, you say you would "use aggregation (prohibit delete)", but in your example its obvious that Person does not sit inside the Country aggregate.
When I used the term aggregate I was talking about the concept that Evans describes in DDD, as in aggregates with an identified root, not the broader definition of the word aggregate.


On Fri, Oct 3, 2008 at 8:36 AM, Peter Morris <mrpmorris@...> wrote:

My rule is simple.

"Can the child exist without the parent?"

[Order] (Order) 1---* (Lines) [OrderLine]

If you delete the Order then its lines should also be deleted, it
makes no sense to have lines exist without an order.

[Country] (CountryOfResidence) 1--* (Residents) [Person]

Here I would use aggregation (prohibit delete) because deleting a
country should not delete lots of people, you would obviously be
deleting a country entered in error or something so you would want the
delete to fail if someone had assigned residents to it.

Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com




#8418 From: "Peter Morris" <mrpmorris@...>
Date: Fri Oct 3, 2008 1:52 pm
Subject: Re: Re: Cascades across aggregates
mrpmorris
Send Email Send Email
 
>>I don't think I follow your point, you say you would "use aggregation (prohibit delete)", but in your example its obvious that Person does not sit inside the Country aggregate.
 
[ClassName]
(RoleName)
 
 
One order has many lines.
[Order] (Order) 1---* (Lines) [OrderLine]
 
This is a composite association, the order lines will be deleted with the order.
 
 
One country has many residents. 
[Country] (CountryOfResidence) 1--* (Residents) [Person]
 
For this I use the UML aggregate association, to indicate that the person cannot exist without a country.  Deleting a country with residents will prohibit the deletion.
 
 
Many people preferring different foods.
[Person] *------> (PreferredFood) [Food]
 
In this case there is no composition or aggregation.  If the Duck Billed Platipus were (for some unknown reason) to become suddenly extinct it is okay to delete it and have the other end unlink rather than cascade or prohibit deletion.
 
 
> When I used the term aggregate I was talking about the concept that Evans describes in DDD, as in aggregates with an identified root, not the broader definition of the word aggregate.
 
I haven't read it.  Unless I am mistaken I am using the UML term for aggregation.  If you mean something else then this would explain the confusion :-)
 
 
Pete
====
 

#8419 From: "Peter Morris" <mrpmorris@...>
Date: Fri Oct 3, 2008 1:54 pm
Subject: Re: Re: Cascades across aggregates
mrpmorris
Send Email Send Email
 
>>
Just as a follow up, thinking about it a bit more, it doesn't really make sense to cascade deletes across aggregate boundaries because you may be breaking referential integrity. When I asked my original question I was really more interested in hearing thoughts about cascading saves. And I still am! I got a useful answer from Bert but was hoping to get more opinions.
<<
 
That's why an aggregated association prohibits delete of the parent, but a composite cascades the delete.  No integrity problems.  As for saves, you would need to save all objects affected by the operation otherwise you will have referential integrity problems :-)
 
 

#8420 From: "Paul Batum" <paul.batum@...>
Date: Fri Oct 3, 2008 2:10 pm
Subject: Re: Re: Cascades across aggregates
paul.batum
Send Email Send Email
 
That would explain why I didn't follow your point earlier. The Evans concept of an aggregate is different to a UML aggregation association.

Regarding your point about losing integrity if you do not cascade saves, that is only true assuming you are performing just ONE save operation. If you save each aggregate root separately then you have no problem. However this might be more effort than simply saving one aggregate root and then relying on cascades. I thought people might be able to offer some downsides to cascades, reasons why it is better to save each root explicitly.

On Fri, Oct 3, 2008 at 2:52 PM, Peter Morris <mrpmorris@...> wrote:

>>I don't think I follow your point, you say you would "use aggregation (prohibit delete)", but in your example its obvious that Person does not sit inside the Country aggregate.
 
[ClassName]
(RoleName)
 
 
One order has many lines.
[Order] (Order) 1---* (Lines) [OrderLine]
 
This is a composite association, the order lines will be deleted with the order.
 
 
One country has many residents. 
[Country] (CountryOfResidence) 1--* (Residents) [Person]
 
For this I use the UML aggregate association, to indicate that the person cannot exist without a country.  Deleting a country with residents will prohibit the deletion.
 
 
Many people preferring different foods.
[Person] *------> (PreferredFood) [Food]
 
In this case there is no composition or aggregation.  If the Duck Billed Platipus were (for some unknown reason) to become suddenly extinct it is okay to delete it and have the other end unlink rather than cascade or prohibit deletion.
 
 
> When I used the term aggregate I was talking about the concept that Evans describes in DDD, as in aggregates with an identified root, not the broader definition of the word aggregate.
 
I haven't read it.  Unless I am mistaken I am using the UML term for aggregation.  If you mean something else then this would explain the confusion :-)
 



#8421 From: "Peter Morris" <mrpmorris@...>
Date: Fri Oct 3, 2008 2:34 pm
Subject: Re: Re: Cascades across aggregates
mrpmorris
Send Email Send Email
 
Why would you want to perform multiple save operations?  Deleting a node and all its sub-nodes is an atomic operation and should therefore occur within a single DB transaction shouldn't it?  There's probably an opinion / approach here I am unfamiliar with :-)
 
 
 

#8422 From: "Paul Batum" <paul.batum@...>
Date: Fri Oct 3, 2008 2:43 pm
Subject: Re: Re: Cascades across aggregates
paul.batum
Send Email Send Email
 
Regardless of which way you want to do it (cascade across aggregate roots, or not) you obviously want it to be atomic. The atomicity is not relevant. Given you are not really familiar with the Evans aggregate I suspect you can't really help me Pete, though I do appreciate your efforts. At the very least it was nice to have this thread activated again, because I had been hoping for more responses.

On Fri, Oct 3, 2008 at 3:34 PM, Peter Morris <mrpmorris@...> wrote:

Why would you want to perform multiple save operations?  Deleting a node and all its sub-nodes is an atomic operation and should therefore occur within a single DB transaction shouldn't it?  There's probably an opinion / approach here I am unfamiliar with :-)


#8423 From: "Peter Morris" <mrpmorris@...>
Date: Fri Oct 3, 2008 3:08 pm
Subject: Re: Re: Cascades across aggregates
mrpmorris
Send Email Send Email
 
In that case maybe you could explain it to me and I could be educated.  Although I do feel that hijacking the word "aggregate" to mean something else from the UML term (and UML is likely to be used in DDD) was probably a bad decision, it hardly helps to form a ubiquitous language does it :-)
 
Maybe if you explain it in detail without assuming a certain amout of pre-requisit knowledge (no jargon) I still might be able to help :-)
 
 

#8424 From: Randy Stafford <randy.stafford@...>
Date: Fri Oct 3, 2008 3:36 pm
Subject: RE: Re: Cascades across aggregates
randalparker...
Send Email Send Email
 

Hi Pete,

 

Check out http://tech.groups.yahoo.com/group/domaindrivendesign/message/7533.

 

With respect to the UML’s notion of aggregation, remember these words from Martin Fowler (UML Distilled, 3rd Ed., p.67):

 

“One of the most frequent sources of confusion in the UML is aggregation and composition. … In the pre-UML days, people were usually rather vague on what was aggregation and what was association.  Whether vague or not, they were always inconsistent with everyone else.  As a result, many modelers think that aggregation is important, although for different reasons.  So the UML included aggregation but with hardly any semantics.  As Jim Rumbaugh says, ‘Think of it as a modeling placebo’ [Rumbaugh, UML Reference].”

 

For this reason, I rarely use the UML’s notion of aggregation in my practice; I use mainly UML association and composition (but I do like your example of a Country and its Residents).  Regardless, in the DDD community, the meaning of Aggregate as described by Eric is well understood.  Here’s the pattern in Google Books: http://tinyurl.com/3w4rbc - I’d be interested to hear your thoughts after you’ve read through it.

 

Thanks,

Randy

http://c2.com/cgi/wiki?RandyStafford

 


From: Peter Morris [mailto:mrpmorris@...]
Sent: Friday, October 03, 2008 9:09 AM
To: domaindrivendesign@yahoogroups.com
Subject: Re: [domaindrivendesign] Re: Cascades across aggregates

 

In that case maybe you could explain it to me and I could be educated.  Although I do feel that hijacking the word "aggregate" to mean something else from the UML term (and UML is likely to be used in DDD) was probably a bad decision, it hardly helps to form a ubiquitous language does it :-)

 

Maybe if you explain it in detail without assuming a certain amout of pre-requisit knowledge (no jargon) I still might be able to help :-)

 

 

Pete

====

http://mrpmorris.blogspot.com

http://www.capableobjects.com


#8425 From: "Peter Morris" <mrpmorris@...>
Date: Fri Oct 3, 2008 5:22 pm
Subject: Re: Re: Cascades across aggregates
mrpmorris
Send Email Send Email
 
Okay, I haven't read in detail, but the first paragraph or two suggests this is a value type scenario.  I recently had to implement value types in an app because the value in question could be a very large video file, so we wanted multiple references to all point to the same instance, and for that instance to get deleted when no more objects referenced it.  My implementation was very simple
 
[VideoFile] (VideoFile) 1-----0..* (References) [VideoFileReference]
 
The trick is to never hold a direct *persistent* reference to VideoFile.  Instead I would do this
 
01: In the constructor of the class that wants to reference a VideoFile construct a VideoFileReference
 
//Constructor that is called when first created, not recreated from persistence
public MyClass(.......)
{
    this.VideoFileReference = new VideoFileReference(.....);
}
 
02: The association from MyClass to VideoFileReference is private
 
[MyClass] 0..* ---------> 1 (VideoFileReference) [VideoFileReference]
 
 
03: The association from MyClass to VideoFile is transient so is never persisted. 
 
public VideoFile VideoFile
{
    get { return VideoFileReference.VideoFile; }
    set { VideoFileReference.VideoFile = value; }
}
 
So far all I have done is two things
A: Ensured that every persistent reference to VideoFile is via a VideoFileReference
B: Hidden this fact inside MyClass and made it look like it references VideoFile directly
 
Next I decorate the VideoFile with a .NET attribute
 
//This isn't exactly how I do it, but the easiest way to explain
[ValueType("References")]
public class VideoFile ......
{
}
 
Finally I run a nightly job which finds all ValueType classes in the model, and then for each class executes the following (expressed as OCL)
 
className.allInstances->select(referenceRoleName->isEmpty)
 
I then delete each one.  If there is an optimistic lock exception then I assume it has been referenced since I executed my query and just move onto the next.
 
 
 
Is that any help, or have I just described something completely irrelevant? :-)  I should write this up in my blog come to think of it.
 
 
 

#8426 From: "Paul Batum" <paul.batum@...>
Date: Fri Oct 3, 2008 9:52 pm
Subject: Re: Re: Cascades across aggregates
paul.batum
Send Email Send Email
 
I'm sorry Pete but to perfectly honest that wasn't at all helpful in regards to answering my question.

On Fri, Oct 3, 2008 at 6:22 PM, Peter Morris <mrpmorris@...> wrote:

Okay, I haven't read in detail, but the first paragraph or two suggests this is a value type scenario.  I recently had to implement value types in an app because the value in question could be a very large video file, so we wanted multiple references to all point to the same instance, and for that instance to get deleted when no more objects referenced it.  My implementation was very simple
 
[VideoFile] (VideoFile) 1-----0..* (References) [VideoFileReference]
 
The trick is to never hold a direct *persistent* reference to VideoFile.  Instead I would do this
 
01: In the constructor of the class that wants to reference a VideoFile construct a VideoFileReference
 
//Constructor that is called when first created, not recreated from persistence
public MyClass(.......)
{
    this.VideoFileReference = new VideoFileReference(.....);
}
 
02: The association from MyClass to VideoFileReference is private
 
[MyClass] 0..* ---------> 1 (VideoFileReference) [VideoFileReference]
 
 
03: The association from MyClass to VideoFile is transient so is never persisted. 
 
public VideoFile VideoFile
{
    get { return VideoFileReference.VideoFile; }
    set { VideoFileReference.VideoFile = value; }
}
 
So far all I have done is two things
A: Ensured that every persistent reference to VideoFile is via a VideoFileReference
B: Hidden this fact inside MyClass and made it look like it references VideoFile directly
 
Next I decorate the VideoFile with a .NET attribute
 
//This isn't exactly how I do it, but the easiest way to explain
[ValueType("References")]
public class VideoFile ......
{
}
 
Finally I run a nightly job which finds all ValueType classes in the model, and then for each class executes the following (expressed as OCL)
 
className.allInstances->select(referenceRoleName->isEmpty)
 
I then delete each one.  If there is an optimistic lock exception then I assume it has been referenced since I executed my query and just move onto the next.
 
 
 
Is that any help, or have I just described something completely irrelevant? :-)  I should write this up in my blog come to think of it.


#8427 From: "Stefan Moser" <stefan.moser@...>
Date: Fri Sep 26, 2008 10:11 pm
Subject: Re: Customizing a domain model
stefanmoser16
Send Email Send Email
 
I worked on a project with similar requirements in the past.  One question you have to ask yourself is does any *logic* change with any of these customization properties. 
 
Here is an example.  Let's say that your application manages parties (the ones with food and drinks and fun) and a major part of your domain is tracking how much fun a person is having.  So you have a Person entity.  Now one of your customers wants to customize the application to add HairColor to the Person entity.  Are they also able to change the *logic* within the Person entity so that when HairColor == HairColor.Blonde that they can also say Fun++?  Sorry, I just couldn't resist. :-)
 
But seriously, it is rarely the case that these kinds of applications allow the customization to have any effect on business logic.  If this is the case, you're basically dealing with this part of the application being simple forms over data.  One way that this can be handled is to not change the core Person in anyay, but to decorate the Person outside of the domain boundaries.
 
Depending on the complexity of your customization requirements, this could become its own pseudo bounded context.  The one I worked on actually had a fair amount of logic in how the customization was set up.
 
The project started with the "let's just extend the database tables" approach, but this caused ssssooooo many problems that I would recommend not going down that route at all.
 
I know it's vague, but hope that helps a little.
 
Stefan

On Fri, Sep 26, 2008 at 2:20 PM, Jørn Wildt <jw@...> wrote:
Does anyone have experience with customization of domain models (and, well, hmmm, entire applications)? I know "customization" is quite a broad term, so let me give an example: our customer wants to be able to extend the system we deliver. He wants to be able to add new customer-specific properties to some of the core entities, and he wants them to show up in the UI (but not necessarily automatically). For instance, the entity Person could be extended with a new enumerated property "HairColor" which we haven't added to the system initially. The customer does not have write access to the application code, but he may freely depend on calling it from other applications.
 
We are using C#, NHibernate and Inversion of Control to model, persist and instantiate our bussiness objects, services and repositories.
 
In a system where only DataRows and DataTables are used, we can easily add extra columns without recompiling the code: just make sure to "select * from..." and all columns in the DB will be passed automatically to the UI (please ignore the perfomance problems with this).
 
But when we have hardwired Person as a class with N properties, how should the customer then extend it? How does a domain model handle that kind of feature request?
 
One solution is to let the customer inherit from Person to CustomPerson, extend it with the custom properties, and then inject new NHibernate mapping files and use IoC in configuration files to make sure all instances of IPerson are mapped to CustomPerson. But that is quite a lot more complex than simply adding a new field to the database - and requires the customer to be quite proficient with that setup.
 
Another solution is to store custom properties in a separate CustomPerson table and then do a "select *" from that table everytime we fetch a Person. The returned columns can then be added to the object Person as a referenced DataRow.
 
Other ideas?
 
Regards, Jørn Wildt


#8428 From: "Mohammed Abed" <moh_abed_2002@...>
Date: Sun Sep 28, 2008 11:59 am
Subject: Re: Broken Business Rules vs Broken Validation
moh_abed_2002
Send Email Send Email
 
I prefer explicitly Specifying validity context, I usually separate
IsValid from IsValidForPersistence, thus the infrastructure would
allow saving of entity by just checking IsValidForPersistence,
otherwise business validity will be done by checking IsValid.

thus i have 2 methods: GetBrokenRules(), and
GetPersistenceBrokenRules() where GetBrokenRules cares about business
validity, also we can make variation like
GetBrokenRulesForTransitionTo(State) for checking state based business
rules validity, the other method GetPersistenceBrokenRules() will
return a list of broken rules that prevents object from persistence.

--- In domaindrivendesign@yahoogroups.com, "Scott Millett" <scott@...>
wrote:
>
> Thanks for the suggestion. I have changed my model so that a Solution is
> always created for each problem, this solution has a category which is
> an enumeration and by default is set to Model.SolutionCategory.NotSet. I
> can then check for this in my broken rules to check if I can or cannot
> save the entity.
>
>
> Public Class Solution
>
>          ' Default the SolutionCategory to 'NotSet'
>          Private _SolutionCategory As SolutionCategory =
> Model.SolutionCategory.NotSet
>          Private _SolutionSteps As List(Of SolutionStep)
>
>          ' Constructor...
>          ' Other Properties/Methods...
>
>           Public Property SolutionCategory() As SolutionCategory
>                  Get
>                            Return _SolutionCategory
>                  End Get
>                  Set(ByVal value As SolutionCategory)
>                           _SolutionCategory = value
>                  End Set
>            End Property
>
>            Public Function GetBrokenRules() As List(Of BrokenRule)
>                 _BrokenRules.Clear()
>
>                 If SolutionCategory = Model.SolutionCategory.NotSet _
>

> And _SolutionSteps.Count > 0 Then
>                           ' We must have a solution category before
> adding solution steps
>                           ' as depending on the solution specified
we may
> have other specifications
>                           ' that need to be satisfied
>                          _BrokenRules.Add(New BrokenRule _
>                                             ("You must select a solution
> category if you are adding solution steps."))
>                 Else
>
>                        For Each ss As SolutionStep In _SolutionSteps
>                                ' A solution step will only check for
> broken rules if it
>                                ' is complete i.e. we can save steps that
> are in progress
>                                ' this is checked in the step entity
>                                If ss.GetBrokenRules.Count > 0 Then
>                                          For Each br As BrokenRule In
> ss.GetBrokenRules
>                                                   _BrokenRules.Add(br)
>                                           Next
>                                End If
>                        Next
>                  End If
>
>                  Return _BrokenRules
>         End Function
> End Class
>
> Public Class Problem
>
>         Private _Solution As Solution
>
>         Public Sub New()
>                  _Solution = New Solution
>         End Sub
>
>         Public ReadOnly Property Solution() As Solution
>                Get
>                         Return _Solution
>                End Get
>         End Property
>
>         ' Other Properties/Methods...
>
>         Public Function GetBrokenRules() As List(Of BrokenRule)
>             _BrokenRules.Clear()
>
>             If Solution.GetBrokenRules.Count > 0 Then
>                   ' For Each Broken Rule in the Solution add it to the
> list of broken rules
>                   For Each BRule As BrokenRule In
Solution.GetBrokenRules
>                            _BrokenRules.Add(BRule)
>                   Next
>             End If
>
>             If String.IsNullOrEmpty(Problem) Then
>                  ' No Problem, we can't let the user save
>                 _BrokenRules.Add(New BrokenRule("No Problem Defined"))
>             End If
>
>             Return _BrokenRules
>         End Function
>
> End Class
> Do you think this design has any major flaws?
>
> Thank you for bearing with me I am learning lots :0)
>
> --- In domaindrivendesign@yahoogroups.com, "matthias.kampen"
> <matthias.kampen@> wrote:
> >
> >
> >
> > --- In domaindrivendesign@yahoogroups.com, "Scott Millett" scott@
> > wrote:
> > >
> > >
> > > Ok I see what you mean about having my business rules being applied
> > > dependant on the state of the problem entity, were you thinking
> along
> > > the lines of something like this:
> > >
> >
> > I would try to get one step further: It should be impossible to reach
> > a certain state as long as there are broken rules. So you might check
> > the rules on state transition and throw an exception when a broken
> > rule appears.
> > After reaching a certain state it should either be impossible to break
> > the required rules (for this state) or the state should change as soon
> > as a borken rule appears.
> >
> > >
> > >
> > > Public Function GetBrokenRules() As List(Of BrokenRule)
> > >
> > > _BrokenRules.Clear()
> > >
> > > Select Case _ProblemState
> > > Case ProblemState.New
> > >
> > > If String.IsNullOrEmpty(Problem) Then
> > > _BrokenRules.Add(New BrokenRule("No
> > > Problem Defined"))
> > > End If
> > >
> > > Case ProblemState.SolutionSelected
> > >
> > > ' We would only check for broken rules on the
> > > parts of the solution
> > > ' that were set as complete
> > > For Each BRule As BrokenRule In
> > > Solution.GetBrokenRules
> > > _BrokenRules.Add(BRule)
> > > Next
> > >
> > > End Select
> > >
> > > Return _BrokenRules
> > > End Function
> > >
> > > Thanks for your help.
> > > Scott
> > >
> > > --- In domaindrivendesign@yahoogroups.com, "matthias.kampen"
> > > <matthias.kampen@> wrote:
> > > >
> > > > It looks like in your domain Problem-Entity is completely valid
> even
> > > > though there are broken rules (a Problem without complete Solution
> is
> > > > a valid domain object).
> > > >
> > > > I think you should try to implement your entities in a way that
> they
> > > > are always in valid state and separate validity from possible
> > > > object-states.
> > > >
> > > > On the other hand you may implement a Specification which checks
> > > > whether a Problem can be saved or not.
>

#8429 From: "Ged Byrne" <ged.byrne@...>
Date: Sun Oct 5, 2008 9:39 am
Subject: Re: Broken Business Rules vs Broken Validation
gedb01
Send Email Send Email
 
--- In domaindrivendesign@yahoogroups.com, "Scott Millett" <scott@...> wrote:
>
>
> I have a Problem entity that may have a Solution entity related to it.
> The Problem entity can be persisted before a solution is assigned to it.
> I would like to be able to save the Problem entity before the solution
> entity is complete as the solution may be completed in steps over some
> time. How do I show that the Solution is not complete (via a collection
> of broken rules) but still allow the entity to be saved? [...]

Scott,

I'm just a newbie, but might I suggest that the Route Specification and
Itinerary example
in the Ubiquitous Language section of Evan's book is an example of this
scenario.  It has
the subtitle 'Scenario 2: Domain Model Enriched to Support Discussion'

In that example there is a Route Specification and an Itinerary that must
satisfy that
specification.  When the itinerary is updated then a routing service reviews the
modified
instance against the specification and is responsible for taking any necessary
follow up
actions.

In your example you could take a similar approach and separate the rules into a
specification object with a service to manage it's relationship with the value
object.

Regards,


Ged Byrne
www.rushcoding.co.uk

#8430 From: "Kevin Lawrence" <kev.lawrence@...>
Date: Wed Oct 1, 2008 10:42 pm
Subject: Complex Domain Model on a Web Farm
kevinwilliam...
Send Email Send Email
 
[my google-fu has failed me. if the answer exists elsewhere, please
point me to it. thanks]

We our dipping our toes into the domain driven waters and have some
newbie questions.

Setting the scene - we have a farm of stateless web servers and our
domain has (will have) fairly complex aggregates that potentially take
up a fair amount of memory and are quite expensive to load from the
database.

[sanitizing the domain a little for confidentiality reasons]

A User has a Plan which has Rules and History and Periods and a whole
bunch of other things that needn't concern us right now - but there
are a lot of them.

Plan seems like a natural aggregate root and I'll assume a
PlanRepository with a findPlanFor(user) method. I get to all the other
entities via the Plan. So far so good?

Here's my question:

Most User interactions with the Plan are read-only and deal with a
tiny slice of the plan. How should I deal with this?

It's not practical to read the entire aggregate (it's too big) so I am
assuming some kind of lazy loading should happen. I am imagining
something like this

Plan.GetHistory(from, to) (or some variant of this using specifications)

but what happens next?

I'd assume the Plan has a reference back to its repository for
Lazy-Loading purposes, but then the repository has to expose a bunch
of methods for low-level queries on non-root entities.

Maybe that's OK? Would you model this differently?

And a more general question - can anyone point me to a write up (or
share experience about) a similar situation viz.
highly-scalable/web-farm using DDD?

Thanks in advance,

Kevin

#8431 From: "Ged Byrne" <ged.byrne@...>
Date: Sun Oct 5, 2008 9:25 am
Subject: Re: Cascades across aggregates
gedb01
Send Email Send Email
 
--- In domaindrivendesign@yahoogroups.com, "Paul Batum" <paul.batum@...> wrote:
>
> [...] When it comes to
> determining whether cascades occur across a particular relationship,
> do you ever have to make an independent decision, or do you just have
> a simple rule that will always tell you what to do? The rule I'm
> currently imagining is: Always and only enable cascades from each
> aggregate root through to all of its leaves. [...]

Hello,

I'm new to the group and still only quarter of a way through the book, so I can
only answer
from my own experience.  My apologies it isn't considered a useful contribution.

My rule of thumb is that cascades are related to identity.  By identify I mean
the key that is
used to access the entity.  If an entity is deleted then everything that is
identified with that
identify is also deleted.

However, I probably would want to leave cross aggregate deletions to the ORM. 
When this
happens you probably want to be able to hook events at a business level.

What I do now is use an effective dating pattern (1) to deal with
cross-aggregate
relationships, so that this scenario is a matter of superceeding the previous
instance
rather than deleting it.  This approach simplifies a lot of the concerns about
when objects
should be destroyed, but it is difficult for people to understand and make
querying the
database a nightmare.  I'm also starting to worry about the implications for
archiving data.

From what I have read so far, I would say that any situations that leads to the
need for a
cross aggregate deletion should be handled by a separate policy and that the
aggregate
boundaries should be reviewed because of the awkwardness of the design.

I present my current thinking in the hope that it may be useful and also to see
how that
thinking might change with practicing domain driven design.  I appreciate any
feed back.

Thanks,


Ged Byrne
www.rushcoding.co.uk

(1) http://martinfowler.com/ap2/effectivity.html

#8432 From: "Eric Evans" <eric@...>
Date: Sun Oct 5, 2008 12:24 pm
Subject: Re: Complex Domain Model on a Web Farm
ericevans0
Send Email Send Email
 
Remember that aggregate boundaries are a modeling choices, and they
are coevolving with the other modeling choices, such as which classes
you want and which relationships. There are many, many possible
models, and if the one you have chosen is not serving you well, start
brainstorming to find another one.

You mentoned that the Plan seems like a 'natural aggregate root' and
that you have a lot of things tied to it. That naturalness is the
place to start, but the decision is more based on the intended usage
of the model.

If most of the usage involves a 'tiny slice of the plan' then my first
thought is that Plan, in your current conception, is too monolithic.
Look for coherent concepts that could give smaller meaningful slices.
'Why are people interested in this particular slice?', I might ask.
Does that slice have some significance? Could there be a concept there
to pull out (which might be a new aggregate root, or might just be a
stepping stone in that direction)?

On the other hand, read-only use-cases are not very demanding in terms
of aggregate modeling. If your big Plan is serving you well in the
scenarios where state is changing, then it isn't so bad to just not
load (lazy load) the parts you are not going to look at in a
particular case.

Eric

--- In domaindrivendesign@yahoogroups.com, "Kevin Lawrence"
<kev.lawrence@...> wrote:
>
> [my google-fu has failed me. if the answer exists elsewhere, please
> point me to it. thanks]
>
> We our dipping our toes into the domain driven waters and have some
> newbie questions.
>
> Setting the scene - we have a farm of stateless web servers and our
> domain has (will have) fairly complex aggregates that potentially take
> up a fair amount of memory and are quite expensive to load from the
> database.
>
> [sanitizing the domain a little for confidentiality reasons]
>
> A User has a Plan which has Rules and History and Periods and a whole
> bunch of other things that needn't concern us right now - but there
> are a lot of them.
>
> Plan seems like a natural aggregate root and I'll assume a
> PlanRepository with a findPlanFor(user) method. I get to all the other
> entities via the Plan. So far so good?
>
> Here's my question:
>
> Most User interactions with the Plan are read-only and deal with a
> tiny slice of the plan. How should I deal with this?
>
> It's not practical to read the entire aggregate (it's too big) so I am
> assuming some kind of lazy loading should happen. I am imagining
> something like this
>
> Plan.GetHistory(from, to) (or some variant of this using specifications)
>
> but what happens next?
>
> I'd assume the Plan has a reference back to its repository for
> Lazy-Loading purposes, but then the repository has to expose a bunch
> of methods for low-level queries on non-root entities.
>
> Maybe that's OK? Would you model this differently?
>
> And a more general question - can anyone point me to a write up (or
> share experience about) a similar situation viz.
> highly-scalable/web-farm using DDD?
>
> Thanks in advance,
>
> Kevin
>

#8433 From: "Tomas Karlsson" <tomas.lg.karlsson@...>
Date: Sun Oct 5, 2008 1:58 pm
Subject: SV: Customizing a domain model
marcellus874
Send Email Send Email
 
Today, we are often using looser typing of the domain model. But only for the attributes that do not affect business logic. Simply a key/value construction where one is allowed to add the key "HairColor" and any value. If you want an enumeration, add an enumeration construction as well. Easy to implement both directly in SQL databases and in some generic subdomain.
 
However, for us these models work fine as long as automated processes, that is code, populates and reads the model. We often talk about a contract between the producer and consumer of the information while the persistent storage and transport layers don't have to know (and act one) the exact meaning of the information.
 
We have also found that user interfaces normally fail to be extendable in such situations. The requirements on usability are so high today som users don't accept something bad generated thing coming from these key/value and enumeration constructions in the domain model.
 
/Tomas 


Från: domaindrivendesign@yahoogroups.com [mailto:domaindrivendesign@yahoogroups.com] För Stefan Moser
Skickat: den 27 september 2008 00:12
Till: domaindrivendesign@yahoogroups.com
Ämne: Re: [domaindrivendesign] Customizing a domain model

I worked on a project with similar requirements in the past.  One question you have to ask yourself is does any *logic* change with any of these customization properties. 
 
Here is an example.  Let's say that your application manages parties (the ones with food and drinks and fun) and a major part of your domain is tracking how much fun a person is having.  So you have a Person entity.  Now one of your customers wants to customize the application to add HairColor to the Person entity.  Are they also able to change the *logic* within the Person entity so that when HairColor == HairColor.Blonde that they can also say Fun++?  Sorry, I just couldn't resist. :-)
 
But seriously, it is rarely the case that these kinds of applications allow the customization to have any effect on business logic.  If this is the case, you're basically dealing with this part of the application being simple forms over data.  One way that this can be handled is to not change the core Person in anyay, but to decorate the Person outside of the domain boundaries.
 
Depending on the complexity of your customization requirements, this could become its own pseudo bounded context.  The one I worked on actually had a fair amount of logic in how the customization was set up.
 
The project started with the "let's just extend the database tables" approach, but this caused ssssooooo many problems that I would recommend not going down that route at all.
 
I know it's vague, but hope that helps a little.
 
Stefan

On Fri, Sep 26, 2008 at 2:20 PM, Jørn Wildt <jw@fjeldgruppen.dk> wrote:
Does anyone have experience with customization of domain models (and, well, hmmm, entire applications)? I know "customization" is quite a broad term, so let me give an example: our customer wants to be able to extend the system we deliver. He wants to be able to add new customer-specific properties to some of the core entities, and he wants them to show up in the UI (but not necessarily automatically). For instance, the entity Person could be extended with a new enumerated property "HairColor" which we haven't added to the system initially. The customer does not have write access to the application code, but he may freely depend on calling it from other applications.
 
We are using C#, NHibernate and Inversion of Control to model, persist and instantiate our bussiness objects, services and repositories.
 
In a system where only DataRows and DataTables are used, we can easily add extra columns without recompiling the code: just make sure to "select * from..." and all columns in the DB will be passed automatically to the UI (please ignore the perfomance problems with this).
 
But when we have hardwired Person as a class with N properties, how should the customer then extend it? How does a domain model handle that kind of feature request?
 
One solution is to let the customer inherit from Person to CustomPerson, extend it with the custom properties, and then inject new NHibernate mapping files and use IoC in configuration files to make sure all instances of IPerson are mapped to CustomPerson. But that is quite a lot more complex than simply adding a new field to the database - and requires the customer to be quite proficient with that setup.
 
Another solution is to store custom properties in a separate CustomPerson table and then do a "select *" from that table everytime we fetch a Person. The returned columns can then be added to the object Person as a referenced DataRow.
 
Other ideas?
 
Regards, Jørn Wildt


#8434 From: "Paul Batum" <paul.batum@...>
Date: Sun Oct 5, 2008 2:43 pm
Subject: Re: Re: Cascades across aggregates
paul.batum
Send Email Send Email
 
Hi Ged,

Thanks for your input! What are your thoughts on the cascading of saves? Are they along the same lines or would you be comfortable with cross-aggregate cascades of saves? I'm assuming that the repository pattern is in use, so cascading saves across aggregate boundaries means that only one repository is required to save the changes, while if you disallow the cascading saves then you must acquire and make use of a the appropriate repository for each aggregate involved in the business transaction.

Paul Batum

On Sun, Oct 5, 2008 at 10:25 AM, Ged Byrne <ged.byrne@...> wrote:

--- In domaindrivendesign@yahoogroups.com, "Paul Batum" <paul.batum@...> wrote:
>
> [...] When it comes to

> determining whether cascades occur across a particular relationship,
> do you ever have to make an independent decision, or do you just have
> a simple rule that will always tell you what to do? The rule I'm
> currently imagining is: Always and only enable cascades from each
> aggregate root through to all of its leaves. [...]

Hello,

I'm new to the group and still only quarter of a way through the book, so I can only answer
from my own experience. My apologies it isn't considered a useful contribution.

My rule of thumb is that cascades are related to identity. By identify I mean the key that is
used to access the entity. If an entity is deleted then everything that is identified with that
identify is also deleted.

However, I probably would want to leave cross aggregate deletions to the ORM. When this
happens you probably want to be able to hook events at a business level.

What I do now is use an effective dating pattern (1) to deal with cross-aggregate
relationships, so that this scenario is a matter of superceeding the previous instance
rather than deleting it. This approach simplifies a lot of the concerns about when objects
should be destroyed, but it is difficult for people to understand and make querying the
database a nightmare. I'm also starting to worry about the implications for archiving data.

From what I have read so far, I would say that any situations that leads to the need for a
cross aggregate deletion should be handled by a separate policy and that the aggregate
boundaries should be reviewed because of the awkwardness of the design.

I present my current thinking in the hope that it may be useful and also to see how that
thinking might change with practicing domain driven design. I appreciate any feed back.

Thanks,

Ged Byrne
www.rushcoding.co.uk

(1) http://martinfowler.com/ap2/effectivity.html



#8435 From: Jørn Wildt <jw@...>
Date: Sun Oct 5, 2008 6:44 pm
Subject: Re: Customizing a domain model
jorn_lind_ni...
Send Email Send Email
 
Hi Thomas
 
> We have also found that user interfaces normally fail to
> be extendable in such situations. The requirements on 
> usability are so high today som users don't accept
> something bad generated thing coming from these
> key/value and enumeration constructions
 
Yes, it ain't really an easy requirement. Mentally I have begun to work with two different extension models, each of which is more complex than the other, but also fullfills more requirements.
 
I think we will go with the key/value approach. With this approach we actually put the extra properties inside the core domain model as simple extra attributes on entities. Just as many people here has suggested. I am pretty sure this can be implemented in a generic way, such that it will be easy to add attribution to any core entity.
 
Since we now have these in the domain model, we can also make use of that in various (developed in-house) reporting tools that can be made attribution aware, such that it will be possible to filter by the attributes and display them.
 
And, yes, that leaves the UI with a simple list of key/values (with proper input validation). But I can easily imagine a situation where our customer suddenly needs to register X (maybe only for a short period), but we don't have time in our schedule to implement it for them. Then it's good for them to know that 1) it will be possible, and 2) they can export and report based on those attributes.
 
But all that only helps with the basic customer scenario. Besides this we have a vision of making a product that others can extend and customize. This leaves us with many many more requirements besides adding extra properties: adding custom reports, adding extra sub-applications, customizing existing bussiness rules and so on.
 
In this more complex case I think it is better to allow a partner to extend our core entities with the own properties and use IoC to make sure the application works on the extended entities.
 
I am quite confident that it is possible - but time will show if it also feasible and gets adapted by others.
 
Thanks for all the interesting replies so far.
 
/Jørn 
 
 
----- Original Message -----
Sent: Sunday, October 05, 2008 3:58 PM
Subject: SV: [domaindrivendesign] Customizing a domain model

Today, we are often using looser typing of the domain model. But only for the attributes that do not affect business logic. Simply a key/value construction where one is allowed to add the key "HairColor" and any value. If you want an enumeration, add an enumeration construction as well. Easy to implement both directly in SQL databases and in some generic subdomain.
 
However, for us these models work fine as long as automated processes, that is code, populates and reads the model. We often talk about a contract between the producer and consumer of the information while the persistent storage and transport layers don't have to know (and act one) the exact meaning of the information.
 
We have also found that user interfaces normally fail to be extendable in such situations. The requirements on usability are so high today som users don't accept something bad generated thing coming from these key/value and enumeration constructions in the domain model.
 
/Tomas 


Från: domaindrivendesign@yahoogroups.com [mailto:domaindrivendesign@yahoogroups.com] För Stefan Moser
Skickat: den 27 september 2008 00:12
Till: domaindrivendesign@yahoogroups.com
Ämne: Re: [domaindrivendesign] Customizing a domain model

I worked on a project with similar requirements in the past.  One question you have to ask yourself is does any *logic* change with any of these customization properties. 
 
Here is an example.  Let's say that your application manages parties (the ones with food and drinks and fun) and a major part of your domain is tracking how much fun a person is having.  So you have a Person entity.  Now one of your customers wants to customize the application to add HairColor to the Person entity.  Are they also able to change the *logic* within the Person entity so that when HairColor == HairColor.Blonde that they can also say Fun++?  Sorry, I just couldn't resist. :-)
 
But seriously, it is rarely the case that these kinds of applications allow the customization to have any effect on business logic.  If this is the case, you're basically dealing with this part of the application being simple forms over data.  One way that this can be handled is to not change the core Person in anyay, but to decorate the Person outside of the domain boundaries.
 
Depending on the complexity of your customization requirements, this could become its own pseudo bounded context.  The one I worked on actually had a fair amount of logic in how the customization was set up.
 
The project started with the "let's just extend the database tables" approach, but this caused ssssooooo many problems that I would recommend not going down that route at all.
 
I know it's vague, but hope that helps a little.
 
Stefan

On Fri, Sep 26, 2008 at 2:20 PM, Jørn Wildt <jw@fjeldgruppen.dk> wrote:
Does anyone have experience with customization of domain models (and, well, hmmm, entire applications)? I know "customization" is quite a broad term, so let me give an example: our customer wants to be able to extend the system we deliver. He wants to be able to add new customer-specific properties to some of the core entities, and he wants them to show up in the UI (but not necessarily automatically). For instance, the entity Person could be extended with a new enumerated property "HairColor" which we haven't added to the system initially. The customer does not have write access to the application code, but he may freely depend on calling it from other applications.
 
We are using C#, NHibernate and Inversion of Control to model, persist and instantiate our bussiness objects, services and repositories.
 
In a system where only DataRows and DataTables are used, we can easily add extra columns without recompiling the code: just make sure to "select * from..." and all columns in the DB will be passed automatically to the UI (please ignore the perfomance problems with this).
 
But when we have hardwired Person as a class with N properties, how should the customer then extend it? How does a domain model handle that kind of feature request?
 
One solution is to let the customer inherit from Person to CustomPerson, extend it with the custom properties, and then inject new NHibernate mapping files and use IoC in configuration files to make sure all instances of IPerson are mapped to CustomPerson. But that is quite a lot more complex than simply adding a new field to the database - and requires the customer to be quite proficient with that setup.
 
Another solution is to store custom properties in a separate CustomPerson table and then do a "select *" from that table everytime we fetch a Person. The returned columns can then be added to the object Person as a referenced DataRow.
 
Other ideas?
 
Regards, Jørn Wildt


#8436 From: "Peter Morris" <mrpmorris@...>
Date: Sun Oct 5, 2008 7:35 pm
Subject: Re: Re: Cascades across aggregates
mrpmorris
Send Email Send Email
 
Hi Randy
 
I think my problem is that I don't have to worry about stuff like this.  In my framework I can visually specify delete rules based on UML association end types
 
Simple = unlink
Aggregate = prohibit
Composite = cascade
 
As for the point on two people editing different POLines on the same order, I am also able to define logical locking regions in my model so I could say that PurchaseOrder + its Lines property should be considered a single entity and any changes to a part constitutes a change to the whole and will therefore throw an OptimisticLockException.  In addition I these locking regions can be sub-objects, for example
 
RaisedDate
DispatchDate
DeliveredDate
 
I can define the regions like so
 
1) RaisedDate + DispatchDate
2) DispatchDate + DeliveredDate
 
If my object has constraints like so
 
RaisedDate <= DispatchDate <= DeliveredDate
 
This means that Person A may edit RaisedDate and Person B may edit DispatchDate, both may save to the DB and succeed without a lock exception.  However, if both try to edit the same property, or either try to edit DispatchDate then it would cause a lock conflict.  It's a clever mechanism that can even include other regions as subregions and also act recursively (so editing a node will also lock all child nodes).
 
In honesty though I haven't used this feature :-)  I've always been aware of it but never worked with a system that needed such a high level of control over what is updated concurrently.  The deletes are handled for me, so I don't worry about it.
 
 
 
Regards
 
 
 
 

#8437 From: "Tomas Karlsson" <tomas.lg.karlsson@...>
Date: Sun Oct 5, 2008 8:04 pm
Subject: SV: Customizing a domain model
marcellus874
Send Email Send Email
 
Hi,
 
Interesting comment on reporting! It will help me in the design of the system I am working on now. We are actually thinking of duplicate models: one DDD model for production of data and one data warehouse model (a relational database 'star') for analysts. I have found out from earlier projects that it can be conflicts if the two approaches are implemented in the same model.
 
We have recently integrated Ruby scripts in Java using the javax.scripting. (I have not written the code, but I know all business needs and details.) Maybe a pluggable Ruby script can be used for validation of the key/value attributes? You define a new attribute by defining a key, one of a set of basic data types (int, float, boolean, and the general String) and an optional Ruby script for validation. We have used Ruby as a light-weight rule engine - and it looks very promising. (By the way, are you using Java? I suppose .NET has some similar connection to scripting languages...)
 
The alternativ is, of course, to define the key as an enumeration and provide a list of valid values. No Ruby script for validation is needed in that case. (By the way, that is also true for booleans..)
 
Adding the 'valid from' and 'valid to' properties on the key definition seems to be a trivial extension.
 
More complex extensions can, of course, be implemented using interfaces with methods like onNewAttribute(value) - with one implementation class per added attribute. However, it is always difficult to have pluggable compiled code. (We have pluggable Java code where we actually upgrade plugins without stopping the JVM by adding the version to the full class name.) Pluggabe scripts are easier, but such code still makes me unhappy: It is to difficult for a customer to understand when their code is triggered and to find something meaningful to do. And I think brilliant and complex solutions should be avoided :-)
 
/Tomas


Från: domaindrivendesign@yahoogroups.com [mailto:domaindrivendesign@yahoogroups.com] För Jørn Wildt
Skickat: den 5 oktober 2008 20:45
Till: domaindrivendesign@yahoogroups.com
Ämne: Re: [domaindrivendesign] Customizing a domain model

Hi Thomas
 
> We have also found that user interfaces normally fail to
> be extendable in such situations. The requirements on 
> usability are so high today som users don't accept
> something bad generated thing coming from these
> key/value and enumeration constructions
 
Yes, it ain't really an easy requirement. Mentally I have begun to work with two different extension models, each of which is more complex than the other, but also fullfills more requirements.
 
I think we will go with the key/value approach. With this approach we actually put the extra properties inside the core domain model as simple extra attributes on entities. Just as many people here has suggested. I am pretty sure this can be implemented in a generic way, such that it will be easy to add attribution to any core entity.
 
Since we now have these in the domain model, we can also make use of that in various (developed in-house) reporting tools that can be made attribution aware, such that it will be possible to filter by the attributes and display them.
 
And, yes, that leaves the UI with a simple list of key/values (with proper input validation). But I can easily imagine a situation where our customer suddenly needs to register X (maybe only for a short period), but we don't have time in our schedule to implement it for them. Then it's good for them to know that 1) it will be possible, and 2) they can export and report based on those attributes.
 
But all that only helps with the basic customer scenario. Besides this we have a vision of making a product that others can extend and customize. This leaves us with many many more requirements besides adding extra properties: adding custom reports, adding extra sub-applications, customizing existing bussiness rules and so on.
 
In this more complex case I think it is better to allow a partner to extend our core entities with the own properties and use IoC to make sure the application works on the extended entities.
 
I am quite confident that it is possible - but time will show if it also feasible and gets adapted by others.
 
Thanks for all the interesting replies so far.
 
/Jørn 
 
 
----- Original Message -----
Sent: Sunday, October 05, 2008 3:58 PM
Subject: SV: [domaindrivendesign] Customizing a domain model

Today, we are often using looser typing of the domain model. But only for the attributes that do not affect business logic. Simply a key/value construction where one is allowed to add the key "HairColor" and any value. If you want an enumeration, add an enumeration construction as well. Easy to implement both directly in SQL databases and in some generic subdomain.
 
However, for us these models work fine as long as automated processes, that is code, populates and reads the model. We often talk about a contract between the producer and consumer of the information while the persistent storage and transport layers don't have to know (and act one) the exact meaning of the information.
 
We have also found that user interfaces normally fail to be extendable in such situations. The requirements on usability are so high today som users don't accept something bad generated thing coming from these key/value and enumeration constructions in the domain model.
 
/Tomas 


Från: domaindrivendesign@yahoogroups.com [mailto:domaindrivendesign@yahoogroups.com] För Stefan Moser
Skickat: den 27 september 2008 00:12
Till: domaindrivendesign@yahoogroups.com
Ämne: Re: [domaindrivendesign] Customizing a domain model

I worked on a project with similar requirements in the past.  One question you have to ask yourself is does any *logic* change with any of these customization properties. 
 
Here is an example.  Let's say that your application manages parties (the ones with food and drinks and fun) and a major part of your domain is tracking how much fun a person is having.  So you have a Person entity.  Now one of your customers wants to customize the application to add HairColor to the Person entity.  Are they also able to change the *logic* within the Person entity so that when HairColor == HairColor.Blonde that they can also say Fun++?  Sorry, I just couldn't resist. :-)
 
But seriously, it is rarely the case that these kinds of applications allow the customization to have any effect on business logic.  If this is the case, you're basically dealing with this part of the application being simple forms over data.  One way that this can be handled is to not change the core Person in anyay, but to decorate the Person outside of the domain boundaries.
 
Depending on the complexity of your customization requirements, this could become its own pseudo bounded context.  The one I worked on actually had a fair amount of logic in how the customization was set up.
 
The project started with the "let's just extend the database tables" approach, but this caused ssssooooo many problems that I would recommend not going down that route at all.
 
I know it's vague, but hope that helps a little.
 
Stefan

On Fri, Sep 26, 2008 at 2:20 PM, Jørn Wildt <jw@fjeldgruppen.dk> wrote:
Does anyone have experience with customization of domain models (and, well, hmmm, entire applications)? I know "customization" is quite a broad term, so let me give an example: our customer wants to be able to extend the system we deliver. He wants to be able to add new customer-specific properties to some of the core entities, and he wants them to show up in the UI (but not necessarily automatically). For instance, the entity Person could be extended with a new enumerated property "HairColor" which we haven't added to the system initially. The customer does not have write access to the application code, but he may freely depend on calling it from other applications.
 
We are using C#, NHibernate and Inversion of Control to model, persist and instantiate our bussiness objects, services and repositories.
 
In a system where only DataRows and DataTables are used, we can easily add extra columns without recompiling the code: just make sure to "select * from..." and all columns in the DB will be passed automatically to the UI (please ignore the perfomance problems with this).
 
But when we have hardwired Person as a class with N properties, how should the customer then extend it? How does a domain model handle that kind of feature request?
 
One solution is to let the customer inherit from Person to CustomPerson, extend it with the custom properties, and then inject new NHibernate mapping files and use IoC in configuration files to make sure all instances of IPerson are mapped to CustomPerson. But that is quite a lot more complex than simply adding a new field to the database - and requires the customer to be quite proficient with that setup.
 
Another solution is to store custom properties in a separate CustomPerson table and then do a "select *" from that table everytime we fetch a Person. The returned columns can then be added to the object Person as a referenced DataRow.
 
Other ideas?
 
Regards, Jørn Wildt


#8438 From: Jørn Wildt <jw@...>
Date: Sun Oct 5, 2008 8:22 pm
Subject: Re: Customizing a domain model
jorn_lind_ni...
Send Email Send Email
 
> More complex extensions can, of course, be implemented using interfaces
 
Thanks for reminding me about this. I would probably have implented a bunch of switch statements somewhere to check for all the basic types (int, date etc.). Having attribution types as real classes makes just about everything easier to manage.
 
We are using .NET, so I don't know about all the Java/Ruby details. It was not my intention to let the customer extend the system with new attribute types, so in my case using an external scripting engine would be overkill.
 
I am although not sure that was what you referred to - it seems like you wanted to add business rules on events like "new attribute". Interesting thought, but I also like the other part: that the customer wouldn't know what to do with that event. I think extension points like that should be added more "on demand" when we know where extensions are needed.
 
/Jørn
 
----- Original Message -----
Sent: Sunday, October 05, 2008 10:04 PM
Subject: SV: [domaindrivendesign] Customizing a domain model

Hi,
 
Interesting comment on reporting! It will help me in the design of the system I am working on now. We are actually thinking of duplicate models: one DDD model for production of data and one data warehouse model (a relational database 'star') for analysts. I have found out from earlier projects that it can be conflicts if the two approaches are implemented in the same model.
 
We have recently integrated Ruby scripts in Java using the javax.scripting. (I have not written the code, but I know all business needs and details.) Maybe a pluggable Ruby script can be used for validation of the key/value attributes? You define a new attribute by defining a key, one of a set of basic data types (int, float, boolean, and the general String) and an optional Ruby script for validation. We have used Ruby as a light-weight rule engine - and it looks very promising. (By the way, are you using Java? I suppose .NET has some similar connection to scripting languages...)
 
The alternativ is, of course, to define the key as an enumeration and provide a list of valid values. No Ruby script for validation is needed in that case. (By the way, that is also true for booleans..)
 
Adding the 'valid from' and 'valid to' properties on the key definition seems to be a trivial extension.
 
More complex extensions can, of course, be implemented using interfaces with methods like onNewAttribute(value) - with one implementation class per added attribute. However, it is always difficult to have pluggable compiled code. (We have pluggable Java code where we actually upgrade plugins without stopping the JVM by adding the version to the full class name.) Pluggabe scripts are easier, but such code still makes me unhappy: It is to difficult for a customer to understand when their code is triggered and to find something meaningful to do. And I think brilliant and complex solutions should be avoided :-)
 
/Tomas


Från: domaindrivendesign@yahoogroups.com [mailto:domaindrivendesign@yahoogroups.com] För Jørn Wildt
Skickat: den 5 oktober 2008 20:45
Till: domaindrivendesign@yahoogroups.com
Ämne: Re: [domaindrivendesign] Customizing a domain model

Hi Thomas
 
> We have also found that user interfaces normally fail to
> be extendable in such situations. The requirements on 
> usability are so high today som users don't accept
> something bad generated thing coming from these
> key/value and enumeration constructions
 
Yes, it ain't really an easy requirement. Mentally I have begun to work with two different extension models, each of which is more complex than the other, but also fullfills more requirements.
 
I think we will go with the key/value approach. With this approach we actually put the extra properties inside the core domain model as simple extra attributes on entities. Just as many people here has suggested. I am pretty sure this can be implemented in a generic way, such that it will be easy to add attribution to any core entity.
 
Since we now have these in the domain model, we can also make use of that in various (developed in-house) reporting tools that can be made attribution aware, such that it will be possible to filter by the attributes and display them.
 
And, yes, that leaves the UI with a simple list of key/values (with proper input validation). But I can easily imagine a situation where our customer suddenly needs to register X (maybe only for a short period), but we don't have time in our schedule to implement it for them. Then it's good for them to know that 1) it will be possible, and 2) they can export and report based on those attributes.
 
But all that only helps with the basic customer scenario. Besides this we have a vision of making a product that others can extend and customize. This leaves us with many many more requirements besides adding extra properties: adding custom reports, adding extra sub-applications, customizing existing bussiness rules and so on.
 
In this more complex case I think it is better to allow a partner to extend our core entities with the own properties and use IoC to make sure the application works on the extended entities.
 
I am quite confident that it is possible - but time will show if it also feasible and gets adapted by others.
 
Thanks for all the interesting replies so far.
 
/Jørn 
 
 
----- Original Message -----
Sent: Sunday, October 05, 2008 3:58 PM
Subject: SV: [domaindrivendesign] Customizing a domain model

Today, we are often using looser typing of the domain model. But only for the attributes that do not affect business logic. Simply a key/value construction where one is allowed to add the key "HairColor" and any value. If you want an enumeration, add an enumeration construction as well. Easy to implement both directly in SQL databases and in some generic subdomain.
 
However, for us these models work fine as long as automated processes, that is code, populates and reads the model. We often talk about a contract between the producer and consumer of the information while the persistent storage and transport layers don't have to know (and act one) the exact meaning of the information.
 
We have also found that user interfaces normally fail to be extendable in such situations. The requirements on usability are so high today som users don't accept something bad generated thing coming from these key/value and enumeration constructions in the domain model.
 
/Tomas 


Från: domaindrivendesign@yahoogroups.com [mailto:domaindrivendesign@yahoogroups.com] För Stefan Moser
Skickat: den 27 september 2008 00:12
Till: domaindrivendesign@yahoogroups.com
Ämne: Re: [domaindrivendesign] Customizing a domain model

I worked on a project with similar requirements in the past.  One question you have to ask yourself is does any *logic* change with any of these customization properties. 
 
Here is an example.  Let's say that your application manages parties (the ones with food and drinks and fun) and a major part of your domain is tracking how much fun a person is having.  So you have a Person entity.  Now one of your customers wants to customize the application to add HairColor to the Person entity.  Are they also able to change the *logic* within the Person entity so that when HairColor == HairColor.Blonde that they can also say Fun++?  Sorry, I just couldn't resist. :-)
 
But seriously, it is rarely the case that these kinds of applications allow the customization to have any effect on business logic.  If this is the case, you're basically dealing with this part of the application being simple forms over data.  One way that this can be handled is to not change the core Person in anyay, but to decorate the Person outside of the domain boundaries.
 
Depending on the complexity of your customization requirements, this could become its own pseudo bounded context.  The one I worked on actually had a fair amount of logic in how the customization was set up.
 
The project started with the "let's just extend the database tables" approach, but this caused ssssooooo many problems that I would recommend not going down that route at all.
 
I know it's vague, but hope that helps a little.
 
Stefan

On Fri, Sep 26, 2008 at 2:20 PM, Jørn Wildt <jw@fjeldgruppen.dk> wrote:
Does anyone have experience with customization of domain models (and, well, hmmm, entire applications)? I know "customization" is quite a broad term, so let me give an example: our customer wants to be able to extend the system we deliver. He wants to be able to add new customer-specific properties to some of the core entities, and he wants them to show up in the UI (but not necessarily automatically). For instance, the entity Person could be extended with a new enumerated property "HairColor" which we haven't added to the system initially. The customer does not have write access to the application code, but he may freely depend on calling it from other applications.
 
We are using C#, NHibernate and Inversion of Control to model, persist and instantiate our bussiness objects, services and repositories.
 
In a system where only DataRows and DataTables are used, we can easily add extra columns without recompiling the code: just make sure to "select * from..." and all columns in the DB will be passed automatically to the UI (please ignore the perfomance problems with this).
 
But when we have hardwired Person as a class with N properties, how should the customer then extend it? How does a domain model handle that kind of feature request?
 
One solution is to let the customer inherit from Person to CustomPerson, extend it with the custom properties, and then inject new NHibernate mapping files and use IoC in configuration files to make sure all instances of IPerson are mapped to CustomPerson. But that is quite a lot more complex than simply adding a new field to the database - and requires the customer to be quite proficient with that setup.
 
Another solution is to store custom properties in a separate CustomPerson table and then do a "select *" from that table everytime we fetch a Person. The returned columns can then be added to the object Person as a referenced DataRow.
 
Other ideas?
 
Regards, Jørn Wildt


#8439 From: "moffdub" <moffdub@...>
Date: Mon Oct 6, 2008 12:06 pm
Subject: Re: DDD and The Spreadsheet Conundrum
moffdub
Send Email Send Email
 
It's funny how the more I obsess over this topic and search the web
for opinions, the more my own thoughts have already
been...er..thought.

Check out this:

http://www.c2.com/cgi/wiki?DoubleDispatchExample

Which is saying essentially the same thing as Sequence.dialOn
(Dialable) and Dialable.dial(Sequence), except no stack overflow
danger. You'd have Dialable.dial(Sequence) do the actual dialing.

--- In domaindrivendesign@yahoogroups.com, "Zach Dennis"
<zach.dennis@...> wrote:
>
> > What do you think keeping your options open by using both (aside
from
> > the clear potential infinite loop)?
>
> > DialableDevice.dial(Sequence) and Sequence.dialOn(DialableDevice)
>
> If you go this route, so much for SRP.
>
>
> --
> Zach Dennis
> http://www.continuousthinking.com
> http://www.mutuallyhuman.com
>

Messages 8410 - 8439 of 24071   Oldest  |  < Older  |  Newer >  |  Newest
Add to My Yahoo!      XML What's This?

Copyright © 2010 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Guidelines NEW - Help