In domain driven design we create bounded contexts. Which means that aggregates don't share a common model.
This image from Microsoft shows how aggregates communicate using commands and events (source).
Assuming those aggregates are at least two different microservices coded in different repositories. How should they share the scheme definition for the commands and events they communicate with? In my case those applications are .net core applications, so serialization and deserialization compatible with .net would be appreciated.
Also, maybe I'm missing some point as I'm new to domain events and communication works different, then I would like to know, what I'm not seeing.
Each service can have an internal model and you can use a Canonical Data Model for the communication between the services.
It's common to have a separate model used for integration that the internal model a service uses.
You can also check all the patterns in enterpriseintegrationpatterns.com and get the book. It's highly recommended.
Edit:
Here's an example with the order system. I'll skip some of the data that the objects will have to simplify the example and try to concentrate on the important parts i.e. the CDM and the internal model.
NOTE For a simple example, it's always difficult to justify some of the decisions as most of the things will be a lot simpler with the additional stuff. The implementation is done this way to help with the example.
Before I continue: Having a CDN will have some overhead in translation from the internal to the external model. If you think you can go without it, do so. Do not make things more complex than they need to be. The problem here is that if you need to change a command or event, this will propagate to all services and will cause a huge ripple effect in your system. The Domain-Driven Design book has a section on the Anti-Corruption Layer. Do check it out.
Why do we use a CDM? For Encapsulation. The same way an object encapsulates its data, the service encapsulates its internals. The CDM is intended to be used only for the communication/integration between the services and is intended to be shared between them.
Sharing the Internal Model of a Service with other Services is a bad thing because it will lock the developers from changing this Internal Model. Also sometimes details from one service can leak to other services and can cause huge problems.
Sharing a Special Data Model designed only for the communication between services is a good thing because it enforces a well-defined model for the communication and your system won't become a mess of events and commands with unknown schemas where every Service posts and consumes whatever it likes. I've seen those kinds of horrors, trust me you don't want that!
This model should be designed at a higher level of abstraction: The system level, having it's processes and flows in mind. It should be void of any details about the internals of the individual services.
What you need is Translation between the internal and external models. Also, you can use ContentFilter and ContentEnricher if you need to filter incoming events or commands and add more data to outgoing events or commands.
// Canonical Data Model
namespace CDM {
public interface ICommand { }
public interface IEvent { }
public class CustomerInfo {
public Guid Id { get; set; }
// notice here the CDM uses the two separate properties for the first and last name
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class LineItemData {
public Guid ProductId { get; set; }
public Quantity Quantity { get; set; }
public Money ListPrice { get; set; }
}
public class PlaceOrderCommand : ICommand {
public CustomerInfo CustomerInfo { get; set; }
public IReadOnlyList<LineItemData> LineItems { get; set; }
}
public class OrderPlacedEvent : IEvent {
public Guid OrderId { get; set; }
public IReadOnlyList<LineItemData> LineItems { get; set; }
}
} // end Canonical Data Model namespace
// Order Service Internals
// the name is done this way to differentiate between the CDM
// and the internal command, do not use it this way into production
public class LineItem {
// the internal one includes the OrderId { get; set; }
public Guid OrderId { get; set; }
public Guid ProductId { get; set; }
public Quantity Quantity { get; set; }
public Money ListPrice { get; set; }
}
public class PlaceOrderInternalCommand {
public Guid CustomerId { get; set; }
public string CustomerFullName { get; set; } // a single full name here
public IReadOnlyList<LineItemData> LineItems { get; set; }
}
public class Event { }
public class OrderPlacedInternalEvent : Event {
public Guid OrderId { get; set; }
public IReadOnlyList<LineItem> { get; set; }
}
// this is part of the infrastructure, received messages and translates/transforms
//them from the external CDM to the internal model.
// This is the input/receiving part of the service
public class CommandDispatcher {
public void Dispatch(ICommand cmd) {
// here we will use a MessageTranslator, check PatternsUsed section
var translator = TranlatorsRegistry.GetFor(cmd);
var internalCommand = translator.Translate(cmd);
Dispatch(internalCommand);
}
}
public class CommandHandler {
public void Handle(PlaceOrderInternlCommand cmd) {
// this will create the OrderCreated event
var order = CreateOrder(cmd);
// this will save the OrderCreated event
OrderRepository.Save(order);
}
}
// Another part of the infrastructure that publishes events.
// This is the output/sending part of the service
public class EventPublisher {
public void Publish(Event event) {
// another usage of the MessageTranslator pattern, this time on events
var translator = EventTranslatorRegisty.GetFor(event);
var cdmEvent = translator.Translate(event);
// publish to kafka or whatever you are using
PubilshToMessageMiddleware(cdmEvent);
}
}
Patterns Used:
Canonical Data Model
MessageTranslator
CommandMessage
EventMessage
Related
I am in a situation where the creation of an entity requires the creation and ID of other entities, however, I am unsure how this is best implemented using MediatR.
For example, say I have a User object...
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public ICollection<Submission> Submissions { get; set; }
}
a Submission object...
public class Submission
{
public int Id { get; set; }
public string Reference { get; set; }
public User User { get; set; }
public ICollection<QuestionsAndAnswer> QuestionAndAnswers { get; set; }
}
and a QuestionAndAnswer object.
public class QuestionAndAnswer
{
public int ID { get; set; }
public string Question { get; set; }
public string Answer { get; set; }
public Submission { get; set; }
}
Each user can have multiple submissions and each submission has multiple questions and answers.
In this instance, the user has gone through a series of questions, provided answers, filled in the final form which provides asks for their contact details and then submitted the information to the API. At this point, I am unsure how to handle the data using MediatR, because the User must be created, with their ID returned as a result to create the submission object which in turn is required so that the questions and answers can be saved.
Should I implement a command which is called CreateUserWithSubmissionQuestionAndAnswersCommand, the handler of which somehow then calls the handlers for the three separate commands and executes them in order, and if so how?
I am just a bit lost on how to implement this scenario as a single HTTPRequest without violating CQRS. The only other way I could think of is implementing separate endpoints which perform each of these tasks individually which requires the client to make and receive three separate calls in succession (CreateUser, CreateSubmission, CreateQuestionAndAnswer)?
Anybody got any ideas?
I usually model the user interactions/user stories as MediatR requests. In most cases this means mapping an single HTTP request to a single MediatR request.
In your case this would be a single request which encapsulates the processing of the submission(s), e.g. ProcessSubmissions. This request would contain properties for the user as well as the submission(s) and the associated question/answer pairs. Then a single handler would persist the individual entities in the correct order.
For completeness, this is what this solution could look like:
public class ProcessSubmission : IRequest
{
public User User { get; set; }
public ICollection<Submission> Submissions { get; set; }
}
public class ProcessSubmissionHandler : IRequestHandler<ProcessSubmission>
{
public async Task<Unit> Handle(ProcessSubmission request, CancellationToken cancellationToken)
{
// Persist the user in the database
var userId = PersistTheUser(request.User);
foreach (var submission in request.Submissions)
{
// Persist each submission with questions and answers
}
}
}
Got a bit of an issue with MVC and using Entity Framework POCO classes.
I've used database first in a separate project to represent my domain layer which has been referenced by my MVC project as the MVC side of things only represents a small UI portion of a larger solution.
Issue being is that the UI is not a true representation of my domain layer, so I've been creating ViewModel classes that bridge together UI objects with domain objects. I use translation methods in between to convert domain objects in the controller into the relevant UI object.
To me this seems a bit of a long winded process and is quite error prone as when an update is made the the UI, or database you have to reflect it in the UI object and vice versa, and the translate methods get increasingly complex as the UI grows.
Would this be the right approach? Is there an alternative mapper for these kinds of objects?
Domain Object
public class Ticket
{
public int Id { get; set; }
public int ClientRef { get; set; }
public int PriorityRef { get; set; }
public int CategoryRef { get; set; }
public DateTime CreatedDate { get; set; }
}
View Model Object
public class TicketViewModel
{
public int Id { get; set; }
public int ClientRef { get; set; }
public int PriorityRef { get; set; }
public int CategoryRef { get; set; }
public DateTime CreatedDate { get; set; }
public SelectList PrioritySelectList { get; set; }
public SelectList CategorySelectList { get; set; }
public static TicketViewModel Translate(Ticket ticket)
{
return new TicketViewModel
{
Id = ticket.Id,
ClientRef = ticket.ClientRef,
PriorityRef = ticket.PriorityRef,
CategoryRef = ticket.CategoryRef,
CreatedDate = ticket.CreatedDate,
PrioritySelectList = GetPrioritySelectList(),
CategorySelectList = GetCategorySelectList()
}
}
}
I wouldn't worry about it too much to be honest.
I also agree that this is the way to go. If you want to be as safe as possible when changes happen, just make sure that you only have to change one layer and that's the translation layer.
The UI never or seldom changes, because it is a right pain in the proverbial to have to go and change every single view when any data bit changes. So, anything changes in the DB, like a field renamed for example or even newly added, you deal with it on the translation layer.
The UI will never be a 100% mirror of your business layer and that's totally fine.
My application has a business logic layer, and a data access layer. I want to give only the data access layer access to the database model. Now, I can easily do this, but then my UI classes cannot access the database classes like Reminder:
namespace Database
{
using System;
using System.Collections.Generic;
public partial class Reminder
{
public long Id { get; set; }
public string Name { get; set; }
public string Date { get; set; }
public string RepeatType { get; set; }
public string Note { get; set; }
public long Enabled { get; set; }
public string SoundFilePath { get; set; }
public string PostponeDate { get; set; }
public Nullable<long> EveryXCustom { get; set; }
public string RepeatDays { get; set; }
public Nullable<long> DayOfMonth { get; set; }
}
}
which is inside the database class library
I use this reminder class to store reminders. In my UI classes I use this class for various reasons.
To make use of this Reminder class, I simply add a reference to the class library that needs to use it. This works fine, but the problem is that every class library that references this, can alter the database like this.
If I'm not using Entity Framework, I could simply have a Reminder class outside the model (because there is no model) and load reminders from the database into that and extract them without using Entity Framework.
Here's an example of why I need to use the Reminder class in my UI classes (this is just a small code sample of one UI class)
This code is inside a timer that ticks every 30 seconds
// We will check for reminders here every 30 seconds.
foreach (Reminder rem in BLReminder.GetReminders())
{
// Create the popup. Do the other stuff afterwards.
if(rem.PostponeDate != null && Convert.ToDateTime(rem.PostponeDate) <= DateTime.Now && rem.Enabled == 1)
{
allowRefreshListview = true;
// temporarily disable it. When the user postpones the reminder, it will be re-enabled.
rem.Enabled = 0;
BLReminder.EditReminder(rem);
MakePopup(rem);
}
else if(Convert.ToDateTime(rem.Date.Split(',')[0]) <= DateTime.Now && rem.PostponeDate == null && rem.Enabled == 1)
{
allowRefreshListview = true;
// temporarily disable it. When the user postpones the reminder, it will be re-enabled.
rem.Enabled = 0;
BLReminder.EditReminder(rem);
MakePopup(rem);
}
}
GetReminders will do get the reminders from the database and put them in reminder objects
using (RemindMeDbEntities db = new RemindMeDbEntities())
{
localReminders = (from g in db.Reminder select g).ToList();
db.Dispose();
}
You can create separate project called i.e. Shared and put there all classes which are used in many projects. Then you need to reference this project by UI project and data access project (and by others which use these classes).
Both will have access to shared classes and UI won't be able to call data access layer directly.
You can also create interface outside of data access layer but if your classes are DTOs (Data Transfer Object) first option will be better.
If im not using the entity framework, i could simply have a reminder
class outside the model
You could create an interface instead of a class outside of the model in a shared assembly:
public interface IReminder
{
public long Id { get; }
public string Name { get; }
public string Date { get; }
public string RepeatType { get; }
public string Note { get; }
public long Enabled { get; }
public string SoundFilePath { get; }
public string PostponeDate { get; }
public Nullable<long> EveryXCustom { get; }
public string RepeatDays { get; }
public Nullable<long> DayOfMonth { get; }
}
Your Entity can than implement the interface:
public partial class Reminder : IReminder
{
//...
}
Maybe you want to make your Entities only internal visible and expose public service methods like IEnumerable<IReminder> GetReminders()
I am building an ASP Web API application and this time I thought I will go with the MVC pattern. I got along with most of the stuff, but there is one thing of which I am unsure. First of all my project consists of the following:
Data Layer
Business Layer
Model Layer (just the model with the properties)
Service Application (here are my controllers)
every one of them in a separate project
Lets say I have the following controller
public class TestController : ApiController
{
ISomeService _someBusiness;
public TestController(ISomeService someBusiness)
{
_someBusiness = someBusiness;
}
public **SomeModelObject** GetModelObject(ind id)
{
return _someBusiness .GetSomeModelObject(id);
}
}
Now my problem is the return value of GetModelObject(int id). Here it says SomeModelObject. That implies that my Service application (or my controller) has to know everything about the model which is being used (so I dont see the point in defining it in a separate .dll). One way would be to define the model (precisely the get/set mothods) as an interface, but I think that it would be too much that every model class has an interface (mostly because, as I said, just the properties are being stored inside the model), and despite that I just does not feel right to build an interface for a class which only stores data. So, is there any generic response type which is being used in this case (even some completely different approach), or do I have to use my model classes (or may i just always use string and it is being converted to the appropriate format by the client) ?
There's a good reason to use an interface to hide the complexity of the model object. It holds data, sure. But it holds unnecessary data that is only meaningful to the data layer. Take this EF model:
public class Employee
{
public int Id { get; set; }
public string EmployeeNumber { get; set; }
public string Name { get; set; }
public virtual Collection<TimeCard> TimeCards { get; set; }
public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
}
This is a fairy common EF model. It contains a surrogate key Id, and a foreign key DepartmentId. Those values are meaningless except for the database and, by extension, for entity framework. EmployeeNumber is the natural key which uniquely identifies the entity in the user's domain.
Outside of database access, you should really only deal with natural data values. You could do this by declaring yet another data-carrying class in the Business layer and perform mapping, or a better idea is to use an interface to hide all of the members that are not useful.
public interface IEmployee
{
string EmployeeNumber { get; }
string Name { get; set; }
ICollection<ITimeCard> TimeCards { get; }
IDepartment Department { get; set; }
}
Notice the lack of some setters in the interface. You'll never want to change the EmployeeNumber because that is the natural key for the entity. Likewise, you'll never assign a collection object to the TimeCards property. You'll only ever iterate over, add, or remove them.
Now your Employee class becomes
public class Employee : IEmployee
{
public int Id { get; set; }
public string EmployeeNumber { get; set; }
public string Name { get; set; }
public virtual Collection<TimeCard> TimeCards { get; set; }
ICollection<ITimeCard> IEmployee.TimeCards { get { return TimeCards; } }
public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
IDepartment IEmployee.Department { get { return Department; } set { Department = value; } }
}
In your business layer and above, you'll only use variable of IEmployee, IDepartment, and ITimeCard. So you are exposing a tighter API to the higher layers, which is a good thing.
You could try to use a generic approach at controller level:
public class BusinessController<T> : ApiController
{
ISomeService _someBusiness;
public TestController(ISomeService someBusiness)
{
_someBusiness = someBusiness;
}
public T GetModelObject(ind id)
{
return _someBusiness.GetSomeModelObject(id);
}
}
Finally your controlers inherit from BusinessController instead of ApiController:
public class TestController : BusinessController<SomeModelObject>
{
}
You could also take advance of the templating to inject the right "ISomeService" by using an IoC container and a bootstrapper.
I'm creating a web api program using entity framework. So as the basis, I have an sql server database which I'm connected to with entity framework trought my web api program. Using an add-on for entity framework, I'v generated classes according to my database tables. However i don't want to use these classes for my webservices because I don't need to display some of the attributes generated by the entity framework and little bit tricky with all the proxies problems. These attributes are especially generated because of the foreign keys. As below, for this generated class, I don't need to display "Societe" object and "Utilisateur" object:
public partial class FonctionnalitePerUser
{
public int FonctionUserLngId { get; set; }
public int FonctionUserLngUserId { get; set; }
public int FonctionUserLngSocieteId { get; set; }
public virtual Societe Societe { get; set; }
public virtual Utilisateur Utilisateur { get; set; }
}
I would need some advice to avoid displaying that entities in my webservices.
I was thinking about 3 possibilities:
As it's a partial class, I might create an other partial class with the same name where I put the attributes that I need and override the constructor.
I might inherit a custom class from that one to override the constructor in order to get one structured as I need.
I might create Management classes with functions that create the perfect objects that I need for my webservices. I mean functions that convert "FonctionnalitePerUser" object to "FonctionnalitePerUserCustom" objects.
These are the 3 solutions that I've found. In order to get the best performance, I was wondering if anyone can give me some advise about that or either propose some other solutions.
Thanks in advance
If your using Newtonsoft Json.NET which I think is the default in MVC5 then you can attribute your properties to tell newtonsoft what to serialize and what to ignore.
public class Car
{
// included in JSON
public string Model { get; set; }
public DateTime Year { get; set; }
public List<string> Features { get; set; }
// ignored
[JsonIgnore]
public DateTime LastModified { get; set; }
}
or if you have more properties you want to ignore than you want to serialize you can do this:
[DataContract]
public class Computer
{
// included in JSON
[DataMember]
public string Name { get; set; }
[DataMember]
public decimal SalePrice { get; set; }
// ignored
public string Manufacture { get; set; }
public int StockCount { get; set; }
public decimal WholeSalePrice { get; set; }
public DateTime NextShipmentDate { get; set; }
}
this information was taken from here.
In general, it is often useful to expose a different type of object for a web service API than for persistence. This is for exactly the reason you state: because you don't need to expose all of that persistence stuff to the rest of the world (clients).
Usually, you would map the information that you want to expose from your persistence model (EF entities etc) to a view model object (or DTO).
So, I would say your option 3 is on the right track.
I might create Management classes with functions that create the
perfect objects that I need for my webservices. I mean functions that
convert "FonctionnalitePerUser" object to
"FonctionnalitePerUserCustom" objects
There are several tools out there that help with the converting or mapping of the objects. One is AutoMapper which will map by convention. This can save a lot of mapping code.