Cocoa bindings: get old value upon change - cocoa

I am writing a core data Cocoa application in which there are accounts and transactions (monetary). The account entity description contains a balance attribute. The transaction entity description has a relationship to an account.
I need the application to update account balances when transactions have their accounts set or changed. For example, if a transaction's account is changed from checking to credit, the balances of both checking and credit should be changed to reflect this.
The problem I am having is that I am unsure how to determine the transaction's old account so I can update its balance. I am using bindings.
Can anyone point me in the right direction?

I assume that the account entity has the inverse relationship to the transactions. (Apple strongly suggests you always have inverse relationships. So if you haven't, please set it up!)
Let's say you have a subclass Account of NSManagedObject for the account entity, and Transaction for the transaction entity.
Call the inverse relationship to transactions as transactions.
Then, when you change the account for the transactions, the inverse relationship is automatically updated by CoreData. So, all you have to do is to write a self-observation routine for transactions in Account so that the Account objects keep track of the balance themselves. I think it is more object-oriented-y to make Account objects to take care of themselves than changing the balance from the side of the Transaction object... although of course it depends on your taste.
To perform the observation, you use KVO. Basically, you register the KVO by addObserver:forKeyPath:options:context: with a suitable set of options. Then, you get the change by implementing observeValueForKeyPath:ofObject:change:context:. The changes can be found in the dictionary passed to that method.

Related

Using superclass in Spring Data JPA

I have 2 tables - ClientAccount and BankAccount. Operations allowed are e.g. "buy" - that means transfer money from bank account to client account; and "transfer" - that means transfer money between two client accounts. I want to log both these events. To do so, I created a table Log, with sender and recipient fields, and now I need to define a proper way to define relationships between these 3 tables.
Firstly I decided to make recipient and sender as of ClientAccount type but in this case I cannot add info about "buy" operation (because sender in that case would be of BankAccount type).
Is there any way to create a superclass Account, which will be extended both by BankAccount and ClientAccount so I can use a simple Account type in Log table? What relationships do I have to define then?
You need Account parent entity and children ClientAccount and BankAccount. Then, you would be able to save account-account operation in the log.
It's up to you how to persist it in the database. Different ways are described here:
https://www.baeldung.com/hibernate-inheritance

Validation in Domain Model of Domain Service?

I'm reading the book "Architecting Applications for the Enterpise (Dino Esposito)". It raised a question about validation.
The Domain Model can have a property CanBeSaved which calls the Validate() method of the Domain Model. All good, except for complex situations.
For example a Customer model which needs a unique customer code (ex. 000542). You can only check this with database access. Isn't it better to put the Validation always in a Domain Service. So you have only one way of checking if an aggregate is in a valid state? If you use both, a developer can 'forget' to use the domain service validation for the Customer.
I find it better to have always valid entities rather than rely on an external validation object.
That being said, unique checks are a bit of an exception since it is often not something that the aggregate itself can determine on its own, you have to look into all existing aggregates to see if the value is not already taken. What I do is check for availability of the value before creating the entity, and also put a constraint in the database which will verify uniqueness at persistence time. You could also try to find a domain concept that encompasses all your entities and make it an aggregate that has a list of all codes and enforces the uniqueness invariant.

Which objects are responsible for maintaining references between aggregates?

Suppose I have one aggregate, Ticket. A Ticket will have one assigned Department and one or more assigned Employee.
When instantiating a Ticket, should a TicketFactory be responsible for ensuring that a Ticket is created with a valid/existent Department and Employee?
Likewise, when decommissioning a Department or Employee, what is responsible for ensuring that a new Department or Employee is assigned to a Ticket so as to maintain its invariants? Could there be a service in the domain responsible for decommissioning, or is this a case where eventual consistency or some form of event listening should be adopted?
The TicketFactory would be declare that in order to create a Ticket you need references to both a Department and an Employee. It would not verify that those actually exist. It would be the responsibility of the calling code to obtain the appropriate references.
If using eventual consistency, the decommissioning of a Department and Employee would publish events indicating the decommission. There would be a handler associated with a Ticket which would subscribe to that event and either assign a new department and employee or send some sort of warning to task.
Take a look at Effective Aggregate Design for more on this.
I've recently started exploring DDD, so I have ran into some of the issues you mention.
I think that TicketFactory should always return validated/properly built Ticket instances. If you model is complex, you can have a domain service that validates that a given Department or Employee can be attached to it and then the factory uses it. Otherwise, you can just put it all in the factory. But what comes out of the factory should be a proper ticket.
I'd say that if e.g. only Ticket knows about the other two, a domain service that uses the Department and Employee repos would get the job done. If the relationship is bidirectional, then you can utilize event sourcing. Also, if it's really a event that should be captured in your domain model, and has other consequences other than reshuffling tickets, you can attach one of the handlers to this event to be InvalidTicketHandler. But if it's a small scale thing, keep it simple, just have a domain service that maintains the invariants.
Sidenote: If the Department and/or Employee are aggregates themselves, then you can reference them within Ticket via their identifier (e.g. employee's company ID or ID-code of the department). In that way you'll achieve consistency easier as you will not cross consistency boundaries between different aggregates.
A FACTORY is responsible for ensuring that all invariants are met for the object or AGGREGATE it creates; yet you should always think twice before removing the rules applying to an object outside that object. The FACTORY can delegate invariant checking to the product, and this is often best. [Domain-Driven Design: Tackling Complexity at the Heart of Software]
A depends on question type, but from the look of it it seems like a great candidate for an application layer functionality, i wouldn't go for the event solution though cause i find it only suitable in between layers and not between objects in the same layer.

displaying balance in core data

I have 3 entities in an example app:
Account
name
balance (NSDecimalNumber overall balance of account)
balances (to-many relationship with Balances)
transactions (many-to-many relationship with Transaction.accounts)
Transaction
payee
amount
accounts (many-to-many relationship with Account.transactions)
balances (many-to-one relationship with Balances.transaction)
Balance
amount
account (one-to-many relationship with Account.balances)
transaction (one-to-many relationship with Transaction.balances)
I want to display the transactions of a particular account in an NSTableView. The problem comes in when I want to display the balance of the current account. Because a transaction may be associated with multiple accounts, it may have multiple balances. I can't think of a way to select the particular balance associated with the current account being displayed in an NSTableColumn. Does anyone have any suggestions of how to change the model or how to connect things up to the NSTableView in such a way that the proper balance is displayed?
The only thing I can think of is to create a sub-class of NSCell that knows how to select the balance associated with the current account view or an NSValueTransformer that does a similar thing. This seems like a very inelegant solution though. If there is a better way I would like to know how.
Update
Here's a screenshot of a demo app that illustrates the above. I would like the far right column to display the balance as of that specific transaction. Works well enough if the transaction has a balance attribute; however, in my app the balance is stored in a separate table because there may be multiple types of balances for each transaction. I can't figure out how to get it to display the proper balance in the table view though:
Have you considered populating the table via this NSTableViewDataSource method:
- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
I know, it looks ugly, but you can do somersaults with it.
Bind the table column's value binding to your array controller of Accounts with the controller key selection and the model key path balance.

Creating a Core Data Inverse Relationship

I'm trying to write my first Cocoa app, and Core Data is making it difficult to model my data objects. I have two entities that I want to manipulate: Account and Transaction. Account has a human-readable name and that's about it. Transaction stores a monetary value, and references to two accounts called debitAccount and creditAccount (I'm working on a double-book accounting app).
I want to be able to find all the Transactions for a given Account, whether they use debitAccount or creditAccount. How can I do this? Is there a way to do it that will work easily with Cocoa UI binding?
If I understand you correctly, you want Transaction to be related to Account via two relationships: debitAccount and creditAccount, yes? And you're wondering about creating inverse relationships.
In short, a relationship can only be the inverse of one other relationship. So you won't be able to create a relationship called, say, transactions that is the inverse of both debitAccount and creditAccount. Instead, you'll have to create two relationships, like debitTransactions and creditTransactions (I'm sure you'll think of more appropriate names for these...)
Now, since relationships are modeled as sets (specifically, NSSets), you can union the creditTransactions and debitTransactions relationships for a particular Account to get all transactions that account is involved with.
A (possibly better) alternative would be to introduce an intermediate entity, with a name like TransactionAccount that has a to-one relationship to both Account and Transaction as well as an attribute, like accountRole that identifies the account as being the debit or credit account relative to that particular transaction. You'd create inverse to-many relationships on both Transaction and Account with a name like transactionAccounts. That way, you could write something like this:
[account valueForKeyPath:#"transactionAccounts.transaction"]
to get all the transactions for a particular account. You could use an NSPredicate to filter the set to only transactions where the account was the debit/credit account.
The solution that worked best (and made the most sense) to me was to create a subclass of NSManagedObject to use as my Account entity:
#interface Account : NSManagedObject {
}
-(NSArray*)getTransactions;
#end
I have the actual lookup logic inside -getTransactions, which wasn't too hard to do by hand. This is working out well so far, especially because the method name conforms to KVO.
To make Core Data return Accounts instead of NSManagedObjects, I had to change the entity's "Class" property in Xcode's data modeling tool.

Resources