From: Mikeon on

> Software engineering isn't about 'apply this pattern' or 'apply that
> pattern', it's about solving problems. The thing you have to do is
> solve a problem, not apply a pattern or two. If you don't understand
> the pattern, don't apply it, it's as simple as that. You then go back
> to your original problem and think of another solution.

Actually I know what specification pattern is. In my opinion it is
very good way to express a set of rules for filtering purposes.
According to Jimmy Nilsson's book it should be possible to use "Yet
another approach for querying is to use the Specification pattern "
Next he writes: "Even those Specification classes could very well spit
out IQuery ". IQuery is basically a Query Object.

Question is how to spit the IQuery. And I mean implementation and not
a 1000 meters abstract overview of what can or should or shouldn't be
done.
I appreciate your approach of trying to point me in a more generic way
of thinking, but that I have already behind me on few projects. Now
I'm focused on answering this "simple" question.
Till now I have always used Query objects which I can translate to
queries, but I have found Specification pattern to be more elegant
way.

> What's 'the specification pattern'? I now write professional software
> for over 13 years, but I never heard of the specification patten until
> this thread.

Actually if you don't know what specification pattern is, you cannot
answer my question in a way I need it :-(
Don't get me wrong here, I don't know most of the other patterns, but
I have read that it should be fairly "simple" to use Specifications as
a query mechanism so I wonder how.
And once again, I'm not trying to offend you, despite what you might
think from my style of writing. I'm trying to emphasize my goal here.

--
Michal

From: Mikeon on
> Why would you want to use this, an o/r mapper has this build in
> already, so just write the code in a repository if you want to and swap
> repositories IF you ever want to swap o/r mappers.

Because o/r mapper has its own way of expressing queries - mostly it
is some kind of Query Object.
I don't want to pollute my domain code with Query Objects since they
are usually not strongly typed and reassemble the underlying
datasource more or less.
Currently I have 2 choices, either to go with MS SQL server and some
kind of o/r mapper or use an object database: db4o.
Db4o handles my problem natively i.e. they can analyze my code, get
the usages specifications (native queries as they call them) and make
more database friendly queries out of them. Non of the other o/r
mappers I know of can do it automatically.
I don't know which way I will go now. Until very late in the
development I don't want to deal with persistance layer in any form. I
abstract access to persistance in repositories. I use specifications
to filter the results of queries.
I won't decide on the persistance until very late in the project. Do
you know of a better way to do it other than what I have described
above?

> Frankly, not a lot of people swap o/r mappers. Like there aren't many
> people writing their code in such a way that they can swap out a
> complete UI widget library on the spot, because 'you'll never know!'...

I won't swap it either. It's just that I don't even want to chose one
right now.

>
> > I'm aware that in .NET there are new features comming: expression
> > trees in particular, that will solve my problem: i.e.: I know how to
> > write SQL given expression tree.
>
> No, that won't solve your problem, because parsing that expression
> tree is very complicated and unnecessary.

Actually that would solve my concrete problem in a not efficient and
not generic way. That is exactly why I'm asking my question in the
first place.

--
Michal

From: Frans Bouma on
Mikeon wrote:

> > Why would you want to use this, an o/r mapper has this
> > build in already, so just write the code in a repository if you
> > want to and swap repositories IF you ever want to swap o/r mappers.
>
> Because o/r mapper has its own way of expressing queries - mostly it
> is some kind of Query Object.
> I don't want to pollute my domain code with Query Objects since they
> are usually not strongly typed and reassemble the underlying
> datasource more or less.

yes, though so does your code. A repository method GetCustomer, gets a
.... customer, and likely it's mapped to some sort of table which
represents the same abstract entity definition.

People often don't understand that the work they spend on abstracting
it all away is really moot because they're the ones working with the
code anyway, and second of all, the code they end up with is more
complex due to the abstraction layers and STILL polluted with the
concepts of which entities they're using.

I'm not saying everything should be crammed into a single
routine/class, on the contrary, though finding the right balance
between what to abstract and FOR WHAT REASON, is key to have a
successful project. Too many times people simply abstract away because
someone told them it's better, while there are no real reasons to
abstract it away.

> Currently I have 2 choices, either to go with MS SQL server and some
> kind of o/r mapper or use an object database: db4o.
> Db4o handles my problem natively i.e. they can analyze my code, get
> the usages specifications (native queries as they call them) and make
> more database friendly queries out of them. Non of the other o/r
> mappers I know of can do it automatically.

Use more efficient queries ? Why not? Most o/r mappers offer
span-prefetchpath fetches, update only the fields which are changed etc.

> I don't know which way I will go now. Until very late in the
> development I don't want to deal with persistance layer in any form. I
> abstract access to persistance in repositories. I use specifications
> to filter the results of queries.
> I won't decide on the persistance until very late in the project. Do
> you know of a better way to do it other than what I have described
> above?

So, just because you postpone this decision, which you eventually HAVE
TO MAKE, you are stuck with a problem and a complex conversion layer.

Don't you see, that after you've made the decision, the application is
polluted with an abstraction layer that's unnecessary?

So, because you have to make the decision sooner or later, why not
make the decision NOW, and forget about this complex problem? Because
it's not only the specifications you have to convert, also probably the
data. Entities need change tracking for example, how are you going to
handle that? Do the entities track themselves, or does your persistence
solution does that for you? If the latter, not every persistence
solution is able to detect if an entity is 'new' or just 'updated',
because it could be the entity isn't created by that same session
object. (often a problem in distributed applications or even webapps)

Abstractions are sometimes necessary, though this abstraction is
simply unnecessary as it's not serving the project, you HAVE TO make
the decision anyway, so the abstraction layer will end up in the
software for no apparent reason as after the project has been
completed, the layer is there but there's no rational reasoning for it.

> > Frankly, not a lot of people swap o/r mappers. Like there
> > aren't many people writing their code in such a way that they can
> > swap out a complete UI widget library on the spot, because 'you'll
> > never know!'...
>
> I won't swap it either. It's just that I don't even want to chose one
> right now.

Not wanting to choose now is a decision you've made. Decisions have
consequences. Because you don't want to choose now, you have to deal
with the consequence of having to write a large stack (because don't
underestimate this) of code to convert specifications in format A to
format B, plus likely convert entities in format A to format B and
back, while at the same time miss the features a solid persistence
framework offers you, like full entity management, support for
validation etc. etc.

So, if I were you, I'd bite the bullet, choose a persistence solution,
and start writing code for your APPLICATION, instead of writing layer
upon layer of plumbing because you postponed a decision (which you have
to make anyway, it's unavoidable)

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
From: Mikeon on
> yes, though so does your code. A repository method GetCustomer, gets a
> ... customer, and likely it's mapped to some sort of table which
> represents the same abstract entity definition.
>
> People often don't understand that the work they spend on abstracting
> it all away is really moot because they're the ones working with the
> code anyway, and second of all, the code they end up with is more
> complex due to the abstraction layers and STILL polluted with the
> concepts of which entities they're using.

I agree with you on this. But there is a small thing that makes this
project different than all others: it is a personal, hobby dirven
project, which doesn't have to be completed on a fixed date. It
doesn't even has to be completed at all! The goal is to learn
something new. I have already tried the approach with data mapper. I
have even created my own mapper with its own Query Objects (or
Criteria as I called them) by which you could fetch object from the
database. It worked very well so I know what you mean about
unnecessary abstracting.

> Too many times people simply abstract away because
> someone told them it's better, while there are no real reasons to
> abstract it away.

I want to do it because it is different.

> > Currently I have 2 choices, either to go with MS SQL server and some
> > kind of o/r mapper or use an object database: db4o.
> > Db4o handles my problem natively i.e. they can analyze my code, get
> > the usages specifications (native queries as they call them) and make
> > more database friendly queries out of them. Non of the other o/r
> > mappers I know of can do it automatically.
>
> Use more efficient queries ? Why not? Most o/r mappers offer
> span-prefetchpath fetches, update only the fields which are changed etc.

None of the mappers I have seen can do a performant query out of this:

repository.Get(delegate(User usr) { return usr.Name == "John"; });

I have to admint though that I haven't made a research in this scope
so maybe there are some that can.
LINQ makes this easier of course. I suppose mappers usually use some
kind of "hack" i.e. code generation to do it.

> So, just because you postpone this decision, which you eventually HAVE
> TO MAKE, you are stuck with a problem and a complex conversion layer.
>
> Don't you see, that after you've made the decision, the application is
> polluted with an abstraction layer that's unnecessary?
>
> So, because you have to make the decision sooner or later, why not
> make the decision NOW, and forget about this complex problem? Because
> it's not only the specifications you have to convert, also probably the
> data.

My goal is to come out with a generic repository that I can use in any
project, and only pass it its data access implementation via IoC. So
Making the decision now would impact my future decisions. I want to be
independant as much as I can.

> Entities need change tracking for example, how are you going to
> handle that? Do the entities track themselves, or does your persistence
> solution does that for you? If the latter, not every persistence
> solution is able to detect if an entity is 'new' or just 'updated',
> because it could be the entity isn't created by that same session
> object. (often a problem in distributed applications or even webapps)

That one I have already solved using unit of work pattern which I pass
to a repository.
I can send you my code if you wish, please contact me via email. You
will see then where my problem lies.

> Abstractions are sometimes necessary, though this abstraction is
> simply unnecessary as it's not serving the project, you HAVE TO make
> the decision anyway, so the abstraction layer will end up in the
> software for no apparent reason as after the project has been
> completed, the layer is there but there's no rational reasoning for it.

Reason described above. I want to get a reusable repository.

> Not wanting to choose now is a decision you've made. Decisions have
> consequences. Because you don't want to choose now, you have to deal
> with the consequence of having to write a large stack (because don't
> underestimate this) of code to convert specifications in format A to
> format B, plus likely convert entities in format A to format B and
> back, while at the same time miss the features a solid persistence
> framework offers you, like full entity management, support for
> validation etc. etc.

I am perfectly aware of the consequences. Moreover, my original
question is just that: how to convert Specfication objects (via
Specification Pattern) to Query Objects (via Query Object pattern).
Former is a domain level concept (via Domain Driven Design) the later
is more of a data access component dependant concept.

> So, if I were you, I'd bite the bullet, choose a persistence solution,
> and start writing code for your APPLICATION, instead of writing layer
> upon layer of plumbing because you postponed a decision (which you have
> to make anyway, it's unavoidable)

By now, knowing that the main goal is to learn I'm sure you would not
chose the persistence and kept researching the problem :-)

--
Michal

From: Frans Bouma on
Mikeon wrote:
> > Too many times people simply abstract away because
> > someone told them it's better, while there are no real reasons to
> > abstract it away.
>
> I want to do it because it is different.

ok, though unnecessary actions don't learn you anything unless you
realize the abstraction was unnecessary.

> > > Currently I have 2 choices, either to go with MS SQL server and
> > > some kind of o/r mapper or use an object database: db4o.
> > > Db4o handles my problem natively i.e. they can analyze my code,
> > > get the usages specifications (native queries as they call them)
> > > and make more database friendly queries out of them. Non of the
> > > other o/r mappers I know of can do it automatically.
> >
> > Use more efficient queries ? Why not? Most o/r mappers offer
> > span-prefetchpath fetches, update only the fields which are changed
> > etc.
>
> None of the mappers I have seen can do a performant query out of this:
>
> repository.Get(delegate(User usr) { return usr.Name == "John"; });

err, isn't that simply resulting in
SELECT ... FROM User WHERE Name = @name

so @name = "John" ?

> I have to admint though that I haven't made a research in this scope
> so maybe there are some that can.

any o/r mapper will issue a select with a where in that case, unless
you meant something different.

> LINQ makes this easier of course. I suppose mappers usually use some
> kind of "hack" i.e. code generation to do it.

Linq is a way to formulate queries, so just a different way of
formulating the query than you would in the o/r mapper's native query
language.


> > So, just because you postpone this decision, which you
> > eventually HAVE TO MAKE, you are stuck with a problem and a complex
> > conversion layer.
> >
> > Don't you see, that after you've made the decision, the
> > application is polluted with an abstraction layer that's
> > unnecessary?
> >
> > So, because you have to make the decision sooner or later,
> > why not make the decision NOW, and forget about this complex
> > problem? Because it's not only the specifications you have to
> > convert, also probably the data.
>
> My goal is to come out with a generic repository that I can use in any
> project, and only pass it its data access implementation via IoC. So
> Making the decision now would impact my future decisions. I want to be
> independant as much as I can.

So you're more looking for a generic wrapper for all o/r mappers out
there? Good luck ;)

FB
--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------