Re: aggregate boundries
- From: "H. S. Lahman" <h.lahman@xxxxxxxxxxx>
- Date: Mon, 30 Jan 2006 18:12:20 GMT
Responding to Kurbylogic...
I'm attempting to create a program to help me budget my money. I want to do something different form money/quicken in that I assign my existing assets to categories such as mortgage and savings each expense will then be deducted from the category and credited by my paychecks allowing me to more easily determine how much money I have set aside for the category. But I'm having a bit of trouble determining how to maintain the relationship invariants in OO.
Account, Category, and Payee are root objects Category is a composite containing other Categories Account owns Transactions and Transaction owns TransactionCategory
OK, so far this sounds like:
* identified in R1
[Transaction] -------------------------- [Payee]
| * pays 1
| identified in
|
| R2
|
| updates
| 1 1 child of
[Account] [Category] -----------+
| | |
+--------+--------------+ |
| R3 | R4
_ |
V * contains |
[CategoryContext] ----------------------+
+ currentBalanceNote that the Category structure is just a simple GoF Composite pattern. What I am unclear about is what [Payee] represents. I assume this is who the money goes to when a check is written. You suggest below that [Payee] may be hierarchically organized as well. In that case one would need a similar Composite pattern for [Payee] as well (i.e., the name on the check is only provided by a leaf).
The invariants are that Transaction.Payee is member of Payees and TransactionCategory.Category is member of Categories
I'm not sure why Transaction needs to know the Category. Isn't a Transaction just an update of a specific Account? If so, then the Category is defined by the R4 hierarchical relationship. So if one has a Transaction in hand one just needs to navigate R2 -> R4 to obtain the immediate Category. One can then "walk" all the way up the Category hierarchy via R4 to handle the debits and credits at each level.
I've created a larger aggregate DataContext to encapsulate the list of accounts, payees and root categories. I use an identity map during
I suspect that Accounts and Payees are leaves in orthogonal data structures. So I would probably not have as wide an umbrella as you suggest here for DataContext.
load to ensure the correct instances are assigned to each object. The model is not bi-directional so if I ask for all transactions by category I search every transactioncategory of every transaction in every account. My primary view will be by category so I think a bi-directional relation here might be best but at the moment category knows nothing about transaction, and I've optimized the search a bit by assigning left/right tree numbers to each category. The question I have is what the best way to control modifications is. My first thought was that when context is saved my thinking was I would enumerate all transactions in the datacontext if no id is assigned its new, if transaction.HasChanges I update and if the transaction was loaded but is no longer in the transaction collection it was deleted, and likewise for each payee, category, and transaction.
The problem is that this doesn't ensure the invariants above are not violated, context.getAccounts()[0].getTransactions()[0].Payee = new Payee("Test"); and similarly in relation to categories. I don't want to reload the data on every change and in some cases is not possible as I'm also performing updates via an Indigo service to allow me to access my info from home or work but at some clients I'm not allowed to connect my laptop to the network and so I wanted to be able to save a serialized copy of the datacontext to disk and queue modifications so that they can be sent later when connection is available.
This is a very different and potentially very nasty problem. Essentially your application is caching data from the DB than is not in synch with the DB for extended periods of time. Money/Quicken don't have this problem because they update the DB with every transaction immediately. (Note that newer versions of Quicken don't even have a Save button anymore.) Enter stage left, tripping: DB replication.
You have an added problem due to the complexity (nesting) of your summaries. Money/Quicken basically have only one total number to keep track of at the Account level, the current balance. Your summaries add another level of complexity due to the nesting and the requirement that the subcatagories sum to the supercategory.
However, I don't think the problem is insurmountable if you have a complete copy of the DB on your laptop. [If you don't then you will have a problem reading Transactions for UI display when the base is unavailable. B-)] So long as that laptop copy is internally consistent for recent activity, you can just do the brute force approach and copy it to you home desktop or whatever when you get the chance. IOW, do a poor man's replication by treating the home server as a backup.
For the posting mechanics to ensure internal consistency you just need to "walk" the Composite tree above and make the same adjustment at every level above Account _when you update Account_. That will ensure that the numbers are consistent so long as you do the update prior to processing any other change. [Note that if the transaction in hand is changed at the account level you obviously have to post the delta of the change to Account and the categories. But that delta will be the same at every level.]
To do that you just need to keep a lastBalance attribute in Transaction. When you create a Transaction or have completed the update of Account and the Categories for a change, you set lastBalance to currentBalance. So the only time they will be different is when you have made a change to an existing transaction in the UI. You just need to look for that when you post to Account to determine whether you need the straight amount or a delta. IOW, just make sure you complete the posting before processing another Return in the UI.
************* There is nothing wrong with me that could not be cured by a capful of Drano.
H. S. Lahman hsl@xxxxxxxxxxxxxxxxx Pathfinder Solutions -- Put MDA to Work http://www.pathfindermda.com blog: http://pathfinderpeople.blogs.com/hslahman (888)OOA-PATH
.
- Follow-Ups:
- Re: aggregate boundries
- From: kurbylogic@xxxxxxxxxxx
- Re: aggregate boundries
- References:
- aggregate boundries
- From: kurbylogic@xxxxxxxxxxx
- aggregate boundries
- Prev by Date: Re: File system and UML diagrams
- Next by Date: Re: Is it a facade
- Previous by thread: aggregate boundries
- Next by thread: Re: aggregate boundries
- Index(es):