Let's say i got 2 entities - Foo and Bar. Foo is an aggregate root and contains Bar. As far as i understand, it should look like this:
public class Foo{
private readonly Bar Bar;
}
I want to provide functionality for users to choose Bars for Foos from a defined list (and change it).
If repositories are supposed to be for aggregate roots only it means that there will be no repository for Bar entity.
This leads to problem - Bar can't be created/updated independently without a reference to Foo.
Does that mean that Bar is supposed to have a repository despite that it has no meaning without a Foo?
If you want to select from a list of Bars where they're not associated with Foo, then this is not an aggregate root. For example, you can't get list of OrderItems without their Order, so this is single aggregate root (Order), but you can get list of Products to assign to OrderItems, so Product is not part of the Order aggregate root.
Notice that while OrderItem is part of Order aggregate root, you can still create and update it independently. But, you cannot get it without reference to Order. Same for your Bar, even if it was part of Foo, you could get each(Foo.Bars) and work with it, or do Foo.AddBar(new Bar()). But if you need to get List without Foo, Bar is not part of Foo aggregate. It is a separate entity.
Well, that's how I see DDD here, but I'm not Eric Evans, of course.
The reasons for having Aggregate roots are:
They provide controlled and directed access to composite entities
They can enforce rules to ensure that the entire aggregate is valid
My take:
If you need to select Bar objects without a Foo, use a BarRepository.
But...
What if you update a Bar, and it breaks a validation rule for it's parent Foo? If this could happen, you should access Bar via it's parent Foo.
If, however, you need to access a bunch of Bar objects (e.g for a batch job or report), and you know that Foos won't get broken, go ahead and access them via BarRepository.
Remember that aggregate roots can be composed of other aggregate roots. You may discover that Bar is an aggregate root itself, giving you justification for a BarRepository :)
Are you sure that Bar need to be a entity? Do you have the need to track it and change it in the domain? If you can look at it as a value object, I would suggest that you fetch it from a service and then "connect" the selected value object to the Foo entity. For instants through a dropdown list.
Related
I am a bit confused how to use the component <sw-entity-multi-select>. I understand that the difference between this component and the <sw-entity-multi-id-select> is that the first one returns the entities and the latter one returns just the id of the selected entities. But from the structure and the props they are totally different.
I am confused, because I mainly use the component as this:
<sw-entity-multi-select
entityName="language"
:entity-collection="languages"
:criteria="salesChannelLanguageCriteria"
:label="Language"
#change="selectLanguage"
>
</sw-entity-multi-select>
I could remove the entityName here, as the name is retrieved from the collection as well. But when I dig into the core, I see that inside selectLanguage I should do this:
selectLanguage(languages) {
this.languageIds = languages.getIds();
this.languages = languages;
}
I now understand that languageIds are kind of the v-model that determine, which entities should be selected in the component. Is this true? Why do I have to set the this.languages here again then? To me it's kind of magic if languageIds have this role here, because it's not referenced anywhere on the component. How does it work and how do I tell the component which items are selected - is using languageIds the correct way?
I now understand that languageIds are kind of the v-model that determine, which entities should be selected in the component. Is this true?
No. This example probably just extracts the IDs for some other use, e.g. for adding associations of language to another entity. One could arguably that if this is the only purpose of the selection sw-entity-multi-id-select might be the better component to use.
Why do I have to set the this.languages here again then?
Because you want to store the updated entity collection to persist the selection. Whatever is selected within the multi select is derived from that collection. So, let's say, initially you start out with an empty entity collection. You select some entities and the change is emitted with the updated collection containing the selected entities. Given we have :entity-collection="languages" we then want this.languages to be this updated collection, so the selection persists. So we kinda complete a loop here.
On another note, you could also use the collection with v-model="languages". In that case any additions or removals within the selection would be applied reactively to the collection and you wouldn't need to set this.languages after each change and you could also remove :entity-collection="languages". So basically, which of these approaches you use depends on whether you want your changes applied reactively or not.
Assume I have the relationship where every customer has an address (which in this case, is an entity), like below:
Customer{ Id, Name, MyAddress (instance of Address) }
Should I be allowing a structure that exposes the following option:
MyCustomer.MyAddress.Street = "Pine Street";
CustomerRepository.Save(MyCustomer);
Should this cascade a save, both for the Customer class and for the Address class? Or, is it better to perform the following:
MyCustomer.MyAddress.Street = "Pine Street";
AddressRepository.Save(MyCustomer.MyAddress);
Unfortunately, Address really is a value object, but I cannot make it interchangable like DDD requires as the Id tag is present; for example, if I did the following:
Customer1.setAddress(Customer2.getAddress());
Both Customer1 and Customer2 now have the same binding to the same record, which is dangerous.
None of your samples is DDD. Each one is simple CRUD.
Don't "set fields". Do meaningful operations.
customer.MoveTo(new Address(...))
customer.FixAddressTypo(new Address(...))
Repositories are for aggregates, not any entities. Identify your aggregates. http://dddcommunity.org/library/vernon_2011/
Why not map the Addres value Object as a bunch of fields in the Cutomers table? You don't need separate table just because you have a separate class.
Value objects should be immutable.
I'm developing an application with Domain Drive Design approach. in a special case I have to retrieve the list of value objects of an aggregate and present them. to do that I've created a read only repository like this:
public interface IBlogTagReadOnlyRepository : IReadOnlyRepository<BlogTag, string>
{
IEnumerable<BlogTag> GetAllBlogTagsQuery(string tagName);
}
BlogTag is a value object in Blog aggregate, now it works fine but when I think about this way of handling and the future of the project, my concerns grow! it's not a good idea to create a separate read only repository for every value object included in those cases, is it?
anybody knows a better solution?
You should not keep value objects in their own repository since only aggregate roots belong there. Instead you should review your domain model carefully.
If you need to keep track of value objects spanning multiple aggregates, then maybe they belong to another aggregate (e.g. a tag cloud) that could even serve as sort of a factory for the tags.
This doesn't mean you don't need a BlogTag value object in your Blog aggregate. A value object in one aggregate could be an entity in another or even an aggregate root by itself.
Maybe you should take a look at this question. It addresses a similar problem.
I think you just need a query service as this method serves the user interface, it's just for presentation (reporting), do something like..
public IEnumerable<BlogTagViewModel> GetDistinctListOfBlogTagsForPublishedPosts()
{
var tags = new List<BlogTagViewModel>();
// Go to database and run query
// transform to collection of BlogTagViewModel
return tags;
}
This code would be at the application layer level not the domain layer.
And notice the language I use in the method name, it makes it a bit more explicit and tells people using the query exactly what the method does (if this is your intent - I am guessing a little, but hopefully you get what I mean).
Cheers
Scott
The issue
I have a popup button (NSPopUpButton) that is bound to an NSArrayController. This array controller handles parent objects that each have a collection of child objects. I have an NSTableView in which I need to show these children for the selected item in popup. In addition, the list of children needs to be manipulated (add/remove).
I've tried to accomplish this in many ways but always run into some thing that complicates the solution. What is the best way to implement this?
The data is managed here by Core Data and thus, the collections are NSSets. I've tried adding a conversion method in the parent to return a sorted NSArray (in order to bind it with NSArrayController) but this approach prevents the KVO and the array controller is not updated properly.
Thank you in advance.
An example
To clarify, here's a hypothetic example:
Let's say I have a list of countries that is maintained elsewhere. One of these countries is selected in a popup button. Each country has a set of cities. When a country is selected a table view is populated by it's cities.
There is a solution for this without the delegate/datasource setup.
My context is this:
CoreData model with Parents and Children, one Parent has multiple Children via a relationship named children. Both have a attribute name.
The two Entities must be available as classes (each with a .m and a .h). (Xcode will write them for you if you go to File-New-File-CoreData-NSManagedObjectSubclass.) Now the ChildObjects of a ParentObject can be accessed by ParentObject.children
Two NSArrayControllers: ParentArrayController and ChildArrayController.
Two NSTableViews: ParentTable and ChildTable, each with one column for name. (It should not matter whether you use a Popup or a table as long as it's controlled by a NSArrayController.)
The steps to take are as follows:
Connect both NSArrayControllers to the MangagedObjectContext as usual and set them to Mode: Entity Name with their respective Entity (Parent or Child)
Bind both TableViews (their columns) to their NSArrayController as usual.
Now comes the magic: In the ChildArrayControllers binding section under ControllerContent-ContentSet bind to the ParentArrayController with ControllerKey: selection and ModelKeyPath: children.
Done. If you select a ParentObject in the ParentTable the ChildTable shows its children.
To add and remove children to parents you can use the (void)addChildrenObject:(Child *)value; method that Xcode wrote for you in the Parents.m class file.
I didn't find any way to implement this by simply with dragging and dropping. I had to implement a delegate and data source for the table of cities (from the example). The window controller is notified of the selection changes in the popup button and this updates the content on the table view delegate / data source.
I actually feel this is little bit better way to implement the issue (than with bindings and array controllers) since it gives more control over special cases.
I want to follow the DDD philosophy and not access entity objects of an aggregate directly. So, i have to call the root object to get the associated entity. But In other cases I dont always want every associated entity to load when the root is called. Is that the purpose of lazy loading?
How do I access entity objects through the root without loading all the associated objects everytime if i disable lazyloading feature of linq?
EDIT:
For example, If I have a Person as the Root Entity, and the Person has Name, Addresses and OwnedProperties. If I want to get a list of People so that I could display their names, I dont necvessarily want to load up Owned Properties every time on the call to the Repository. Conversely, on another page I may want to show a list of OwnedProperties, but do not want the other information to load with the call. what is the simple way of just calling the Person without the owned property entity other than creating a new person object without that owned properties?
I don't thinks that's possible without lazy loading.
Getting all data at once: Eager Loading
Getting data when accessed: Lazy Loading
According to your edit:
What I do in these situations, is create a 'View' class or a 'DTO' class which just contains the properties that I'm interested in.
For instance, I could have a 'PersonView' class which just has a Name property for instance.
Then, using my OR/M mapper (I use NHibernate), I create a HQL query (or Criteria query) which works on my 'Person' entity. Before I execute the query, I tell NHibernate that I want 'PersonView' objects as a result (I specify a projection). Then, NHibernate is smart enough to execute a query that only retrieves the columns that are necessary to populate the PersonView instances.
One way to avoid lazy loading is just using the object 'id'