I have a Core Data model similar to this:
When a Webgallery or Article object gets saved, it may use one or many pictures. They can use the same photographical subject but maybe in different sizes. I don't save pictures that don't get used in either a WebGallery or an Article.
Picture's relationships instance and social are set to cascade, so when the Picture object gets deleted, the corresponding PictureInstance and Social objects get deleted too.
1) Is there any way to know when a picture doesn't get used anymore, neither by WebGallery nor by Article so it can be deleted?
2) Is it a problem that the relationships previewPicture and teaserPicture don't have an inverse?
You should have an inverse for the relationship. With the inverse, the question becomes trivial. When a simple cascade rule will delete them from WebGallery and Article. (or perhaps you just want to nullify).
You should typically model relationships in both directions, and specify the inverse relationships appropriately. Core Data uses this information to ensure the consistency of the object graph if a change is made (see “Manipulating Relationships and Object Graph Integrity”). For a discussion of some of the reasons why you might want to not model a relationship in both directions, and some of the problems that might arise if you don’t, see “Unidirectional Relationships.”
(Core Data Programming Guide)
You can simply check if a picture is used whenever you delete it from a gallery or article:
[gallery removePictureObject:pictureToRemove];
if (pictureToRemove.galleries.count == 0 && pictureToRemove.articles.count == 0) {
[managedObjectContext deleteObject:pictureToRemove];
}
Related
I'm receiving an error connected with CloudKit when I made my Core Data Model.
Here's my model:
The errors:
Entity.attribute must specify an inverse relationship
Entity.attribute must not be ordered
Is my Core Data model connected properly and how can I fix the errors?
Please refer to the Apple Documentation titled “Creating a Core Data Model for CloudKit”...
Specifically under the subheading “Design a CloudKit-Compatible Core Data Model”.
Relationships
All relationships must be optional. Due to operation
size limitations, relationship changes may not be saved atomically.
All relationships must have an inverse, in case the records
synchronize out of order. (In a Core Data model, an inverse is
strongly recommended but not required.)
You’ll need to modify your object graph to include an inverse for each of your relationships.
With reference to the image you’ve provided, once you’ve completed that task, you’ll see an arrow at either end of the connecting “relationship” lines.
For a “to-many” relationship, you’ll see double chevron (>>) and for a “to-one” relationship you’ll see a single chevron (>).
Would you just do what CloudKit asked you?
Eg. for
"Sold.toClient must specify an inverse relationship"
go to grid-style Editor for Clients entity
in Relationships section add relationship named, say, toSold
select in Destination column Sold from popup, and in Inverse column toClient from popup.
Do some for other entities. CloudKit has own requirements for data model, so to integrate you must follow them even though locally your data model works.
Assume read model ProductCatalogueItem is built from aggregates/write-models, stored separately from write-models, and contains each product available for selling, and has following properties:
basics: product_code, name, price, number_of_available_stock,
documentation: short_description, description,...
product characteristics: weight, length, depth, width, color,...
And, there are two views:
product list containing list/table/grid of available product offers, and the view needs only following basic properties: product_code, name, price, number_of_available_stock,
product details showing all the properties - basics, documentation, product characteristics.
Naturally, there come two ViewModels in mind:
ProductCatalogueListItem containing only basic properties,
ProductCatalogueItemDetails containing all the properties.
Now,.. there two options (I can see).
ViewModels are 1:1 representation of ReadModels
Therefore the are two read models, not one, ProductCatalogueListItem and ProductCatalogueItemDetails. And, the read service will have two methods:
List<ProductCatalogueListItem> searchProducts(FilteringOptions),
ProductCatalogueItemDetails getProductDetails(product_code).
And, controllers return these models directly (or, mapped to dto for transport layer).
The issue here is filtering,.. should read service perform search query on a different read model, than is returned from the method call? Because, ProductCatalogueListItem doesn't have enough information to perform filtering.
ViewModels are another project of ReadModels
The read service will have two methods:
List<ProductCatalogueItem> searchProducts(FilteringOptions),
ProductCatalogueItem getProduct(product_code).
And, the mapping from ReadModels to ViewModels is done by upper layer (probably controller).
There is no issue with filtering,... But, there is another issue, that more data leave domain layer, than is actually needed. And, controllers would grow with more logic. As there might be different controllers for different transport technologies, then mapping code would probably get duplicated in those controllers.
Which approach to organize responsibilities is correct according to DDD/CQRS, or completely something else?
The point is:
should I build two read models, and search using one, then return other?
should I build single read model, which is used, and then mapped to limited view to contain only base information for view?
First of all, you do a wrong assertion:
...read model ProductCatalogueItem is built from aggregates/write-models...
Read model doesn't know of aggregates or anything about write model, you build the read model directly from the database, returning the data needed by the UI.
So, the view model is the read model, and it doesn't touch the write model. That's the reason why CQRS exists: for having a different model, the read model, to optimize the queries for returning the data needed by the client.
Update
I will try to explain myself better:
CQRS is simply splitting one object into two, based on the method types. There are two method types: command (any method that mutates state) and query (any method that returns a value). That's all.
When you apply this pattern to the service boundary of an application, you have a write service and a read service, and so you can scale differently the command and query handling, and you can have also two models.
But CQRS is not having two databases, is not messaging, is not eventual consistency, is not updating read model from write model, is not event sourcing. You can do CQRS wihtout them. I say this because I've seen some misconceptions in your assertions.
That said, the design of the read model is done according to what information the user wants to see in the UI, i.e., the read model is the view model, you have no mapping between them, they both are the same model. You can read about it in the references (3) and (6) bellow. I think this answer to your whole question. What I don't understand is the filtering issue.
Some good references
(1) http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/
(2) http://www.cqrs.nu/Faq/command-query-responsibility-segregation
(3) "Implementing Domain Driven Design" book, by Vaughn Vernon. Chapter 4: Architecture, "Command-Query Responsibility Segregation, or CQRS" section
(4) https://kalele.io/really-simple-cqrs/
(5) https://martinfowler.com/bliki/CQRS.html
(6) http://udidahan.com/2009/12/09/clarified-cqrs/
As you already built your read model using data which arrived from one or more services, your problem is now in another space(perhaps MVC) rather in CQRS.
Now assume your read model is a db object and ProductCatalogueListItem and ProductCatalogueItemDetails are 2 view models. When you have a request to serve list of products you will make a query in your read db from read model (ProductCatalog table). May be you make queries for additional filters using additional where clauses. Now where do you put your mapping activities in your code after fetching db objects? Its a personal choice. You don't have to do it on uupper llayer aat aall. When I use dapper I fetch db objects using view models inside generic. So I can directly return result from my service method whose return type would be IEnumerable.
For a detail view I would use the same db object. I know CQRS suggests to have different read models for different views. But question yourself - do you really need another db object for detail view? You will need only an id to get all columns where in the first case you needed some selected columns. So I would design your case with a mixture of your 2 above mentioned methods - have 2 service methods returning 2 different objects but instead of having a 1:1 read model to view model have a single read db object and build 2 different view models from it.
I'm trying to improve my design using some DDD concepts. Currently I have 4 simple EF entites as shown in the following image:
There are multiple TaskTemplates each of them storing multiple TasksItemTemplates. The TaskItemTemplates contains various information (description, images, default processing times).
Users can create new concrete Tasks based on a TaskTemplate. In the current implementation, this will also create a TaskItem for every TaskItemTemplate, but in the future it might be possible to select one some relevant TasksItemTemplates.
I wonder how to model this requirement in DDD. The reference from TaskItem to TaskTemplateItem is not allowed, because TaskTemplateItem is not an aggregate root. But without this reference it is not possible to get the properties of the TaskTemplateItem.
Of course I could just drop the reference and copy all properties from TaskTemplateItem to TaskItem, but actually I like the possibility to update TaskItems by updating the TaskTemplateItems.
Update: Expected behaviour on Task(Item)Template updates
It should be possible to edit TaskTemplate and TaskItemTemplate and e.g. fix Typos in Name or Description. I expect these changes to be reflected in the Task/TaskItem.
On the other hand, if the DefaultProcessingTime is modified, this should not change the persisted DueDate of a TaskItem.
In my current Implemenation it is not possible to add/remove TaskItemTemplates to a persisted TaskTemplate, but this would be a nice improvement. How would I implement something likes this? Add another entity TaskTemplateVersion between TaskTemplate and TaskItemTemplate?
Update2: TaskItemTemplateId as ValueObject
After reading Vaughn's slides again, I think with a simple modification, my model is correct according to DDD:
Unfortunately I do not really understand, why this Design is better (is it better?). Okay, there won't be unnecessary db queries for TaskItemTemplates. But on the other side I almost ever need a TaskItemTemplate when working with a TaskItem and therefore everything gets more complicated. I cannot any longer do something like
public string Description
{
get { return this.taskItemTemplate.Description; }
}
Based on the properties that you list beneath TaskItem and TaskItemTemplate I'd say that they should be value objects instead of entities. So if there isn't a reason (based on the information in your question there isn't) to make them entities, change them to immutable value objects.
With that solution, you just create a TaskItem from a TaskItemTemplate by copying its data.
Regarding the update scenario that you describe, it see the following solution:
TaskItems are created from a specific version of the TaskItemTemplate. Record that version with a TaskItem.
The TaskTemplate is responsible for updating its items and keep track of their version.
If a template changes, notify all Tasks that are derived from the template if immediate action is required. If you just want to be able to "pull in" the template changes at a later time (instead of acting when the template changes), you just compare the versions.
To make informed decisions, it is very important that you fully understand the pros and cons of immutability. Only then you will see a benefit in modelling things as value objects. One source on the topic that I find very valuable is Eric Lippert's series on immutability.
Also, the book Implementing DDD by Vaughn Vernon explains the concepts of value objects and entities very well.
I´m a little confused about inheritance and relationships in core data, and I was hopping someone could drive to the right path. In my app i have created 3 entities, and none of them have (and are not suppose to have) common properties, but there´s gonna be a save and a load button for all the work that the user does. From my understanding I need to "wrap" all the entities "work" into an object which will be used to save and load, and my question is, do I need to create relationships between the entities? Because I have to relate them somehow and this is what make sense to me. Is my logic correct?
I'm implementing a budget calculator, and for the purpose of everyone understand what my issue is, I´m going to give an practical example and please correct me if my logic is incorrect:
Let´s just say you are a fruit seller, and because of that it´s normal to have a database of clients and also a fruit database with the kinds of fruit you sell. From my understanding I find two entities here:
Client with properties named: name, address, phone, email, etc.
Stock with properties named: name, weight, stock, cost, supplier, etc.
TheBudget with properties named: name, amount, type, cost, delivery, etc.
I didn´t put all the properties because I think you get the point. I mean as you can see, there´s only two properties I could inherit; the rest is different. So, if I was doing a budget for a client, I can have as many clients I want and also the amount of stock, but what about the actual budget?
I´m sorry if my explanation was not very clear, but if it was..what kind of relationships should I be creating? I think Client and TheBudget have a connection. What do you advise me?
That's not entirely correct, but some parts are on the right track. I've broken your question down into three parts: relationships, inheritance and the Managed Object Context to hopefully help you understand each part separately:
Relationships
Relationships are usually used to indicate that one entity can 'belong' to another (i.e. an employee can belong to a company). You can setup multiple one-to-many relationships (i.e. an employee belongs to a company and a boss) and you can setup the inverse relationships (which is better described with the word 'owns' or 'has', such as 'one company has many employees).
There are many even more complicated relationships depending on your needs and a whole set of delete rules that you can tell the system to follow when an entity in a relationship is deleted. When first starting out I found it easiest to stick with one-to-one and one-to-many relationships like I've described above.
Inheritance
Inheritance is best described as a sort of base template that is used for other, more specific entities. You are correct in stating that you could use inheritance as a sort of protocol to define some basic attributes that are common across a number of entities. A good example of this would be having a base class 'Employee' with attributes 'name', 'address' and 'start date'. You could then create other entities that inherit from this Employee entity, such as 'Marketing Rep', 'HR', 'Sales Rep', etc. which all have the common attributes 'name', 'address' and 'start date' without creating those attributes on each individual entity. Then, if you wanted to update your model and add, delete or modify a common attribute, you could do so on the parent entity and all of its children will inherit those changes automatically.
Managed Object Context (i.e. saving)
Now, onto the other part of your question/statement: wrapping all of your entities into an object which will be used to save and load. You do not need to create this object, core data uses the NSManagedObjectContext (MOC for short) specifically for this purpose. The MOC is tasked with keeping track of objects you create, delete and modify. In order to save your changes, you simply call the save: method on your MOC.
If you post your entities and what they do, I might be able to help make suggestions on ways to set it up in core data. You want to do your best to setup as robust a core data model as you can during the initial development process. The OS needs to be able to 'upgrade' the backing store to incorporate any changes you've made between your core data model revisions. If you do a poor job of setting up your core data model initially and release your code that way, it can be very difficult to try and make a complicated model update when the app is in the wild (as you've probably guessed, this is advice born out of painful experience :)
I have a CoreData entity X, and controllers for this entity, XController.
Now there's another entity, XGroup, containing a collection of X entities, and a XGroupController.
Now the problem is that XGroupController needs to interact with XController, and it would be nice to just pass XGroupController a XGroup to observe, and then get the XControllers from the X entities.
So the question is: is it a good idea to store a (weak, to avoid retain cycles) reference to a controller in an entity? It just feels a bit "wrong". Is there another design pattern for this?
[Edit] Some more information:
XController/XGroupController are view controllers; and the reason why it felt "wrong" is that the view layer shouldn't be in the model layer. So #TechZen is right with his first paragraph.
However, how would I do that if I don't have that reference?
The way I see is to pass XGroupController all existing XControllers (plus update them when they change), and then when the items in the XGroup change, find the corresponding controllers (by checking if the XControllers property for it's X entity is in the XGroup) and finally talk to the XControllers.
I have to do work again for stuff the model already handles very nicely.
Doesn't it make the model layer kind of pointless if I have to handle groups in the controller layer another time?
The difference that makes in terms of Loc/complexity is just so significant, am I missing something? (Perhaps I should add that in my scenario it doesn't make sense to store the information XGroupController needs to give to XController via the model).
If by "controller" you mean a MVC view/interface controller then yes it is wrong because it breaks encapsulation. The data model should be completely unconcerned with how it's data is displayed.
If your "controller" is just an entity with that name then you probably want to use a fetched relationship to get the two controllers to talk to each other. That prevents circular relationships in the object graph.