Self help (2) ...
- From: Michael Meeks <michael ximian com>
- To: <gnome-devel-list gnome org>
- Subject: Self help (2) ...
- Date: Tue, 14 Aug 2001 13:53:40 -0400 (EDT)
As threatened, more mumbo jumbo masquerading as insightful
comment. This week some Bonobo related ramblings.
* A random thought.
Did you know, that an interface is not like a class inasmuch
that it specifies no data/method hiding, layout or implementation
detail - just pure interfacing information [ un-cluttered by dangerous
crud such as public data elements ]. Yes ?
* Good taste, and readability.
Variables should be scoped as tightly as possible. This
removes ambiguity, and allows small self contained bits of code to be
safely and easily split out to cure the "function growth hormone
imbalance syndrome". For example:
. static void
. a_new_function (int a)
. {
. int i;
.
. for (i = 0; i < 10; i++) {
. int j;
. char tmp_buf [10];
.
. for (j = 0; j < 10; j++)
. ...do something...
. }
. }
This also allows the side effects, and useful scope of the
variable to be made explicit. It also reduces the possibilities for
combat coding, means that having read that code you can discard
'tmp_buf' from your mental stack, it's also helpful for the compiler
etc. etc.
* BonoboXObject - it's use in practice.
Sadly BonoboXObject was developed at the end of the Bonobo 1.0
lifecycle and squeezed through the crack under the rapidly descending
portcullis of freeze deadlines and other fascism :-). Consequently it
is not perfect, however (to re-mint a phrase): 'it sucks less'.
Say we have a complex industrial interface like this
(bonobo/samples/bonobo-class):
. module Bonobo { module Sample {
. interface Echo : Bonobo::Unknown {
* void echo (in string message);
. };
. }; };
We need to inherit our new GtkObject from BonoboXObject, but
in particular the class must include the epv in-line.
. typedef struct {
. BonoboXObjectClass parent_class;
.
* POA_Bonobo_Sample_Echo__epv epv;
. } EchoClass;
Inside the gtk_type_new function, instead of gtk_type_unique
we use:
. type = bonobo_x_type_unique (
. PARENT_TYPE,
* POA_Bonobo_Sample_Echo__init, NULL,
. GTK_STRUCT_OFFSET (EchoClass, epv),
. &info);
Alternatively the type creation method can be replaced by:
. BONOBO_X_TYPE_FUNC_FULL (Echo, Bonobo_Sample_Echo,
. PARENT_TYPE, echo);
NB. Using a 'PARENT_TYPE' macro is good practice for explicit
classes, and helps reduce bugs [ inasmuch that BonoboXObject is not
at all tolerant of chaining errors ].
Clearly then we need to initialize the epv to point to our
new method, so in the class_init method we do:
. klass->epv.echo = impl_Bonobo_Sample_Echo_echo;
So, to create a CORBA server we simply do:
. Echo *echo = gtk_type_new (echo_get_type ());
And to get the CORBA reference to it we do:
. Bonobo_Sample_Echo corba_ref = BONOBO_OBJREF (echo);
Tragicaly, BonoboXObject made it too easy to inherit
interfaces, which leads us nearly to the next point but first ...
* Another stylistic point
During the last minute, with an in-depth review of over a
badzillion lines of code it has been accurately calculated that a good
program has ~ 6 bugs / 1000 lines of code.
Luckily the prophets K&R understood this concept when they
invented C, and in order to minimise the number of bugs, and retain
taste and sanity, they not only invented the 'for' construct ( for
suffering while users ), but also a bracing convention of infinite and
inscrutible wisdom thusly:
if (x is true) {
we do y
}
However, there is one special case, namely functions: they have the
opening brace at the beginning of the next line, thus:
int function(int x)
{
body of function
}
Note that the reduction in line count ( and hence bugs ) not
only makes the code beautiful ( in combination with 8 stop indents of
course ), but satisfies the stringent new Kyoto requirements on the
preserving of that vital non-renewable resource: visible screen lines.
cf. /usr/doc/linux/Documentation/CodingStyle - chapter 2.
* Inheriting vs. Aggregating.
By cunningly opening a bumper value, super size, 'new
formula', can of worms, I plan to bring Gnome productivity to a total
halt so here goes: I've seen interfaces that look like something like
this[1]:
interface Foot : Bonobo::BodyPart {
long getNumberDigets ();
void setCompressiveForce (double forceInNewtons);
};
Whilst all well and good [2] there is no particularly good
reason to derive a Foot from BodyPart. Indeed, it ties the perfectly
generic and re-usable Foot interface to a body, and ignores the
thousands of lattice propelled ACME mechanical feet not to speak of
the humble prosthesis.
Consequently before inheriting consider -
* Do I really need to.
* Is the derived interface unarguably inextricably
intertwined with the parent.
* Why my interface is totaly non-generic; should I not
be re-using a generic interface, such as a property
bag in the above example.
* Whether the IRS inheritance tax form 7165B is really
worth filling in, wouldn't it be better to leave
everything to Battersea Dogs Home ?
I have seen inheritance badly misused, please write nice
separate generic interfaces and aggregate them together.
Also, when you see a huge and cumbersome interface replete
with get and set methods, carefuly consider using a PropertyBag
instead.
* Summary
* Scope your variables as tightly as you can bear.
* Inherit only under great duress.
* Use BonoboXObject
* Trust K&R
Due to an increasing weariness of my own type, a suspicion
that no-one will ever read to here [ Hi Mum ], and after careful
greasing, the billed reference counting and re-enterancy features
appear to have slipped into some hypothetical future mail, possibly
next week. Also then, a discussion of setjmp / longjmp.
HTH,
Michael.
[1] seemingly following the axiom "If it breathes inherit from it".
[2] under close inspection it appears that a Foot is a BodyPart.
--
mmeeks gnu org <><, Pseudo Engineer, itinerant idiot
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]