Boost logo

Boost :

Subject: Re: [boost] [Review] UUID library (mini-)review starts today, November 23rd
From: Andy Tompkins (atompkins_at_[hidden])
Date: 2008-12-02 16:29:43


On Tue, 2 Dec 2008 11:21:08 +1000, Vladimir.Batov_at_[hidden] said:
> Andy,
>
> >> ...
> >
> > The first thing that comes to mind is size. A uuid class that holds
> > the data at text ... As a much more minor note, ...
>
> I thought you might jump on my mikki-mouse string-based UUID... and in
> fact it was a trap of a sort. :-) I had a strong impression that the
> discussion in this thread revolved too much about actual
> implementation (MAC retrieval springs to mind) and too little about
> the interface. Yes, the implementation is important but it is the
> interface that makes it or breaks it as far as user's acceptance is
> concerned. That (acceptance) buys you time to improve the
> implementation hidden behind the interface. My concern with the
> proposal is that IMHO the interface has not been given enough
> consideration from the user perspectives.

Agreed, the interface is very important.

> > I agree that many users do not care about the algorithm used. If
> > they really don't care, is it an issue to use the
> > boost::uuids::uuid_generator since they don't really care what it
> > does anyway?
>
> I feel that "do not care" is an oversimplification. The user does care
> -- he wants the "best available" without getting bogged down
> investigating what that "best available" exactly is. That is what
> Linux uuid_generate() gives the user right out of the box. To be
> successful boost::uuid just has to match that offer.

Your right. Its not that they don't care. Its that they don't want
to have to care. They want to _know_ that the algorithm is great
and move on.

> > I believe they would just use this function and assume all is well.
>
> I have to disagree. As a user I do not want to *assume*. I want to
> *know* that my application uses the available infrastructure to the
> fullest. That way if/when something goes wrong, it'll the OS to blame
> and not my application.
>
> > Those who care will look at what boost::uuids::uuid_generator does
> > and decide for themselves.
>
> Unfortunately, the reality begs for correction. I do care. However,
> with dead-lines approaching and the boss breathing down my neck I
> simply have no resources to look at every damn thing to decide for
> myself. In fact, I do not want to as I expect much-smarter-than-me
> people to have taken care of that for me. Exactly as I do not try
> reinventing std::map (even though I am aware of other than red-black-
> tree algorithms available).
>
> > They will likely be happy as long as there are the options that
> > they want.
>
> Giving options is merely part of the deal -- people often hate
> choice/options as they have to stop/think/evaluate/decide -- that
> process in time-consuming and draining, it distracts people from their
> main task. The only option pretty much guaranteed to succeed IMHO is
> the "best available" option.
>
> > I do want boost::uuid to provide algorithms to create uuids. I
> > don't want platforms that don't provide an algorithm to not be able
> > to easily create a uuid. Thus I don't want boost::uuid to be just a
> > wrapper around OS functionality.
>
> I do not think I said I wanted to see boost::uuid to be just a
> wrapper. In a nut-shell I'd like to see boost::uuid providing the user
> with the "best available" option. If that means Linux uuid_generate()
> or your own algorithm under the hood, then it's fine by me.

I wasn't trying to say that you did or didn't want boost::uuid to just
be a wrapper. I was simply stating that I didn't want boost::uuid to
just be a wrapper. Sorry I was unclear.

> > > Does boost::uuid provide superior support and a upgrade path?
> >> ...
> >
> > I would agree, that boost::uuid will never have the support of
> > industrial/commercial scale. I now think that boost::uuid should
> > provide a windows_uuid_generator (that uses UuidCreate), a
> > linux_uuid_generator (that uses uuid_generate), plus possibility
> > others platform specific ones, plus some of it's own. Then a
> > boost::uuids::uuid_generator could use one of these if available and
> > if not, use it's own generator. This would give users the support
> > and upgrade paths that you are talking about.
>
> Makes a lot of sense to me. Saying to the user -- Dear user, I've done
> the hard yards for you and I've come up with the best option available
> on your platform -- is a lot. I believe the overwhelming majority will
> be very happy. The curious ones (or with too much time :-) on their
> hands) will still be able to play with explicit uuid generators via
> "uuid id(some-generator);"
>
> > ... I do believe that a null uuid is a valid uuid, but regardless,
> > if the common use case really is as you say, then sure lets have the
> > default constructor call a function to generate a unique uuid. And
> > still provide a way to create a null uuid.
>
> Please do not take my word for it. Just look around at your own usage
> pattern of the default constructor beyond the UUID domain.

Hmm, I looked at some other value types in boost and this is what I
found.

boost::gregorian::date() creates an 'not_a_date_time'.
  One can exclude this constructor with a #define.
boost::posix_time::ptime() is the same as above
boost::function() is initialized as empty
std::string() is initialized as empty
boost::numeric::interval() the created interval is the singleton zero
boost::quaternion() initialized each component/member to the default
  values for their type (i.e. zero for floating numbers)
boost::optional() is uninitialized
boost::rational() is 'zero'

And so I think we are debating the questions: Is a null uuid a valid
uuid?
And, what should the default constructor do? Create a null uuid or a
unique one?

Maybe there shouldn't be a default constructor, and force one to be
explicit when they make a null uuid and when they make a unique
uuid as:
boost::uuids::uuid u1(boost::uuids::null());
boost::uuids::uuid u2(boost::uuids::uuid_generator());

> > My work also heavily relies on uuids, but we almost never create one
> > ourselves in code. We get almost all our uuids from the database
> > that our program uses.
>
> Understood. Our usage is pretty much the same. Still, if my component
> does not create UUIDs, then IMHO it has to state that with
>
> Foo()
> :
> uuid_(boost::uuid::null()) // initially invalid {}
>
> That way the other poor soul coming after me won't be getting any
> wrong ideas/interpretations what the code is actually doing.

This is what I want to prevent as well. I'm concerned about the user
who does:
 boost::uuid u; // this create a unique uuid
and does not realize that they just ran a computational intensive
function when they didn't need or want to.

> > I would be surprised if there aren't many others that use uuids in
> > the same way, they receive them, they don't generate them.
>
> Understood. I do not believe you should be providing the default
> constructor for that usage pattern -- it feels like the copy
> constructor is in order here.

Fair. These people are likely either doing:

boost::uuid u = get_uuid_from_somewhere(); // eg from database

or

boost::uuid u;
get_uuid_from_somewhere(u); // eg from database

The second case would create a unique uuid unless they remembered to do:
boost::uuid u(boost::uuid::null());

It sounds very easy for one to forget. This doesn't change symentics,
it is just less efficient.

Regardless of what the default construction does (null, or unique uuid),
I do really like having an explicit way of creating a null uuid.
Something like:
boost::uuid u(boost::uuid::null());
In fact boost::uuid::null() should be just another uuid generator.

> All in all my impression of the *current* situation with the proposal
> is that at *present* we have many useful and promising bits and pieces
> lying around. I see good ideas. I see good suggestions. I fail to see
> the product. It surely is a good start but to me we have not reached
> the destination yet. I'd be more comfortable after I see those bits
> and pieces taking shape. For me that shape primarily would be the
> interface and the documentation -- the initial pieces of the contract
> between the user and the implementor. Once both parties are happy with
> the contract, you'll beaver away providing the content/implementation.
>
> Thanks, Vladimir.

Regards,
Andy Tompkins


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