Andre Pang on why OO sweetness is not just in the syntactic sugar

Jeff Waugh <[email protected]> Sun, 8 Feb 2004 18:33:22 +1100
Newsgroups gmane.org.user-groups.slug.pearls
Message-ID <20040208073321.GA1071@lazarus>
----- Forwarded message from [email protected] -----

On 08/02/2004, at 1:56 AM, invisible ink wrote:

> What's the fundamental difference between learning a language and learning
> a library? A lot of GNOME hackers joke about coding in glib, which happens
> to be remarkably familiar if you've coded in C before.

Firstly, there are all the reasons which are mentioned on the gtkmm FAQ 
<http://www.gtkmm.org/gtkmm2/docs/FAQ/html/index.html#id2479521>:

Why use gtkmm instead of GTK+?

	1.  	gtkmm allows you to write code using normal C++ techniques 
	such as encapsulation, derivation, and polymorphism. As a C++ programmer you 
probably already realise that this leads to clearer and better 
organised code.

	2.  	gtkmm is more type-safe, so the compiler can detect errors 
	that would only be detected at run time when using C. This use of specific 
types also makes the API clearer because you can see what types should 
be used just by looking at a method's declaration.

	3.  	Inheritance can be used to derive new widgets. The 
	derivation of new widgets in GTK+ C code is so complicated and error prone 
that almost no C coders do it. As a C++ developer you know that derivation 
is an essential Object Orientated technique.

	4.  	Member instances can be used, simplifying memory management. 
	All GTK+ C widgets are dealt with by use of pointers. As a C++ coder you 
know that pointers should be avoided where possible.

	5.  	Less code. The GTK+ C object model uses prefixed function 
	names and cast macros. For instance:

        gtk_button_set_text(GTK_BUTTON(button), "sometext");

    gtkmm C++ code is shorter and clearer. For instance:

        button.set_text("sometext");

	6.  	There's no need to worry about GTK+'s inconsistent 
reference-counting policy.

If you have support for objects at the language level, you don't have 
to relearn a new object system when you go work on another project.  
You know that "object.foo()" means "invoke method foo on object".  You 
even know that the _correct_ foo will get called for that object if you 
use late binding.  I'm having a look at some of the code from the "Glib 
Object System" tutorial now[1], and the amount of hoops you have to 
jump through just to implement late binding (i.e. C++ virtual methods, 
or completely normal methods in Java/Python) is just plain silly.  
Please tell me how this code:

    static void
    maman_bar_real_do_action_two (MamanBar *self, /* parameters */)
    {
        /* Default implementation for the virtual method. */
    }

    static void
    maman_bar_class_init (BarClass *klass)
    {
        /* pure virtual method: mandates implementation in children. */
        klass->do_action_one = NULL;
        /* merely virtual method. */
        klass->do_action_two = maman_bar_real_do_action_two;
    }

    void maman_bar_do_action_one (MamanBar *self, /* parameters */)
    {
        MAMAN_BAR_GET_CLASS (self)->do_action_one (self, /* parameters 
*/);
    }
    void maman_bar_do_action_two (MamanBar *self, /* parameters */)
    {
        MAMAN_BAR_GET_CLASS (self)->do_action_two (self, /* parameters 
*/);
    }

is easier than:

    class MamanBar
    {
       virtual void DoActionOne (parameters) = 0;
       virtual void DoActionTwo (parameters);
    }

    void MamanBar::DoActionTwo (parameters)
    {
        /* Default implementation for the virtual method. */
    }

Besides this, I haven't even included the maman-bar.h file for the C 
example, which will probably make it a good 20-50 lines longer.  You 
also have to make sure that any class which contains one or more 
virtual methods must have the correct code, you have to write the 
vtables yourself, and you have to use a whole bunch of glib macros to 
work.  So you have more maintenance problems with the C code, it looks 
more fugly, it's less type-safe, you have to learn far more about the 
implementation details of how glib's gobjects work just use use it, and 
you have to write plenty more code to do the same thing.

That's just one example, too.  Check out 
<http://le-hacker.org/papers/gobject/ch05s02.html> to see how to define 
a Java-style interface with glib.  I'd paste the code in here, but it'd 
make this email about 4x longer.  So, check out that ridiculously long 
200 lines of code or whatever, and tell me how that's easier (and 
clearer, and more maintainable) than:

    class MamanIbaz
    {
        virtual void maman_ibaz_do_action () = 0;
    }

    class MamanBaz : public MamanIbaz
    {
        virtual void maman_ibaz_do_action ()
        {
            /* Implementation goes here */
        }
    }

And, of course, you have to learn a whole new object library if another 
C projects decides that glib's object model sux0rz or whatever.  I'll 
go and bang my head into a wall some more now, because I like the 
bleeding!

1. http://le-hacker.org/papers/gobject/ch05.html#howto-gobject


-- 
% Andre Pang : trust.in.love.to.save

----- End forwarded message -----
-- 
SLUG Pearls
http://lists.slug.org.au/listinfo/pearls