--
Le doute n'est pas une condition agréable, mais la certitude est absurde.
Each decorator can have its own dependencies resolved the same way.
I don't really understand your anti-DI thing, in a world where pretty much every project starts with one already... Why not leverage it if you are already using it for other parts of the system?
/kzu from Android
I have no problem with leveraging a container but in this case it
really doesn't buy me much except for having to teach people how to
use something and risk. I can replace it in most systems in < 50 lines
of code... why take such a big dependency to save 50 lines of code?
Keep in mind the dependency isn't just actually linking to you but
also your release schedule, your versioning of APIs, any learning
curve associated with developers not familiar with your container,
cost of making sure licensing fits our model, and of course let's not
forget the risk that maybe there are bugs in your code. This is
assuming that said framework is non-invasive and doesn't require me to
structure my code in certain ways.
Taking on a framework dependency is a very big decision. There is a
lot of risk that needs to get factored in and frankly when dealing
with a situation of take on a dependency that prevents me from writing
40-50 lines of code .... it will take me longer just to research than
to write the code.
Work with DDD a bit more and you will discover that the only place you
tend to use DI is to Application Services/Command Handlers.
The
dependencies for the use case get injected into the service/command
handler and there isn't a container being used in a ton of other
places as you say.
I have no problem with leveraging a container but in this case it
really doesn't buy me much except for having to teach people how to
use something
and risk. I can replace it in most systems in < 50 lines
of code... why take such a big dependency to save 50 lines of code?
Keep in mind the dependency isn't just actually linking to you but
also your release schedule
, your versioning of APIs
, any learning
curve associated with developers not familiar with your container,
cost of making sure licensing fits our model
, and of course let's not
forget the risk that maybe there are bugs in your code.
This is
assuming that said framework is non-invasive
and doesn't require me to
structure my code in certain ways.
Taking on a framework dependency is a very big decision.
There is a lot of risk
that needs to get factored in and frankly when dealing
with a situation of take on a dependency that prevents me from writing
40-50 lines of code
.... it will take me longer just to research than to write the code.
Awesome you have reached the dogma level of SQL. Congrats.
I won't argue with you as your interests are well known. But please
stop saying not wanting to use a container equates to manually writing
all dependencies
> Wiring up dozens (far more I'd say on any reasonable complex system) of
> handlers with 2-3 service dependencies each, with those services
> construction too (they may also have their own dependencies), plus building
Why on earth would your handlers have 2-3 service dependencies each?!
Sounds like a modelling problem. And why would you be having say
hundreds of handlers in a given context?
> I think you're exaggerating the supposed complexity a DI container brings to
> the table (while at the same time over-minimizing the complexity CQRS itself
> brings ;)).
Could you define what CQRS is to you? CQRS is a very simple pattern.
On Mon, Aug 29, 2011 at 9:31 PM, Daniel Cazzulino
> It might have been a few years back. Nowadays, every project I've worked onwhat mocking framework?"
> starts from day one asking "what DI framework are we gonna use?
Awesome you have reached the dogma level of SQL. Congrats.
I won't argue with you as your interests are well known.
But please
stop saying not wanting to use a container equates to manually writing
all dependencies
> Wiring up dozens (far more I'd say on any reasonable complex system) ofWhy on earth would your handlers have 2-3 service dependencies each?!
> handlers with 2-3 service dependencies each, with those services
> construction too (they may also have their own dependencies), plus building
Sounds like a modelling problem. And why would you be having say
hundreds of handlers in a given context?
> I think you're exaggerating the supposed complexity a DI container brings toCould you define what CQRS is to you? CQRS is a very simple pattern.
> the table (while at the same time over-minimizing the complexity CQRS itself
> brings ;)).
Never had it take more than a second. I guess if we are comparing 1
second vs .001 yeah way faster but I don't care. Its done once at
start up and I am perfectly happy to have it finish in one second.
>> > Wiring up dozens (far more I'd say on any reasonable complex system) of
>> > handlers with 2-3 service dependencies each, with those services
>> > construction too (they may also have their own dependencies), plus
>> > building
>>
>> Why on earth would your handlers have 2-3 service dependencies each?!
>
> aggregate repository, query side (for set validation, etc.), maybe a logger
> or something? not too far fetched, no?
a logger.. couldn't we do that in the chain?
public Unit Log(Func<Unit, T> next, T message) : where T:Message {
MyLoggingFramework.Log("received " + message);
next(message);
}
This also shows a bit why I don't use the style of what you are doing
anymore ... much nicer to deal with functions instead of classes that
meet an interface. Its even nicer in a language like Scala. We can
even do "dependency injection"
public void BarHandler(IDepend1 d1, IDepend2 d2, BarCommand cmd) {
}
x = > BarHandler(new CD1(), new CD2());
returning a Func<T,Unit> where T:Command
Now if I ended up having nesting levels of 2-3 levels deep, yeah I
would consider using a DI framework but I generally don't run into
this scenario or its very limited.
A repository ... I would make it come by default (after applying cqrs
there is only one Get method after all no?)
So back to one dependency .. and I need a container to handle my one dependency?
so now I operate on a Func<IRepository, T, Unit> ... just a partial
application away.
On Mon, Aug 29, 2011 at 10:11 PM, Daniel Cazzulino
>> But pleaseNever had it take more than a second. I guess if we are comparing 1
>> stop saying not wanting to use a container equates to manually writing
>> all dependencies
>
> Oh, right! You do that fancy reflection/dynamic thing that is slow as a dog
> and you call it a day! :P (yeah, I measured, and it's just painfully slow,
> the fancy dynamic dispatching).
> That's why DI containers exist. They have taken that "poor man's" approach
> and made it fly.
second vs .001 yeah way faster but I don't care. Its done once at
start up
and I am perfectly happy to have it finish in one second.
a logger.. couldn't we do that in the chain?
>> > Wiring up dozens (far more I'd say on any reasonable complex system) of
>> > handlers with 2-3 service dependencies each, with those services
>> > construction too (they may also have their own dependencies), plus
>> > building
>>
>> Why on earth would your handlers have 2-3 service dependencies each?!
>
> aggregate repository, query side (for set validation, etc.), maybe a logger
> or something? not too far fetched, no?
public Unit Log(Func<Unit, T> next, T message) : where T:Message {
MyLoggingFramework.Log("received " + message);
next(message);
}
This also shows a bit why I don't use the style of what you are doing
anymore ... much nicer to deal with functions instead of classes that
meet an interface. Its even nicer in a language like Scala. We can
even do "dependency injection"
public void BarHandler(IDepend1 d1, IDepend2 d2, BarCommand cmd) {
}
x = > BarHandler(new CD1(), new CD2());
returning a Func<T,Unit> where T:Command
Now if I ended up having nesting levels of 2-3 levels deep, yeah I
would consider using a DI framework but I generally don't run into
this scenario or its very limited.
A repository ... I would make it come by default (after applying cqrs
there is only one Get method after all no?)
So back to one dependency .. and I need a container to handle my one dependency?
so now I operate on a Func<IRepository, T, Unit> ... just a partial
application away.
"Most systems need dynamic composition at runtime" ... you have
measured this how exactly? I tend to not need it. An off the cuff
guess would be < 5% of use cases need this (probably closer to 1% but
will estimate high).
On Mon, Aug 29, 2011 at 10:54 PM, Daniel Cazzulino
And if you are suggesting that DDD or CQRS based systems aren't
compositional then I'm not sure where the conversation can continue
from as no one else seems to have problems with this.
On Mon, Aug 29, 2011 at 11:11 PM, Daniel Cazzulino
Auto-wiring command handlers is trivial and doesn't require to build
on every request. It requires a build when a new assembly is detected.
Let's try going back to actual dynamic pipelines. When do you use
them? When do you build a different pipeline for a FooCommandHandler
than for another FooCommandHandler ..
And if you are suggesting that DDD or CQRS based systems aren't
compositional
then I'm not sure where the conversation can continue
from as no one else seems to have problems with this.
Umm no it doesn't, and you wouldn't have to have any
Activator.CreateInstance dealing with funcs. If using objects I still
*rarely* ever create a new pipeline in the processing of a command.
There are a few use cases out there that would need this but again
this is < 5%. So I might have to write a little code to do that a few
times in the building of a medium sized system. I am willing to accept
that (we are talking about 2-5 lines of code for each one)
DI is cool, it has its place. There are other methods that are cool
too, they have their places as well. You sound very dogmatic,
especially when you make statements like "before we start a project we
figure out which container and mocking framework to use". I have built
many systems with neither a mocking framework nor a container and yet
somehow they still work and are as well factored as if using such
frameworks. It can be done. There are other ways of solving problems.
Containers are not a new concept, have alternatives, and their own
weaknesses associated with them.
In writing CommandHandlers you will in most circumstances if following
bounded contexts find little to no value in using a container as it
just doesn't save you much.
>> And if you are suggesting that DDD or CQRS based systems aren't
>> compositional
>
> ? where did I say that?
On Mon, Aug 29, 2011 at 11:22 PM, Daniel Cazzulino
> Show me your auto-wiring command handlers without slow-as-a-dogUmm no it doesn't, and you wouldn't have to have any
> Activator.CreateInstance (and that only works if ALL your command handlers
> have exactly the same required dependencies and nothing more).
Activator.CreateInstance dealing with funcs. If using objects I still
*rarely* ever create a new pipeline in the processing of a command.
There are a few use cases out there that would need this but again
this is < 5%. So I might have to write a little code to do that a few
times in the building of a medium sized system. I am willing to accept
that (we are talking about 2-5 lines of code for each one)
DI is cool, it has its place. There are other methods that are cool
too, they have their places as well.
You sound very dogmatic,
especially when you make statements like "before we start a project we
figure out which container and mocking framework to use".
I have built
many systems with neither a mocking framework nor a container and yet
somehow they still work and are as well factored as if using such
frameworks. It can be done.
There are other ways of solving problems.
Containers are not a new concept, have alternatives, and their own
weaknesses associated with them.
In writing CommandHandlers you will in most circumstances if following
bounded contexts find little to no value in using a container as it
just doesn't save you much.
<5% of 100 != 100 you're point is meaningless when comparing 10-25
lines of code vs the dependency. Understanding a point before trying
to argue is useful. As well to have 100 command handlers in a bounded
context pretty much tells me your bounded context is wrong.
> Command handlers should be single-call style, no? (as in, every request gets
> a new instance of the handler, likewise for its decorators/pipeline). Did I
> miss something? :S
Exactly why would you want stateful command handlers? If they are not
stateful ...
what dependencies might they have? A repository might be stateful,
easy enough ... what other stateful things are you passing? Why are
you passing those things?
>"My point being that if you tell people "of course you can do CRQS+ES with DI and an >ORM!" rather than "why on earth would you want to do such an abomination?", you get >them interested, rather than scared off."
Why would I tell them to do such a stupid thing? To do ES with an ORM?
I tell people regularly that they can use an ORM with CQRS, its just
kinda doesn't make any sense at all to use an ORM + ES.
I also don't tell people *not* to use a container. I tell them to
evaluate what they get from taking the dependency and to consider
alternatives. I don't say containers are bad, I say there are choices
and they should be looked at.
--
Many people do CQRS with an ORM though.
On Tue, Aug 30, 2011 at 10:50 AM, Daniel Cazzulino
<k...@clariusconsulting.net> wrote:
--
Call it the CTO, the Architect, the 'IT guy'. Whoever you have to present the project, plan and intended architecture to get the contact. They do care, I think.
/kzu from Android
On Tue, Aug 30, 2011 at 7:52 PM, Daniel Cazzulino
On Tue, Aug 30, 2011 at 1:11 PM, Daniel Cazzulino
<k...@clariusconsulting.net> wrote:
<snip>
I wonder if anyone has merged both ORM and ES in a Frankenstein of a
hybrid that leaves biz owners happy (ORM) and alpha geeks too
(CQRS+ES). Something like placing ES and Commands on top of an
ORM-driven model...
</snip>
Not sure how he could misunderstand his own paragraph. My guess is he
is confusing the concept of "Audit Log" and "Event Sourcing".
<snip>
If you think about what they want, it's the ORM keeping the
authoritative "current" state of the app, not the event stream.
So, there's hardly a single query. It's "plain old" ORM-driven
persistence, ORM-driven query side too, transactional across command
and query ("consistency is overrated" doesn't usually fly ;)
</snip>
pretty much once we say the "event log is not the authoritative" the
concept of ES is not there any more.
My guess is its just a complete misunderstanding as to what ES is.
Precisely one of ashic points "The free audit was greatly appreciated.".
> THAT is an easy sell. Now, and here's the "retarded" thought: if you get the
> project buying 99% of CQRS+ES, where the only remaining 1% is essentially
> the loading of aggregates from events
THIS IS NOT EVENT SOURCING THIS IS AN EVENT LOG.
Perhaps you should bother watching the video where I discuss your
"magical" ORM + ES architecture and discuss why it will be a massive
failure?
Anyways, no conversation I have had with you nor any conversation I
have seen from you in this group has been constructive so I will stop
talking now.
On Tue, Aug 30, 2011 at 10:23 PM, Daniel Cazzulino
You seriously must have not watched the video. I talk about what you
are talking about for an hour.
THIS IS NOT EVENT SOURCING THIS IS AN EVENT LOG.
Precisely one of ashic points "The free audit was greatly appreciated.".
> THAT is an easy sell. Now, and here's the "retarded" thought: if you get the
> project buying 99% of CQRS+ES, where the only remaining 1% is essentially
> the loading of aggregates from events
Perhaps you should bother watching the video where I discuss your
"magical"
ORM + ES architecture and discuss why it will be a massive
failure?
Anyways, no conversation I have had with you nor any conversation I
have seen from you in this group has been constructive so I will stop
talking now.
Because you can't prove the deltas from the ORM are the same as the
deltas you generate as events so your log is useless, your db from ORM
is master ... Your events are meaningless. If you go one step further
and try to denormalize a model off of them your models will go out of
sync. Your event log is useless because you can't do anything with it.
But again this is all covered ad nsm both in this thread and in the video.
btw: LMAO@"it's NOT pure ES" .. yes there is a name for the pattern
thats "not pure es" its called an event log and has been around for
decades. Maybe you should stop calling it event sourcing? I think I
will start calling MVP MVC but then call it "not pure MVC" that should
avoid confusion with others right?
On Tue, Aug 30, 2011 at 10:56 PM, Daniel Cazzulino
On Tue, Aug 30, 2011 at 11:05 PM, Rinat Abdullin
The official system of record can either be the event logs or the current application state. If the current application state is held in a database, then the event logs may only be there for audit and special processing.
> You could prove the correctness pretty easily: just have a background
> process that replays the events and verifies the resulting state is the same
> in both cases. Not terribly hard to do if the benefit is convincing the
> product owner to adopt ES.
So ok let me get this straight ... you are going to write all of the
transformations from your event log to run asynchronously against your
database to see that your event log is correct? Providing you wrote
all of these what would be the point of having the ORM write at all to
the db it being you could just use them to build the db model in the
first place...
And you would be less error prone as the same code would build it both
times .... oh and yes this is in the video as well as of the solution
to the issue...
On Tue, Aug 30, 2011 at 11:48 PM, Daniel Cazzulino
"Application states can be stored either in memory or on disk. Since
an application state is purely derivable from the event log, you can
cache it anywhere you like."
You would not meet this part of the definition. But the narrative can
probably be cleaned up a little bit. Email sent to Martin.
On Tue, Aug 30, 2011 at 11:48 PM, Daniel Cazzulino
I never do ... however I my current state is purely derivable from the
event log which means I can throw them away and rebuild them if I find
a problem. Events are the source of truth and everything is based off
of them.
This is not the case when you are using an ORM / event log as which
one is right? You can say that you will write handlers off the event
log to double check that the ORM did it right too but now you just did
double the work as you could just use those handlers in the first
place as opposed to having all the handlers and all the ORM mappings.
Also when you get problems more likely than not its going to be some
difference between the handlers and the ORM as opposed to a bug in
generation.
/Anders
2011/8/31 Greg Young <gregor...@gmail.com>:
If working on a brownfield app though and if its as a transient
stepping stone then its not too worrisome.
" I'm doing it in a way that will allow me to drop the database
> and replay events to get it back, but I'm not using the events for
> authoritative state."
If you can do that then your events are authoritative.
The ORM model is pretty much just Entity Framework "Generate model
from database". For the events I'm trying to do it more DDD (but they
are created by the command handlers instead of a domain).
> If working on a brownfield app though and if its as a transient
> stepping stone then its not too worrisome.
The plan is to move to proper DDD eventually, but with the skill level
of most developers I'm working with currently it may take some time.
> " I'm doing it in a way that will allow me to drop the database
>> and replay events to get it back, but I'm not using the events for
>> authoritative state."
>
> If you can do that then your events are authoritative.
I'm hoping that I'll be able to use ES eventually without having to
rebuild the entire system; that would be the ultimate proof.. The
thing I'm worried about the most is that the events I'm creating now
may be spanning more than one Aggregate in a future possible domain
model. And that seems like a bad thing when using ES.
/Anders
Event Sourcing ensures that all changes to application state are stored as a sequence of events. Not just can we query these events, we can also use the event log to reconstruct past states, and as a foundation to automatically adjust the state to cope with retroactive changes.
I said doing CQRS + ES + ORM is retarded. This is not ES.
"If you need to drop the database, then you can, as everything is
going to the event store anyways, and you can even have a default DB
initializer that just detects a dropped DB and replays everything back
and saves at the end."
And you only did twice the work (especially when you consider that you
need to be able to determine if what the ORM did is the same as what
the event log says ... eg reconciliation)
<snip from Martin email>
>I agree with you 100% on this. I'll think about whether I should add a clarification.
>
>
>Martin Fowler
>http://martinfowler.com
>
>
>
>
>On Aug 31, 2011, at 24:31 , Greg Young wrote:
>
> Was just dealing with someone who was getting confused over the paragraph of:
>
> "The official system of record can either be the event logs or the
> current application state. If the current application state is held in
> a database, then the event logs may only be there for audit and
> special processing. Alternatively the event logs can be the official
> record and databases can be built from them whenever needed."
>
> He took it to mean just keeping an audit log = event sourcing (eg just
> writing events to a log then saving with an ORM back to a database).
> I am pretty sure we are in agreement that this would not be event
> sourcing as the current state is no longer derivable from the log but
> wanted to drop you a note.
>
> --
> Le doute n'est pas une condition agréable, mais la certitude est absurde.
On Wed, Aug 31, 2011 at 10:52 AM, Daniel Cazzulino
" I'm doing it in a way that will allow me to drop the databaseIf you can do that then your events are authoritative.
> and replay events to get it back, but I'm not using the events for
> authoritative state."
Enjoy refactoring your domain model.
On Wed, Aug 31, 2011 at 11:16 AM, Daniel Cazzulino
--
How would you know when an event has finished being "handled" by all handlers? (especially since they might be async?)