Core Data Managed Objects Sets - core-data

I am trying to write a simple personal finance app for my own use and have the following issue and wondered if anybody can set me straight.
My data model is quite simple, I have 'account' managed objects which have an NSSet of 'transaction' managed objects which in turn have an NSSet of 'split' managed objects.
The 'split' object has a category and an amount so any transaction can be made up of multiple categories with differing amounts. e.g transaction total is £40 made up from £25 - Food and £15 - Fuel etc
The 'transaction' managed object can also have an optional 1 to 1 relation with another 'transaction' managed object. This is for when I want to represent a transfer. Therefore I have 2 'transaction' objects with the same attributes like date etc but each belongs to a different 'account' so shows up when I query for a list of transactions for an account.
I have overridden the appropriate setters on the 'transaction' managed object like setDate so that when this is called, it checks to see if it has another 'transaction' managed object linked to it and if it has, also changes the date of that transaction. That way changes made to one transaction are reflected in the other account transaction.
Still with me..? Now the problem is with the NSSet of 'split' objects for a transaction.
Lets say I created a new transaction in account A.
I set the date for the transaction
I create a 'split' object for the transaction which for arguments sake has a category of food for £20.
In my UI, I then say this transaction is a transfer. This prompts me to pick the account I want to transfer to, I pick account B.
In the background, a new 'transaction' object is created, its account is set to account B, I copy across the date etc from the original transaction in account a but I want to set both 'transaction' objects to point to the same NSSet of 'splits'.
That way, if I change the category or amount in the split of one of the transactions its reflected in the other? Changes to the simpler attributes are handled through the setters like setDate mentioned before. Can both 'transaction' objects point to the same NSSet of splits or do I manually have to synchronise the changes to both sets when a change is made?
Hope this makes sense and thanks for any help received.

Your relationship would need to be many:many between transaction and split entities.
If you want to do that then it would be better to create custom methods for setting both the transfer and splits rather than trying to override. You do need to write the logic for how one relationship is updated based on a change to another objects relationship. Once you have the relationship configured the objects at the other end are common so changes to the split instances are trivial.
It's also a good idea to be using mogenerator to manage your custom code separately to the auto generated code.

I would suggest changing your model.
The Transaction entity is for data shared by the Split entity like date and description. Each Transaction always has at least 1 Split (or 2 Splits if you are making the system double entry accounting). You can expose the transaction properties through the Split entity.
Your Account entity won't have a direct relationship to Transaction. It will only have a direct relationship to the Split entity.

Related

DDD: It's correct to use Domain Events to guarantee invariants consistency? Do I have alternatives?

In my domain model I have the project entity (which is also aggregate root) which has products entity as child. One of the invariants of my domain model is that I can't have two products with the same code children of the same project (but is ok if the project is different).
My products are composed by parts which also has a similar rule (every part must have unique code within the same product) so parts are child of products because I need to ensure that rule. Children of product are also the activities that I need to do to create it because I'm describing a production tracking system.
Now, activities can have subactivities which can be assigned to factory area and so on.
Substantially what I have is that all entities starts from project just because I need to ensure one invariant(=business rule) but is not the best solution because every time I need to retrieve an entity I need to fill all the project (which can have 2000+ products).
What can I do to split that preserving my invariant but also freeing me to load a specific activity (or product) without retrieving all products of my project every time I need a child entity?
Should I need to split the Entities in several AggregateRoots, maintaining in the project a list of ProjectProductValueObject(string code) and use Domain Events in Aggregate's constructor to fire something like ProductCreatedEvent which try to create and add a new ProjectProductValueObject in my project using the AddProduct(ProjectProductValueObject product) method which contain my business rule and throws an exception if that's not satisfied? Is that ok and compliant to DDD principles?
Do I have other alternatives?
I have the feeling that you're overcomplicating the model.
From your description I've understood that:
Projects are root entities that can contain a list of
AssignedProduct, that is another root entity that contains a binding between the project (its id, see as a value object) and the product (I see it also as a value object)
So on with object and assigned object
In this way you've several Products that could be assigned to several Projects, but only the ones stored in AssignedProduct are valid. To avoid multiple assignments is just a matter of checking if the same couple of objects are already bound together.
If this doesn't match your model, ignore it.

Updating a value object from the aggregate in one-to-many relationship

I have recently dived into DDD and this question started bothering me. For example, take a look at the scenario mentioned in the following article:
Let's say that a user made a mistake while adding an EstimationLogEntry to the Task aggregate, and now wants to correct that mistake. What would be the correct way of doing this? Value objects by nature don't have identifiers, they are identified by their structure. If this was a Web application, we would have to send the whole EstimationLogEntry value object as a request parameter, along with the new values, just so we could replace the old value object with the new one. Should EstimationLogEntry be an entity?
It really depends. If it's a sequence of estimations, which you append every time, you can quite possibly envision an operation which updates the value only of the VO. This would use VO semantics (the VO is called to clone itself in-mem with the updated value on the specific property), and the command can just be the estimation (along with a Task id).
If you have an array of VO's which all semantically apply to Task (instead of just the "latest" or something)... it's a different matter. In that case, you'd probably have to send all of them in the request, and you'd have to include all properties too, but I'd say that the need to change just one, probably implies a need to reference them, which in turn implies a need to have an Entity instead of a VO.
DDD emphasizes the Ubiquitous language and many modelling questions like this ones will derive their answer straight from that language.
First things first, if there's an aggregate that contains a value object, there's a good chance that the value object isn't directly created by the user. That is, the factory that creates the value object lives on the aggregates API. The value object(s) might even be derived directly from the aggregates state instead of from any direct method call. In this case, do you want to just discard the aggregate and create a new one? That might make sense depending on your UL.
In some cases, like if you have immutable value objects (based on your UL), you could simply add a new entry into the log entry that "reverses" the old entry. An example of this would be bank accounts and transactions. If bank accounts are aggregate roots and transactions are the value objects. If a transaction is erroneously entered, you can simply write a reversing transaction to void it.
It is definitely possible that you want to update the value object but that must make sense in your UL and it's implementation must also be framed around your UL. For example, if you have a scheduling application and an aggregate root is a person's schedule while the value objects are meetings. If a user erroneously enters a meeting, what your aggregate root should do would be to invalidate the old meeting (flip a flag, mark its state cancelled e.t.c) and create a new one. These actions fit the UL for your scheduling app. The same thing as what you are calling "updating the entry" above.

DDD: Connection objects are Entity Object or Value Object?

I am working on an application where users can follow each other, in a similar fashion to Twitter.
After reading up on DDD, I understand that my users are Entity Objects - I refer to them using their unique ID.
When one user 'follows' another (i.e. forms a Connection), the relationship is stored in a many-to-many table. Its fields include FollowerID, TargetID, and Status. There can be only two records for each Follower/Target combination (one Active, the other Inactive), so I can safely identify objects based on their attributes.
So, I think my Connection objects are Value Objects, not Entity Objects, but I'm not sure. Can you help me with this decision?
You are correct that entities are unique and carry the notion of having an identity (i.e. only one unique user can exist). A Connection is dependent on other User entities. It represents some aspect between two users. That aspect is whether there is an active or inactive connection. Without containing the data of which users are connecting, a connection has no identity. It may even have it's own primary key in the database, but from a domain perspective, it has no identity of it's own.
Therefore, I would say that Connection is a value object.
To support my conclusion, Microsoft.Net Architecting Applications for the Enterprise, page 187, says:
A value object class represents an entity in the domain that mostly
contains data and lives for the data it contains. A value object is
fully identified by a combination of values it contains. An entity
object, on the other hand, has its own life and rich behavior
regardless of the data it contains. Entity objects are usually objects
with a longer lifetime. A value object represents an aspect of an
entity and can live only in relation to an entity.
And also on page 189:
One further comment is needed to explain the difference between
entities and value objects. You don’t need a repository or a data
mapper for a value object. You need a repository only for an entity.
The repository (or the mapper) for a given entity will certainly take
care of all value objects that depend on a given entity.
Some time ago, I saw a cartoon about scientist that had invented cloning. Every time he cloned himself, he destroyed previous version. Then person that was watching demonstration decided to interrupt and sabotaged destruction part so there were two scientists. Cartoon ended with some interesting existential questioning.
Values vs entities is not about having or not having id fields in one or another form. Point is - how we are looking at those objects through our domain perspective. If they are value objects, then only their value matters - 1st, 3rd and 53rd scientist are the same. If we care about identity, if we think that cloning 3rd scientist will never be like 1st one, then our object is an entity.

How should I enforce relationships and constraints between aggregate roots?

I have a couple questions regarding the relationship between references between two aggregate roots in a DDD model. Refer to the typical Customer/Order model diagrammed below.
First, should references between the actual object implementation of aggregates always be done through ID values and not object references? For example if I want details on the customer of an Order I would need to take the CustomerId and pass it to a ICustomerRepository to get a Customer rather then setting up the Order object to return a Customer directly correct? I'm confused because returning a Customer directly seems like it would make writing code against the model easier, and is not much harder to setup if I am using an ORM like NHibernate. Yet I'm fairly certain this would be violating the boundaries between aggregate roots/repositories.
Second, where and how should a cascade on delete relationship be enforced for two aggregate roots? For example say I want all the associated orders to be deleted when a customer is deleted. The ICustomerRepository.DeleteCustomer() method should not be referencing the IOrderRepostiory should it? That seems like that would be breaking the boundaries between the aggregates/repositories? Should I instead have a CustomerManagment service which handles deleting Customers and their associated Orders which would references both a IOrderRepository and ICustomerRepository? In that case how can I be sure that people know to use the Service and not the repository to delete Customers. Is that just down to educating them on how to use the model correctly?
First, should references between aggregates always be done through ID values and not actual object references?
Not really - though some would make that change for performance reasons.
For example if I want details on the customer of an Order I would need to take the CustomerId and pass it to a ICustomerRepository to get a Customer rather then setting up the Order object to return a Customer directly correct?
Generally, you'd model 1 side of the relationship (eg., Customer.Orders or Order.Customer) for traversal. The other can be fetched from the appropriate Repository (eg., CustomerRepository.GetCustomerFor(Order) or OrderRepository.GetOrdersFor(Customer)).
Wouldn't that mean that the OrderRepository would have to know something about how to create a Customer? Wouldn't that be beyond what OrderRepository should be responsible for...
The OrderRepository would know how to use an ICustomerRepository.FindById(int). You can inject the ICustomerRepository. Some may be uncomfortable with that, and choose to put it into a service layer - but I think that's overkill. There's no particular reason repositories can't know about and use each other.
I'm confused because returning a Customer directly seems like it would make writing code against the model easier, and is not much harder to setup if I am using an ORM like NHibernate. Yet I'm fairly certain this would be violating the boundaries between aggregate roots/repositories.
Aggregate roots are allowed to hold references to other aggregate roots. In fact, anything is allowed to hold a reference to an aggregate root. An aggregate root cannot hold a reference to a non-aggregate root entity that doesn't belong to it, though.
Eg., Customer cannot hold a reference to OrderLines - since OrderLines properly belongs as an entity on the Order aggregate root.
Second, where and how should a cascade on delete relationship be enforced for two aggregate roots?
If (and I stress if, because it's a peculiar requirement) that's actually a use case, it's an indication that Customer should be your sole aggregate root. In most real-world systems, however, we wouldn't actually delete a Customer that has associated Orders - we may deactivate them, move their Orders to a merged Customer, etc. - but not out and out delete the Orders.
That being said, while I don't think it's pure-DDD, most folks will allow some leniency in following a unit of work pattern where you delete the Orders and then the Customer (which would fail if Orders still existed). You could even have the CustomerRepository do the work, if you like (though I'd prefer to make it more explicit myself). It's also acceptable to allow the orphaned Orders to be cleaned up later (or not). The use case makes all the difference here.
Should I instead have a CustomerManagment service which handles deleting Customers and their associated Orders which would references both a IOrderRepository and ICustomerRepository? In that case how can I be sure that people know to use the Service and not the repository to delete Customers. Is that just down to educating them on how to use the model correctly?
I probably wouldn't go a service route for something so intimately tied to the repository. As for how to make sure a service is used...you just don't put a public Delete on the CustomerRepository. Or, you throw an error if deleting a Customer would leave orphaned Orders.
Another option would be to have a ValueObject describing the association between the Order and the Customer ARs, VO which will contain the CustomerId and additional information you might need - name,address etc (something like ClientInfo or CustomerData).
This has several advantages:
Your ARs are decoupled - and now can be partitioned, stored as event streams etc.
In the Order ARs you usually need to keep the information you had about the customer at the time of the order creation and not reflect on it any future changes made to the customer.
In almost all the cases the information in the value object will be enough to perform the read operations ( display customer info with the order ).
To handle the Deletion/deactivation of a Customer you have the freedom to chose any behavior you like. You can use DomainEvents and publish a CustomerDeleted event for which you can have a handler that moves the Orders to an archive, or deletes them or whatever you need. You can also perform more than one operation on that event.
If for whatever reason DomainEvents are not your choice you can have the Delete operation implemented as a service operation and not as a repository operation and use a UOW to perform the operations on both ARs.
I have seen a lot of problems like this when trying to do DDD and i think that the source of the problems is that developers/modelers have a tendency to think in DB terms. You ( we :) ) have a natural tendency to remove redundancy and normalize the domain model. Once you get over it and allow your model to evolve and implicate the domain expert(s) in it's evolution you will see that it's not that complicated and it's quite natural.
UPDATE: and a similar VO - OrderInfo can be placed inside the Customer AR if needed, with only the needed information - order total, order items count etc.

What's the Best Way to Simulate an Array Type Attribue in Core Data?

I've got a list of contacts, each having several emails.
Should I create a Contact Core Data entity and a Email entity and link several email objects to one contact object? Or should I do it another way e.g concatenate all the emails and store them as one big string?
What's the cleanest and most efficient way to deal with such a configuration ?
Thanks
Always think of Core Data as an object graph and model your data accordingly.
You should have a Contact entity and an Email entity. The email should be on the other end of a one-to-many bi-directional relationship with Contact. If you care about a specific order then you should also have some orderable value in the Email entity for later sorting.
Should I create a contact CoreData entity and a email entity and link several email objects to one contact object ?
This solution sounds reasonable. Still it is not an "array type attribute" as to-many relations are unordered sets instead of ordered arrays.
Your entity graph would look something like (pseudocode):
Contact{
name:string
emailAddress:string
//...other attributes of contacts
emails<--(optional,cascade)-->>Email.contact
}
Email{
from:string
// ... other attributes of emails
contact<<--(required,nullify)-->Contact.emails
}
In both the entity (abstract) and object (concrete) graphs, you need only link contacts to their emails without any particular order. You shouldn't worry about ordering the relationships in the entity graph because the order in which you want to display the objects might change from moment-to-moment. That order is determined by the sort descriptor of each particular fetch request. The fetch request will return an array in any order you define. E.g one time you want emails sorted by date received, another time by from, another time by some other attribute. You can even resort the array the returned by a fetch to get exactly the order you want.
You just want to make sure that the entities have attributes that capture the information on which you want to sort.
In the very rare cases in which some type of ordering is absolutely required in the entity graph itself, you should add a ordering attribute to the entity itself and write custom code to maintain the sort order.

Resources