Note that there are some explanatory texts on larger screens.

plurals
  1. POProgramming paradigm; wondering if rewriting/refactoring is necessary
    primarykey
    data
    text
    <p>for quite some time I've been working on an application. As programming is just a hobby this project is already taking way too long, but that's besides the point. I'm now at a point where every "problem" becomes terribly difficult to solve. And I'm thinking of refactoring the code, however that would result in a "complete" rewrite.</p> <p>Let me explain the problem, and how I solved it currently. Basically I have data, and I let things to happen over this data (well I described about every program didn't I?). What happens is:</p> <blockquote> <p>Data -> asks viewer to display -> viewer displays data based on actual data viewer returns user input -> data -> asks "executor" to execute it -> new data</p> </blockquote> <p><img src="https://i.stack.imgur.com/3Nfnl.png" alt="enter image description here"></p> <p>Now this used to work very well, and I was thinking originally "hey I might for example change command prompt by qt, or windows - or even take that external (C#) and simply call this program".</p> <p>However as the program grew it became more and more tiresome. As the most important thing is that the data is displayed in different manners depending on what the data is and -more importantly- where it is located. So I went back to the tree &amp; added someway to "track" what the parent-line is". Then the general viewer would search for the most specific actual widget. It uses has a list with [location; widget] values, and finds the best matching location.</p> <p>The problems starts when updating for new "data" - I have to go through all the assets - viewer, saver etc etc. Updating the check-mechanism gave me a lot of errors.. Things like "hey why is it displaying the wrong widget now again?".</p> <p>Now I can completely swap this around. And instead of the tree datastructure calling to a generic viewer. I would use OO "internal" tree capabilities. The nodes would be childs (&amp; when a new viewer or save-mechanism is needed a new child is formed).</p> <p>This would remove the difficult checking mechanism, where I check the location in the tree. However it might open up a whole other can of worms. And I'd like some comments on this? Should I keep the viewer completely separate - having difficulty checking for data? Or is the new approach better, yet it combines data &amp; execution into a single node. (So if I wish to change from qt to say cli/C# it becomes almost impossible)</p> <p><img src="https://i.stack.imgur.com/NCikl.png" alt="enter image description here"></p> <p>What method should I pursue in the end? Also is there something else I can do? To keep the viewer separate, yet prevent having to do checks to see what widget should be displayed?</p> <p>EDIT, just to show some "code" and how my program works. Not sure if this is any good as I said already it has become quite a clusterfuck of methodologies.</p> <p>It is meant to merge several "gamemaker projects" together (as GM:studio strangely lacks that feature). Gamemaker project files are simply sets of xml-files. (Main xml file with only links to other xml files, and an xml file for each resource -object, sprite, sound, room etc-). However there are some 'quirks' which make it not really possible to read with something like boost property trees or qt: 1) order of attributes/child nodes is very important at certain parts of the files. and 2) white space is often ignored however at other points it is very important to preserve it.</p> <p>That being said there are also a lot of points where the node is exactly the same.. Like how a background can have <code>&lt;width&gt;200&lt;/width&gt;</code> and a room too can have that. Yet for the user it is quite important which width he is talking about.</p> <p>Anyways, so the "general viewer" (AskGUIFn) has the following typedefs to handle this:</p> <pre><code> typedef int (AskGUIFn::*MemberFn)(const GMProject::pTree&amp; tOut, const GMProject::pTree&amp; tIn, int) const; typedef std::vector&lt;std::pair&lt;boost::regex, MemberFn&gt; &gt; DisplaySubMap_Ty; typedef std::map&lt;RESOURCE_TYPES, std::pair&lt;DisplaySubMap_Ty, MemberFn&gt; &gt; DisplayMap_Ty; </code></pre> <p>Where "GMProject::pTree" is a tree node, RESOURCE_TYPES is an constant to keep track in what kind of resource I am at the moment (sprite, object etc). The "memberFn" will here simply be something that loads a widget. (Though AskGUIFn is not the only general viewer of course, this one is only opened if other "automatic" -overwrite, skip, rename- handlers have failed).</p> <p>Now to show how these maps are initialized (everything in namespace "MW" is a qt widget):</p> <pre><code>AskGUIFn::DisplayMap_Ty AskGUIFn::DisplayFunctionMap_INIT() { DisplayMap_Ty t; DisplaySubMap_Ty tmp; tmp.push_back(std::pair&lt;boost::regex, AskGUIFn::MemberFn&gt; (boost::regex("^instances "), &amp;AskGUIFn::ExecuteFn&lt;MW::RoomInstanceDialog&gt;)); tmp.push_back(std::pair&lt;boost::regex, AskGUIFn::MemberFn&gt; (boost::regex("^code $"), &amp;AskGUIFn::ExecuteFn&lt;MW::RoomStringDialog&gt;)); tmp.push_back(std::pair&lt;boost::regex, AskGUIFn::MemberFn&gt; (boost::regex("^(isometric|persistent|showcolour|enableViews|clearViewBackground) $"), &amp;AskGUIFn::ExecuteFn&lt;MW::ResourceBoolDialog&gt;)); //etc etc etc t[RT_ROOM] = std::pair&lt;DisplaySubMap_Ty, MemberFn&gt; (tmp, &amp;AskGUIFn::ExecuteFn&lt;MW::RoomStdDialog&gt;); tmp.clear(); //repeat above t[RT_SPRITE] = std::pair&lt;DisplaySubMap_Ty, MemberFn&gt;(tmp, &amp;AskGUIFn::ExecuteFn&lt;MW::RoomStdDialog&gt;); //for each resource type. </code></pre> <p>Then when the tree datastructure tells the general viewer it wishes to be displayed the viewer executes the following function:</p> <pre><code>AskGUIFn::MemberFn AskGUIFn::FindFirstMatch() const { auto map_loc(DisplayFunctionMap.find(res_type)); if (map_loc != DisplayFunctionMap.end()) { std::string stack(CallStackSerialize()); for (auto iter(map_loc-&gt;second.first.begin()); iter != map_loc-&gt;second.first.end(); ++iter) { if (boost::regex_search(stack, iter-&gt;first)) { return iter-&gt;second; } } return map_loc-&gt;second.second; } return BackupScreen; } </code></pre> <p><strong>And this is where the problems began to be frank.</strong> The <code>CallStackSerialize()</code> function depends on a call-stack.. However that call_stack is stored inside a "handler". I stored it there because everything starts FROM a handler. I'm not really sure where I ought to store this "call_stack". Introduce another object that keeps track of what's going on? I tried going the route where I store the parent with the node itself. (Preventing the need for a call-stack). However that didn't go as well as I wished: each node simply has a vector containing its child nodes. So using pointers is out of the question to point to the parent note... (PS: maybe I should reform this in another question..)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload