This should probably go off list if you wish to continue as it is spam given
the topic.



      Really? So DDD doesn't say you should add BL code to your entities?

          I am talking more about your "method" of adding the BL code. What
you are essentially doing is trying to work around serious design problems,
the problem is that you in the process make the code that much more
difficult to work with and harder to maintain.

I see AOP as a technique to inject code into a class. You apparently see
AOP as a way to do software design.

AOP does not just "inject" code into a class, there is a part which can do
similar things called "Inner Type Members" aka "mixins" but this concept is
not unique to AOP (You can do it quite easily through aggregation) and it
carries with it many of its own problems.


I am not going to copy and paste your customer example but it is a PERFECT
example of where one would want to use a specification/strategy pattern. But
first let's look at the "just adding it to the class" example.

As you said someone "could" just add these items to the class directly and
then they will have a problem when it came time to deal with the second
domain .. Too bad ... poor design leads to maintenance problems. I could
also put it into a shared module that in turn started a lisp interpreter and
used Console redirection to write a lisp program to get back the results ..
Of course I am sure even you would concede that to be a bad design.

Your suggestion then I presume is to use an inner type member to produce a
IsGoldCustomer property on the Customer object. This seems fine in thought
but is a complete nightmare .. So I create my customer object (without a
IsGoldCustomer proeprty).

public class Customer {
   public int Sales;
}

I then create a mixin which has the IsGold Customer code in it.

public class IsGoldCustomerMixin : IProxyAware { //note we have to use the
IProxyAware type interface so the generated proxy will know that it needs to
let us know who our proxy is
    Customer m_Customer;

   public bool IsGoldCustomer() {
          return ((Customer) m_Customer).Sales > 1000
   }
   public void SetProxy(object _Customer) {
       m_Customer = _Customer;
   }
}

Great! We have now "seperated" in an AOP based way right? This might work
great if we had full language support but instead in .NET we tend to use
dynamically generated proxies. If you remember I said this might be more
feasable if we were dealing with an aspect aware language. So now we end up
with a run time generated class something similar to the following

public class CustomerProxy : Customer {
   private IsGoldCustomerMixin m_Mixin;
   public bool IsGoldCustomer() {
       return m_Mixin.IsGoldCustomer();
   }
}

Note that I am leaving out alot of magic that has to happen here dealing
with constructors etc. We still have a MAJOR problem though .. although we
have this wonderful new IsGoldCustomer method on our CustomerProxy class ..
we can't actually USE it unless we revert to a dynamic call .. We see the
object as a customer, the customer does not have a IsGoldCustomer method.
This also applies to intellisense as we will no longer have intellisense ..
So to work around this we now have to create an IHasIsGoldCustomer
interface...

public interface IHasIsGoldCustomer {
   bool IsGoldCustomer();
}

now we would have to add that to our generated proxy ..

public class CustomerProxy : Customer, IHasIsGoldCustomer {
   private IsGoldCustomerMixin m_Mixin;
   public bool IsGoldCustomer() {
       return m_Mixin.IsGoldCustomer();
   }
}

Now in order to actually use our method ..

Customer c = CustomerRepository.FetchById(1);
//do stuff with c
IHasIsGoldCustomer tmp = c as IHasIsGoldCustomer;
if(tmp != null) {  //someone could have removed the interface by accident
   bool isgoldcustomer = tmp.IsGoldCustomer();
}

So now we finally have it working as an aspect. We still have intellisense
support and normal calling conventions but we now have code all over the
place that may just start failing (i.e. if you were to forget to add the
aspect to the object, the code would just blow up at runtime .. there is no
way of checking this). We still have all other sorts of issues to deal with
but many AOP frameworks handle them pretty (you know small things like
serialization, or remoting this object?). I won't even get into the
situation that comes up if you have a mixin that needs to talk to another
mixin that may or may not be there and you won't know until run-time.

Of course the biggest problem here is that the next place I go may not know
or care what a "gold" customer is .. I will however still care about the
concept of a CustomerLevel which is the domain concept a
specification/strategy pattern would support.

This code is significantly more complex than simply adding a specification
for the object and we have completely lost the concept of the operation from
our ubiquitous language. With a specification we would probably have
something along the lines of a GoldCustomerSpecification .. sounds nice
right? Using the specification methodology not only are we saving tons of
code, we are also coming up with a nice extensible model.

"       If you can simply have a set of entities (generated for example)
and inject the BL code at runtime, what's against that? I  don't see it."

The simple fact of the matter is that is not what AOP gives you. Issues with
types, serialization, etc make it a tricky task.

"       Isn't that definition-voodoo? I mean, 'it's not a domain concept,
so it must be bad'. How can a BL rule not be a domain concept? You just use
AOP to inject it in the class."

It most certainly is not an explicit domain concept .. you have created
a mixin class/interface pair that can be applied to ANY domain object while
I have abstracted the concept of giving customers levels .. Customers having
levels based upon a specification is a domain concept .. the mixin is not. I
can re-use the domain completely at another place who does
Platinum/VIP/normal customers simply by changing my specifications. I
maintain that as you use more apps (with dependency injection) your
refactorring becomes less and less providing you are dealing with different
logic withint he same domain. Eventually you hit a point where moving the
domain to an identical model with a new set of logic is as simple as writing
a series of strategies and specifications for the particular domain because
you have previously abstracted them.


The power of AOP is the exact same reason why it is a poor choice. The mixin
is something that can be applied to _ANY_ object. While this is hugely
successful when it comes to cross cutting concerns this is not good for a
domain concept.


      Closing the eyes for that just because it's not compliant with the
definition of AOP is IMHO erm... limiting yourself. :)

I don't care if its "compliant" with AOP .. I am closing my eyes because it
creates a brittle solution while adding high amounts of complexity to the
domain when there is a simpler, better solution that better abstracts my
domain while not putting in the knowledge overhead of an AOP framework

Perfectly fine by me. Because others use DDD, I got this idea of using AOP
for bl in >those contexts.
There are other techniques, I use these as well, though that doesn't make
using AOP for it 'wrong'. There's no such thing as 'wrong'

As I gave in an example earlier .. I could shell out to a consolt to lisp
interpreter and have it do some of this logic for me .. thats not wrong
either just not a good path to building maintainable software.

      ps: did you like the article, book?

I question the appropriateness of the article in a DDD based book although
it is in an interesting counter point to have included with the book, but I
tend to design systems that reused with multiple datasources that I do not
control so data driven doesn't work for me. The problem is 20 pages or so
really isn't enough to actually discuss all of the differences between a
data driven and a domain driven approach (in fact I would say 200 pages
would not be enough). With 20 pages you can't even discuss the repercussions
of model driven design vs data driven.

As for the book you can see my comments on the praise page

On 6/4/06, Frans Bouma <[EMAIL PROTECTED]> wrote:

> *       No on the contrary. If you want to do true DDD, and
> you want to
> re-use your entities but in a different context / app, you
> will run into the problem of having to alter the BL code
> inside the entities. With AOP you can avoid that. That was my
> point. So 1/ntier development style.
> *
>
> Frans,
>
> I would love to see you post that to the DDD mailing as a
> best practice. I think you would have better luck selling
> tickets to a bull fight at a PETA rally.

       Really? So DDD doesn't say you should add BL code to your entities?





I am curious as to how many times you have actually tried
> this, I have read about such possibilities in academia (all
> of which were using languages with aspect support btw) but I
> have never seen someone try to actually implement it ... let
> alone implement it in a language such as C# which does not
> have language based aspect support (yes you could use
> something like EOS but at this point we enter into completely
> obscurity).

       Well, let's not get ahead of ourselves. AOP is quite 'new' compared
to other techniques, and as I'm not in the Java camp,
it's more or less a new territory for me as it is for most of us here. I
see AOP as a technique to inject code into a class. You
apparently see AOP as a way to do software design. That's fine but I don't
care. The thing is that if someone cooks up a definition,
I don't see why I should follow that definition and use the technique
solely in that context.

> The general goal of AOP is not to move the core concern out
> of an object, it is to modularize cross cutting concerns.
> This modularization has huge immediate gains in the form of
> reducing coupling and simplyfying the domain allowing objects
> to deal with their core concerns (a perfect example is
> caching the return value from a service). If you are not
> actually reusing your aspects in multiple places you have
> added a significant level of complexity to your system with
> almost nothing to show for it.

       Let me give you an example.
       You have an entity class Customer. You have 2 apps to write.
There's this concept of a gold customer. You have to validate
if a customer is a gold customer. Both apps have different rules for that.


       It appears to me that you could use AOP to inject this rule code
into the customer entity. You could also write the rule
into a validator object and add that to the customer and use a strategy
pattern. You can also write it hardcoded into the entity
class and keep two codebases.

       Now, it seems to me that AOP can be used for this, right? It's a
way to extend the class with logic without adding the code
to the class. Now, you might say "Noo! that's against the goal of AOP",
but why should I care about that? If I don't use mock
objects, am I then violating some TDD contract as well?

       The core question is: why do you limit yourself by not using a
technique (!) for some aspect (pun intended) in your program?

       You've to know that I don't care about definitions. So if someone
says "That's not AOP, so you shouldn't call it AOP", fine,
I can understand that, but if I get a nickle for every time someone says
ORM for O/R mapping, I'd be very rich, so let's leave that
out of the discussion, ok? :)

       Now, back to my example. Of course you can write a validator, or BL
