C++ work

John Ralls jralls at ceridwen.us
Tue Sep 9 17:50:57 EDT 2014

On Sep 9, 2014, at 2:24 PM, Geert Janssens <janssens-geert at telenet.be> wrote:

> On Tuesday 09 September 2014 15:12:33 Aaron Laws wrote:
>> The short question is: What GUI framework is gnucash likely to target
>> in c++?
> Equally short answer: likely Qt or WxWidgets. But we never did a detailed evaluation yet.
>> I've heard it mentioned that the current framework (GTK?) doesn't make
>> sense in c++ because it's so gobject-oriented, but I didn't hear
>> anything else suggested. I know there's a QT effort which seems like
>> a reasonable way to go, but haven't heard it actually endorsed
>> anywhere.
> Exactly
>> Currently, c++ work is starting at the deepest point (the part of the
>> code that is relied on by everything), qof, so that a C api has to be
>> maintained until everything that relies on QOF has a way of accessing
>> the c++ interfaces. This means that c++ and C interfaces need to be
>> created and maintained in parallel until everything's ready to
>> switch. This has grated on me for quite a while, but I see it as a
>> very difficult problem. I don't see a quick way to fix it. I've tried
>> (and technically succeeded ^_^) compiling the whole project as c++,
>> but that's not so great because the dynamic linking doesn't work
>> because of mangling. Repairing this solution doesn't seem like a
>> profitable way forward. It's sort of like throwing all your
>> belongings into a river, then swimming across yourself, and trying to
>> collect everything on the other side, making sure you didn't lose
>> anything.
>> Another way that I've been trying to consider is to start on the part
>> of project upon which nothing relies. That way, that part of the
>> project can be completely C++. Then, take the next thing which
>> doesn't expose a *used* C api. Rinse and repeat. This way, there will
>> never (?) have to be a duplicated API in any system.
> Sounds nice in theory. I fear it will be equally if not more difficult than the current approach 
> though.
> Taking your example of first replacing the gui.
> As you bring up yourself it is heavily gobject based. And in addition the controller, model and 
> view code are mixed up. Rewriting it in (say) Qt, means it will now use Qt objects. But the 
> "business logic" (our engine code) is still gobject based.
> So now in order for the gui to talk to the business logic you have to create an interface layer 
> between the engine and the gui that will do the proper translations between the two object 
> models. That is probably more work than maintaining the existing C api in the path currently 
> chosen.
> In addition logically it doesn't make sense to start from the gui and drill down to the model. 
> Your gui should be based on the model and controller logic so it only makes sense to start there. 
> Going the other way around as a sure way to make wrong assumptions about how the lower 
> layers will be implemented and in the best case mean several revisions to the higher layers or 
> having to start over in the worst case.
>> Another way to think about this is as a tree structure. I'll throw
>> something up, and I'll eagerly await corrections! Read "->" as "relies
>> on":
>> GUI (GTK?) -> Business Logic
> So rewrite the gui and an interface layer between the two
>> Alternate gui (WEB?) -> Business Logic
> Same here.
>> GUI (GTK?) -> Reporting Infrastructure
> Same here.
>> Business Logic -> QOF
> Rewrite the business logic and write an interface layer between the two.
> Oops, the way we write the business logic now means we need to change the gui layer, because 
> it made some invalid assumptions on what the business logic would be.
> So rewrite the gui here as well
>> Reporting Infrastructure -> QOF
> Rewrite the reporting infrastructure and write an interface layer between the two.
> Oops, the way we write the reporting infrastructure now means we need to change the gui 
> layer, because it made some invalid assumptions on what the business logic would be.
> So rewrite the gui here as well
>> QOF -> libdrm, etc.
> Rewrite qof and realize we end up with a different implementation that we thought we would. 
> So rewrite the business logic and the reporting infrastructure once more. And bollocks, that kills 
> our gui design again. Rewrite the gui...
>> So, if QOF is changed, it still needs to support Business Logic with a
>> C api until Business Logic is changed which can't happen until all
>> GUIs that rely on it are changed. If, however, a gui layer is
>> changed, that's all there is to it; there are no dependencies (if
>> there are, we should have started at the dependency!). Once all GUIs
>> (I know there's only one, but I'm trying to create a sufficiently
>> complicated example!) are c++-ready, the Business Logic can be
>> converted. No redundant API is necessary.
> See my worst case but not unlikely scenario above. I predict much more work when working top 
> down because it's impossible to rely on a lower level interface if the implementation hasn't 
> been done yet.

What Geert mentioned in passing but left out of his discussion is that there’s a lot of business logic code mixed into the GUI code. That has to be teased out and separated so that the model stuff goes down into the engine where it belongs and the stuff that’s just computation for display or input goes into some middle classes in separate directories, and the GUI directories contain just the code which describes the GUI itself, calling the controller classes as they need. 

The pushing the model stuff down into the engine part of that job makes the most sense to do when the engine is migrated, but the extracting part could be done now. In fact having the pieces clearly separated ahead of time would make it easier to define the engine API when the time comes.

And oh-by-the-way, there’s also some GUI that’s still in scheme and has business logic in it that the C parts of GnuCash can’t see at all. That also needs to get pulled apart into the appropriate MVC layers.

All of that aside, there’s a fundamental flaw in your reasoning. If you write a new C++ GUI, even if there wasn’t an MVC separation issue, all of the controller calls would be to C functions, because that’s what the controller layer if it existed would be written in. It would in turn be calling C functions in the model layer, because that’s what the engine is written in. So even if nothing changed, you’d still be in the position of rewriting each upper layer over to operate on C++ objects instead of GObject objects as you drill down. Everything would be done twice as a *best* case.

John Ralls

More information about the gnucash-devel mailing list