C++ plans? (Re: r23706 - gnucash/trunk/src/register/ledger-core - Bug 721791)

John Ralls jralls at ceridwen.us
Tue Jan 21 17:57:13 EST 2014


On Jan 21, 2014, at 1:04 PM, Christian Stimming <christian at cstimming.de> wrote:

> Am Samstag, 18. Januar 2014, 19:20:45 schrieb John Ralls:
>>> Thanks for fixing the bug!
>>> 
>>> Note that the functions for using the GDate are still relatively new in
>>> gnucash. That's why in most cases they are not (yet) being used, even
>>> though they are more suitable and less error-prone and better altogether
>>> :-)
>> And one of the GLib dependencies that we're getting rid of. ;-)
>> 
>> No worries, though: Boost::gregorian [1] has more-or-less the same
>> functionality with I hope less work.
> 
> Hi John,
> 
> well, I know boost quite well and I fully agree that date handling is just one 
> more example where boost as a very good and long lasting solution. 
> boost::gregorian for the date, boost::posix_time::ptime for date-and-time 
> points in time, and boost::posix_time::time_duration for differences of date-
> and-time, and so on. If you're writing some backend code that is in C++ and is 
> allowed to depend on boost, by all means the date and date-and-time types 
> should be taken from there.
> 
> However, that brings up my actual question: What are your plans for C++ and 
> boost inside gnucash? Is there any sort of migration plan that you have in 
> mind?
> 
> If the choice were there, I would definitely prefer C++ code over C. However, 
> that still doesn't solve the toolkit questions: C++ with boost, yes, but what 
> GUI? If you want C++ with Qt but still use boost, you've already opened the 
> first set of conflicts (e.g. boost::gregorian vs. QDate and QDateTime; boost 
> is much better, but the qt types are needed for interfacing with the qt 
> widgets). That is just one out of several questions. 
> 
> Under the assumption you already have good proposals for this, I have the next 
> question:  What is the migration plan for the gnucash codebase? The unittests 
> cover the current functionality including all its weird and nasty C quirks. 
> When rewriting the engine types as C++ classes, the existing unittests by 
> nature will cover only a smaller part of the new code, so this won't relieve 
> us much here. And a backend C++ class can't be a complete drop-in replacement 
> for an existing C/gobject "object", so we probably can't use the existing GUI 
> code and step by step replace the engine types with C++. What's your idea 
> here?
> 
> To make the picture complete, a few years back I took the try to add C++ 
> wrapper classes on top of the existing gobject classes using glib's C++ 
> wrapper. The code is in src/optional/gtkmm, and it is being compiled both by 
> --enable-gtkmm and also the cmake project "cutecash". In the cutecash 
> experiment, the wrapper classes were working fine... however they clearly look 
> just like wrappers and still keep their old C gobject pointer around, which is 
> also needed sometimes. The code doesn't look elegant as long as it's still 
> only a wrapper. However, this step enables writing GUI code in C++ while still 
> using the existing engine code. Unfortunately, the more interesting GUI stuff 
> can't be done as long as the wrappers are gobject thingies. I tried to look 
> into implementing a GListView derivative in C++, but gave up because of the 
> impermeable gtkmm and gtk stuff :-( However, the Qt implementation of the list 
> view works quite well in cutecash.

Christian,

I have an outline plan to get started:
* Get the current code to compile as C++. Necessary so that we can mix C++ and C in the same modules.
* Replace some of the peripheral classes in qof—GUID, gnc-numeric, gnc-date—as a warm-up.
* Try replacing QofInstance with C++ and see if that explodes. I think it probably won’t, because we don’t actually use GObject’s virtualization or inheritance features. 
* If that goes well, start replacing engine classes, starting with QofBook and leaving the persisted and query-able ones for last.

I don’t actually think that there will be much problem with replacing GObject classes *in the engine* with C++. For the most part we don’t actually use the GObject features that would get in the way. Obviously there’s a lot of code in src/gnome* that does, and where that interacts with the engine may take some special handling. We won’t know until we try, unfortunately. It’s part of my grand plan to get the “controller” code separated from the “view” code and have only the “view” code depend on anything Gnome or any other GUI framework whether it’s Qt, wxWidgets, or M$Windows, but that’s somewhat separate from converting the engine to C++ and making it a proper stand-alone library and I don’t expect that much of it will get done in this cycle.

The third bit of the “grand plan” that does affect the engine is to get rid of the idea of backends and move the SQL database into the middle of the engine, replacing QOFQuery with SQL. I haven’t figured out how to do that incrementally, which is why the plan stops short of rewriting the central classes. I think that’s going to have to be done all at once (in a feature branch, obviously) once all of the support classes are in place. This is the primary prerequisite to multiple simultaneous access, and has the biggest impact on GnuCash’s overall design.

As for Boost::gregorian v QtDate, we’ll just have to put a shim class between the two. I’m sure you’ve already done that in CuteCash to enable calendar controls to talk to Timespecs. Same goes for the GtkCalendar control, for that matter.

Yup, new classes means new tests, which will be adapted from existing tests where they exist. With good class design the new tests should be much easier to write. I’m a bit conflicted about whether to use Boost::Testing for this, saving another dependency, or Google Test and Google Mock which seems to be more popular and includes a Mock facility which Boost::Testing lacks.

One other thing: I’m inclined to write any class that contributes to the engine’s public API (which I intend should be much smaller than it is now) to use PImpl; the pointer class will be passed as a shared_ptr (i.e., reference counted like GObjects are supposed to be but mostly aren’t in GnuCash) holding a unique_ptr to the private implementation object. Do you have any thoughts about that?

Regards,
John Ralls




More information about the gnucash-devel mailing list