object and add that to the customer object at runtime,
using a strategy pattern. In fact, llblgen pro uses that pattern for
validators and concurrency filter factories.

       But that doesn't mean it has to be done that way. Some people want
to add the code inside the entity classes. For example
through partial classes. That's cool, but it mitigates the fact that if
they want to re-use the entity classes in another app, the
BL logic might be outdated and they have to alter it inside the code,
creating 2 codebases. Not that great.

       I'm not saying it's ideal, but it IS a way some people will write
software.
       If you can simply have a set of entities (generated for example)
and inject the BL code at runtime, what's against that? I
don't see it.

[...]
> The concept of domain driven design is about expressiveness
> before it is about reuse. A well distilled domain that
> actually is a good model will by its definition be able to be
> reused at another location that shares the space. If it is
> not able to be re-used  one should be questioning the
> original model and looking for ways to make it more
> expressive, not simply throwing decorations on it for the new model.

       Nice in theory, but it won't work in a lot of cases in practise.
THe core reason for this is that it's very very hard to
create the perfect model. In theory, it's logical to create the perfect
model. In practise the model always has flaws and needs
refactoring. If it's re-used in multiple apps, refactoring gets more and
more expensive.

> The biggest place that these definitions would hurt a domain
> is in the concept of an ubiquitous language.
> Specifications/Strategies compliment the ubiquitous language
> where as aspects (for business logic) would confuse it as the
> aspects themselves would not be domain concepts.

       Isn't that definition-voodoo? I mean, 'it's not a domain concept,
so it must be bad'. How can a BL rule not be a domain
concept? You just use AOP to inject it in the class.

> Just so that I am clear, I believe in using aspects at the
> domain layer (I personally use them heavily). I do not
> however believe that they should be used for non-cross
> cutting concerns as you are gaining little in their use.
> If the aspects are providing modularization then I am all for
> them, if they are simply 1-1 relations with business logic I
> think someone completely missed the real power of both concepts.

       How can I miss some power if I utilize the power of the concept to
make something work which didn't work before?

> My challenge to you is to come up with a hypothetical
> situation where you have a non-cross cutting business rule
> that the existing constructs offer a less revealing solution for.

       I'm not in school anymore, Greg, so I won't do assignments.

       It's also not about 'existing constructs which offer a less
releavling solution'. It's about how people tend to write
software. As an O/R mapper vendor I know how many different ways there
apparently are how people want to work with entities, trust
me on that. Telling everyone that there's just 1 way to do it is stupid as
it also depends on the context of the project, the skills
of the developer and frankly, most of these 'methodologies' have great
things but also sucky things, so a developer is IMHO better
of picking the best things of various methods and work out a good method
for him/herself. I hopefully don't have to come up with an
example how for example TDD zealots try to force you every little aspect
of their methodology on you, even if you just like 50% of
it.

       For example a math library is better written in a procedural
language. Yet OO languages also have a math library. Not ideal,
but hey, it's OO so let's write the methods in a big static class. For
some OO fetisjists this is incredibly bad. For others it's
simply using the tools at hand, do their thing and move on. I'm not sure
who's better of at the end of the day.

> Also, from everything I have heard/read you completely
> disagree with the very root concept of domain driven design
> so I am curious where this opinion/advice comes from. I think
> the title of your paper in ADDDP  "The Database Model Is the
> Domain Model" really summarizes your position well.
> Given that you completely disagree with the very root concept
> of domain driven design, how can you profess strategies for
> implementing domain driven design?

       Well, perhaps I'm not as closed minded as some people on this list,
eh? ;)

       What *I* think about DDD and how people should write software
doesn't make it *THE* way to write software. It also doesn't
imply DDD or other methods suck so much you should avoid them. I just
disagree with some root concepts. I also know others disagree
with me and think the opposite. Perfectly fine by me. Because others use
DDD, I got this idea of using AOP for bl in those contexts.
There are other techniques, I use these as well, though that doesn't make
using AOP for it 'wrong'. There's no such thing as 'wrong'
in software engineering (no not even in the context of stored procedures
;)), some things have just more cons than pros in a given
context, so it might be not the wisest choice, that's all.

       As we're all at the start of an era where software is more and more
generated, where BL rules are more and more applied to
objects at runtime through workflow systems and BL engines, it might be
AOP has a place in that spectrum because it has the
techniques on board to make that happen.

       Closing the eyes for that just because it's not compliant with the
definition of AOP is IMHO erm... limiting yourself. :)

               FB

       ps: did you like the article, book?

===================================
This list is hosted by DevelopMentor(r)  http://www.develop.com

View archives and manage your subscription(s) at
http://discuss.develop.com




--
If knowledge can create problems, it is not through ignorance that we can
solve them.

Isaac Asimov

===================================
This list is hosted by DevelopMentorĀ®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to