[ https://issues.apache.org/jira/browse/CASSANDRA-8984?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14385731#comment-14385731 ]
Benedict commented on CASSANDRA-8984: ------------------------------------- bq. the more interacting objects and abstractions around behavior we have, the more the complexity burden My model of complexity is: for any set of actions (units of execution) or abstractions you want to understand or modify, what is the transitive closure of _interactions_ with other actions/abstractions that need to be understood and considered in conjunction to ensure correctness. In parallel with this, I would suggest that fragility is the portion of this complexity that is implicit, or easily missed\*. To go back to your 5 20x complexity vs 100 1x complexity, this can be the difference between additive and multiplicative complexity. If all 20 points of complexity in each five classes can interact with any other point in any of the five classes, then the complexity burden is 3.2M, not 100. \* or if the complexity is too large to fit into your working memory My point is simply that if a new class reduces the number of interactions that need to be considered (i.e. isolation), then complexity is reduced. This is a bit of an abstract discussion, but I do love me some meta argumentation. (In my model of complexity, what I called acclimation is the number of high level abstractions a newcomer needs to have a vague understanding of to mentally map and model the overall functional unit they're addressing. I think this complexity is completely drowned out by the other once real work starts to happen. NB: I don't pretend this model of complexity is complete, but I think it serves for this discussion) bq. having to manage some state transitions manually leaks that portion of the Transactional abstraction Leakage at the precise clearly defined point cuts for interaction (i.e. the abstract methods requiring some boilerplate) aren't such a problem for complexity (by my definition), but they are _ugly_. I've uploaded an alternative approach [here|https://github.com/belliottsmith/cassandra/tree/8984-alt] that I do prefer, but technically increases the number of classes and doesn't reduce the amount of boilerplate, so I initially avoided (as inner classes can be even worse for acclimation IME), but does have the advantage of that boilerplate being better managed by the compiler and IDE. That is, solving the multiple inheritance problem through Java's only other mechanism besides code duplication: implementation proxies. bq. What's your confidence regarding the likelihood of 8690 delivering on that safety? safety or safely? The latter: high; the former: medium (i'm sure we can improve it, but doubt we'll get it to the same level) bq. I haven't had the time to sit down and really consider revisions to this design I'll leave both approaches I've concocted in your court for now, then. If you can come up with a third approach, I'm all ears :) > Introduce Transactional API for behaviours that can corrupt system state > ------------------------------------------------------------------------ > > Key: CASSANDRA-8984 > URL: https://issues.apache.org/jira/browse/CASSANDRA-8984 > Project: Cassandra > Issue Type: Improvement > Components: Core > Reporter: Benedict > Assignee: Benedict > Fix For: 2.1.4 > > Attachments: 8984_windows_timeout.txt > > > As a penultimate (and probably final for 2.1, if we agree to introduce it > there) round of changes to the internals managing sstable writing, I've > introduced a new API called "Transactional" that I hope will make it much > easier to write correct behaviour. As things stand we conflate a lot of > behaviours into methods like "close" - the recent changes unpicked some of > these, but didn't go far enough. My proposal here introduces an interface > designed to support four actions (on top of their normal function): > * prepareToCommit > * commit > * abort > * cleanup > In normal operation, once we have finished constructing a state change we > call prepareToCommit; once all such state changes are prepared, we call > commit. If at any point everything fails, abort is called. In _either_ case, > cleanup is called at the very last. > These transactional objects are all AutoCloseable, with the behaviour being > to rollback any changes unless commit has completed successfully. > The changes are actually less invasive than it might sound, since we did > recently introduce abort in some places, as well as have commit like methods. > This simply formalises the behaviour, and makes it consistent between all > objects that interact in this way. Much of the code change is boilerplate, > such as moving an object into a try-declaration, although the change is still > non-trivial. What it _does_ do is eliminate a _lot_ of special casing that we > have had since 2.1 was released. The data tracker API changes and compaction > leftover cleanups should finish the job with making this much easier to > reason about, but this change I think is worthwhile considering for 2.1, > since we've just overhauled this entire area (and not released these > changes), and this change is essentially just the finishing touches, so the > risk is minimal and the potential gains reasonably significant. -- This message was sent by Atlassian JIRA (v6.3.4#6332)