I had a conceptual problem with Core Data.
I have an entity called OBJ which has an OBJ entity in a relationship. I get very eloquent messages like "An error occured." when I test my model.
For each OBJ entity, I wish to define one or more ACTIONs associated with another OBJ entity. So I guess my mistake comes from a loop, but not sure.
At first, I defined an inverse relationship (as advised by the doc, a relationship should always have its inverse):
ENTITY OBJ
Attributes:
name
status
Relationships:
actions
<-------- >>
ENTITY ACTION
Attributes:
name
Relationships:
obj
Well, it does not work, because the OBJ always refers to itself. I have therefore decoupled relationships. The ACTION points to an OBJ and the OBJ points to several ACTIONs, without reciprocity. Error message.
My basic idea is that each of the ACTIONs associated with a particular OBJ can run if the status of another OBJ allows it.
How to build this to be MVC consistent? The basic idea seems simple, it is his achievement that is less so. Is it a wrong Core Data modeling? Do I make a mistake at the controller level? Interface? Note that at this level I have not written a single line of code.
Thank you!
If you want to
define one or more ACTIONS associated with another OBJ
it means that one OBJ can have many ACTIONS and one ACTION can have many OBJs.
Therefore you should define a relationship between ACTION and OBJ that is to-many in both directions.
OBJ.actions <<-------->> ACTION.obj
Unless you intend to have "sub-objects" (such as CATEGORY and subCATEGORY) you should not have a relationship between OBJ and OBJ.
I found a solution by adding a new relationship between "OBJ" and "ACTION".
OBJ ACTION
… …
Relationships Relationships
targetObject <------->> actions
conditionObject <------->> condition
If I don't, the inverse relationship always refers to the same (self) object. So, by changing a relationship, I was changing the object itself!
By adding a new one-to-many relationship, I can indirectly make a OBJ to OBJ relation (the targetObject and conditionObject may be the same one) AND keep the graph consistent.
Each day, I understand better what "Core Data is not for beginners" means…
Related
If you have an entity with a value object as an attribute.
Which would be the parameters of the entity constructor, the value object? Or the primitive types of the value object?
First I did it building the value object outside the entity and I passed the value object to the entity constructor... but then I realized that maybe it would be the entity itself that has to build the value object.
I thought this because the entity and the value object are in fact an aggregate, and it is supposed that you have to access the inside of an aggregate through the aggregate root, i.e., through the entity.
So which is the right way? Is it allowed to deal with the value object outside the entity? Or the value object just can be used by the entity?
Thank you.
EDIT:
For example, I have an entity "Task" that is the aggregate root. This entity has a value object "DeliveryDate" (in format "dd/mm/yyyy hh:mm"). The entity has more value objects too.
class DeliveryDate extends ValueObject {
private String formattedDeliveryDate;
private DeliveryDate() {
super();
}
DeliveryDate ( String formattedDeliveryDate ) {
this();
this.setFormattedDeliveryDate ( formattedDeliveryDate );
}
private void setFormattedDeliveryDate ( String formattedDeliveryDate ) {
<< check that the string parameter "formattedDeliveryDate" is a valid date in format "dd/mm/yyyy hh:mm" >>
this.formattedDeliveryDate = formattedDeliveryDate;
}
........
The entity constructor:
Task ( TaskId taskId, Title title, Delivery deliveryDate, EmployeesList employeesList ) {
this();
this.setTaskId(taskId);
this.setTitle(title);
this.setDeliveryDate(deliveryDate);
this.setEmployeesList(employeesList);
}
My doubt is: Is this ok? (passing to the constructor the DeliveryDate object)
Or should I pass the string? (and the constructor creates the DeliveryDate object)
I think it's more a question of "should the outside of the aggregate know about the DeliveryDate concept?"
In general my doubt is about any value object of any entity, not just Task and DeliveryDate (this is just an example).
I have asked the question about the constructor, but it's valid for factories too (if the process of creating an instance is complicated)... should the aggregate factory parameter be the value object? or the primitives to create the value object?
In your case it might seem that the two solutions are similar. It doesn't really matter if you create the value object outside or inside of the entity. But think about when your entity will have more than one value object, the entity constructor will contain too much logic in order to make sure it creates the VOs correctly and at the same time enforce the entity's invariants.
One solution to avoid this unnecessary complexity is to use factories. The factory will abstract the creation process and this will keep you entity code simple.
In DDD, factories are very useful for creating aggregates. In the blue book there is a whole chapter about factories and here is good article about the use of factories in DDD http://culttt.com/2014/12/24/factories-domain-driven-design/
Edit
My doubt is: Is this ok? (passing to the constructor the DeliveryDate object) Or should I pass the string? (and the constructor creates the DeliveryDate object)
Yes, it is ok. Task should not know about how to create the value objects. You should not pass the strings cause that will add more complexity and responsibilities to the Task constructor.
I think it's more a question of "should the outside of the aggregate know about the DeliveryDate concept?"
Yes, it is not problems that the outside of the aggregate knows about the DeliveryDate. It is the same as knowing about strings and integer. Value objects are simple to deal with and reason about and they are part of the domain so I think there is no problems in dealing with them outside of the aggregate.
should the aggregate factory parameter be the value object? or the primitives to create the value object?
Here I would say the Factory should receive the primitive types and encapsulate the objects creation. cause if you pass the values objects to the factory it will just pass the same parameters to the Entity constructor and that is a middleman code smell.
Domain Driven Design doesn't offer any specific guidance here.
A common case might look something like this: we've retrieved a DTO from the database, and now want to create a Entity from it....
class Entity {
private Value v;
Entity (Value v) {
if (null == v) throw new IllegalArgumentException();
this.v = f;
}
Entity (DTO dto) {
this(new Value(dto));
}
// ...
}
Does it really matter if you invoke the second constructor rather than the first? Not much.
A language check:
DTOs are not retrieved from database. What you retreive from a database is an aggregate, not a DTO
I had to abandon that idea - that definition leads to too many problems.
For example, in event sourced designs, the database typically stores representations of events, not aggregates.
Even in traditional designs, it doesn't hold up -- the boundaries of your aggregates are defined by the constraints enforced by the domain model. Once you take the data out of the domain model, what you have left is just representations of state. Expressed another way, we save state in the database, but not behaviors, and not constraints -- you can't derive the constraints from the saved data, because you can't see the boundaries.
It's the model, not the database, that decides which data needs to be kept internally consistent.
I tend to use the term DTO because that's its role: to carry data between processes -- in this particular instance, between the data base and the domain model. If you wanted to use message or document instead, I wouldn't quibble.
I'm reading "Patterns, Principles, and Practices of Domain-Driven Design". The book suggests that properties of an Entity should be value objects in order to model domain's ubiquities language. I've seen many examples like EmailAddress or Age with only one field to model domain concepts. I'm confused about it. Is every property of an Entity a value object? Can you provide examples when we can use normal languages provided data types for properties?
No, not every property of an entity is a value object.
Properties of entities are one of the following:
As you already know, value objects. Value objects represent simple values without identity.
Primitives. These are just value objects from a DDD perspective, really. Primitives are ok to use in DDD, but take care not to become a victim of Primitive Obsession.
Entities. An entity can contain other entities. All entities that have direct (navigable) references between them are part of the same Aggregate. The "top-most" entity within an aggregate is called the Aggregate Root. Only the root has a global identity, inner entities have only local identity.
References to entities of other aggregates. Never reference these directly, use an ID. IDs themselves can in turn be modeled as value objects.
I think that your real question is: Is every value object a Class?
Because you can think that for the Age a Java Integer can be enough and this is true. So you have in your entity Person a value object Age of type Integer, there is no need of an age type.
OOP also says that an object is state + behaviour. In your Age case, I assume that it has no behavior so a simple primitive or wrapper class will do the trick, in fact I would go with option this because is simpler.
My advise is, go with a primitive/wrapper class and if you advert that some behavior is needed in that value object, make a class/type.
I'm doing an assignment on class diagram and the following shows the association between classes Order and Menu Item. Should the link be aggregation (weak) or composition (strong)?
I'm confused because I've seen example showing aggregation. I felt it should be composition as an Order must have at least 1 Menu Item added. Am I wrong?
Should the link be aggregation (weak) or composition (strong)?
It can be both. The main difference is:
In case it's a composition:
MenuItem objects are instantiated at the instantiation time of the Order object.
The MenuItem objects are destructed as soon as the Order object is destructed.
C++ example:
class Order {
MenuItem menus[NUMBER_OF_MENUS];
};
In case it's a aggregation:
The lifetime of the MenuItem objects is independent of the Order object lifetime.
C++ example:
class Order {
MenuItem* menus[NUMBER_OF_MENUS];
};
So it's a design decision. And might also depend on the implementation language. In Java, for example, there is no distinction between both, all object variables are references.
A lot is dependent on context. Let's use an example that should clarify the difference for you.
Suppose you are assembling a Car object in a car factory. The Car object has two Axle objects, four Wheel objects, a Motor object, and so on. All of those objects only have meaning within the context of the entire car (once you put them in, they stay there). That's composition.
Now, suppose you have a Car object in a junkyard. The Car object has the same stuff, but you can pull wheels or axles or the motor out of it and sell them separately. In that case, each part has a lifetime separate from that of the car. That's aggregation.
In my app Core Data model I have Sheet and Text entities. Sheet entity can have two Text's: privacyNotes and termsOfUse.
Both of Text type. So in XCode data modeler I create to-one relationships called "privacyNotes" and "termsOfUse" in Sheet with Text destination. Next goes to-one relationship "sheet" in Text. Then I select that Text.sheet relationship as inverse for Sheet.privacyNotes. So far so good. But when I set same Text.sheet relationship as inverse for Sheet.termOfUse XCode deletes this relationship as inverse Sheet.privacyNotes!
I understand that relationships in DB can be not so simple compared to Objective-C objects relationships, but I really don't get why SQLite or (CoreData) can't reuse one relationship as inverse for FEW other relationships?
A little peek under the abstraction hood might be enlightening*: a relation can only be the inverse for exactly one other relation because, in the backing store, they're represented by the same data. If a Text and a Sheet can have a certain relationship, Core Data does what a good human data modeler would do and stores that relationship as succinctly as possible. The relation properties of the entity objects are just ways of looking at that relationship.
To get the effect of what you're going for: go ahead and give Sheet properties for privacyNote and termsOfUse; but give Text properties like sheetIAmTermsFor and sheetIAmPrivacyNoteFor, and set them as inverses appropriately. Then in the Text class, add a synthetic property along these lines:
// in interface
#property (nonatomic, readonly) Sheet *sheet;
// in impl
-(Sheet *)sheet
{
if ([self sheetIAmTermsFor])
return [self sheetIAmTermsFor];
else
return [self sheetIAmPrivacyNoteFor];
}
If you want to write a setter too, you'll have to decide which role that setter should bestow on the Text (which Core Data can't figure out for you, another reason a property can't be the inverse of two different properties.)
If you need to enforce a constraint that a Text can only ever be a "privacyNote" or a "terms" but never both, override the setters for sheetIAmTermsFor and sheetIAmPrivacyNoteFor, following Apple's pattern in the docs, and have each null the other property when set.
(* Apple regards the SQLite databases Core Data generates as private to their implementation, but inspecting their schemas can be very educational. Just don't be tempted to write shipping code that goes behind CD's back to poke at the db directly.)
You are far better off having a one to many relationship between Sheet and Text with a validation limit of 2. Then you should have a type property in the text which declares it as either a privacyNotes or termsOfUse. From there you can add convenience methods to your Sheet subclass that allows you to retrieve either one.
Suppose I have the following data model:
Entity Person
Attribute name String
Attribute personType String
Attribute dailyRecords
Entity CarpenterDailyRecord
Attribute numberOfNailsHammered Int
Attribute picNameOfFinishedCabinet String
Entity WindowWasherDailyRecord
Attribute nameOfBuildingWashed String
Attribute numberOfWindowsWashed Int
I would like to establish a to-many relationship between the Person.dailyRecords and 1 of the daily record entities (which changes depending on the person type). Of course, i could create a CarpenterPerson and WindowWasher entity which each points to it's unique daily record structure, but i have to group people together in my app somehow.
so if i do a Group Entity:
Entity Group
Attribute people array
i'm still stuck. how do i point to multiple & different Person entities?
There must be an obvious answer, it's just i'm so new to all of this. thanks!
Create a parent (DailyRecord) entity that handles the relationship (Person <-->> DailyRecord). [CarpenterDailyRecord|WindowWasherDailyRecord] then inherits from DailyRecord.
The risk with this, however, is that all of the children (WindowWasherDailyRecord, CarpenterDailyRecord) will be in one table in the underlying sqlite structure and therefore can cause a performance impact. This is not a reason to avoid inheritance, just something to be aware of while designing your data model.