Boost logo

Boost :

From: Jake Voytko (jakevoytko_at_[hidden])
Date: 2007-06-15 22:34:09


Phil,

That's certainly the most influential I've received against the idea of
implementing the program as a stream interface. However, I think you and I
prioritize our design decisions differently, as I'll explain below. I'm
going to need to mull over this thread, and I'll take Paul Bristow's
suggestion and put up all of the candidates under a new thread under the
title "Request for views on how to present.." to get final thoughts on the
matter before I make a decision.

On 6/15/07, Phil Endecott <spam_from_boost_dev_at_[hidden]> wrote:
>
> 2. Write free functions instead of methods. i.e. instead of writing
> if (the_animal.has_four_legs()) { ... }
> you have to write
> if (has_four_legs(the_animal)) { ... }
> The only real problem with this way is the you have to remember whether
> each 'method' is a real method of the base class or a free function.
> One option for a class that expects to be extended is to put
> *everything* in free functions, having a minimal set of
> invariant-preserving public methods that access the private data. (You
> can even do without them using friend declarations.)

I think if I were going this route (and I'm starting to see its merits, but
more on that in a second), I would have all "set" functions that work in a
chaining manner, and if I wanted to extend functionality as above, do as
follows:

void my_settings(svg_plot& plot)
{
    my_plot . set_axis_color()
                . set_axis_line_width()
                . set_axis_line_style()
      // snip
}

Let's think about iostreams for a moment. There the need is to be able
> to extend the ostream class with new methods for formatted output of
> new types. Essentially what it does is:
>
> ostream strm(fn);
> int i;
> char c;
> std::string s;
> somo_other_type z;
> write(strm,i);
> write(strm,c);
> write(strm,s);
> write(strm,z);
>
> i.e. free functions for each extension, except that the library
> designers chose not to use a conventional function name like 'write',
> but instead chose operator<<. Is this a good choice? Well, there is a
> famous quote somewhere (would anyone like to remind me who it was)
> something like "well I gave up on C++ when I saw them doing a left
> shift on the standard output". It's a jokey quote, but adding extra
> "magic" syntax is something that makes what's really going on in the
> program less transparent. It doesn't take at all long for someone to
> learn that A.B(C) means "pass C as the parameter to method B of object
> A" (and it helps that it is essentially the same in most OO
> languages). But you need to get a lot further in to your textbook to
> understand what is really going on when you write A<<B<<C.

Here is where we fundamentally disagree. It seems that you're saying (though
you don't explicitly pass judgement, so I apologize if I take this the wrong
way), that overloading the left shift operator for streams is a bad design
because it does not stick with the de-facto standard class interface.
However, when I switched from C to C++ in high school, (don't ask me why I
started with C.. it wasn't an informed decision, and I certainly would have
been better off learning it second ;D) I was struck by the syntax for the
output and input. It was efficient and elegant compared to C calls (and
compared to the boiled-down version above), everything that syntax should
strive to be. Yes, I had to put in a little extra work with understanding
underneath the hood how it worked, but I felt that it significantly aided my
productivity once I got it.

That was why I initially agreed with John Maddock's suggestion of providing
it as a stream interface.. I felt that it made the learned user more
productive, and the interface more easily extensible (though I forgot about
this point until Joaquín Muñoz brought it up again) and elegant, at the cost
of stumbling through an initially unfamiliar syntax. I agree with your
statement that this isn't about looks. I will, however, split hairs and say
that aesthetics do matter.. the difference between an iPod and, well, any
other music player. Not that my header gets 5 stars in the interface
department, and the << idea may be a miss, but I think experimenting with
syntax in pursuit of that goal isn't completely misguided. As you show, the
<<() operator doesn't just carry with it positive implications that I'd like
it to have.

So let me write it out in full, as I would probably implement it:
>
> image_size (p, 800, 600);
> show_axis(p);
> x_axis_color(p, blue );
> y_axis_color(p, darkgray );
> x_axis_major_tick_color(p, gray);
> y_axis_major_tick_color(p, darkgray );
> x_axis_minor_tick_color(p, gray );
> y_axis_minor_tick_color(p, gray );
> show_background_border(p);
> background_border_color (p, darkgray );
> background_border_thickness(p, 5 );
> background_color (p, lightblue );
>
> Now what is so special about this particular library that that isn't
> good enough?

I think that this question is the wrong question to ask. The real question
in my playbook is "What's so special about your syntax that it solves your
problem better than does the standard syntax?"

I feel that being able to write, literally,

    my_plot << my_usual_settings << hide_axis();

is powerful stuff, and is more elegant than writing

my_usual_settings( my_plot );
my_plot.hide_axis();

In summary:
>
> - You don't need to overload operator<< to make your class extensible.

I don't know where my brain was earlier, but I agree with that.

- Operator overloading makes the library harder to learn because what's
> going on is less transparent.

I also agree. However, the operator overloading isn't purely a design based
on my excessive malace towards the learning curve of my potential users :)

Don't view this post as a rebuff against your ideas, as they are grounded on
solid principles, worth consideration, and are backed up by what appears to
be a majority consensus. But as for now, I think the best thing is to wait
until this is a little further along so there's more to show (All of the
proposed changes look like they could be done in a few hours with a few cups
of coffee and some vinyl records blasting).

Thank you for your time,
Jake


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk