tag:blogger.com,1999:blog-3391776337973860668.post1049437945382070454..comments2023-11-18T01:40:32.514-08:00Comments on ZAN KAVTASKIN: Applied Domain-Driven Design (DDD) - Event Logging & Sourcing For AuditingZan Kavtaskinhttp://www.blogger.com/profile/10698403630279097421noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-3391776337973860668.post-65716817060031569892020-03-23T06:46:09.770-07:002020-03-23T06:46:09.770-07:00Absolutely pragmatic, just the solution to any mid...Absolutely pragmatic, just the solution to any mid sized enterprise application!<br />A good compromise between CQRS and DDD in a way every developer is capable of interpreting fast enough to make adequate changes.<br />Norberthttps://www.blogger.com/profile/11466588019881724689noreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-41674864264641059542019-01-10T02:00:36.295-08:002019-01-10T02:00:36.295-08:00Hi Mr. Kavtaskin
I'm new to learning DDD and...Hi Mr. Kavtaskin <br /><br />I'm new to learning DDD and repositories. It looks confusing but thanks to your blog.<br /><br />Say you have a Repository <br /><br />as in your code we have:<br /><br />public class Product : IAggregateRoot<br /> {<br /> private List returns = new List();<br /><br /><br /> public virtual Guid Id { get; protected set; }<br /> public virtual string Name { get; protected set; }<br /> ......<br /><br />and then we have static factory methods like<br /><br /> public static Product Create(string name, int quantity, decimal cost, ProductCode productCode)<br /> {<br /> return Create(Guid.NewGuid(), name, quantity, cost, productCode);<br /> }<br /> ......<br /><br />I wonder how this will be compatible with let's say Entity Framework because even there is default constructor, the fields are protected set. If I'm implementing something else aside from EF but uses reflection. Do I need an extra layer of DTO to map the domain object from EF or custom implementation? thanks<br /><br />Vinhttps://www.blogger.com/profile/18172549581911827409noreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-62946339974648977832018-03-13T19:22:25.346-07:002018-03-13T19:22:25.346-07:00Hi Zan,
Is is possible to use 'Serilog' i...Hi Zan,<br /><br />Is is possible to use 'Serilog' in Domain Driven Design for Domain Model class using Domain event and domain handlerRanjithttps://www.blogger.com/profile/15993353764085896240noreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-70540361669021616972017-06-27T09:18:27.451-07:002017-06-27T09:18:27.451-07:00Hi Denis,
This is a good question. I can’t think...Hi Denis, <br /><br />This is a good question. I can’t think of an elegant solution right now however, here are some high-level ideas:<br />1. Use ORM to track changes for you, NHibernate example: http://gunnarpeipman.com/2013/07/implementing-simple-change-tracking-using-nhibernate/, EntityFramework example: http://www.entityframeworktutorial.net/change-tracking-in-entity-framework.aspx.<br />2. Create a background process that squashes duplicate data.<br />3. Wrap your entity in a proxy class so that changes are tracked automatically. <br />4. Manually take a snapshot of the object before the change, when you raise the event provide before and after objects and let handler work it out.Zan Kavtaskinhttps://www.blogger.com/profile/10698403630279097421noreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-51851023752266479142017-06-24T14:50:56.923-07:002017-06-24T14:50:56.923-07:00How you would deal if there is a requirement do no...How you would deal if there is a requirement do not introduce changes if data was not really changed? I understand that presentation layer should check that email should be different before submitting to the service. But, if submitting more complex objects where property A and B were changed, but C was not (and C is another depended aggregate root). In this case only A and B should be submitted into repository. So, on domain level (commands, and events handlers) you would check if there are any changes before handing it over to repositories? And raising "changed" events only if data was changed?Anonymoushttps://www.blogger.com/profile/18249726184867585461noreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-88079327214553026422017-04-18T05:27:41.100-07:002017-04-18T05:27:41.100-07:00Hi Dmitri,
Thank you for the question!
Well you...Hi Dmitri,<br /><br />Thank you for the question! <br /><br />Well you have few options:<br />1. Use service locator inside the method to look up ISystemClock. This is not great as it will mess with your testing. <br />2. Use static method to get the time information, this StackOverflow Q&A explains it well http://stackoverflow.com/questions/2425721/unit-testing-datetime-now. This is my favorite option. As you can test and you don’t have to worry about the DI. <br />3. Use method overloading, which is what you are referring to. I agree, I don’t like this option, I don’t mind it if DI resolves it for you, but if you have to manually pass it in it just seems wrong. <br />Zan Kavtaskinhttps://www.blogger.com/profile/10698403630279097421noreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-16930481378876383802017-04-11T23:29:44.680-07:002017-04-11T23:29:44.680-07:00And then you should pass systemClock as a paramete...And then you should pass systemClock as a parameter to any Method (even to constructor) on the aggregate? i.e inside Handle we will have smth like:<br />var user = userRepository.FindById(userId);<br />user.ChangeAddress(newAddress, systemClock);<br />...<br /><br />Did I get you correct? Don't you find this design brittle and cumbersome? Thanks!Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-56453590969178869882017-04-11T13:15:23.952-07:002017-04-11T13:15:23.952-07:00Hi,
Thank you for the question!
I would use dep...Hi,<br /><br />Thank you for the question! <br /><br />I would use dependency injection and inject ISystemClock into the constructor, so it will look something like this:<br />public class SomethingHandle : Handles<br />{<br /> readonly ISystemClock systemClock;<br /><br /> public CustomerCreatedHandle(ISystemClock systemClock)<br /> {<br /> this.systemClock = systemClock;<br /> }<br /><br /> public void Handle(Something args)<br /> {<br /> //Use systemClock here. <br /> }<br />}<br /><br /><br /><br />Zan Kavtaskinhttps://www.blogger.com/profile/10698403630279097421noreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-78187920377870000852017-04-06T12:44:17.309-07:002017-04-06T12:44:17.309-07:00Hi Zan! How do you recommend to set up OccuredOn p...Hi Zan! How do you recommend to set up OccuredOn property on Domain Event? I don't want to initialize this property directly in the event with DateTime.UtcNow. I want to take the time value from ISystemClock implementation. How would you suggest to do it?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-46266230238378842852017-03-18T16:46:37.524-07:002017-03-18T16:46:37.524-07:00Hello Pavan,
Thank you for the question!
I’ve c...Hello Pavan, <br /><br />Thank you for the question!<br /><br />I’ve created class called “DomainEventHandle”, you can find it here:<br />https://github.com/zkavtaskin/Domain-Driven-Design-Example/blob/master/eCommerce/Helpers/Domain/DomainEventHandle.cs<br /><br />This class is registered using dependency injection here:<br />https://github.com/zkavtaskin/Domain-Driven-Design-Example/blob/master/eCommerce.WebService/App_Start/Installers/DomainModelLayerInstall.cs<br /><br />What happens is:<br />DomainEvents.Raise is invoked.<br /><br />.Raise method resolves everything that handles CustomerCreated event.<br /><br />In this case there are 2 handles, CustomerCreatedHandle and DomainEventHandle, these two handles get resolved and called. <br /><br />DomainEventHandle flattens the event and saves it to some storage (this can be any storage).<br /><br />DomainEvent abstract class can be found here: <br />https://github.com/zkavtaskin/Domain-Driven-Design-Example/blob/master/eCommerce/Helpers/Domain/DomainEvent.cs<br /><br />You can save the following metadata against the event:<br />Created (date)<br />CreatedBy (you will need to figure out how you are going flow the relevant identity down)<br /><br />You can’t save the following: <br />Modified by<br />Modified (date)<br /><br />Why? Because events are immutable, they have happened and they can’t be changed. <br /><br />While I was writing this I realised that DomainEventHandle is not the best name for the class, better name would be something like DomainEventPersistenceHandle.<br /><br />I hope this helps. Zan Kavtaskinhttps://www.blogger.com/profile/10698403630279097421noreply@blogger.comtag:blogger.com,1999:blog-3391776337973860668.post-4573815004840046062017-03-13T00:34:39.790-07:002017-03-13T00:34:39.790-07:00Dear Zan,
I've downloaded the example code fr...Dear Zan,<br /><br />I've downloaded the example code from Github. Could you please let me know where you are saving the Domain Events? Can we save it to the log tables of SQL Server? How about the audit fields like Modified Date, Modified By, Created Date, Created By? I'm now having these fields in a class called AuditEntity.<br /><br />Could you please throw some light on these Domain Events..<br /><br />Thanks,<br />PavanAnonymousnoreply@blogger.com