Is it better to have a method like this:
#1 void AddPerson(Person p);
or
#2 void AddPerson(int id, string lastName, string firstName);
Explain.
The one issue I noticed is I cannot point my web browser to AddPerson and test for #1, but I can for #2.
In addition to what ahus1 said, creating a separate Person.xsd XML schema is almost always a good idea, because this way you could import this Person.xsd into other XML schemas such as Invoice.xsd, creating a common language in order to describe your business.
Also, it makes it more simple to orchestrate services, imagine that you might have a given customer atribute into Invoice that is actually from Person Type. This way you could assign the customer value to other Person elements in just one step instead of having to copy all Person attributes in each step.
You may find at Canonical Schema SOA Pattern, good information about the benefits of this approach.
if you pass a person instead of the different elements, it will be easier for you when you enhance the Person in the future for example with a date of birth: your method names stay the same, you just enhance your domain model fill or read the date of birth where you need it.
Also you will find that as soon as you get a nested objects (if you want to add i.e. an address), a Person instead of the elements will give a uniform way for your methods.
Best regards,
Alexander.
Related
Can I construct a value object in the event handler or should I pass the parameters to the aggregate to construct the value object itself? Seller is the aggregate and offer is the value object. Will it be better for the aggregate to pass the value object in the event?
public async Task HandleAsync(OfferCreatedEvent domainEvent)
{
var seller = await this.sellerRepository.GetByIdAsync(domainEvent.SellerId);
var offer = new Offer(domainEvent.BuyerId, domainEvent.ProductId, seller.Id);
seller.AddOffer(offer);
}
should I pass the parameters to the aggregate to construct the value object itself?
You should probably default to passing the assembled value object to the domain entity / root entity.
The supporting argument is that we want to avoid polluting our domain logic with plumbing concerns. Expressed another way, new is not a domain concept, so we'd like that expression to live "somewhere else".
Note: that by passing the value to the domain logic, you protect that logic from changes to the construction of the values; for instance, how much code has to change if you later discover that there should be a fourth constructor argument?
That said, I'd consider this to be a guideline - in cases where you discover that violating the guideline offers significant benefits, you should violate the guideline without guilt.
Will it be better for the aggregate to pass the value object in the event?
Maybe? Let's try a little bit of refactoring....
// WARNING: untested code ahead
public async Task HandleAsync(OfferCreatedEvent domainEvent)
{
var seller = await this.sellerRepository.GetByIdAsync(domainEvent.SellerId);
Handle(domainEvent, seller);
}
static Handle(OfferCreatedEvent domainEvent, Seller seller)
{
var offer = new Offer(domainEvent.BuyerId, domainEvent.ProductId, seller.Id);
seller.AddOffer(offer);
}
Note the shift - where HandleAsync needs to be aware of async/await constructs, Handle is just a single threaded procedure that manipulates two local memory references. What that procedure does is copy information from the OfferCreatedEvent to the Seller entity.
The fact that Handle here can be static, and has no dependencies on the async shell, suggests that it could be moved to another place; another hint being that the implementation of Handle requires a dependency (Offer) that is absent from HandleAsync.
Now, within Handle, what we are "really" doing is copying information from OfferCreatedEvent to Seller. We might reasonably choose:
seller.AddOffer(domainEvent);
seller.AddOffer(domainEvent.offer());
seller.AddOffer(new Offer(domainEvent));
seller.AddOffer(new Offer(domainEvent.BuyerId, domainEvent.ProductId, seller.Id));
seller.AddOffer(domainEvent.BuyerId, domainEvent.ProductId, seller.Id);
These are all "fine" in the sense that we can get the machine to do the right thing using any of them. The tradeoffs are largely related to where we want to work with the information in detail, and where we prefer to work with the information as an abstraction.
In the common case, I would expect that we'd use abstractions for our domain logic (therefore: Seller.AddOffer(Offer)) and keep the details of how the information is copied "somewhere else".
The OfferCreatedEvent -> Offer function can sensibly live in a number of different places, depending on which parts of the design we think are most stable, how much generality we can justify, and so on.
Sometimes, you have to do a bit of war gaming: which design is going to be easiest to adapt if the most likely requirements change happens?
I would also advocate for passing an already assembled value object to the aggregate in this situation. In addition to the reasons already mentioned by #VoiceOfUnreason, this also fits more naturally with the domain language. Also, when reading code and method APIs you can then focus on domain concepts (like an offer) without being distracted by details until you really need to know them.
This becomes even more important if you would need to pass in more then one value object (or entity). Rather passing in all the values required for construction as parameters not only makes the API more resilient to refactoring but also burdens the reader with more details.
The seller is receiving an offer.
Assuming this is what is meant here, fits better than something like the following:
The seller receives some buyer id, product id, etc.
This most probably would not be found in conversations using the ubiquitous language. In my opinion code should be as readable as possible and express the behaviour and business logic as close to human language as possible. Because you compile code for machines to execute it but the way you write it is for humans to easily understand it.
Note: I would even consider using factory methods on value objects in certain cases to unburden the client code of knowing what else might be needed to assemble a valid value object, for instance, if there are different valid constellations and ways of constructing the same value objects where some values need reasonable default values or values are chosen by the value object itself. In more complex situations a separate factory might even make sense.
Suppose I have the following api where vin is a Vehicle Identification Number and belongs to a single car.
GET /fleets/123/cars/55/vin
GET /fleets/123/cars/55/history
And I want to get all the vins for all the cars for a fleet. Which would be preferred among these:
GET /fleets/123/cars/all/vin
GET /fleets/123/cars/*/vin
GET /fleets/123/vins
GET /fleets/123/cars/vins
The first two preserve the hierarchy and make the controller more intuitive. The last three feels like it breaks consistency.
Are any of these preferred or is there a better way?
This is mostly an opinion-based question. There's no one true way here, so you'll get my opinion.
I'm not sure what a vin is, but if it's a type of resource, and there's a collection of vins as a child of a fleet resource, I would expect it to live here:
GET /fleets/123/vins
This communicates to me a vin is not a subordinate of a car. It's its own thing and I'm getting all vins for a specific fleet.
The fact that a vin also exists as a subordinate of car (to me) is kind of irrelevant to this. It makes perfectly sense to me that for those, that they live here:
GET /fleets/123/cars/55/vin
Similarly, if I would model the last 2 apis as 2 functions, I would call them:
findVinsForFleet(fleetId: number);
findVinForCar(fleetId: number, carId: number);
Say I have a class Product {string name; double price;...}
So if I want to implement a seasonal or a discounted product, I can add declare a isPromoted/isSeasonal or I can create a new class promotedProduct : Product {...}, seasonalProduct : Product{} and much more.
I have been told that beginners tend to misuse inheritance and how it is evil. So I am not sure if I am considered misusing in this case. Or maybe they are both wrong and using interface is better etc.
Will products simply be on promotion or not - ie - no actual promotion details (different rates, dates etc) - if do you'll want your first solution. Otherwise you'll want a relation to a Promotions class which would store such details.
Hope this helps.
Note: this is a general programming answer having never used Java personally.
One good rule of thumb is to separate what changes from what doesn't.
You cannot change type at runtime but you probably want to be able to promote/demote a product easily.
One option is to store state directly on the Product as fields (but this will get ugly if they accumulate, isLowInStock etc).
Probably better os treat Product as an entity and separate the isPromoted/isSeasonal state by:
Use the State pattern to encapsulate the state (you can tie particular behaviour to state changes with Strategy)
Externalize the state and make service calls
Use #1 to guard against future change (i.e. more fields). #2 is probably overkill.
Please don't use double to represent Price - see this question or google.
Do seasonal or discounted products add attributes? Do they have different behavior? That's what drives inheritance. I suspect there's no real difference in behaviour and no real difference in the attributes they carry.
Hence, I'd look at a discount simply as an attribute that every product has: any product might go an sale and get discounted, so I'd have a property indicating the current discount percentage or amount (which probably defaults to zero, or perhaps it's nullable. Ditto for seasonal: should that simply be a boolean flag?
Venue 1 may use a a specific message to request say Market Data, whilst venue 2 may use another message for the same task. Now what is the best way of mapping this? Any suggestions would be appreciated
Plus is it sensible to append extra fields to a venues message, to make mapping easier?
Can anyone provide insight on how an exchange performs this task? As an exchange which is connected to multiple venues must surely have to parse and translate each venues spec.
Unfortunately, the flexible nature of FIX doesn't really make this an easy task. My other answer goes into more detail on why converting between FIX versions is not feasible and how two venues using the same FIX version can actually be radically incompatible.
In my experience, you really have to write a custom adapter for each venue. One way is to create a venue-independent set of data objects for your app to use, and then implement conversions between your objects and the FIX messages to/from the venue. The app would see the converter as only a generic interface; it doesn't need to know whether the target venue is 4.2 or 4.4 or whatnot.
For instance, you could create a GenericNewOrder class and an IConverter interface with a method SendNewOrder(GenericNewOrder). The IConverter has an implementation for each venue, e.g. VenueAConverter and VenueBConverter. VenueAConverter creates a new order message appropriate for VenueA, and VenueBConverter creates one for VenueB. If you ever have to add a new venue, just implement a new IConverter.
That's the best pattern I've been able to come up with.
(Questions like yours actually come up semi-frequently on the QuickFIX mailing lists.)
Assume that Book and Author are Aggregate Roots in my model.
In read model i have table AuthorsAndBooks which is a list of Authors and Books joined by Book.AuthorId
When BookAdded event is fired i want to receive Author data to create a new AuthorsAndBooks line.
Because Book is an Aggregate Root, information about Author doesn't included in BookAdded event. And i cannot include it because Author root doesn't have getters (according to guidelines of all examples and posts about CQRS and Event Sourcing).
Usually i receive two types of answers on this question:
Enrich your domain event with all data you need in event handlers. But as i said i cannot do it for Aggregates Roots.
Use available data from View Model. I.e. load Author from View Model and use it to build AuthorsAndBooks row.
The last one has some problems with concurrency. Author data can be not available in View Model at the time BookAdded event is handling.
What approach do you use to solve this? Thank you.
As a general advice, let the event handlers be idempotent and make sure you can deal with out of order message handling (either by re-queuing or building in mechanisms to fill in missing data).
On the other hand, do question why author and book are such desperate aggregate roots. Maybe you should copy from the author upon adding a book (what the f* is "adding a book", how's that a command). The problem is all these made-up examples. Descend to the real world, I doubt your problem exists.
Your question is missing some context, for example what is the user scenario that leads to this event and what is the state you are starting from? If you were writing the BDD tests for this case, what would they look like? Knowing this would help a lot in answering your question.
How you solve the problem of relating an book to an author is domain dependent. First we are assuming it makes sense for your domain to have an aggregate for Author and an aggregate for Book, for example, if I was writing a library system, I doubt I would have an aggregate for authors, since I don't care about an author without his/her book, what I care about is books.
As for the lack of getters, it's worth mentioning that aggregate roots don't have getters because of a preference for a tell-don't-ask style of OOP. However you can tell one AR to do something which then then tells something to another AR if you need. Part of what is important is the AR tells the others about itself rather than writing code where you ask it and then pass it along.
Finally, I have to ask why you don't have the author's ID at the time you are adding the book? How would you even know who the author is then? I would assume you could just do the following (my code assumes you are using a fluent interface for creation of AR, but you can substitute factories, constructors, whatever you use):
CreateNew.Book()
.ForAuthor(command.AuthorId)
.WithContent(command.Content);
Now perhaps the scenario is you are adding a book along with a brand new author. I would either handle this as two separate commands (which may make more sense for your domain), or handle the command the following way:
var author = CreateNew.Author()
.WithName(command.AuthorName);
var book = CreateNew.Book()
.ForAuthor(author.Id)
.WithContent(command.Content);
Perhaps the problem is you have no getter on the aggregate root Id, which I don't believe is necessary or common. However, assuming Id encapsulation is important to you, or your BookAdded event needs more information about the author than the Id along can provide, then you could do something like this:
var author = CreateNew.Author()
.WithName(command.AuthorName);
var book = author.AddBook(command.Content);
// Adds a new book belonging to this Author
public Book AddBook(BookContent content) {
var book = CreateNew.Book()
.ForAuthor(this.Id)
.WithContent(command.Content);
}
Here we are telling the author to add a book, at which point it creates the aggregate root for the book and passes it's Id to the book. Then we can have the event BookAddedForAuthor which will have the id of the author.
The last one has downsides though, it creates a command that must act through multiple aggregate roots. As much as possible I would try to figure out why the first example isn't working for you.
Also, I can't stress enough how the implementation you are looking for is dictated by your specific domain context.
IMHO, populate read model from author/book events, using reordering to handle cases, where events get out of order (view handler is within it's own consistency boundary and should handle ordering/deduplication cases anyway).
The first thing I would ask is why there are concurrency issues in the read model. If the client is sending a reference to the author aggregate inside the AddBook command, where did it get the information from? If the book and author are created at the same time, then your event can probably be enriched. Let me know if I'm missing something here.
The last one has some problems with
concurrency. Author data can be not
available in View Model at the time
BookAdded event is handling.
What about "handling the event later"? So you simply put it to the back of the queue until this data is available (maybe with a limit of x tries and x time between each try).