In the first place, I'm neither complaining or criticizing :)
I'm a Castle ActiveRecord user and I really like it, and so does a big community. I've seem Fluent NHibernate, a friend told he is using it and liking it very much, as so does lots of other people. But I can't get out of my head one of Ayende's comments about it, and after reading quite a few discussions about it, I gathered some general complaints:
1 - "I don't like the relation attributes poluting my model" - Ok, I don't think they are pretty also, but I do think that there's a good reason to put them on the model: their relationship is meaningfull to the domain. If I look, for example, at a ShoppingCartItem object I want to know who's his father, if he has dependencies, etc, and how they are supossed to work (one to many, many to many, etc). I don't want to know the details of the implementation, but I do want to know the logical relationships.
2 - "You have to inherit the objects from ActiveRecordBase" - not true. Even though this is an option, maybe the quick option, you can use a Repository Pattern without effort, eliminating the reason for this complaint.
I saw the discussion over validation methods and in the end will need to "polute" the model with NHibernate.Validator attributes to accomplish part of that. Then, why not use Castle's validators, which can be used to validate other things other than NHibernate stuff?
I'm studding which changes would be necessary to re-implement the sample application to use ActiveRecord, so I can show something a little more substantial.
I'm digging #Arch, but there are some points in which I have some doubts and maybe some discussion can help. I'm sure you all, specially Billy, have spent a lot of time thinking about the pros and cons of each choice, and I'd like to understand them better.
Thanks for the questions as they provide some good points of
clarification.
I've used Castle ActiveRecord as well and had great experiences with
it on a couple of smaller ecommerce sites. Personal experience over a
number of projects has led me down the path towards domain driven
rather than a model driven design. I feel that ActiveRecord, like the
ADO.NET Entity Framework is more reflective of the latter - being
model driven - and not something I tend to use on a large project.
This is simply my personal preference and not a reflection of the
quality of these alternatives for the problems that they are trying to
solve.
With respect to attributes polluting the model, there aren't any
association attributes used within #Arch; assuming
NHibernate.Mapping.Attributes is what your alluding to. The Fluent
NHibernate mapping classes are stored within the MyProject.Data
assembly; so the domain layer is completely ignorant of their
existence - pollutant free if you will. Let me know if I've
misinterpreted your first comment.
Concerning the inheritance of a base object, there's no need to
inherit from a base object in #Arch, such as DomainObject or
PersistentObject. These base classes are simply helpers for providing
a consistent means of storing the ID of objects and comparing them to
others. The data access code, such as the
SharpArch.Data.NHibernate.Repository base repository class doesn't
care what the persisted object is (or inherits from) as long as it has
a mapping file associated with it, be it HBMs, mapping attributes, or
class maps.
As you noted, Castle's validators are also a great validation
mechanism. Although #Arch includes support for NHibernate.Validator
out of the box, there's nothing to preclude you from using an
alternative validation utility. Although NHibernate.Validator forces
the addition of a reference to it, it doesn't oblige a reference to
NHibernate as well; so it should really be seen as a quality
validation framework which just happens to work very nicely with
NHibernate - NHibernate.Validator may be leveraged without the use of
NHibernate. When it came down to it, I wanted to have a preferred
validation framework (it looks like "opinionated" is the new buzzword
in the blogsphere ;) while having seemless integration with
NHibernate. NHibernate.Validator fit the bill nicely.
Finally, I don't think that ActiveRecord would be a good choice for
#Arch; IMO, it defeats the purpose of the current architecture which
provides - indeed forces - a clean separation between business logic
and data access concerns while emphasizing domain driven design. As I
mentioned, ActiveRecord is a terrific framework for model driven
development, but not in alignment with the fundamental motivations of
#Arch. With that said, a specialized base foundation, inspired by
#Arch but leveraging ActiveRecord, might make a great codeproject.com
article or even a new OSS project, as a couple others have done.
Billy
On Nov 18, 4:37 pm, "Rafael Rosa" <rafaelros...@gmail.com> wrote:
> In the first place, I'm neither complaining or criticizing :)
> I'm a Castle ActiveRecord user and I really like it, and so does a big
> community. I've seem Fluent NHibernate, a friend told he is using it and
> liking it very much, as so does lots of other people. But I can't get out of
> my head one of Ayende's comments about it, and after reading quite a few
> discussions about it, I gathered some general complaints:
> 1 - "I don't like the relation attributes poluting my model" - Ok, I don't
> think they are pretty also, but I do think that there's a good reason to put
> them on the model: their relationship is meaningfull to the domain. If I
> look, for example, at a ShoppingCartItem object I want to know who's his
> father, if he has dependencies, etc, and how they are supossed to work (one
> to many, many to many, etc). I don't want to know the details of the
> implementation, but I do want to know the logical relationships.
> 2 - "You have to inherit the objects from ActiveRecordBase" - not true. Even
> though this is an option, maybe the quick option, you can use a Repository
> Pattern without effort, eliminating the reason for this complaint.
> I saw the discussion over validation methods and in the end will need to
> "polute" the model with NHibernate.Validator attributes to accomplish part
> of that. Then, why not use Castle's validators, which can be used to
> validate other things other than NHibernate stuff?
> I'm studding which changes would be necessary to re-implement the sample
> application to use ActiveRecord, so I can show something a little more
> substantial.
> I'm digging #Arch, but there are some points in which I have some doubts and
> maybe some discussion can help. I'm sure you all, specially Billy, have
> spent a lot of time thinking about the pros and cons of each choice, and I'd
> like to understand them better.
I'm using ActiveRecord in it's basic form in my current project, but I was convinced by some friends' experience that the Repository Pattern is very useful, and I decided to try it. The main question is why use Fluent NHibernate to make the mappings if this forces us to create a second class to do just that? The key about Ayende's comment is "if I need to touch 2 places, something is wrong". I'm not suggesting to use the basic implementation of ActiveRecord, but use it to define the models and let it do all the mapping stuff, instead of create another class.
For example, this is the current Category implementation:
public class Category : PersistentObject { public Category() { } public Category(string name) { Name = name; }
[DomainSignature] [NotNullNotEmpty] public virtual string Name { get; protected set; } }
And this is the mapping class:
public class CategoryMap : ClassMap<Category>, IMapGenerator { public CategoryMap() { WithTable("Categories");
Using ActiveRecord for mapping would be something like this:
[ActiveRecord] public class Category : PersistentObject { public Category() { } public Category(string name) { Name = name; }
[PrimaryKey] public virtual int ID; [DomainSignature] [Property, ValidateNonEmpty] public virtual string Name { get; protected set; }
[HasMany(typeof(SubInformation))] public virtual IList<SubInformation> {get; set;} }
That's it, no mapping class, and I even added a sub property just to show a has many relationship. We could change the PersistentObject class so it automaticaly adds the ID property as the primary key, eliminating the need to declare it here. The best part is that you have just on place to look, one class to worry about, and the object under it is still POCO, as much as before anyway.
The repositories are keept almost the same, but just add an implementation of ActiveRecordRepository, which in fact will call ActiveRecordMediator and we won't need to make any effort to talk to NHibernate. If we want to validate the model, just add the necessary attributes, which is already done today, and bingo. The project modules (Core, Data, Controllers, Web and Tests) remains the same, the details os quering repositories and stuff kept inside Data, with the repositories implementation.
I don't think that this approch break DDD, it just eliminates the need to have an extra class to worry about. Everything else still works: schema generation, custom NHibernate configuration, etc, plus it adds the expertise and seasoning of Castle project. There are a lot of interesting tools in RhinoCommons too, but it lacks good documentation (at least for newcomers) or good examples.
As I said, this is just an idea, another way to make some things. As I said before, I'll re-implement the Northwind project with these tools so I can show what I mean. At least, will know how dificult is to change some of the tools in place today, and might generate some ideas of how this can be made easier.
I've only looked at active record and, as Billy said, it's a good framework, but not one I'd use in a DDD project for sure.
regarding the "if I need to touch 2 places, something is wrong", I still can't believe Ayende said that, especially because I know he uses R#. I've been using fluent nhibernate for some time and even though it has one or two bugs, I can't really count the number of ways it has helped me maintain the mapping consistency between my classes and my tables. The biggest problem most people face with the traditional mapping xml files is that refactoring isn't supported there (ok, there was a r# plugin that was supposed to do that, but I think it never worked out very well). With fluent nhibernate, for instance, I can only do a simple renaming on a property and know that it will be propagated onto the mappings. And as Billy said, you can put the mappings on your repository assembly and you'll still have POCO. That won't happen with attributes...
One more thing regarding validation: even though I still haven't looked at nhibernator validator, I'm positive that validation is really a concrete domain aspect and I'm a believer that it should be put inside the domain base assembly. What I'm saying is that it is possible to add some basic core interfaces and base classes for validation and they should be inside the core assembly and know nothing about any data access details (ok, I haven't looked at the last bits, so I don't know how validation was added to it. what I', proposing is adding some sort of methods that would do 2 things: give broken validation rules and give the broken rules when an object would be transitioning from the current state to an hipotetical future state)...
I'm not sure if this was the right time to start working with Fluent
NHibernate library, as it lacks documentation.
I had to restructure my code, and until now I couldn't pass all the
tests.
Its pretty hard to put things to work when it kept throwing exceptions
that you know why but cant find out a
way to solve it.
One of the problems I'm facing and cant find a solution is on enum
mapping.
Maybe I can get an answer from you guys. Here's what I have:
public class Person : PersistentObject
{
//other properties and constructor
public virtual ISet<Contact> Contacts { get; protected set; }
}
public class Contact : PersistentObject
{
[DomainSignature]
public virtual ContactType Type { get; set; }
[DomainSignature]
public virtual string Description { get; set; }
> -----Original Message-----
> From: sharp-architecture@googlegroups.com [mailto:sharp-
> architecture@googlegroups.com] On Behalf Of Neo
> Sent: Thursday, November 20, 2008 4:12 PM
> To: S#arp Architecture
> Subject: Re: Why Fluent NHibernate?
> I'm not sure if this was the right time to start working with Fluent
> NHibernate library, as it lacks documentation.
> I had to restructure my code, and until now I couldn't pass all the
> tests.
> Its pretty hard to put things to work when it kept throwing exceptions
> that you know why but cant find out a
> way to solve it.
> One of the problems I'm facing and cant find a solution is on enum
> mapping.
> Maybe I can get an answer from you guys. Here's what I have:
> public class Person : PersistentObject
> {
> //other properties and constructor
> I'm using something very similar for mapping enums...the only difference I
> see is that I'm not using the CanNotBeNull method call...
> Any more info on the stack from the exception?
> --
> Luis Abreu
> > -----Original Message-----
> > From: sharp-architecture@googlegroups.com [mailto:sharp-
> > architecture@googlegroups.com] On Behalf Of Neo
> > Sent: Thursday, November 20, 2008 4:12 PM
> > To: S#arp Architecture
> > Subject: Re: Why Fluent NHibernate?
> > I'm not sure if this was the right time to start working with Fluent
> > NHibernate library, as it lacks documentation.
> > I had to restructure my code, and until now I couldn't pass all the
> > tests.
> > Its pretty hard to put things to work when it kept throwing exceptions
> > that you know why but cant find out a
> > way to solve it.
> > One of the problems I'm facing and cant find a solution is on enum
> > mapping.
> > Maybe I can get an answer from you guys. Here's what I have:
> > public class Person : PersistentObject
> > {
> > //other properties and constructor
I've also noticed that you're using the setattribute call for specifying a
short...does it work with an integer (ie, if you remove that attribute, does
it work)?
> On Nov 20, 3:59 pm, "Luis Abreu" <lab...@gmail.com> wrote:
> > I'm using something very similar for mapping enums...the only
> difference I
> > see is that I'm not using the CanNotBeNull method call...
> > Any more info on the stack from the exception?
> > > I'm not sure if this was the right time to start working with
> Fluent
> > > NHibernate library, as it lacks documentation.
> > > I had to restructure my code, and until now I couldn't pass all the
> > > tests.
> > > Its pretty hard to put things to work when it kept throwing
> exceptions
> > > that you know why but cant find out a
> > > way to solve it.
> > > One of the problems I'm facing and cant find a solution is on enum
> > > mapping.
> > > Maybe I can get an answer from you guys. Here's what I have:
> > > public class Person : PersistentObject
> > > {
> > > //other properties and constructor
That's really weird...I've reviewed na old post I've written on it and it
seems like the only place where I had to perform a cast was on the
discriminate subclass thingy (I had an int column on db and while trying to
pass the enum directly, it kept trying to save a string, which wasn't what I
wanted). On the other places where I had enums, I didn0t had any problems
with it. Btw, the post I mention is here:
> On Nov 20, 3:59 pm, "Luis Abreu" <lab...@gmail.com> wrote:
> > I'm using something very similar for mapping enums...the only
> difference I
> > see is that I'm not using the CanNotBeNull method call...
> > Any more info on the stack from the exception?
> > > I'm not sure if this was the right time to start working with
> Fluent
> > > NHibernate library, as it lacks documentation.
> > > I had to restructure my code, and until now I couldn't pass all the
> > > tests.
> > > Its pretty hard to put things to work when it kept throwing
> exceptions
> > > that you know why but cant find out a
> > > way to solve it.
> > > One of the problems I'm facing and cant find a solution is on enum
> > > mapping.
> > > Maybe I can get an answer from you guys. Here's what I have:
> > > public class Person : PersistentObject
> > > {
> > > //other properties and constructor
> That's really weird...I've reviewed na old post I've written on it and it
> seems like the only place where I had to perform a cast was on the
> discriminate subclass thingy (I had an int column on db and while trying to
> pass the enum directly, it kept trying to save a string, which wasn't what I
> wanted). On the other places where I had enums, I didn0t had any problems
> with it. Btw, the post I mention is here:
> > On Nov 20, 3:59 pm, "Luis Abreu" <lab...@gmail.com> wrote:
> > > I'm using something very similar for mapping enums...the only
> > difference I
> > > see is that I'm not using the CanNotBeNull method call...
> > > Any more info on the stack from the exception?
> > > > I'm not sure if this was the right time to start working with
> > Fluent
> > > > NHibernate library, as it lacks documentation.
> > > > I had to restructure my code, and until now I couldn't pass all the
> > > > tests.
> > > > Its pretty hard to put things to work when it kept throwing
> > exceptions
> > > > that you know why but cant find out a
> > > > way to solve it.
> > > > One of the problems I'm facing and cant find a solution is on enum
> > > > mapping.
> > > > Maybe I can get an answer from you guys. Here's what I have:
> > > > public class Person : PersistentObject
> > > > {
> > > > //other properties and constructor
No way man.
I can only say it's a Fluent NHibernate bug.
This SHOULD work:
HasMany<Contact>(person => person.Contacts)
.WithTableName("Contact")
.WithKeyColumn("Per_Id")
.Component(ct =>
{
ct.Map(c => c.Type, "ContactType").
.CanNotBeNull().SetAttribute("type", "short");
ct.Map(c => c.Description, "Description")
.CanNotBeNull();
}).AsSet();
Because I have the same map as XML and worked sweetly:
<set name="Contacts" table="Contact" lazy="true">
<key column="Per_ID" />
<composite-element class="Contact">
<property name="Type" column="ContactType" not-null="true"
type="short"></property>
<property name="Description" not-null="true"></property>
</composite-element>
</set>
> Now I got an Sql Error exception.
> Looking at the query generated, it has an invalid character
> Person person0_
> inner join [Contact] contacts1_ on
> person0_.Id=contacts1_.Per_Id
> [Contact] <- this is the problem, it should be Contact, not [Contact]
> Why NHibernate is enclosing the Contact???
> Problem after problem... I'm getting out of patience, lol.
> Neo
> On Nov 20, 5:31 pm, "Luis Abreu" <lab...@gmail.com> wrote:
> > That's really weird...I've reviewed na old post I've written on it and it
> > seems like the only place where I had to perform a cast was on the
> > discriminate subclass thingy (I had an int column on db and while trying
> to
> > pass the enum directly, it kept trying to save a string, which wasn't
> what I
> > wanted). On the other places where I had enums, I didn0t had any problems
> > with it. Btw, the post I mention is here:
> > > On Nov 20, 3:59 pm, "Luis Abreu" <lab...@gmail.com> wrote:
> > > > I'm using something very similar for mapping enums...the only
> > > difference I
> > > > see is that I'm not using the CanNotBeNull method call...
> > > > Any more info on the stack from the exception?
> > > > > I'm not sure if this was the right time to start working with
> > > Fluent
> > > > > NHibernate library, as it lacks documentation.
> > > > > I had to restructure my code, and until now I couldn't pass all the
> > > > > tests.
> > > > > Its pretty hard to put things to work when it kept throwing
> > > exceptions
> > > > > that you know why but cant find out a
> > > > > way to solve it.
> > > > > One of the problems I'm facing and cant find a solution is on enum
> > > > > mapping.
> > > > > Maybe I can get an answer from you guys. Here's what I have:
> > > > > public class Person : PersistentObject
> > > > > {
> > > > > //other properties and constructor
> > > > > The only thing I see its not exactly like the Fluent way is that
> > > > > 'type' attribute on Type property.
> > > > > I've tried this also:
> Person person0_ > inner join [Contact] contacts1_ on > person0_.Id=contacts1_.Per_Id
> [Contact] <- this is the problem, it should be Contact, not [Contact]
> Why NHibernate is enclosing the Contact???
i think that won't be problematic...what nh is doing is escaping the name to make sure that it's not using any sql reserved term (putting [] will "escape" the word you're using).
I've noticed that I've performed some changes on the mappings and I've ended up using integers. Here's my code:
On Fri, Nov 21, 2008 at 10:38 AM, Luis Abreu <lab...@gmail.com> wrote:
> > Person person0_
> > inner join [Contact] contacts1_ on
> > person0_.Id=contacts1_.Per_Id
> > [Contact] <- this is the problem, it should be Contact, not [Contact]
> > Why NHibernate is enclosing the Contact???
> i think that won't be problematic...what nh is doing is escaping the
> name to make sure that it's not using any sql reserved term (putting
> [] will "escape" the word you're using).
> I've noticed that I've performed some changes on the mappings and I've
> ended up using integers. Here's my code:
> > Person person0_
> > inner join [Contact] contacts1_ on
> > person0_.Id=contacts1_.Per_Id
> > [Contact] <- this is the problem, it should be Contact, not [Contact]
> > Why NHibernate is enclosing the Contact???
> i think that won't be problematic...what nh is doing is escaping the
> name to make sure that it's not using any sql reserved term (putting
> [] will "escape" the word you're using).
> I've noticed that I've performed some changes on the mappings and I've
> ended up using integers. Here's my code:
> Great call Luis! Neo, does this resolve your issue as well?
> Billy
> On Nov 21, 5:38 am, "Luis Abreu" <lab...@gmail.com> wrote:
> > > Person person0_
> > > inner join [Contact] contacts1_ on
> > > person0_.Id=contacts1_.Per_Id
> > > [Contact] <- this is the problem, it should be Contact, not [Contact]
> > > Why NHibernate is enclosing the Contact???
> > i think that won't be problematic...what nh is doing is escaping the
> > name to make sure that it's not using any sql reserved term (putting
> > [] will "escape" the word you're using).
> > I've noticed that I've performed some changes on the mappings and I've
> > ended up using integers. Here's my code:
Although documentation still needs to be fleshed out more for the
Fluent NHibernate project, there were some great resources sent out on
the NHibernate developer mailing list which might assist:
> On Nov 21, 1:05 pm, Billy <googlegro...@emccafferty.com> wrote:
> > Great call Luis! Neo, does this resolve your issue as well?
> > Billy
> > On Nov 21, 5:38 am, "Luis Abreu" <lab...@gmail.com> wrote:
> > > > Person person0_
> > > > inner join [Contact] contacts1_ on
> > > > person0_.Id=contacts1_.Per_Id
> > > > [Contact] <- this is the problem, it should be Contact, not [Contact]
> > > > Why NHibernate is enclosing the Contact???
> > > i think that won't be problematic...what nh is doing is escaping the
> > > name to make sure that it's not using any sql reserved term (putting
> > > [] will "escape" the word you're using).
> > > I've noticed that I've performed some changes on the mappings and I've
> > > ended up using integers. Here's my code:
Thanks for the links, they are really nice, full of good information.
I do understand the advantages of Fluent NHibernate, but I still don't
think it's better than Castle ActiveRecord. Being able to look at the
domain objects and see how they are connected and how they are
validated in just one place is something that improves code
readability and is more intention revealing, and I'd rather have
attributes attached to them than having a separated code file for the
mapping, even though this is much better than XML.
I'll work on an alternate Northwind implementation so I can show what
I mean, but I've being quite busy these last few weeks.
> -----Original Message-----
> From: sharp-architecture@googlegroups.com [mailto:sharp-
> architecture@googlegroups.com] On Behalf Of Rafael
> Sent: Thursday, November 27, 2008 7:39 PM
> To: S#arp Architecture
> Subject: Re: Why Fluent NHibernate?
> Billy,
> Thanks for the links, they are really nice, full of good information.
> I do understand the advantages of Fluent NHibernate, but I still don't
> think it's better than Castle ActiveRecord. Being able to look at the
> domain objects and see how they are connected and how they are
> validated in just one place is something that improves code
> readability and is more intention revealing, and I'd rather have
> attributes attached to them than having a separated code file for the
> mapping, even though this is much better than XML.
> I'll work on an alternate Northwind implementation so I can show what
> I mean, but I've being quite busy these last few weeks.
> Cheers,
> Rafael.
> No virus found in this incoming message.
> Checked by AVG - http://www.avg.com > Version: 8.0.176 / Virus Database: 270.9.10/1813 - Release Date: 27-11-
> 2008 09:02
The answer is Yes and No :) The standard use of Castle ActiveRecord
does implement the Active Record pattern, it was inspired by Ruby on
Rails as well. But, if you want, you can also use it with the
Repository pattern and use it's attributes to do the object's mapping
and access then using a custom repository or some other built in
features. Take a look at my second post so you can see how you can
declare an object in this way, and the following links to see a little
bit more of code:
I'm not saying that Fluent NHibernate is a bad choice, but I'd rather
have more information about the object's relationships on my domain
model and skip the need for a mapping class. These informations
doesn't necessarily refer to the implementation, like table names and
the like, you can treat this somewhere else when you need it. However,
when dealing with legacy databases Fluent NHibernate have some
advantages, but I think that Castle's ActiveRecord is better for
greenfield projects or when your database is designed with an ORM in
mind, so these two can get along smoothly.
> The answer is Yes and No :) The standard use of Castle ActiveRecord > does implement the Active Record pattern, it was inspired by Ruby on > Rails as well. But, if you want, you can also use it with the > Repository pattern and use it's attributes to do the object's mapping > and access then using a custom repository or some other built in > features. Take a look at my second post so you can see how you can > declare an object in this way, and the following links to see a little > bit more of code:
Yes, I'm not discussing which way is better. Personally, I prefer to have POCO, but that's my opinion only. There's probably nothing wrong with tying the properties/fields to table fields through attributes. As I've said, I do prefer POCOs and in this case, I do see some advantages on using fluent NH. However, if you don't want to go with POCOs, then there really isn't much I have to say about the way you set up the relationships...
What I'm saying is that it's not DDD. If you really look at a well modeled DDD app, you'll notice that you tend to have lots of methods used for interacting with objects (and that's natural because methods tend to be more "descriptive" than properties and one of the main objectives of DDD is having a model which is easily understood by everyone that knows the ubiquitous language of that domain). Ok, so do I use properties/fields? Yes, I do that and NH is configured for loading them from the database, but the difference is that on my domain, most interactions are not done through properties, but through method calls.
I really can't see why using this approach for mapping is no DDD, and
I why decorating objects with attributes makes them less POCO. The
approach I'm talking about doesn't need to use a complex base class,
so you won't be hiding a lot of stuff under the hood. The attributes
won't change the object's behavior, will be meaningful just when you
use the ActiveRecord engine to do the dirty work, just like Fluent
NHibernate when it's using the mapping class. You can put as many
methods as you want, to do whatever you need, there's no difference
there, the only change is how the objects will be mapped.
I also think that POCO is good and I cannot see how this breaks the
rules.
> I really can't see why using this approach for mapping is no DDD, and > I why decorating objects with attributes makes them less POCO. The
No, no, no, that's not what I'm saying:) (mapping with attribs is not DDD). Regarding the POCO, adding the attributes means that your objects end up "knowing" details about the db and you end up adding an unnecessary reference to the active record assembly (at least, that is what happens when you use attributes with NH). With the xml file or NH fluent that doesn't need to happen because you can build your domain assembly without any references to NH assemblies (ok, not sure if that is true with the current version of this framework, but I think it should be). Having said this, if you don't want to use POCO, there's nothing wrong with the attributes...
As for POCO, well, not linking the domain objects library to some
external framework references is something I don't believe we can ever
achieve, unless we're working with very simple objects. The need for
validation is the first thing that comes to my mind, and things like
DomainSignature, for example, are very useful and I think that
outweighs the problems of referring a few external libraries.
On the other hand, adding another class to do the mapping obscures the
code, makes us search basic informations about our model in two
different places, and that's something that I qualify as much more
important than linking one or two external libraries, and in the case
o ActiveRecord you don't need to reference NHibernate's.
As for DB implementation details, if you build your objects correctly
and makes your DB schema comply to your objects structure, not the
other way around, you won't need to give any details about
implementation on the attributes, just make explicit the logical
relationships, which will make the code clearer. For example, if you
have all your tables named after the objects and all table's fields
name after your objects properties, them you don't need to specify the
implementation name in the attributes. But if you have an object named
Client and a table named CLI_DETAILS then you'll have problems, the
same for fields and properties name, but that's why I said that this
approach is better for a greenfield project with ORM in mind.
Check the example on my second e-mail, there's no DB details there,
the logical relationship between Category and SubInformation is very
clear, we don't use any strings so it's all checked at compile-time
and we don't need two objects. Then again, this is just another
approach option, an has it's own benefits and costs.
> As for POCO, well, not linking the domain objects library to some > external framework references is something I don't believe we can ever > achieve, unless we're working with very simple objects. The need for > validation is the first thing that comes to my mind, and things like > DomainSignature, for example, are very useful and I think that > outweighs the problems of referring a few external libraries.
validation is easy achievable with inversion of control, though most guys will not go that far. As I've said, it all depends on what you want: if you don't mind having those dependencies, then there's nothing wrong with the attributes :)
> On the other hand, adding another class to do the mapping obscures the > code, makes us search basic informations about our model in two > different places, and that's something that I qualify as much more > important than linking one or two external libraries, and in the case > o ActiveRecord you don't need to reference NHibernate's.
I disagree. Persistence information is a detail...important, but not a domain detail, and that's why I don't think it's important that you don't put that kind of info on the domain. There's a detail here: you keep mentioning databases, but is that really important when you tjhink about domain driven design? I know there are several guys out there which don't use databases for storing the domain objects and I'll be trying to use that approach in my work. to make that happen, I really want my objects to be persistent ignorant and that means no attributes or any db info on my domain model...
> As for DB implementation details, if you build your objects correctly > and makes your DB schema comply to your objects structure, not the > other way around, you won't need to give any details about > implementation on the attributes, just make explicit the logical > relationships, which will make the code clearer. For example, if you > have all your tables named after the objects and all table's fields > name after your objects properties, them you don't need to specify the > implementation name in the attributes. But if you have an object named
To me the db is a detail related with storage. I don't really care about the table structure and I will always build the database from the object model I have in my domain (not the other way around)... -- Regards, Luis Abreu
Inversion of Control is a good practice, and I would even say a vital
on when working with static languages such as C#, no questions about
it. But, isn't validation part of the domain concerns? For example,
allowing or denying a empty property on an object should be an
explicit on the domain model, don't you think? Of course there are a
lot of other validations, but I consider them domain logic not an
implementation or persistence detail.
As for referring to databases, well, 90% of all domain objects will be
persisted to a RDBMS, so I use it as a reference, but the information
added by the attributes are not exclusive to databases, they express
the logical relationships between objects, it doesn't matter how you
store them. A has-many relationship can be expressed on a database or
a XML file, and I believe it's important to differentiate it from,
let's say, a many-to-many relationship on both scenarios, or even if
you're not persisting them at all.
I think that using domain objects that are too skinny, devoid of all
context, is an error, we need enough information to know how objects
should work (validation included) and how they are connected to others
(logical relationship), and separating these essential pieces of
information just makes it harder to understand them. If these
informations will be used to make the persistence is irrelevant, and
these concerns will be addressed on another part of the system. In the
end we aren't tying domain logic to persistence details, keeping these
two worlds apart as it should be.