Context
I'm dealing with a large, nested, structured document, which shows up on the screen as a scene graph. The user needs to have the ability to modify this document -- which I am currently using functional zippers to implement.
Now, currently, I'm redrawing the entire document after every change. However, when the use of a scene graph, I would only need to modify the part that changes.
However (without intending to start a flamewar), I'm increasingly starting to feel that this problem is fundamentally a problem about state, not functions. In particular:
user actions (up, down, left, right, insert char, delete char) are about manipulating state, not doing calculations
there's only one copy of the document at once, it's only hit by one thread, and there's no gain for sharing
Current Approach
I use functional zippers to store the document and to provide state manipulation functions. Then, I continuously redraw.
Solution I suspect might be correct:
Store everything in a scene graph, ditch function zippers, and after modification, directly modify the part of the scene graph that changes.
Technical Question:
Have others dealt with this? Is there a technical, formal name for this problem? (Equiv of "Dining Philosophers" in concurrency?) Is there a well established solution to this problem?
Disclaimer
This question is a bit soft. I can't paste a code example of minimal broken case since
* my code is around 5K LOC
* it's not for me to share publicly
However, this is a real technical solution, and I hope others can share their answers
Thanks!
Your fundamental process sounds fine. It is flexible in it's current form because you have the option of having a separate thread update the tree for instance and you can implement an "undo" button rather trivially. If after each modification you return both the new tree and the path to the part that changed you could then update only the part that changed in the display. Lots of people have stronger opinions than me on separating "models" and "views" though I suspect that at least some of their wisdom applies here.
Related
I'm trying to create a subclass of QUndoCommand that represents a movement of one or more QGraphicsItem. If several items are moved at once (by selecting them first), this should be represented as a single command within the QUndoStack.
Since the whole movement logic (including selections) is already implemented by QGraphicsScene, I'm not sure what would be the best place to create the undo commands.
The undoframework example provided by Qt subclasses QGraphicsScene and overrides mousePressEvent() / mouseReleaseEvent() to perform some manual hit testing. Is this really the way to go?
I'm afraid that this approach could miss some special cases such that the generated undo commands do not reflect exactly the same movement that has been performed by the internal Qt implementation. Some items could have the ItemIsMovable flag unset for example. Also, when moving multiple items at once, it seems better to store just the delta movement instead of old and new position.
It would be great if you could provide some short sample code/sketch for clarification.
I personally would wrap and encapsulate QGraphicsScene and implement the undo/redo stuff there. This allows to define your own and cleaner interface, free of the clutter of all the functionality you won't need. It will also make it easier to replace QGraphicsScene with another API if such a need arises in the future and makes your core stuff more portable.
Many of the high level classes in Qt, especially those for graphics, are not exactly what I'd call "cutting edge", the same applies even more so to the rudimentary examples Qt provides for them. There are several professional graphics applications that use Qt, but none of them uses stuff like QGraphicsScene. I suppose the reason for this is also the reason I extrapolated from my own experience using Qt - as big as a framework it may be, there is a lot of stuff that's missing, and a lot of stuff that just doesn't really work the way people have come to expect from professional software, or even common logic in such workflows. Qt was developed by very good programmers, but it seems like they didn't have someone experienced in the actual graphics applications workflow to advise them.
Focus on a wrapper that features the functionality you need, and make it work with QGraphicsScene instead of using it directly. This way there is less chance that you miss something, your design is more self contained and cleaner too. The same applies to the undo API as well, don't feel obligated to use Qt's, I myself have tried it and ended up implementing my own, as I found the one provided by Qt was rather "stiff".
In the case of moving several items at once - yes, that should create a single undo entry, which will undo the moving of a selection group, which will feature all the selected items. Whether you will use a delta or position - it is entirely up to you. The delta does make a little more sense when you move multiple selected items, since the selection group is not really an item with position.
Another consideration, if you plan on making history persistent across different sessions - you can't rely on pointers, since those will be arbitrary each time you run your application. My strategy is to implement a unique integer ID and an associative registry which stores the id and pointer for each item. Then you use the ID for the history, and that will internally map to the pointer of the actual item.
In this presentation SceneGraph and SceneTree are presented.
ST (SceneTree) is essentially an unfolded synchronized copy of SG (SceneGraph).
Since you are going to need ST anyway because:
it offers instance, where you need to save attributes
you need to traverse ST anyway for updating transformation and other cascading variables, such as visibility
even if SG offers less redundancy, what is the point to have SG in the first place?
To quote Markus Tavenrath, the guy who gave that presentation, who was asked the same question: http://pastebin.com/SRpnbBEj (as a result of a discussion on IRC (starts ~9:30))
[my emphasis]
One argument for a SceneGraph in general is that people have their
custom SceneGraphs implementation already and need to keep them for
legacy reasons and this SceneGraph is the reason why the CPU is the
bottleneck during the rendering phase. The goal of my talks is to show
ways to enhance a legacy SceneGraph in a way that the GPU can get the
bottleneck. One very interesting experiment would be adding the
techniques to OpenSceneGraph…
Besides this a SceneGraph is way more powerful with regards to data
manipulation, data access and reuse. I.e. the diamond shape can
be really powerful if you want to instantiate complex objects with
multiple nodes. Another powerful feature in our SceneGraph is the
properties feature which will be used for animation in the future
(search for LinkManager). With the LinkManager you can create a
network of connected properties and let data flow along the links in a
defined order. What’s missing for the animations are Curve objects
which can be used as input for animations. All those features have a
certain cost on the per object level with regards to memory size and
more memory means more touched cachelines during traversal which means
more CPU clocks spend on traversal.
The SceneTree is designed to keep only the hierarchy and the few
attributes which have to be propagated along the hierarchy. This way
the nodes are very lightweight and thus traversal is, if required,
very efficient. This also means that a lot of features provided in the
SceneGraph are no longer available in the SceneTree. Though with the
knowledge gained by the SceneTree it should be possible to write a
SceneGraph which provides most of the performance features of the
SceneTree.
Depending on the type of application you’re writing you might even
decide that the SceneTree is too big and you could write your
application directly on an interface like RiX which doesn’t have the
hierarchy anymore and thus eliminating yet another layer ;-).
So first reason is that people are already used to using a scenegraph and many custom implementations exist.
Other than that the scenetree is really a pruned scenegraph where only the necessary components which means that a scenegraph is more useful to the artists and modelers as it better abstracts the scene. A complex property may for example be a RNG seed that affect the look of each person in a crowd.
In a scenegraph that root Person node would just have a single property seed. Its children would select the exact mesh and color based on that seed. But in the expanded tree the unused meshes for alternate hairstyles, clothing and such will already have been pruned.
I wish to present the idea of MVC to a bunch of old C++ spaghetti coders (at my local computer club).
One of them that has alot of influence on the rest of the group seems to finally be getting the idea of encapsulation (largely due in part to this website).
I was hoping that I could also point him in the right direction by showing him Model View Controller, but I need to do it in a way that makes sense to him, as well as it probably needs to be written in C/C++!
I realize that MVC is a very old architectural pattern so it would seem to me that there should be something out there that would do the job.
I'm more of a web developer, so I was wondering if anybody out there who is a good C/C++ coder could tell me what it is that made the MVC light switch turn on in your head.
Don't start off with MVC. Start off with Publish / Subscribe (AKA the "listener" pattern).
Without the listener pattern fully understood, the advantages of MVC will never be understood. Everyone can understand the need to update something else when something changes, but few think about how to do it in a maintainable manner.
Present one option after another, showing each option's weaknesses and strengths: making the variable a global, merging the other portion of code into the variable holder, modifying the holder to directly inform the others, and eventually creating a standard means of registering the intent to listen.
Then show how the full blown listener can really shine. Write a small "model" class and add half a dozen "listeners" and show how you never had to compromise the structure of the original class to add "remote" updates.
Once you get this down, move the idea into to the "model view" paradigm. Throw two or three different views on the same model, and have everyone amazed on how comparatively easy it is to add different views of the same information.
Finally discuss the need to manage views and update data. Note that the input is partially dependent on items which are not in the view or the model (like the keyboard and mouse). Introduce the idea of centralizing the processing where a "controller" needs to coordinate which models to create and maintain in memory, and which views to present to the user.
Once you do that, you'll have a pretty good introduction to MVC.
You might find it easier to sell them on the Document/View or Document/Presenter patterns. MVC was invented on Smalltalk where everything about the different UI elements had to be coded by the developer (as I understand, never used the thing). Thus the controller element was necessary because didn't have things like TextElement::OnChange. Now days, more modern GUI API's use Document/View but Document/Presenter is something I've seen proposed.
You might also consider reading Robert Martin's article on the TaskMaster framework.
You might also consider that any C++ developer who is not familiar with these patterns and already understands their purpose and necessity is either a complete newb or a basket-case best avoided. People like that cause more harm than good and are generally too arrogant to learn anything new or they already would have.
Get some spaghetti C++ code (theirs?), refactor it to use MVC, and show them what advantages it has, like easier unit testing, re-use of models, making localized changes to the view with less worry, etc.
Having read up on quite a few articles on Artificial Life (A subject I find very interesting) along with several questions right here on SO, I've begun to toy with the idea of designing a (Very, very, very) simple simulator. No graphics required, even. If I've overlooked a question, please feel free to point it out to me.
Like I said, this will hardly be a Sims level simulation. I believe it will barely reach "acceptable freeware" level, it is simply a learning exercise and something to keep my skills up during a break. The basic premise is that a generic person is created. No name, height or anything like that (Like I said, simple), the only real thing it will receive is a list of "associations" and generic "use", "pick up" and "look" abilities.
My first question is in regards to the associations. What does SO recommend as an efficient way to handle such things? I was thinking a multimap, with the relatively easy set up of the key being what it wants (Food, eat, rest, et cetera) and the other bit (Sorry, my mind has lapsed) being what it associates with that need.
For example, say we have a fridge. The fridge contains food (Just a generic base object). Initially the person doesn't associate fridge with food, but it does associate food with hunger. So when its hunger grows it begins to arbitrarily look for food. If no food is within reach it "uses" objects to find food. Since it has no known associations with food it uses things willy-nilly (Probably looking for the nearest object and expanding out). Once it uses/opens the fridge it sees food, making the connection (Read: inserting the pair "food, fridge") that the fridge contains food.
Now, I realise this will be far more complex than it appears, and I'm prepared to hammer it out. The question is, would a multimap be suitable for a (Possibly) exponentially expanding list of associations? If not, what would be?
The second question I have is probably far easier. Simply put, would a generic object/item interface be suitable for most any item? In other words, would a generic "use" interface work for what I intend? I don't think I'm explaining this well.
Anyway, any comments are appreciated.
If you were doing this as a hard-core development project, I'd suggest using the equivalent of Java reflection (substitute the language of your choice there). If you want to do a toy project as a starter effort, I'd suggest at least rolling your own simple version of reflection, per the following rationale.
Each artifact in your environment offers certain capabilities. A simple model of that fact is to ask what "verbs" are applicable to each object your virtual character encounters (including possible dependence on the current state of that object). For instance, your character can "open" a refrigerator, a box of cereal, or a book, provided that each of them is in a "closed" state. Once a book is opened, your character can read it or close it. Once a refrigerator is opened, your character can "look-in" it to get a list of visible contents, can remove an object from it, put an object in it, etc.
The point is that a typical situation might involve your character looking around to see what is visible, querying an object to determine its current state or what can be done with it (i.e. "what-state" and "what-can-i-do" are general verbs applicable to all objects), and then use knowledge about its current state, the state of the object, and the verb list for that object to try doing various things.
By implementing a set of positive and negative feedback, over time your character can "learn" under what circumstances it should or should not engage in different behaviors. (You could obviously make this simulation interactive by having it ask the user to participate in providing feedback.)
The above is just a sketch, but perhaps it can give you some interesting ideas to play with. Have fun! ;-)
To the first question:
My understanding is that you have one-to-possibly-many relationship. So yes, a multimap seems appropriate to me.
To the second question:
Yes, I believe a generic interface for objects is appropriate. Perhaps use something similar to REST to manipulate object state.
I heard a podcast a while back with the developer of The Noble Ape Simulation, which may be interesting to you - conceptwise and perhaps codewise, as you can access the source code, as well as download binaries.
The podcast was FLOSS Weekly 31 with Randal Schwartz and Leo Laporte.
Life with lisp(sbcl) :)
I have inherited a monster.
It is masquerading as a .NET 1.1 application processes text files that conform to Healthcare Claim Payment (ANSI 835) standards, but it's a monster. The information being processed relates to healthcare claims, EOBs, and reimbursements. These files consist of records that have an identifier in the first few positions and data fields formatted according to the specs for that type of record. Some record ids are Control Segment ids, which delimit groups of records relating to a particular type of transaction.
To process a file, my little monster reads the first record, determines the kind of transaction that is about to take place, then begins to process other records based on what kind of transaction it is currently processing. To do this, it uses a nested if. Since there are a number of record types, there are a number decisions that need to be made. Each decision involves some processing and 2-3 other decisions that need to be made based on previous decisions. That means the nested if has a lot of nests. That's where my problem lies.
This one nested if is 715 lines long. Yes, that's right. Seven-Hundred-And-Fif-Teen Lines. I'm no code analysis expert, so I downloaded a couple of freeware analysis tools and came up with a McCabe Cyclomatic Complexity rating of 49. They tell me that's a pretty high number. High as in pollen count in the Atlanta area where 100 is the standard for high and the news says "Today's pollen count is 1,523". This is one of the finest examples of the Arrow Anti-Pattern I have ever been priveleged to see. At its highest, the indentation goes 15 tabs deep.
My question is, what methods would you suggest to refactor or restructure such a thing?
I have spent some time searching for ideas, but nothing has given me a good foothold. For example, substituting a guard condition for a level is one method. I have only one of those. One nest down, fourteen to go.
Perhaps there is a design pattern that could be helpful. Would Chain of Command be a way to approach this? Keep in mind that it must stay in .NET 1.1.
Thanks for any and all ideas.
I just had some legacy code at work this week that was similar (although not as dire) as what you are describing.
There is no one thing that will get you out of this. The state machine might be the final form your code takes, but thats not going to help you get there, nor should you decide on such a solution before untangling the mess you already have.
First step I would take is to write a test for the existing code. This test isn't to show that the code is correct but to make sure you have not broken something when you start refactoring. Get a big wad of data to process, feed it to the monster, and get the output. That's your litmus test. if you can do this with a code coverage tool you will see what you test does not cover. If you can, construct some artificial records that will also exercise this code, and repeat. Once you feel you have done what you can with this task, the output data becomes your expected result for your test.
Refactoring should not change the behavior of the code. Remember that. This is why you have known input and known output data sets to validate you are not going to break things. This is your safety net.
Now Refactor!
A couple things I did that i found useful:
Invert if statements
A huge problem I had was just reading the code when I couldn't find the corresponding else statement, I noticed that a lot of the blocks looked like this
if (someCondition)
{
100+ lines of code
{
...
}
}
else
{
simple statement here
}
By inverting the if I could see the simple case and then move onto the more complex block knowing what the other one already did. not a huge change, but helped me in understanding.
Extract Method
I used this a lot.Take some complex multi line block, grok it and shove it aside in it's own method. this allowed me to more easily see where there was code duplication.
Now, hopefully, you haven't broken your code (test still passes right?), and you have more readable and better understood procedural code. Look it's already improved! But that test you wrote earlier isn't really good enough... it only tells you that you a duplicating the functionality (bugs and all) of the original code, and thats only the line you had coverage on as I'm sure you would find blocks of code that you can't figure out how to hit or just cannot ever hit (I've seen both in my work).
Now the big changes where all the big name patterns come into play is when you start looking at how you can refactor this in a proper OO fashion. There is more than one way to skin this cat, and it will involve multiple patterns. Not knowing details about the format of these files you're parsing I can only toss around some helpful suggestions that may or may not be the best solutions.
Refactoring to Patterns is a great book to assist in explainging patterns that are helpful in these situations.
You're trying to eat an elephant, and there's no other way to do it but one bite at a time. Good luck.
A state machine seems like the logical place to start, and using WF if you can swing it (sounds like you can't).
You can still implement one without WF, you just have to do it yourself. However, thinking of it like a state machine from the start will probably give you a better implementation then creating a procedural monster that checks internal state on every action.
Diagram out your states, what causes a transition. The actual code to process a record should be factored out, and called when the state executes (if that particular state requires it).
So State1's execute calls your "read a record", then based on that record transitions to another state.
The next state may read multiple records and call record processing instructions, then transition back to State1.
One thing I do in these cases is to use the 'Composed Method' pattern. See Jeremy Miller's Blog Post on this subject. The basic idea is to use the refactoring tools in your IDE to extract small meaningful methods. Once you've done that, you may be able to further refactor and extract meaningful classes.
I would start with uninhibited use of Extract Method. If you don't have it in your current Visual Studio IDE, you can either get a 3rd-party addin, or load your project in a newer VS. (It'll try to upgrade your project, but you will carefully ignore those changes instead of checking them in.)
You said that you have code indented 15 levels. Start about 1/2-way out, and Extract Method. If you can come up with a good name, use it, but if you can't, extract anyway. Split in half again. You're not going for the ideal structure here; you're trying to break the code in to pieces that will fit in your brain. My brain is not very big, so I'd keep breaking & breaking until it doesn't hurt any more.
As you go, look for any new long methods that seem to be different than the rest; make these in to new classes. Just use a simple class that has only one method for now. Heck, making the method static is fine. Not because you think they're good classes, but because you are so desperate for some organization.
Check in often as you go, so you can checkpoint your work, understand the history later, be ready to do some "real work" without needing to merge, and save your teammates the hassle of hard merging.
Eventually you'll need to go back and make sure the method names are good, that the set of methods you've created make sense, clean up the new classes, etc.
If you have a highly reliable Extract Method tool, you can get away without good automated tests. (I'd trust VS in this, for example.) Otherwise, make sure you're not breaking things, or you'll end up worse than you started: with a program that doesn't work at all.
A pairing partner would be helpful here.
Judging by the description, a state machine might be the best way to deal with it. Have an enum variable to store the current state, and implement the processing as a loop over the records, with a switch or if statements to select the action to take based on the current state and the input data. You can also easily dispatch the work to separate functions based on the state using function pointers, too, if it's getting too bulky.
There was a pretty good blog post about it at Coding Horror. I've only come across this anti-pattern once, and I pretty much just followed his steps.
Sometimes I combine the state pattern with a stack.
It works well for hierarchical structures; a parent element knows what state to push onto the stack to handle a child element, but a child doesn't have to know anything about its parent. In other words, the child doesn't know what the next state is, it simply signals that it is "complete" and gets popped off the stack. This helps to decouple the states from each other by keeping dependencies uni-directional.
It works great for processing XML with a SAX parser (the content handler just pushes and pops states to change its behavior as elements are entered and exited). EDI should lend itself to this approach too.