etoile / CoreObject

Distributed version control + object persistence framework

Home Page:http://coreobject.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Clean COEditingContext/PersistentRoot/Branch internals

ericwa opened this issue · comments

Working on lazy loading reminded me that these classes are getting unwieldily.

One feeling I have is that COBranch and COPersistentRoot are doing 2 roles:

  • public API for the way branches / persistent roots are presented to users
  • objects for tracking uncommitted changes, and logic for committing, as well as syncing the in memory state to match changes in the store.

One idea: move internals of COPersistentRoot / COBranch to COEditingContext. I'm not suggesting changing the public API of COEditingContext/ COPersistentRoot / COBranch at all, but just stripping all code and state out of COPersistentRoot / COBranch. All ivars of COPersistentRoot / COBranch (except UUID) would be removed, and the public methods would be forwarded to methods on COEditingContext. e.g. -[COPersistentRoot isDeleted] would call -[COEditingContext persistentRoot:isDeleted].

Then we would need to store all of the state relating to COPersistentRoot/COBranch in COEditingContext.

I feel like the attempt to split code between the 3 classes has failed, and we have a lot of complexity from trying to pretend that they are encapsulated classes. Maybe the logic would be clearer if it was all in one place (i.e. COEditingContext).

Anyway this is just a rambling idea, not sure if it would help.

Ok, I finished updating the first post with what I wanted to say. Github posted an incomplete version before...

I have a feeling a bit similar, but I see it in a different way.

From my perspective, it's a problem between state vs behavior. When you look at the state and how it is split across COEditingContext/COPersistentRoot/COBranch, imo it looks fine. I mean we don't have too much state, it's pretty well balanced and fit the responsibilities you'd expect each class to have.

For the behavior, half of the code looks fine, but the rest doesn't. The change tracking logic and store vs memory synchronization logic could be better but they aren't that bad. For instance, the change tracking logic is still relatively simple. On the other hand, the synchronization logic is complex due to the cross persistent root relationships, but it's almost all in one place in COEditingContext, so it doesn't look so bad either.

However the commit logic is really hard to read and debug, especially since we are splitting some complex behavior accross 3 or 4 classes and also some methods are too big.

My take on this would be to introduce new classes that clarify complex behaviors and may be responsibilities too. For example, a COCommit class could hold all the commit logic in one place. Then we could evaluate if we need to go further and create additional classes such as COChangeTracking or COStoreChangeSynchronization.

In the end, COEditingContext/COPersistentRoot/COBranch would act as both state holders in memory and user-presented objects, while their implementations would be much shorter (by being delegated to private classes representing cross-cutting behaviors).

Anyway that's just a possibility, I'm not sure it would work out entirely. It would probably improve the commit logic, but for the rest I'm less sure.

On a related note, I remember that one thing which was making cross persistent relationships hard to debug was that I constantly had to look to COObjectGraphContext in addition to COEditingContext.

If we don't decide to turn -[COObjectGraphContext replaceObject:withObject:] into a public method, we could consolidate its logic along with the cross persistent relationship code from COEditingContext, into a a helper class like CO(Store)ChangeSynchronization as I was suggesting previously. May be this would help…

This was just to illustrate what I was discussing in my previous post.

Yes, I want to merge -replaceObject:withObject: with the logic used for lazy loading.
I also had trouble with how the code was spread out. Probably the logic in COObjectGraphContext replaceObject:withObject should be moved to COEditingContext.