Namespaces, file names,...
jralls at ceridwen.us
Fri Sep 5 11:08:48 EDT 2014
On Sep 5, 2014, at 2:46 AM, Geert Janssens <janssens-geert at telenet.be> wrote:
> This topic was lightly touched in the doxygen/design thread currently active on this list. I
> thought it to be important enough to start a new thread on it.
> Historically, gnucash as acquired a lot of namespaces (think function and type prefixes) for
> various reasons.
> Some examples:
> * The oldest engine code uses xaccXYZ because gnucash started as a continuation of the xacc
> project (xacc for X Accounting by the way).
> * More recent engine code and most of the gui related code usually use gnc_ copying the gtk
> name space standards.
> * The qof library introduced qof_ because it was meant to become a separate library at one
> point in time.
> Types are different still:
> * The oldest engine code doesn't use prefixes at all ("Split", "Transaction",...)
> * More recent engine code uses Gnc or GNC, gui code is mostly into Gnc as well.
> And so on...
> The problem with this is that it makes the gnucash "framework" hard to learn. It's not possible
> to learn by similarity like it is in strongly namespaced frameworks such as gtk, qt or boost.
> Those frameworks have a logic to their name structure, so if you know one part of the
> framework you can already imagine what other functions and types in the framework will be
> called. That speeds up adoption a lot.
> The same goes for file names, and especially header files. If there is a recognizable logic in the
> names of the header files, that makes it much faster to learn how to use the framework.
> Now since one of our current design goals is to port our engine code to C++, that means we will
> more or less rewrite every single function and type in it. That would IMO be a good time to think
> about how we want to structure the new classes name-wise and come to a more coherent set
> of names.
> I have seen how some frameworks do it and clearly there are different ways. I don't know
> however whether there exist formal theories or guidelines that we could use to formulate our
> own naming rules.
> For example, in recent years I have worked mostly with the GLib/Gtk frameworks. Some of their
> naming rules include
> * Object names are prefixed with G (for GLib) and Gtk (for Gtk). The names are camel-cased.
> * Function names are prefixed with g_ (for GLib) and gtk_ (for Gtk). An the names use _ to
> separate words.
> If we had planned to continue to use GLib/Gtk in the long term, I would have proposed to use a
> similar naming scheme, using our own Gnc/gnc_ prefixes. That would allow newcomers to
> leverage the muscle memory built up on GLib and Gtk naming.
> The plan is however to move away from those in favour of C++ based alternatives, so I think it
> would make more sense to look for examples of namespacing in the C++ world. That world is
> unknown to me unfortunately so...
> Suggestions anyone ?
C++ actually has a higher level of code scope called namespaces. In behavior it's similar to Python's module naming scheme, and the idea is that it helps to prevent name collisions. I'll leave it to your favorite C++ tutorial/reference to explain further.
Gnome, being dedicated to creating a pretend C++ with C macros, doesn't have the option of enforcing actual namespaces, so they adopted a naming convention and called part of it namespace. Macros being inherently brittle, anything that doesn't comply with that naming convention breaks, though not at compile time and not with a message. There's another reason for the Gnome naming convention: In order to preserve using normal C semantics and because C can't fake the first function argument, all function names must begin with the class name and the first argument must be cast appropriately if it's a derived class. While there's support for vtables (defined in the class_init function), it's not often used outside of Gdk because few C programmers understand it.
We're freed from that with C++. There's no need to stick "GNC" (in any case variation you like) in front of class names, and member functions are automatically recognized and the object parameter taken care of, so instead of
Account *acct = xaccMallocAccount (book);
Account* acct = new Account (book);
acct->beginEdit (); //or acct->begin_edit (); if we decide we like underscore better than camel case
Since we want to make the API useful outside of GnuCash we should declare a namespace to wrap everything in, maybe Gnc. That way an application that wants to extend our Account class could still call their child class Account, like so:
class Account : public Gnc::Account;
using namespace Gnc;
in all of our implementation files so we don't have to write
Gnc::Account* acct = new Gnc::Account (book);
So the question becomes:
* Is Gnc OK for the namespace name?
* Do we want to use camel-case or underscore-separated function and variable names?
N.B. The C++ code above mirrors the old C code to emphasize the different naming and calling conventions. The actual C++ code will be somewhat different.
More information about the gnucash-devel