Re: [boost] [Review] UUID library (mini-)review starts today, November 23rd

Andy, Thank you for taking the criticism the right way and my apologies if some of my comments sound(ed) somewhat harsh. It is never my intention. I won't be addressing the points below directly as some issues I raised are petty (and I somewhat wish I did not raise them). I admit I felt uneasy with the proposal but could not pin-point what it was. I'll try again. Background: We are in our project currently using uuid facility heavily and very dependent on it. The version we use (from memory) is something like (it's not necessarily exactly what we use and I'll omit some scaffolding and stick with the basics): struct uuid : public std::string { typedef std::string base; uuid() : base(generate()) {} explicit uuid(string const& s) : base(s) {} static uuid null() { return uuid(std::string()); } private: std::string generate(); }; On Linux the generate() function calls uuid_generate(). No one (in our project anyway) can be bothered choosing between uuid_generate_random() or uuid_generate_time() -- uuid_generate() takes care of the guess work and picks the best available. The same on Windows -- it'll probably be UuidCreate()&UuidToString(). Given that uuid above is merely a wrapper over OS facilities, we get known behavior, we are guaranteed "support" and an automatic "upgrade" if/when the standard changes or a new better algorithm becomes available. For me (a collective nebulous "me") to switch to your boost::uuid it has to provide something to win me over. Let's see what that might be. Does boost::uuid provide superior implementation? Maybe. If it is, that was not spelt out sufficiently visibly for me to pick up in the documentation. Therefore, as it is now the answer regretfully has to be 'no'. Does boost::uuid provide superior interface? That issue might get very subjective and personal. Therefore, I'll re-focus on if boost::uuid is user-friendlier. Maybe but I doubt it as an ordinary user does not want to be bothered choosing between algorithms. If uuid_generate() and UuidCreate() can make that choice for me, it is good enough for the overwhelming majority of uuid applications. Therefore, the answer seems again 'no'. Does boost::uuid provide superior support and a upgrade path? With all due respect I have to say 'no' again as your support (no matter how enthusiastic it is) cannot compete (on industrial/commercial scale) with vendor-backed support. uuid_generate(), UuidCreate() as printf() come with the system. One has to have really serious reasons to use something else instead. Does boost::uuid provide superior documentation? Well, my impression is that it is 'no' again. What boost::uuid does immediately entice an ordinary user with then it is Boost reputation. However, in all honesty it's not boost::uuid property per se but the reputation for quality of the Boost libraries built over those many years. In this thread I hear some people say "it's OK to ship". I disagree. Every new library has Boost reputation to uphold. It takes time to build such a reputation. It does not take long to lose it -- a couple of just "OK to ship" libraries will probably do. I'd probably be more comfortable if boost::uuid took the approach of boost::thread of providing consistent interface across many platforms via re-use of the functionality provided by the OS (when available) rather than duplicating it. Then though I'd expect the interface to be given considerably more thought. As for the interface I'll express my view to one of your comments below.
I would not want the default constructor to generate a uuid. I don't want users to pay for that if they don't want it. Some use cases will not require generating uuids, only using them.
I have to disagree. I believe that the overwhelming majority of cases falls into the following category -- "I introduce something when/because I need that something". That is, by Foo foo; std::string str1; std::string str2(params); uuid id1; uuid id2(param); I create valid instances. Say, 'str1' is empty but it is still a valid string. I create 'id1' because I need an uuid. You on the other hand use uuid id2(param); // valid instance uuid id1; // invalid instance where #1 creates a valid instance but #2 creates an invalid instance (it lacks its identifying property -- it's NOT unique). Therefore, you use the same (visually and behaviorally) creation mechanism to achieve *different* results. From the user perspective it is inconsistent and likely unexpected. The case you are catering for with uuid() is not mainstream but quite the opposite -- the user introduces something that he does *not* want. Such case should be handled explicitly with the user actually spelling out what he means like Foo::Foo() : uuid_(boost::uuid::null()) // initially invalid {} Best, Vladimir.

On Sat, 29 Nov 2008 00:14:47 +1100, "Vladimir Batov" <batov@people.net.au> said:
Andy,
Thank you for taking the criticism the right way and my apologies if some of my comments sound(ed) somewhat harsh. It is never my intention. I won't be addressing the points below directly as some issues I raised are petty (and I somewhat wish I did not raise them). I admit I felt uneasy with the proposal but could not pin-point what it was. I'll try again.
No offense taken. I value the criticism. It gave my a lot to think about.
Background: We are in our project currently using uuid facility heavily and very dependent on it. The version we use (from memory) is something like (it's not necessarily exactly what we use and I'll omit some scaffolding and stick with the basics):
struct uuid : public std::string { typedef std::string base; uuid() : base(generate()) {} explicit uuid(string const& s) : base(s) {} static uuid null() { return uuid(std::string()); } private: std::string generate(); };
On Linux the generate() function calls uuid_generate(). No one (in our project anyway) can be bothered choosing between uuid_generate_random() or uuid_generate_time() -- uuid_generate() takes care of the guess work and picks the best available. The same on Windows -- it'll probably be UuidCreate()&UuidToString(). Given that uuid above is merely a wrapper over OS facilities, we get known behavior, we are guaranteed "support" and an automatic "upgrade" if/when the standard changes or a new better algorithm becomes available.
For me (a collective nebulous "me") to switch to your boost::uuid it has to provide something to win me over. Let's see what that might be.
Does boost::uuid provide superior implementation? Maybe. If it is, that was not spelt out sufficiently visibly for me to pick up in the documentation. Therefore, as it is now the answer regretfully has to be 'no'.
The first thing that comes to mind is size. A uuid class that holds the data at text (as I believe the above does) will need 32 characters, or 32 bytes. Whereas boost::uuid needs the minimum of 16 bytes. Thus twice as much space is required. Also many functions (compare, assign, ...) likely take twice as long with the above implementation. As a much more minor note, storing a string representation of a uuid opens the door to the possibility of the string not actually representing a valid uuid. ie "1234567890abcdef!@#$%^&*().{}[]-"
Does boost::uuid provide superior interface? That issue might get very subjective and personal. Therefore, I'll re-focus on if boost::uuid is user-friendlier. Maybe but I doubt it as an ordinary user does not want to be bothered choosing between algorithms. If uuid_generate() and UuidCreate() can make that choice for me, it is good enough for the overwhelming majority of uuid applications. Therefore, the answer seems again 'no'.
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 believe they would just use this function and assume all is well. Those who care will look at what boost::uuids::uuid_generator does and decide for themselves. They will likely be happy as long as there are the options that they want. 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.
Does boost::uuid provide superior support and a upgrade path? With all due respect I have to say 'no' again as your support (no matter how enthusiastic it is) cannot compete (on industrial/commercial scale) with vendor-backed support. uuid_generate(), UuidCreate() as printf() come with the system. One has to have really serious reasons to use something else instead.
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.
Does boost::uuid provide superior documentation? Well, my impression is that it is 'no' again.
Again, I plan on improving the documentation.
What boost::uuid does immediately entice an ordinary user with then it is Boost reputation. However, in all honesty it's not boost::uuid property per se but the reputation for quality of the Boost libraries built over those many years. In this thread I hear some people say "it's OK to ship". I disagree. Every new library has Boost reputation to uphold. It takes time to build such a reputation. It does not take long to lose it -- a couple of just "OK to ship" libraries will probably do.
I do hope that Boost's reputation is not all that is going for boost::uuid. I value the input of this list (including yours) to help make boost::uuid a library that would live up to Boost's reputation.
I'd probably be more comfortable if boost::uuid took the approach of boost::thread of providing consistent interface across many platforms via re-use of the functionality provided by the OS (when available) rather than duplicating it. Then though I'd expect the interface to be given considerably more thought.
As above, I agree that boost::uuid should be able to use functionality provided by the OS. But it should not require OS functionality to be useful.
As for the interface I'll express my view to one of your comments below.
I would not want the default constructor to generate a uuid. I don't want users to pay for that if they don't want it. Some use cases will not require generating uuids, only using them.
I have to disagree. I believe that the overwhelming majority of cases falls into the following category -- "I introduce something when/because I need that something". That is, by
Foo foo; std::string str1; std::string str2(params); uuid id1; uuid id2(param);
I create valid instances. Say, 'str1' is empty but it is still a valid string. I create 'id1' because I need an uuid. You on the other hand use
uuid id2(param); // valid instance uuid id1; // invalid instance
where #1 creates a valid instance but #2 creates an invalid instance (it lacks its identifying property -- it's NOT unique). Therefore, you use the same (visually and behaviorally) creation mechanism to achieve *different* results. From the user perspective it is inconsistent and likely unexpected.
The case you are catering for with uuid() is not mainstream but quite the opposite -- the user introduces something that he does *not* want. Such case should be handled explicitly with the user actually spelling out what he means like
Foo::Foo() : uuid_(boost::uuid::null()) // initially invalid {}
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. 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. 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.
Best, Vladimir.
Regards, Andy Tompkins

on Mon Dec 01 2008, "Andy Tompkins" <atompkins-AT-fastmail.fm> wrote:
On Sat, 29 Nov 2008 00:14:47 +1100, "Vladimir Batov" <batov@people.net.au> said:
Andy,
<schnipp>
Regards, Andy Tompkins
Vladimir raised some very compelling arguments, but IMO Andy answered all of them well enough to allay any concerns I had about accepting this library. I'm curious whether Vladimir is satisfied with the response, though. Vladimir? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Sat, 29 Nov 2008 00:14:47 +1100, "Vladimir Batov" <batov@people.net.au> said:
Andy,
<schnipp>
Regards, Andy Tompkins
Vladimir raised some very compelling arguments, but IMO Andy answered all of them well enough to allay any concerns I had about accepting this library.
Is that a formal 'accept'?
I'm curious whether Vladimir is satisfied with the response, though. Vladimir?
Me too. Regards Hartmut
participants (4)
-
Andy Tompkins
-
David Abrahams
-
Hartmut Kaiser
-
Vladimir Batov