thinkbeforecoding / FsUno

Event sourcing implementation sample in F#
76 stars 27 forks source link

Support NEventStore #3

Open bartelink opened 10 years ago

bartelink commented 10 years ago

With a small amount of work, the sample could also persist its events in NEventStore in a SQL database.

As I'll be developing a highly similar pair of readEvents / appendEvents, I could add it here, which would serve as a nice test bed (from my perspective).

However the obvious major risk is that adding yet another front end/store (esp if its in the same lib) is going to be the straw that changes the sample from an elegant communication tool to something that misses the point.

So my (obviously very debatable) proposal is for me to split the FsUno project into

The major plus would be that FsUno would have a lot less files and the switchable stores becomes clearer

FsUno.Tests would only depend on FsUno.Domain and use NUnit

I'd then write a FsUno.Persistence.NEventStore which FsUno.DemoExe can also reference and then you just switch the store type ref in Main. The lib would:

The likelihood is that Serialization.fs would be used for Persistence.NES and Persistence.GES. I'd propose to put the file in a FsUno.Persistence but just link to it from the 2x Persistence projects.

But why oh why do all this here?

What could I do instead?

I could create a bartelink/FunDomain repo with

The problem is that I can't imagine any traction and I'd just be sowing confusion by having a fork of your serialization (and/or your GES bindings)

I hope I've explained myself sufficiently for you to decide quickly which direction you'd like this to take - open to any subsets you consider reasonable and definitely will understand if you say "Don't go toppling my nice tidy sample please!"

thinkbeforecoding commented 10 years ago

Maybe I can start 2 versions of FsUno.. One being very lean to show the shortest way to functional event sourcing. One other presenting alternatives,and enhancements. the second one would include: Switchable stores Load on call/in memory aggregates with agents Snapshots or not...

bartelink commented 10 years ago

@thinkbeforecoding Sounds good.

I assume the second/'serious' one would be async only ?

Main thing for me is having a fsproj with no common proj references per store. i.e if you have a XXX.Persistence.EventStore, I'd be able to throw in a matching XXX.Persistence.NEventStore (working on it in local repo - depending on when you have something up I'll either do a PR against yours or else a temp push elsewhere on a temporary basis until you've restructured).

thinkbeforecoding commented 10 years ago

Yes, I think so. Async only. No reason for making it sync. And I would leave only the sync part in the first one.

I'll try to make the split shortly !

bartelink commented 10 years ago

Thanks - think sync in Demo and async in Enterprise will split will help both.

I'm spiking in a local clone of https://github.com/bartelink/FunDomain

Depending on when you get to land your reorg I may push a preview there first.

thinkbeforecoding commented 10 years ago

How should we name the "production ready" implementation ?

thinkbeforecoding commented 10 years ago

Other question: Where would you put Command Handlers and projections ?

It has no direct dependency on infrastructure since readEvents and saveEvents are passed as parameters.. But it's not totally part of domain either...

bartelink commented 10 years ago

Re naming

I guess if the repo is called FsUno, you could have

Having the easy one sort to the top is a plus

bartelink commented 10 years ago

I like the idea of having the core stuff in a Domain assembly so it can have low dependencies and/or be a PCL to optimize the unit test loop. (I know it doesnt need to go places PCLs need to go but I think its an important way to keep the focus on domain concerns)

The obvious issue with the rest is that it depends and you don't want to go too astronaut on it :)

The Command Handlers make sense to have in a FrontEnd layer as they'll invariably be involved in some dance with authorization and/or the composition root - be that a console app or a web project and there's nothing much you can do thats likely to be universally useful. I guess you need to pick the app type and that will inform the decision a lot ;)

If you get into splitting out projections, you also get forced into deciding whether the events get split out too (i.e. a separate assembly and/or file). I guess that points to leaving the projections in the front end.

Pehaps having a Handlers assembly with Command Handlers and Projections might make sense? In principle if both get passed functions, the only place a comment-in-out / reference change / addition needs to take place is in the composition root

For my FunDomain testbed, I will likely have Domain, Handlers, Persistence.NEventStore and Acceptance.NEventStore

The acceptance project will prob be the composition root and will wire up an NEventStore pointing at an empty SQL Server Local Db. The lib has a function to do the DDL.

At some stage, potentially I'll do an Agent to process Projections [driven from the Acceptance.NEventStore].

In my for real project, the default split will be a web project with Handlers and Projections subdirs in a web project. Maybe that might be an idea for a FsUno console app or web app?

(Thinking aloud) Any point in having the console app say whose turn it is and asking for a card to play (independent of shuffling/dealing) to make it 'more real'?

bartelink commented 10 years ago

Have got an end to end with NEventStore [in memory, havce not actually run it into a SQL db but no reason it shouldnt]

I did some refactoring in the process which I'd appreciate comments on -- I've tried lots of things and would really like you to bat back some of them - esp unidiomatic and/or ugly to your sensibilities code.

I'm also thinking its time to implement Kickback and/or something else as its looking too small and boring with my succint syntax IMNSHO :)

Its at https://github.com/bartelink/FunDomain

bartelink commented 10 years ago

@thinkbeforecoding Hi Jeremie, wondering whether you're sitting on a commit. I had a 2 week break en France which was v nice. Coming up relatively soon I'll be doing some [closed source] stuff on a Functional Event Sourcing stack.

I'm aiming to have it talk to NES over an async interface (NES is sync so that impl will do an async over sync wrapping) but also be able to be switchable to GES (or at a minimum not completely paint myself into a corner). Also will prob look at doing protobuf serialization as Acceptance.NES perf is pretty bad and I want to be able to rename fields without much messing.

Any thoughts on the structure of FunDomain ?

If you're planning to do for intro/for real splitting of the code base, I'd be happy to contribute.

If that doesnt fit your plan/availability.... Perfhaps if I renamed FunDomain to Fes (Functional Event Sourcing) and had

where would it live? I'd be happy with a separate org but equally so it you want to have it alongside/inside FsUno in order to avoid frameworkization.

thinkbeforecoding commented 10 years ago

Hehe, my weeks have been quite busy lately (kids vacations, work etc.), but I'm home alone this week, and I'll have time to put some more effort to all this. Tomorrow probably :smile:

bartelink commented 10 years ago

@thinkbeforecoding Cool; will hold off so. Playing with protobuf against DUs. Will likely make that a switchable aspect (perf for my NES acceptance test is pretty much unacceptable at moment).