Breaking existing libraries

You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range. Here’s a short summary: We are currently (firmwide) using boost 1.33.1. I am in the process of trying to migrate and test some of our apps with boost 1.37. In 1.35 there was a breaking change to Boost.Range with respect to how singular ranges behave. This brings up several issues: 1) The breakage was silent. The interface stayed the same but the behavior changed, and drastically so. 2) No communation: While I don’t usually post to boost.devel/boost.user, I and my colleagues still read it. Nobody recalls any mention of this on the list. Searching gmane brings up nothing, either. 3) No documentation on the boost website. As far as I can see, this change was introduced in 1.35 this March. On http://www.boost.org/users/news/version_1_35_0, there is no mention of a breaking change to Boost.Range. 4) The new Boost.Range behaves differently in debug and release builds. The public function is_singular() always returns false in release builds even when it would return true in debug builds. Apart from the fact that this change breaks a lot of our code and obsoletes several useful (necessary?) idioms, the manner in which it happened is far below the standards that one has come to expect from boost. At the moment, I have to say I don’t have a good answer to how to fix our code. However, I would at least like to try to make sure this kind of silent breakage doesn’t happen again. Tom

on Thu Nov 20 2008, Tomas Puverle <Tomas.Puverle-AT-morganstanley.com> wrote:
You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range. Here’s a short summary: We are currently (firmwide) using boost 1.33.1. I am in the process of trying to migrate and test some of our apps with boost 1.37. In 1.35 there was a breaking change to Boost.Range with respect to how singular ranges behave. This brings up several issues:
1) The breakage was silent. The interface stayed the same but the behavior changed, and drastically so. 2) No communation: While I don’t usually post to boost.devel/boost.user, I and my colleagues still read it. Nobody recalls any mention of this on the list. Searching gmane brings up nothing, either. 3) No documentation on the boost website. As far as I can see, this change was introduced in 1.35 this March. On http://www.boost.org/users/news/version_1_35_0, there is no mention of a breaking change to Boost.Range. 4) The new Boost.Range behaves differently in debug and release builds. The public function is_singular() always returns false in release builds even when it would return true in debug builds.
Apart from the fact that this change breaks a lot of our code and obsoletes several useful (necessary?) idioms, the manner in which it happened is far below the standards that one has come to expect from boost.
At the moment, I have to say I don’t have a good answer to how to fix our code. However, I would at least like to try to make sure this kind of silent breakage doesn’t happen again.
Hi Tom, Yes, this is an unfortunate situation. If you indeed want to try to make sure this kind of silent breakage doesn’t happen again, there's something you can do about it: write a page of library maintenance guidelines on the wiki at http://svn.boost.org. We are sorely missing a policy on this, and when less-experienced library authors come along, they often don't hew to the same standards that many of us take for granted. If you don't have write permission for the wiki, please let us know and we'll send you an invitation. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

----- Original Message ----- From: "David Abrahams" <dave@boostpro.com> To: <boost@lists.boost.org> Sent: Thursday, November 20, 2008 8:32 PM Subject: Re: [boost] Breaking existing libraries
Hi Tom,
Yes, this is an unfortunate situation. If you indeed want to try to make sure this kind of silent breakage doesn’t happen again, there's something you can do about it: write a page of library maintenance guidelines on the wiki at http://svn.boost.org. We are sorely missing a policy on this, and when less-experienced library authors come along, they often don't hew to the same standards that many of us take for granted. If you don't have write permission for the wiki, please let us know and we'll send you an invitation.
Hi, I also found this kind of situations unafortunated. I'm not sure a page of library maintenance guidelines on the wiki will address all the issues reported by Tom. Anyway, I would like to try it. Can I get permission for the wiki to start this Maintenace Guidelines page. As my english is incorrect and not very rich I expect from others to make the necessary corrections and improvements. Best regards, Vicente

on Fri Nov 21 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
I'm not sure a page of library maintenance guidelines on the wiki will address all the issues reported by Tom. Anyway, I would like to try it.
Can I get permission for the wiki to start this Maintenace Guidelines page. As my english is incorrect and not very rich I expect from others to make the necessary corrections and improvements.
Thanks Vincente! It looks like someone gave you write permission already. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

----- Original Message ----- From: "David Abrahams" <dave@boostpro.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 6:23 PM Subject: Re: [boost] Breaking existing libraries
on Fri Nov 21 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
I'm not sure a page of library maintenance guidelines on the wiki will address all the issues reported by Tom. Anyway, I would like to try it.
Can I get permission for the wiki to start this Maintenace Guidelines page. As my english is incorrect and not very rich I expect from others to make the necessary corrections and improvements.
Thanks Vincente! It looks like someone gave you write permission already.
Oh, I didn't know that. If permissions to the track system implies permissions on the wiki, then I should have them. Because we are talking of Maintenace, Evolution, ... I would like to know first which are the current criteria for acceptance of library modifications, in order to make a clear difference on what *must* be done and what *could* be done. Can some one point me to some written document? Thanks, Vicente

on Fri Nov 21 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
----- Original Message ----- From: "David Abrahams" <dave@boostpro.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 6:23 PM Subject: Re: [boost] Breaking existing libraries
on Fri Nov 21 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
I'm not sure a page of library maintenance guidelines on the wiki will address all the issues reported by Tom. Anyway, I would like to try it.
Can I get permission for the wiki to start this Maintenace Guidelines page. As my english is incorrect and not very rich I expect from others to make the necessary corrections and improvements.
Thanks Vincente! It looks like someone gave you write permission already.
Oh, I didn't know that. If permissions to the track system implies permissions on the wiki, then I should have them.
It's the Trac wiki I'm referring to.
Because we are talking of Maintenace, Evolution, ... I would like to know first which are the current criteria for acceptance of library modifications, in order to make a clear difference on what *must* be done and what *could* be done. Can some one point me to some written document?
There are no set criteria. All modifications are at the discretion of the library maintainer. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

----- Original Message ----- From: "David Abrahams" <dave@boostpro.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 7:25 PM Subject: Re: [boost] Breaking existing libraries
on Fri Nov 21 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
----- Original Message ----- From: "David Abrahams" <dave@boostpro.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 6:23 PM Subject: Re: [boost] Breaking existing libraries
on Fri Nov 21 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
Because we are talking of Maintenace, Evolution, ... I would like to know first which are the current criteria for acceptance of library modifications, in order to make a clear difference on what *must* be done and what *could* be done. Can some one point me to some written document?
There are no set criteria. All modifications are at the discretion of the library maintainer.
I suposse that atleast the library must conforms to the "Boost Library Requirements and Guidelines". Vicente

David Abrahams wrote:
on Thu Nov 20 2008, Tomas Puverle <Tomas.Puverle-AT-morganstanley.com> wrote:
You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range. Here’s a short summary: We are currently (firmwide) using boost 1.33.1. I am in the process of trying to migrate and test some of our apps with boost 1.37. In 1.35 there was a breaking change to Boost.Range with respect to how singular ranges behave. This brings up several issues:
[snip]
At the moment, I have to say I don’t have a good answer to how to fix our code. However, I would at least like to try to make sure this kind of silent breakage doesn’t happen again.
Hi Tom,
Yes, this is an unfortunate situation. If you indeed want to try to make sure this kind of silent breakage doesn’t happen again, there's something you can do about it: write a page of library maintenance guidelines on the wiki at http://svn.boost.org. We are sorely missing a policy on this, and when less-experienced library authors come along, they often don't hew to the same standards that many of us take for granted. If you don't have write permission for the wiki, please let us know and we'll send you an invitation.
Just an idea that popped out of my head - what about running (or at least compiling) the unit/regression tests from the _previous_ major release against the current release as a way to automatically detect and flag interface/behavioral changes? Sure, there are many potential problems with such an approach: - Some library tests are likely to also excercise code at the implementation/detail level. - Already limited testing resources (on the other hand, interface changes are likely to be detected by running such tests for a single, reasonably compliant, compiler). - ... Anyway, this is mostly me thinking out loud; perhaps someone smarter than me could expand on the feasibility of such an idea. / Johan

Johan Nilsson wrote:
Sure, there are many potential problems with such an approach:
- Some library tests are likely to also excercise code at the implementation/detail level. - Already limited testing resources (on the other hand, interface changes are likely to be detected by running such tests for a single, reasonably compliant, compiler). - ...
Anyway, this is mostly me thinking out loud; perhaps someone smarter than me could expand on the feasibility of such an idea.
I hope somebody not claiming to be smarter than you is also allowed to comment ;-) An approach similar to this is used by the GDB project -- there are several versions of the interface from GDB to GUI frontends, and there are presently basically two sets of tests -- one is fixed and tests specific version of the interface. The second set tests all the current behaviour, when it's considered good to go, tests for the current behaviour will be copied into a new set, and won't be touched any more. The primary problem with that approach, in case of GDB, is that it's just not practical to conditionalize every bit of output on used interface version, so the testcases are written to tolerate some "good" additional fields of output. And the testcases have to be modified when new "good" additional fields appear, so the maintenance burden increases. Probably, for C++ Boost this is not an issue, and it's possible to freeze the tests of earlier published interface, and don't touch them. But for C++ Boost, the performance is a real problem. E.g, I suspect that two complete Spirit testsuites, for different versions, will be very hard on test resources. - Volodya

Vladimir Prus wrote:
Johan Nilsson wrote:
Sure, there are many potential problems with such an approach:
- Some library tests are likely to also excercise code at the implementation/detail level. - Already limited testing resources (on the other hand, interface changes are likely to be detected by running such tests for a single, reasonably compliant, compiler). - ...
Anyway, this is mostly me thinking out loud; perhaps someone smarter than me could expand on the feasibility of such an idea.
I hope somebody not claiming to be smarter than you is also allowed to comment ;-)
Ok, I expressed myself badly. Disregard the "smarter" stuff (even though I don't think it should've stopped anyone here from commenting).
An approach similar to this is used by the GDB project -- there are several versions of the interface from GDB to GUI frontends, and there are presently basically two sets of tests -- one is fixed and tests specific version of the interface.
For Boost, this could be equivalent to the interface as accepted during the last public review. How "fixed" are such tests really?
The second set tests all the current behaviour, when it's considered good to go, tests for the current behaviour will be copied into a new set, and won't be touched any more.
Is extending the interface considered equal to breaking the interface?
The primary problem with that approach, in case of GDB, is that it's just not practical to conditionalize every bit of output on used interface version, so the testcases are written to tolerate some "good" additional fields of output. And the testcases have to be modified when new "good" additional fields appear, so the maintenance burden increases.
If this would happen without review, it's almost semantically equivalent to silently breaking the interface. At least if you are talking about the "fixed" tests.
Probably, for C++ Boost this is not an issue, and it's possible to freeze the tests of earlier published interface, and don't touch them. But for C++ Boost, the performance is a real problem. E.g, I suspect that two complete Spirit testsuites, for different versions, will be very hard on test resources.
Yeah, that might be a problem. However, if limiting "interface-regression-testing" to one or two well-conforming compilers running on modern hardware, it might not be such a big problem. / Johan

----- Original Message ----- From: "Johan Nilsson" <r.johan.nilsson@gmail.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 1:02 PM Subject: Re: [boost] Breaking existing libraries
Just an idea that popped out of my head - what about running (or at least compiling) the unit/regression tests from the _previous_ major release against the current release as a way to automatically detect and flag interface/behavioral changes?
Sure, there are many potential problems with such an approach:
- Some library tests are likely to also excercise code at the implementation/detail level. - Already limited testing resources (on the other hand, interface changes are likely to be detected by running such tests for a single, reasonably compliant, compiler). - ...
In order to have the better the author can preserve the test of the older releases and run them on the current release. Vicente

"vicente.botet" <vicente.botet@wanadoo.fr> skrev i meddelandet news:3E6A91215D384FF9AD7BFB070DDD16F7@viboes1...
----- Original Message ----- From: "Johan Nilsson" <r.johan.nilsson@gmail.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 1:02 PM Subject: Re: [boost] Breaking existing libraries
Just an idea that popped out of my head - what about running (or at least compiling) the unit/regression tests from the _previous_ major release against the current release as a way to automatically detect and flag interface/behavioral changes?
Sure, there are many potential problems with such an approach:
- Some library tests are likely to also excercise code at the implementation/detail level. - Already limited testing resources (on the other hand, interface changes are likely to be detected by running such tests for a single, reasonably compliant, compiler). - ...
In order to have the better the author can preserve the test of the older releases and run them on the current release.
Sorry, I don't follow you. / Johan

----- Original Message ----- From: "Johan Nilsson" <r.johan.nilsson@gmail.com> To: <boost@lists.boost.org> Sent: Sunday, November 23, 2008 7:27 PM Subject: Re: [boost] Breaking existing libraries
"vicente.botet" <vicente.botet@wanadoo.fr> skrev i meddelandet news:3E6A91215D384FF9AD7BFB070DDD16F7@viboes1...
----- Original Message ----- From: "Johan Nilsson" <r.johan.nilsson@gmail.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 1:02 PM Subject: Re: [boost] Breaking existing libraries
Just an idea that popped out of my head - what about running (or at least compiling) the unit/regression tests from the _previous_ major release against the current release as a way to automatically detect and flag interface/behavioral changes?
Sure, there are many potential problems with such an approach:
- Some library tests are likely to also excercise code at the implementation/detail level. - Already limited testing resources (on the other hand, interface changes are likely to be detected by running such tests for a single, reasonably compliant, compiler). - ...
In order to have the better the author can preserve the test of the older releases and run them on the current release.
Sorry, I don't follow you.
Daniel Walker has expresed this better "Once accepted, the tests should be a verification that the library does what the community voted on. The tests are a verification of quality. At that point, I think it might be a good idea to quarantine the tests, take them out of the authors hands, and put them under the stewardship of a benevolent dictator of boost as a whole so that they can be used to assure that the library does what the community voted on. " If we need to change while we make evolulion on a library this is a symptom the interface has changed and the same way the test is broken, the user code canbe broken. If we forbid this test changes, we are able to identify breaking changes. Vicenet

vicente.botet wrote:
----- Original Message ----- From: "Johan Nilsson" <r.johan.nilsson@gmail.com>
"vicente.botet" <vicente.botet@wanadoo.fr> skrev i meddelandet news:3E6A91215D384FF9AD7BFB070DDD16F7@viboes1...
----- Original Message ----- From: "Johan Nilsson" <r.johan.nilsson@gmail.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 1:02 PM Subject: Re: [boost] Breaking existing libraries
Just an idea that popped out of my head - what about running (or at least compiling) the unit/regression tests from the _previous_ major release against the current release as a way to automatically detect and flag interface/behavioral changes?
Sure, there are many potential problems with such an approach:
- Some library tests are likely to also excercise code at the implementation/detail level. - Already limited testing resources (on the other hand, interface changes are likely to be detected by running such tests for a single, reasonably compliant, compiler). - ...
In order to have the better the author can preserve the test of the older releases and run them on the current release.
Sorry, I don't follow you.
Daniel Walker has expresed this better "Once accepted, the tests should be a verification that the library does what the community voted on. The tests are a verification of quality. At that point, I think it might be a good idea to quarantine the tests, take them out of the authors hands, and put them under the stewardship of a benevolent dictator of boost as a whole so that they can be used to assure that the library does what the community voted on. "
Sounds like a good idea in general. Reference, please.
If we need to change while we make evolulion on a library this is a symptom the interface has changed and the same way the test is broken, the user code canbe broken. If we forbid this test changes, we are able to identify breaking changes.
In order to truly make such a thing work, I think it would be neccessary to separate interface and implementation tests. There is almost always a need for testing implementation details, which should be free for the author to change (and improve upon). How do you think extensions to the interface should be handled? / Johan

on Sun Nov 23 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
Daniel Walker has expresed this better "Once accepted, the tests should be a verification that the library does what the community voted on. The tests are a verification of quality. At that point, I think it might be a good idea to quarantine the tests, take them out of the authors hands, and put them under the stewardship of a benevolent dictator of boost as a whole so that they can be used to assure that the library does what the community voted on. "
If we need to change while we make evolulion on a library this is a symptom the interface has changed and the same way the test is broken, the user code canbe broken. If we forbid this test changes, we are able to identify breaking changes.
I'm sorry, but I just don't think anything like this is going to work. Among other things, I think it will be a huge pain for existing library authors (suppose I want to _add_ something to a test?) and will deter people from contributing to Boost, and I don't think you're going to get a positive consensus on it among existing contributors. This seems like an overreaction to one person's failure at disciplined management of library evolution. Rather than set up systems that will decrease agility, increase coupling, and give contriutors the sense that the Boost community doesn't trust them to do what's right, suppose we set up a mailing list to which all the test checkins are posted? Then anyone who wants to monitor the evolution of a library's tests can subscribe to that list. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Mon, Nov 24, 2008 at 9:28 AM, David Abrahams <dave@boostpro.com> wrote:
on Sun Nov 23 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
Daniel Walker has expresed this better "Once accepted, the tests should be a verification that the library does what the community voted on. The tests are a verification of quality. At that point, I think it might be a good idea to quarantine the tests, take them out of the authors hands, and put them under the stewardship of a benevolent dictator of boost as a whole so that they can be used to assure that the library does what the community voted on. "
If we need to change while we make evolulion on a library this is a symptom the interface has changed and the same way the test is broken, the user code canbe broken. If we forbid this test changes, we are able to identify breaking changes.
I'm sorry, but I just don't think anything like this is going to work. Among other things, I think it will be a huge pain for existing library authors (suppose I want to _add_ something to a test?) and will deter people from contributing to Boost, and I don't think you're going to get a positive consensus on it among existing contributors. This seems like an overreaction to one person's failure at disciplined management of library evolution.
I see your point and I agree that policies should not make it difficult for authors to test their code. However, submitting a patch is not so difficult. As for contributing to Boost, people are also deterred when they take the time to understand a library and submit improvements to it, only to have the rug pulled out from under them. This is actually my personal experience with Boost.Range. The Range concepts used to have an empty(r) that I believe addressed the issue of empty ranges independently of iterator_range. But the whole thing falls on its face when for no sensible reason the function was removed from the concept definition. Why should I use the new Range concepts, let alone contribute to the library, if these are not even the concepts that were released after review and acceptance for boost? I mean, I'm not throwing in the towel, I'm just expressing my frustration, not only as a user but as a contributer.
Rather than set up systems that will decrease agility, increase coupling, and give contriutors the sense that the Boost community doesn't trust them to do what's right, suppose we set up a mailing list to which all the test checkins are posted? Then anyone who wants to monitor the evolution of a library's tests can subscribe to that list.
I think this is a good idea, and in principle I could support it. However, I must point out that it brings up another issue: Individuals in the Boost community have some responsibility for monitoring Boost development. If I had been paying closer attention, I could have protested the changes in the Range concepts a long time ago. Unfortunately, it's not easy to pay participate in all the mail traffic on this list, especially when you have other demands on your attention in life. This is why I'd like to automat quality control of testing to the extent that after the community reviews and votes on the unit tests as part of library acceptance, they can expect their votes won't one day be nullified so easily. I don't know that my suggestion would have even been enough to catch the problem in Boost.Range, but it might help in the future. Daniel Walker

Daniel Walker skrev:
On Mon, Nov 24, 2008 at 9:28 AM, David Abrahams <dave@boostpro.com> wrote:
on Sun Nov 23 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
As for contributing to Boost, people are also deterred when they take the time to understand a library and submit improvements to it, only to have the rug pulled out from under them. This is actually my personal experience with Boost.Range. The Range concepts used to have an empty(r) that I believe addressed the issue of empty ranges independently of iterator_range. But the whole thing falls on its face when for no sensible reason the function was removed from the concept definition. Why should I use the new Range concepts, let alone contribute to the library, if these are not even the concepts that were released after review and acceptance for boost? I mean, I'm not throwing in the towel, I'm just expressing my frustration, not only as a user but as a contributer.
Rather than set up systems that will decrease agility, increase coupling, and give contriutors the sense that the Boost community doesn't trust them to do what's right, suppose we set up a mailing list to which all the test checkins are posted? Then anyone who wants to monitor the evolution of a library's tests can subscribe to that list.
I think this is a good idea, and in principle I could support it. However, I must point out that it brings up another issue: Individuals in the Boost community have some responsibility for monitoring Boost development. If I had been paying closer attention, I could have protested the changes in the Range concepts a long time ago.
Daniel, I just want to reiterate something. It is true that there was no second review of the new concepts and that the change could have been announced better. But the change was far from accidental, and was not only motivated by my wish to break peoples code (ironi), but came about because users of the library had great troubles with the original concepts. We had lengthy discussion here on the list. Eric Niebler initiated some of them because he was trying to use boost.range in Boost.for_each. Although you might be of a different opinion, then it was not without sensible reason to remove empty() from the concepts. The new concepts are much clearer, and let us define empty as boost::empty(r) without imposing additional concept requirements. The library changed after its original form, and into something much better. And the change was motivated by real user feedback, something which the original review in some sense could not provide as much of. best regards -Thorsten

On Mon, Nov 24, 2008 at 4:40 PM, Thorsten Ottosen
The library changed after its original form, and into something much better. And the change was motivated by real user feedback, something which the original review in some sense could not provide as much of.
This relates to another thread. Should libraries be marked as stable/experimental? No library can be stable before it has met its first real users. New libraries are marked as experimental in at least one Boost release. This ought to be OK, since the Boost release cycle is so short nowadays. The release must be commonly available first though. /$

Henrik Sundberg <storangen <at> gmail.com> writes:
On Mon, Nov 24, 2008 at 4:40 PM, Thorsten Ottosen
The library changed after its original form, and into something much better. And the change was motivated by real user feedback, something which the original review in some sense could not provide as much of.
This relates to another thread. Should libraries be marked as stable/experimental? No library can be stable before it has met its first real users. New libraries are marked as experimental in at least one Boost release. This ought to be OK, since the Boost release cycle is so short nowadays. The release must be commonly available first though.
Precisely. Are you talking about Dave and my idea of having two different release cycles for "stable" and "new" components? Glad you brought it up - it seems to have gotten completely ignored initially.

on Mon Nov 24 2008, Tomas Puverle <Tomas.Puverle-AT-morganstanley.com> wrote:
Henrik Sundberg <storangen <at> gmail.com> writes:
On Mon, Nov 24, 2008 at 4:40 PM, Thorsten Ottosen
The library changed after its original form, and into something much better. And the change was motivated by real user feedback, something which the original review in some sense could not provide as much of.
This relates to another thread. Should libraries be marked as stable/experimental? No library can be stable before it has met its first real users. New libraries are marked as experimental in at least one Boost release. This ought to be OK, since the Boost release cycle is so short nowadays. The release must be commonly available first though.
Precisely. Are you talking about Dave and my idea of having two different release cycles for "stable" and "new" components? Glad you brought it up - it seems to have gotten completely ignored initially.
I'm really warming up to the idea. I don't think it was mine in any way, but thanks for the credit (or is there another Dave here?) -- Dave Abrahams BoostPro Computing http://www.boostpro.com

"David Abrahams" <dave@boostpro.com> wrote in message news:87d4g9fa15.fsf@mcbain.luannocracy.com...
Precisely. Are you talking about Dave and my idea of having two different release cycles for "stable" and "new" components? Glad you brought it up - it seems to have gotten completely ignored initially.
I'm really warming up to the idea. I don't think it was mine in any way, but thanks for the credit (or is there another Dave here?)
Sorry, I was referring to Dave Handley.

on Mon Nov 24 2008, "Henrik Sundberg" <storangen-AT-gmail.com> wrote:
On Mon, Nov 24, 2008 at 4:40 PM, Thorsten Ottosen
The library changed after its original form, and into something much better. And the change was motivated by real user feedback, something which the original review in some sense could not provide as much of.
This relates to another thread. Should libraries be marked as stable/experimental?
I like it, but I would prefer stable/new. Libraries that aren't new shouldn't be unstable, and rewrites would make the library "new" again. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

"David Abrahams" <dave@boostpro.com> wrote in message news:87hc5lfak7.fsf@mcbain.luannocracy.com...
This relates to another thread. Should libraries be marked as stable/experimental?
I like it, but I would prefer stable/new. Libraries that aren't new shouldn't be unstable, and rewrites would make the library "new" again.
Agreed completely. This would be very useful to have.

David Abrahams wrote:
on Mon Nov 24 2008, "Henrik Sundberg" <storangen-AT-gmail.com> wrote:
This relates to another thread. Should libraries be marked as stable/experimental?
I like it, but I would prefer stable/new. Libraries that aren't new shouldn't be unstable, and rewrites would make the library "new" again.
This raises the obvious question: Where do you trace the line between a minor change ('fix') and a rewrite ? And how do you enforce it ? Thanks, Stefan -- ...ich hab' noch einen Koffer in Berlin...

on Wed Dec 03 2008, Stefan Seefeld <seefeld-AT-sympatico.ca> wrote:
David Abrahams wrote:
on Mon Nov 24 2008, "Henrik Sundberg" <storangen-AT-gmail.com> wrote:
This relates to another thread. Should libraries be marked as stable/experimental?
I like it, but I would prefer stable/new. Libraries that aren't new shouldn't be unstable, and rewrites would make the library "new" again.
This raises the obvious question: Where do you trace the line between a minor change ('fix') and a rewrite ? And how do you enforce it ?
There's very little we can enforce here, so you don't. You make it a "cultural imperative." Set up the guidelines page, let people know when their libraries are accepted that they should read and follow it, and scream loudly if things are handled badly. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Mon, Nov 24, 2008 at 10:40 AM, Thorsten Ottosen <thorsten.ottosen@dezide.com> wrote:
But the change was far from accidental, and was not only motivated by my wish to break peoples code (ironi), but came about because users of the library had great troubles with the original concepts. We had lengthy discussion here on the list. Eric Niebler initiated some of them because he was trying to use boost.range in Boost.for_each.
Name one trouble that anyone had with the Range concepts that was caused by the presence of the empty(r) requirement. The accusation doesn't make any sense. How did removing empty(r) fix a bug or implementation or interface issue with Boost.For_each? Was there a name conflict?! I mean, look, even if for some reason you did need a Range concept that didn't require empty(r), the solution is not to deny all types the ability to model Range concepts that require empty(r). If you need an even less specific concept of a Range, define a less specific Range concept. Don't artificially collapse the requirements of richer concept specifications. By analogy, the fact that the most general iterator is a SinglePassIterator doesn't mean that we should remove the additional refinements of the ForwardIterator, BidirectionalIterator, and RandomAccessIterators. That there is a minimalist Container concept definition does not mean that we should remove the refinements that give us AssociativeContainers, etc. If you needed a Range concept that didn't include empty(r), you should define the new, less refined Concept, not destroy the more refined Concepts.
Although you might be of a different opinion, then it was not without sensible reason to remove empty() from the concepts. The new concepts are much clearer, and let us define empty as boost::empty(r) without imposing additional concept requirements.
Concept requirements are not imposing; they are enabling! Without the empty(r) requirement users are not able to test a range for emptiness directly in a generic way. In other words, if a function's only type requirements is that it support the expressions begin(r), end(r) and empty(r), then it should require that the type model a concept with these expressions. If the Range concept no longer supports these expression, then users can no longer write generic functions that require them. Removing empty(r) also puts limits on the authors of types modeling Range. Say you write a type that models Range where the values in the range are held in a database on the other side of the network. Perhaps there's a fast way to implement empty(r) if you know something about the database and/or network topology. However, if empty(r) is not required by the concept then you can't offer this benefit to users who writing generic code for any Range based on the definition of the Range concept. This issue is just going to become more pronounced as concepts play a more prominent role in C++0x.
The library changed after its original form, and into something much better.
How is it better to not be able to check for emptiness in a generic way?
And the change was motivated by real user feedback, something which the original review in some sense could not provide as much of.
I'm sure you had feedback regarding iterator_range. However, I seriously doubt that you received feedback from users demanding that empty(r) be immediately removed from the definition of the Range concept. That doesn't make any sense, Daniel Walker

Daniel Walker skrev:
On Mon, Nov 24, 2008 at 10:40 AM, Thorsten Ottosen <thorsten.ottosen@dezide.com> wrote:
And the change was motivated by real user feedback, something which the original review in some sense could not provide as much of.
I'm sure you had feedback regarding iterator_range. However, I seriously doubt that you received feedback from users demanding that empty(r) be immediately removed from the definition of the Range concept. That doesn't make any sense,
The feedback was related to the core concepts and on how to map your own type to the range concept. This task was greatly simlpified in the new version. Having redundant spec in a concept is never going to fly. I'm to busy to argue this case anymore. The original design was much worse than the current. Period. -Thorsten

on Mon Nov 24 2008, "Daniel Walker" <daniel.j.walker-AT-gmail.com> wrote:
On Mon, Nov 24, 2008 at 10:40 AM, Thorsten Ottosen <thorsten.ottosen@dezide.com> wrote:
But the change was far from accidental, and was not only motivated by my wish to break peoples code (ironi), but came about because users of the library had great troubles with the original concepts. We had lengthy discussion here on the list. Eric Niebler initiated some of them because he was trying to use boost.range in Boost.for_each.
Name one trouble that anyone had with the Range concepts that was caused by the presence of the empty(r) requirement. The accusation doesn't make any sense.
Sure it does. It makes it more tedious and error-prone to create a conforming range, with no benefit at all AFAICT. Is there some benefit I'm missing, if we can define a single generic empty algorithm in terms of Range's begin/end requirements? Seems to me, requiring empty() in ranges is sort of equivalent to requiring iterators to support distance.
How did removing empty(r) fix a bug or implementation or interface issue with Boost.For_each? Was there a name conflict?!
I mean, look, even if for some reason you did need a Range concept that didn't require empty(r), the solution is not to deny all types the ability to model Range concepts that require empty(r).
I can't understand what you're saying. Removing empty(r) from the range concept doesn't suddenly make all types that support empty(r) non-ranges.
If you need an even less specific concept of a Range, define a less specific Range concept. Don't artificially collapse the requirements of richer concept specifications.
I would agree with you if the collapse was artificial, but it's not, IMO. It's merely zeroing in on the right concept. I realize, of course, that others may disagree with me, but I really do think there exists a Platonic Range concept, and it doesn't require empty().
By analogy, the fact that the most general iterator is a SinglePassIterator doesn't mean that we should remove the additional refinements of the ForwardIterator, BidirectionalIterator, and RandomAccessIterators. That there is a minimalist Container concept definition does not mean that we should remove the refinements that give us AssociativeContainers, etc. If you needed a Range concept that didn't include empty(r), you should define the new, less refined Concept, not destroy the more refined Concepts.
BidirectionalIterator provides additional capabilities not available with SinglePassIterator. What additional capabilities are provided by RangeWithEmpty?
Although you might be of a different opinion, then it was not without sensible reason to remove empty() from the concepts. The new concepts are much clearer, and let us define empty as boost::empty(r) without imposing additional concept requirements.
Concept requirements are not imposing; they are enabling!
Have you written any iterators by hand lately?
Without the empty(r) requirement users are not able to test a range for emptiness directly in a generic way.
boost::empty(r) ?
In other words, if a function's only type requirements is that it support the expressions begin(r), end(r) and empty(r), then it should require that the type model a concept with these expressions. If the Range concept no longer supports these expression, then users can no longer write generic functions that require them.
Empty is defined as // C++0x syntax template <Range R> bool empty(R const& x) { return x.begin() == x.end(); } In other words, you can call it on any Range.
Removing empty(r) also puts limits on the authors of types modeling Range.
I don't see how?
Say you write a type that models Range where the values in the range are held in a database on the other side of the network. Perhaps there's a fast way to implement empty(r) if you know something about the database and/or network topology. However, if empty(r) is not required by the concept then you can't offer this benefit to users who writing generic code for any Range based on the definition of the Range concept. This issue is just going to become more pronounced as concepts play a more prominent role in C++0x.
Copying and comparing iterators is supposed to be efficient. If it isn't reasonably efficient, you've done something wrong. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
Seems to me, requiring empty() in ranges is sort of equivalent to requiring iterators to support distance.
Does removing empty from the range concept prevent the empty algorithm from being specialized for ranges with a more efficient way to determine calculate empty? For instance a vector-like range might store a pointer to the first element and a element count in this case empty is bool empty() const { return !count; } where as the default range empty is equivalent to writing empty as bool empty() const { return p != p+count; } perhaps there is a range refinement which can support ranges which have a more efficient empty? -- Michael Marcin

Neil Groves wrote: I think that empty() is not beneficial as part of the Range concept. It adds nothing in features or performance. On Wed, Dec 3, 2008 at 7:50 PM, Michael Marcin <mike.marcin@gmail.com>wrote:
David Abrahams wrote:
Seems to me, requiring empty() in ranges is sort of equivalent to requiring iterators to support distance.
Does removing empty from the range concept prevent the empty algorithm from being specialized for ranges with a more efficient way to determine calculate empty?
For instance a vector-like range might store a pointer to the first element and a element count in this case empty is
bool empty() const { return !count; }
where as the default range empty is equivalent to writing empty as
bool empty() const { return p != p+count; }
perhaps there is a range refinement which can support ranges which have a more efficient empty?
We could use adl to find a boost_range_empty() function from boost::empty(). This could be implemented by comparing iterators by default, and specialised as desired for optimisation purposes.
-- Michael Marcin
Neil Groves
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

David Abrahams-3 wrote:
on Sun Nov 23 2008, "vicente.botet" <vicente.botet-AT-wanadoo.fr> wrote:
Daniel Walker has expresed this better "Once accepted, the tests should be a verification that the library does what the community voted on. The tests are a verification of quality. At that point, I think it might be a good idea to quarantine the tests, take them out of the authors hands, and put them under the stewardship of a benevolent dictator of boost as a whole so that they can be used to assure that the library does what the community voted on. "
If we need to change while we make evolulion on a library this is a symptom the interface has changed and the same way the test is broken, the user code canbe broken. If we forbid this test changes, we are able to identify breaking changes.
I'm sorry, but I just don't think anything like this is going to work. Among other things, I think it will be a huge pain for existing library authors (suppose I want to _add_ something to a test?) and will deter people from contributing to Boost, and I don't think you're going to get a positive consensus on it among existing contributors. This seems like an overreaction to one person's failure at disciplined management of library evolution.
Rather than set up systems that will decrease agility, increase coupling, and give contriutors the sense that the Boost community doesn't trust them to do what's right, suppose we set up a mailing list to which all the test checkins are posted? Then anyone who wants to monitor the evolution of a library's tests can subscribe to that list.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Hi, I'm soory I didn't want to forbid nothing to the authors. The fact I used 'we' and 'forbid' was misleading. Mi intention was other, please reconsider my phase as follows:" If the author need to change while he makes evolulion on his library this could be a symptom the interface has changed and the same way the test is broken, the user code could also be broken. If the author forbid himself to changes the test from the preceding version, he will be able to identify early breaking changes." Don't you think that an author would practice this himself for his own convenience? Vicente -- View this message in context: http://www.nabble.com/Breaking-existing-libraries-tp20605440p20663004.html Sent from the Boost - Dev mailing list archive at Nabble.com.

suppose we set up a mailing list to which all the test checkins are posted? Then anyone who wants to monitor the evolution of a library's tests can subscribe to that list.
Dave, I don't know how much email you get a day but this doesn't sounds workable. It's bad enough to try to keep up with the users and devel traffic, let alone with extra emails whenever the developer decides to change a test case. This cannot be automated - I would argue that it should be the responsibility of the library maintainer to let the users know of any large impeding changes.

on Mon Nov 24 2008, "Tomas Puverle" <Tomas.Puverle-AT-morganstanley.com> wrote:
suppose we set up a mailing list to which all the test checkins are posted? Then anyone who wants to monitor the evolution of a library's tests can subscribe to that list.
Dave, I don't know how much email you get a day but this doesn't sounds workable.
Along with filtering rules, it can be managed.
It's bad enough to try to keep up with the users and devel traffic, let alone with extra emails whenever the developer decides to change a test case.
This cannot be automated - I would argue that it should be the responsibility of the library maintainer to let the users know of any large impeding changes.
Of course it is, but the suggestions to which I responded seemed not to be aimed at leaving it _entirely_ in the hands of the maintainers. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
on Thu Nov 20 2008, Tomas Puverle <Tomas.Puverle-AT-morganstanley.com> wrote:
You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range. Here’s a short summary: We are currently (firmwide) using boost 1.33.1. I am in the process of trying to migrate and test some of our apps with boost 1.37. In 1.35 there was a breaking change to Boost.Range with respect to how singular ranges behave. This brings up several issues:
1) The breakage was silent. The interface stayed the same but the behavior changed, and drastically so. 2) No communation: While I don’t usually post to boost.devel/boost.user, I and my colleagues still read it. Nobody recalls any mention of this on the list. Searching gmane brings up nothing, either. 3) No documentation on the boost website. As far as I can see, this change was introduced in 1.35 this March. On http://www.boost.org/users/news/version_1_35_0, there is no mention of a breaking change to Boost.Range. 4) The new Boost.Range behaves differently in debug and release builds. The public function is_singular() always returns false in release builds even when it would return true in debug builds.
Apart from the fact that this change breaks a lot of our code and obsoletes several useful (necessary?) idioms, the manner in which it happened is far below the standards that one has come to expect from boost.
At the moment, I have to say I don’t have a good answer to how to fix our code. However, I would at least like to try to make sure this kind of silent breakage doesn’t happen again.
Hi Tom,
Yes, this is an unfortunate situation. If you indeed want to try to make sure this kind of silent breakage doesn’t happen again, there's something you can do about it: write a page of library maintenance guidelines on the wiki at http://svn.boost.org. We are sorely missing a policy on this, and when less-experienced library authors come along, they often don't hew to the same standards that many of us take for granted. If you don't have write permission for the wiki, please let us know and we'll send you an invitation.
The issue is not so much that breakage occurs but that it is sometimes undocumented. No wiki entry is going to fix that, since there is little in general to say about it other than the very obvious. Which is that if any library developer, whether Boost or otherwise, makes a change from one release to the next which changes some functionality the end-user can use, that change needs to be documented so that end-users can easily see it and adjust their code which uses that library if necessary. How Boost in particular accomplishes that is up to the Boost developers, not the end-user community, although it is appreciated that Boost developers may solicit input from end users about this matter as you have done in your answer.

Tomas Puverle wrote:
You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range.
[cut]
At the moment, I have to say I don’t have a good answer to how to fix our code. However, I would at least like to try to make sure this kind of silent breakage doesn’t happen again.
Tom
I sympathize with you, since it also happened to me a few days ago with updating to 1.37 with the boost::exception - previously documented features such as BOOST_ERROR_INFO completely disappeared and others like diagnostic_information suddenly became free functions and not members like before. Yes, the new *substitutes* are nicer and make more sense, but the authors could have simply depreciated the old interface (*not* remove it) and add the new "features" parallel to it. In my case there were only a few lines/macros that needed changing but it was annoying regardless. As in your case I couldn't find any written trace of the changes until I started compiling and the library wasn't even mentioned in the "changed libraries" in the 1.37 release notes! -- Hrvoje Prgeša

----- Original Message ----- From: "Hrvoje Prgeša" <hrvoje.prgesa@gmail.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 1:46 AM Subject: Re: [boost] Breaking existing libraries
As in your case I couldn't find any written trace of the changes until I started compiling and the library wasn't even mentioned in the "changed libraries" in the 1.37 release notes!
You are right, I was reported to this ML the list of libraries that have changed on1.37 and asked the authors and the release manager to add them to the release contents. Unfortunately it was too late and only Boost.Exception posted its new contetns. Best, Vicente

Tomas Puverle <Tomas.Puverle <at> morganstanley.com> writes:
You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range. Here’s a short summary: We are currently (firmwide) using boost 1.33.1. I am in the process of trying to migrate and test some of our apps with boost 1.37. In 1.35 there was a breaking change to Boost.Range with respect to how singular ranges behave. This brings up several issues: [...] Apart from the fact that this change breaks a lot of our code and obsoletes several useful (necessary?) idioms, the manner in which it happened is far below the standards that one has come to expect from boost. [...]
In advance: I suffer from breaking changes in boost all the time and bite the table plate quite often. Indeed we have a problem here. The changes in e.g. spirit are a drama and I fear the day I have to check all of my (absolute stable) parser code, just in order to get things up-to-date, introducing a plethora of new bugs in code I did not want to touch again. [Sidenote: I'd prefer boost::spirit to stay as it is and spirit2c be renamed to boost::ultimate_parser, since it is a *completely* *different* library.] The boost community has not found the perfect way to deal with breaking changes yet, since this is an issue that cannot be easily solved. OTOH: There is a tradeoff between quality of implementation and innovation that we all have to live with. Boost is a project traded by volunteers with an aim towards bleeding edge technology, not always waiting for customers to nod. Boost developers sometimes move faster than lightning (try to follow the code changes made by Eric Niebler for 2 weeks just to get an impression) and if you compare the collateral damages of this to the benefits I would still give the boost community a higher credit than Microsoft (they break everything every 3 years and no one even tries to complain). The key issue is: You did not pay for what you use. The Good News (TM) is that you can pay for it now: People at boost-consulting can help you with your problem within a week or so (middleman fees to me, please ;-)). But let us go back on the we-do-not-pay-for-it path: IMHO it is a severe error of your development process that you do not check your code with new versions of all compilers and all libraries on a *regular* basis. In management parlance: your risk management is defective. It always is a good idea to use the svn repo of boost and the beta version of the next compiler just to see the breaking changes early enough, which gives everyone plenty of time to react. Version 1.33.1 is from the stone age (remember boost is moving faster than light[ning]) and I always expect things to be broken the next time (which is not nice, but compared to the problems solved by boost this still can be neglected). regards, Markus

On Fri, Nov 21, 2008 at 8:26 AM, Markus Werle <numerical.simulation@web.de>wrote:
Tomas Puverle <Tomas.Puverle <at> morganstanley.com> writes:
You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range. Here's a short summary: We are currently (firmwide) using boost 1.33.1. I am in the process of trying to migrate and test some of our apps with boost 1.37. In 1.35 there was a breaking change to Boost.Range with respect to how singular ranges behave. This brings up several issues: [...] Apart from the fact that this change breaks a lot of our code and obsoletes several useful (necessary?) idioms, the manner in which it happened is far below the standards that one has come to expect from boost. [...]
In advance: I suffer from breaking changes in boost all the time and bite the table plate quite often. Indeed we have a problem here. The changes in e.g. spirit are a drama and I fear the day I have to check all of my (absolute stable) parser code, just in order to get things up-to-date, introducing a plethora of new bugs in code I did not want to touch again. [Sidenote: I'd prefer boost::spirit to stay as it is and spirit2c be renamed to boost::ultimate_parser, since it is a *completely* *different* library.] The boost community has not found the perfect way to deal with breaking changes yet, since this is an issue that cannot be easily solved.
OTOH:
There is a tradeoff between quality of implementation and innovation that we all have to live with. Boost is a project traded by volunteers with an aim towards bleeding edge technology, not always waiting for customers to nod. Boost developers sometimes move faster than lightning (try to follow the code changes made by Eric Niebler for 2 weeks just to get an impression) and if you compare the collateral damages of this to the benefits I would still give the boost community a higher credit than Microsoft (they break everything every 3 years and no one even tries to complain).
The key issue is: You did not pay for what you use. The Good News (TM) is that you can pay for it now: People at boost-consulting can help you with your problem within a week or so (middleman fees to me, please ;-)).
But let us go back on the we-do-not-pay-for-it path: IMHO it is a severe error of your development process that you do not check your code with new versions of all compilers and all libraries on a *regular* basis. In management parlance: your risk management is defective. It always is a good idea to use the svn repo of boost and the beta version of the next compiler just to see the breaking changes early enough, which gives everyone plenty of time to react.
Version 1.33.1 is from the stone age (remember boost is moving faster than light[ning]) and I always expect things to be broken the next time (which is not nice, but compared to the problems solved by boost this still can be neglected).
This is a very useful post, and makes some excellent points. In particular this cuts to the very core of what Boost is. There are, I'm sure, various statements throughout the site concerned with the 'Boost Mission', but in reality it it is very much a moving target and constantly evolving. However, as a group we do tend to be a bit schizophrenic about this, and about balancing the 'technical showcase' aspects with the 'reliable product' aspects. We do, in my opinion, encourage the use of the libraries in commercial products, and as such it seems to me that we have a duty to be mindful of that in our practices and policies. Failure to do that will result in the Boost project becoming marginalised as just a bunch of (very highly skilled!) hackers, which would be a shame. Alarmingly I already see that happening in some companies I've worked in, in which less progressive elements exploit exactly these kind of perceived weaknesses to spread Fear, Uncertainty and Doubt. As with everything it is ultimately about balance, and my feeling is that these changes to the Boost.Range library do not balance these considerations well. - Rob.

Markus Werle escribió:
But let us go back on the we-do-not-pay-for-it path: IMHO it is a severe error of your development process that you do not check your code with new versions of all compilers and all libraries on a *regular* basis. In management parlance: your risk management is defective. It always is a good idea to use the svn repo of boost and the beta version of the next compiler just to see the breaking changes early enough, which gives everyone plenty of time to react.
On this particular point, I find that beta periods usually gather very little feedback from actual users of the code, and it is later in time when people begin to complain about breaking changes (I'm meaning unintentional breaking changes here). Somehow the Boost *users* community seems not to be very involved in the release process, and we should find ways to press them to test betas more thouroughly than it's being done currently. Maybe we can begin by proactively sending announce mails to the companies in the "Who's using Boost" entry whenever a beta period begins; we'd need a contacts list to do that. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

joaquin@tid.es wrote:
Markus Werle escribió:
But let us go back on the we-do-not-pay-for-it path: IMHO it is a severe error of your development process that you do not check your code with new versions of all compilers and all libraries on a *regular* basis. In management parlance: your risk management is defective. It always is a good idea to use the svn repo of boost and the beta version of the next compiler just to see the breaking changes early enough, which gives everyone plenty of time to react.
On this particular point, I find that beta periods usually gather very little feedback from actual users of the code, and it is later in time when people begin to complain about breaking changes (I'm meaning unintentional breaking changes here). Somehow the Boost *users* community seems not to be very involved in the release process, and we should find ways to press them to test betas more thouroughly than it's being done currently. Maybe we can begin by proactively sending announce mails to the companies in the "Who's using Boost" entry whenever a beta period begins; we'd need a contacts list to do that.
Do you think it will work? You basically want users to grab new Boost, build it, update their source code, and do automatic and manual QA. And all this during 2-weeks window. And further, if user runs into a bug he has to fix it, or discuss with Boost developers, and this means maintaining two branches of the code, which the associated overhead. So, it's no surprise that many users prefer to wait till release is out, for quite some time. More publicity for beta will somewhat improve things, but I suspect we won't get very much testing still. Examining the changes in testcases might help, but I don't know who's gonna do it. - Volodya

Vladimir Prus escribió:
joaquin@tid.es wrote:
Markus Werle escribió:
But let us go back on the we-do-not-pay-for-it path: IMHO it is a severe error of your development process that you do not check your code with new versions of all compilers and all libraries on a *regular* basis. In management parlance: your risk management is defective. It always is a good idea to use the svn repo of boost and the beta version of the next compiler just to see the breaking changes early enough, which gives everyone plenty of time to react.
On this particular point, I find that beta periods usually gather very little feedback from actual users of the code, and it is later in time when people begin to complain about breaking changes (I'm meaning unintentional breaking changes here). Somehow the Boost *users* community seems not to be very involved in the release process, and we should find ways to press them to test betas more thouroughly than it's being done currently. Maybe we can begin by proactively sending announce mails to the companies in the "Who's using Boost" entry whenever a beta period begins; we'd need a contacts list to do that.
Do you think it will work? You basically want users to grab new Boost, build it, update their source code, and do automatic and manual QA. And all this during 2-weeks window. And further, if user runs into a bug he has to fix it, or discuss with Boost developers, and this means maintaining two branches of the code, which the associated overhead.
What's the purpose of having a beta then if not to let users test the code before the final release? If two weeks is too little time maybe we should consider extending it, but undergoing a beta period without actually expecting to receive users' feedback makes no sense to me. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

joaquin@tid.es wrote:
Do you think it will work? You basically want users to grab new Boost, build it, update their source code, and do automatic and manual QA. And all this during 2-weeks window. And further, if user runs into a bug he has to fix it, or discuss with Boost developers, and this means maintaining two branches of the code, which the associated overhead.
What's the purpose of having a beta then if not to let users test the code before the final release? If two weeks is too little time maybe we should consider extending it, but undergoing a beta period without actually expecting to receive users' feedback makes no sense to me.
I guess that the only feedback we can practically expect is that the next release is not a brick. Maybe also some feedback about cool new features that users are dying for -- if such features are advertised properly. Interface-breaking changes in a specific library are likely to be missed, so *if* we want interface compatibility in some form, we need some other mechanism in place, for example: * A policy that interface breakage need to be discussed * Running old release tests against new Boost version * Dot releases - Volodya

Interface-breaking changes in a specific library are likely to be missed, so *if* we want interface compatibility in some form, we need some other mechanism > in place, for example:
* A policy that interface breakage need to be discussed * Running old release tests against new Boost version * Dot releases
I think I would add another, stronger point: Completely changing the (documented!) behaviour of a component is not allowed in a single release.

on Fri Nov 21 2008, Markus Werle <numerical.simulation-AT-web.de> wrote:
Tomas Puverle <Tomas.Puverle <at> morganstanley.com> writes:
You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range. Here’s a short summary: We are currently (firmwide) using boost 1.33.1. I am in the process of trying to migrate and test some of our apps with boost 1.37. In 1.35 there was a breaking change to Boost.Range with respect to how singular ranges behave. This brings up several issues: [...] Apart from the fact that this change breaks a lot of our code and obsoletes several useful (necessary?) idioms, the manner in which it happened is far below the standards that one has come to expect from boost. [...]
In advance: I suffer from breaking changes in boost all the time and bite the table plate quite often. Indeed we have a problem here. The changes in e.g. spirit are a drama and I fear the day I have to check all of my (absolute stable) parser code, just in order to get things up-to-date, introducing a plethora of new bugs in code I did not want to touch again. [Sidenote: I'd prefer boost::spirit to stay as it is and spirit2c be renamed to boost::ultimate_parser, since it is a *completely* *different* library.] The boost community has not found the perfect way to deal with breaking changes yet, since this is an issue that cannot be easily solved.
It's something that we could easily do better.
OTOH:
There is a tradeoff between quality of implementation and innovation that we all have to live with. Boost is a project traded by volunteers with an aim towards bleeding edge technology, not always waiting for customers to nod. Boost developers sometimes move faster than lightning (try to follow the code changes made by Eric Niebler for 2 weeks just to get an impression) and if you compare the collateral damages of this to the benefits I would still give the boost community a higher credit than Microsoft (they break everything every 3 years and no one even tries to complain).
The key issue is: You did not pay for what you use.
I'm sorry to contradict, but I don't think that's the key issue. IMO, the key issue is giving care to disoverability and the ability to make a transition: * Avoiding completely silent breakage * Using a deprecation period to give users notice that a breaking change is coming * Documenting a transition procedure * ....etc.
The Good News (TM) is that you can pay for it now: People at boost-consulting can help you with your problem within a week or so (middleman fees to me, please ;-)).
I'll see if there's something we can do ;-)
But let us go back on the we-do-not-pay-for-it path: IMHO it is a severe error of your development process that you do not check your code with new versions of all compilers and all libraries on a *regular* basis.
I agree that testing needs to be made more regular and thorough. However, IMO the universe of compilers and libraries is much too large --- and in some cases, the software is too expensive --- for us to check code with new versions of *all* compilers and *all* libraries. We need to select a subset against which we'll test. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

This is a attempt to start discussing the interface of multivariate distributions. In this example I've used the bivariate normal distribution, but it the idea's should extend to multivariate distributions. An instance of the bivariate normal distribution is uniquely defined by its mean (2 elements) and its covariance matrix. The covariance matrix is symmetric by definition. The covariance matrix should also be "semi-positive definite", a check for that might end up in the "detail/common_error_handling.hpp" Below are three version of construction a (bi)(multi)variate normal distribution. The first version uses vectors and matrices as argument to present the info. The other versions are variadic constructors, presents all the necessary *elements* of the vector and matrix, circumventing the need to "use" and "fill" specific containers for vectors and matrices. The dimension should be deducible from the number of arguments. // Constructor #1: // pass the mean vector, as an object of vector type // pass the covariance matrix as an object of matrix type // // traits: real the scalar type used for precision, return type of functions... // vector should have an operator(i) // matrix should have an operator(i,j) // VectorType mean; MatrixType cov; ... bivariate_normal_distribution<RealType,VectorType,MatrixType> BN1(mean,cov); // Constructor #2: // pass the mean vector, element-by-element: x,y // pass the upper covariance matrix: COV(x,x), COV(x,y), COV(y,y) // // the generic N-variate case will have N means and N*(N+1)/2 COV elements // N | Number of argument // 2 | 2+3 = 5 // 3 | 3+6 = 9 // 4 | 4+10 = 14 // ... // N | N*(N+3)/2 bivariate_normal_distribution<> BN1(0.1, 0.1, 1.0, 0.9, 1.0); // Constructor #3: // pass the mean vector, element-by-element: x,y // pass the full covariance matrix: COV(x,x), COV(x,y),COV(y,x), COV(y,y) // // the generic N-variate case will have N means and N*N COV elements // // the generic N-variate case will have N means and N*(N+1)/2 COV elements // N | Number of argument // 2 | 2+4 = 6 // 3 | 3+9 = 12 // 4 | 4+16 = 20 // ... // N | N*(N+1) bivariate_normal_distribution<> BN1(0.1, 0.1, 1.0, 0.9, 0.9, 1.0);

David Abrahams wrote:
I agree that testing needs to be made more regular and thorough. However, IMO the universe of compilers and libraries is much too large --- and in some cases, the software is too expensive --- for us to check code with new versions of *all* compilers and *all* libraries. We need to select a subset against which we'll test.
However, in this case the change in the API should have been detected by the regression tests by any compiler in any platform. IMHO regression tests were created precisely to avoid situations like this. Test results should not be changed to accommodate a new API without thorough discussion nor without a transition period. --> Mika Heiskanen

on Fri Nov 21 2008, Mika Heiskanen <mika.heiskanen-AT-fmi.fi> wrote:
David Abrahams wrote:
I agree that testing needs to be made more regular and thorough. However, IMO the universe of compilers and libraries is much too large --- and in some cases, the software is too expensive --- for us to check code with new versions of *all* compilers and *all* libraries. We need to select a subset against which we'll test.
However, in this case the change in the API should have been detected by the regression tests by any compiler in any platform. IMHO regression tests were created precisely to avoid situations like this. Test results should not be changed to accommodate a new API without thorough discussion nor without a transition period.
Fully agreed. That's a completely separate point, though. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Fri, Nov 21, 2008 at 7:47 PM, David Abrahams <dave@boostpro.com> wrote:
I agree that testing needs to be made more regular and thorough. However, IMO the universe of compilers and libraries is much too large --- and in some cases, the software is too expensive --- for us to check code with new versions of *all* compilers and *all* libraries. We need to select a subset against which we'll test.
I think we're forgetting here that although BoostPro offers commercial support for Boost releases in the form of consulting and enterprise support, it's all really a matter of how much volunteers can really give as far as committing resources is concerned. For one thing us users of Boost have our own software that we take care of -- rather than relying on the open source community around Boost to perform the testing for us, we should be doing our due diligence and make sure that *if* or *when* we do decide to upgrade whatever we use (be it Boost, the compiler, some third party library we use with Boost, build tools, continuous integration environments, etc.) that we do our own testing. The least we can do is when we do find problems, we report them and/or submit patches to fix the problems. Although the Boost Open Source Model is not the same as other models -- i.e. what goes in/out of a library is determined by the library maintainer and not the whole community at large -- it still is a volunteer effort that will benefit from as much feedback as us users can give. We can either keep changing the model, or we can work with the model we have and continue moving forward and getting bugs reported then fixed for everybody's collective success. I for one know how hard it is to get other people to use Boost -- but thankfully the quality of the implementation of the libraries contained and that we've eventually used have dispelled the initial insecurity other people have with the collection. Given that it's peer-reviewed and is largely well-implemented, it's not hard to show people how much readable+efficient code is when using the boost libraries. What's hard to justify though is the notion of an upgrade: the question "why do we have to upgrade if it's not broken?" comes up and is really hard to answer. At any rate, I for one am still stuck with Boost 1.35 and GCC 4.1.2 -- and moving to Boost 1.37 and a newer GCC may be a problem, but there's nothing stopping me from trying it out for myself and seeing/verifying for myself what broke or what improvements/regressions I do get if I do upgrade. We all want to have well tested code, but the best tests we can run/write are those tests that actually test the software we do write -- because only these tests are the ones that really matter in the context of the software we are writing and in deciding whether to upgrade the libraries we use or not. Just my $0.02 worth. -- Dean Michael C. Berris Software Engineer, Friendster, Inc.

On Friday 21 November 2008 10:00:44 Dean Michael Berris wrote:
We all want to have well tested code, but the best tests we can run/write are those tests that actually test the software we do write -- because only these tests are the ones that really matter in the context of the software we are writing and in deciding whether to upgrade the libraries we use or not.
Well said. From a mere user's point of view, most of the complaints about interface changes are bogus: 1. No one forces anyone else to upgrade from one boost version to another; some of the projects I work on use 1.33.1 and others use svn versions; every change in external dependencies must be validated against internal tests (of the client software). Whenever external dependencies (even compilers) change, be prepared for breakage unless you have a rigorous test suite. 2. One person's bug fix is another's breaking change. The only arbiter is the library author. Boost explicitly avoids design by committee and unless that policy is changed, there cannot be multiple arbiters. The only valid claim that can be made is that all changes must be properly documented. 3. In a corporate environment, building a new version of boost is extremely simple; as Volodya said, only 5-10min of actual human time is required. The only real work is in validating local conformance tests, which must be done for every change in external dependencies anyway. 4. Boost interfaces have been pretty stable for the most part. The core Boost libraries whose interface will rarely ever change are the ones supplied by your compiler vendor, i.e., the ones accepted by the C++ committee. All others are in continuous improvement; changes are made by the authors because they believe it improves the library. Judgements regarding library upgrades (e.g., trading off interface changes for the benefits of upgrading that accrue to that particular user) are subjective; see point 2 above about arbiters. Boost goes through similar discussions every few months almost as if on schedule, and the regardless of the conensus (if any), the procedure simply has stayed unchanged because any change requires more manpower which is simply not available. I don't believe any changes will be precipitated by this discussion either. Regards, Ravi

----- Original Message ----- From: "Ravi" <lists_ravi@lavabit.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 6:20 PM Subject: Re: [boost] Breaking existing libraries
Boost goes through similar discussions every few months almost as if on schedule, and the regardless of the conensus (if any), the procedure simply has stayed unchanged because any change requires more manpower which is simply not available. I don't believe any changes will be precipitated by this discussion either.
I hope that you are wrong and that we can improve at least a little bit. Of course more quality implies more resources, but more quality also implies more users can be interested and at the end participate to Boost. Vicente

on Fri Nov 21 2008, "Dean Michael Berris" <mikhailberis-AT-gmail.com> wrote:
On Fri, Nov 21, 2008 at 7:47 PM, David Abrahams <dave@boostpro.com> wrote:
I agree that testing needs to be made more regular and thorough. However, IMO the universe of compilers and libraries is much too large --- and in some cases, the software is too expensive --- for us to check code with new versions of *all* compilers and *all* libraries. We need to select a subset against which we'll test.
I think we're forgetting here that although BoostPro offers commercial support for Boost releases in the form of consulting and enterprise support, it's all really a matter of how much volunteers can really give as far as committing resources is concerned.
Not really. The whole point of Boostpro Enterprise is that addressing those issues does *not* rest solely on the shoulders of volunteers. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Sat, Nov 22, 2008 at 1:29 AM, David Abrahams <dave@boostpro.com> wrote:
on Fri Nov 21 2008, "Dean Michael Berris" <mikhailberis-AT-gmail.com> wrote:
On Fri, Nov 21, 2008 at 7:47 PM, David Abrahams <dave@boostpro.com> wrote:
I agree that testing needs to be made more regular and thorough. However, IMO the universe of compilers and libraries is much too large --- and in some cases, the software is too expensive --- for us to check code with new versions of *all* compilers and *all* libraries. We need to select a subset against which we'll test.
I think we're forgetting here that although BoostPro offers commercial support for Boost releases in the form of consulting and enterprise support, it's all really a matter of how much volunteers can really give as far as committing resources is concerned.
Not really. The whole point of Boostpro Enterprise is that addressing those issues does *not* rest solely on the shoulders of volunteers.
I think I mis-stated (or was misunderstood here). I meant that although paid support is available, the continued development and evolution of the open source version of the Boost release is by and large a volunteer effort -- as well as the support that comes in the form of mailing list discussions. This is by no means a problem, but it's rather a huge constraint on what can be reasonably expected from a largely voluntary effort -- the development, submission, review, distribution, and maintenance of the libraries is a volunteer effort and these are by no means trivial in terms of resource requirements. It's actually surprising that despite Boost C++'s being a volunteer-developed/supported software product the community manages to churn out great libraries bar none. However we live in a world where even the largest most resource-rich developers/companies aren't able to produce 100% bug-free code 100% of the time (or do 100% perfect transitions from older versions to newer versions of released tools/libraries) and that this reality is something we have to take into account for in the processes we employ and actions we take. We will not be able to please everyone, but it should be reasonable to expect (both from the users' and developers' perspective) that we will strive to not surprise everyone with surprise/undocumented/breaking changes or insane (?) backward compatibility requirements. It's a good thing that BoostPro is there to help those who will pay for the services they offer. Having said this, it does not change that the testing and development of the libraries (and the distribution) is still largely voluntary. -- Dean Michael C. Berris Software Engineer, Friendster, Inc.

----- Original Message ----- From: "David Abrahams" <dave@boostpro.com> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 12:47 PM Subject: Re: [boost] Breaking existing libraries
on Fri Nov 21 2008, Markus Werle <numerical.simulation-AT-web.de> wrote:
[Sidenote: I'd prefer boost::spirit to stay as it is and spirit2c be renamed to boost::ultimate_parser, since it is a *completely* *different* library.] The boost community has not found the perfect way to deal with breaking changes yet, since this is an issue that cannot be easily solved.
It's something that we could easily do better.
Please could you be more precise?
The key issue is: You did not pay for what you use.
I'm sorry to contradict, but I don't think that's the key issue. IMO, the key issue is giving care to disoverability and the ability to make a transition:
* Avoiding completely silent breakage
* Using a deprecation period to give users notice that a breaking change is coming
* Documenting a transition procedure
* ....etc.
I'm completly in face with this but what do you mean by transition procedure? Do you mean to document how the deprecated features are removed? Thanks, Vicente

Comments inlined: Markus Werle writes: <snip>
But let us go back on the we-do-not-pay-for-it path: IMHO it is a severe error of your development process that you do not check your code with new versions of all compilers and all libraries on a *regular* basis. In management parlance: your risk management is defective. It always is a good idea to use the svn repo of boost and the beta version of the next compiler just to see the breaking changes early enough, which gives everyone plenty of time to react.
I'm going to have to very strongly disagree here. Depending on the usage of boost, checking a new version is often not a trivial process, and the vast majority of companies have other priorities for their software developers. My last company worked in shrink-wrapped software, and we had a policy that we would tag the new versions of all libraries just after our major annual release to give plenty of bed-in time before our next major release. In my current job though, using a new version of boost involves rebuilding an entire library stack, some of which is outside our direct control. Also stability is highly important, much more so that working on the latest and greatest. Therefore, we have a tendency to move to the latest version of boost when we actually need a new feature. As such we've skipped 1.30, 1.31, 1.32, 1.34, 1.35, 1.36.
Version 1.33.1 is from the stone age (remember boost is moving faster than light[ning]) and I always expect things to be broken the next time (which is not nice, but compared to the problems solved by boost this still can be neglected).
This is actually a flaw with the current release process within boost. Ever since boost moved to the accelerated release path that it is now on I have been worried that things like this would happen. As far as I am aware (and I'm willing to be corrected here) the accelerated release process that probably started around 1.35 is primarily to get new libraries out into the wild faster. In the process though, core libraries that have been around for years, or on which everything else is built, can become more unstable. What I would personally like to see is boost split into 2 parts, something like boost core, and boost general. Boost core would contain all the stable libraries and the core libraries that other people build libraries off. Shared_ptr, bind, lambda, iterator, operators, range, ublas, etc. Boost general would contain all the new libraries, and anything that is still very actively being developed. The idea would be that if you download the latest version of both libraries, you could unpack them to the same area and you would get the equivalent of current boost (even down to identical directory structure); but the crucial difference would be the release process for each library. Boost general would have the accelerated release process that boost currently has. 2 week beta trials, and new releases multiple times each year. Boost core on the other hand would have much longer beta periods, with lots of users involved as Joaquin recommends later in this thread. Beta periods could easily last 6 months for major new releases, and major releases could be restricted to being no more than annual. Obviously dot releases are available for urgent bug-fixes. You could even make the process relatively transparent by providing an already merged "boost complete" that took the latest core and general libraries. The key thing though, core libraries would be way more stable. In time, new infrastructure type libraries would get moved from general to core once they had stabilised. I suspect that if you spoke to a lot of corporate users of boost they would really like a change of this type. I remember from the time I supported boost for a very large company that there was always competing pressures for upgrading versions of boost. On the one hand you always had developers shouting for the latest cool library; on the other hand, knowing that your entire internal library stack would need to be rebuilt, and that users would have to go through lengthy testing cycles, usually provided a strong pressure not to upgrade. As such upgrades would usually come in every few years, and at least 2 different versions of boost are always in use at any time - with the application interoperability issues that you get with using 2 different library stacks simultaneously. I really like boost, and have used it consistently since the very early 2000s. Historically, it has been pretty good at avoiding major interface issues (with a few notable exceptions); but the rate at which it is growing now means that more controls are necessary IMHO to prevent major interface issues in the future. If the community doesn't address this, my biggest fear is that our big corporate users will end up freezing on old versions, and a lot of the new and cool libraries that are coming out in new releases won't get the audience they deserve. I've got one final point to make here. I went through and reviewed the code changes in boost.range that Tom is referring to. I wouldn't be happy putting this type of code change through in my own libraries. Changing the functionality of a default constructed object just to get rid of a single test against bool in a couple of functions (ostensibly for performance) seems to me misguided. Furthermore, having different functionality in debug and release, for most major users of a library, is just dangerous. The size and empty functions for example assert in debug, but just silent fail in release. The issingular function is even worse, it tells you whether a range is singular in debug, but always returns false in release. Don't get me wrong, I think the boost.range library is an excellent library, but I just think that the implications of the changes in 1.35.0 weren't properly considered. Dave

Dave Handley wrote:
I'm going to have to very strongly disagree here. Depending on the usage of boost, checking a new version is often not a trivial process, and the vast majority of companies have other priorities for their software developers. My last company worked in shrink-wrapped software, and we had a policy that we would tag the new versions of all libraries just after our major annual release to give plenty of bed-in time before our next major release. In my current job though, using a new version of boost involves rebuilding an entire library stack, some of which is outside our direct control. Also stability is highly important, much more so that working on the latest and greatest. Therefore, we have a tendency to move to the latest version of boost when we actually need a new feature. As such we've skipped 1.30, 1.31, 1.32, 1.34, 1.35, 1.36. I totally agree with this.
Furthermore, Boost's current beta release schedule would only find bugs. It would be too late for beta testers to argue against intentional changes in the libraries. Boost libraries should either maintain backward compatibility or mark themselves with a "user beware -- for experimental use only" caveat. -- Dick Hadsell 914-259-6320 Fax: 914-259-6499 Reply-to: hadsell@blueskystudios.com Blue Sky Studios http://www.blueskystudios.com 44 South Broadway, White Plains, NY 10601

on Fri Nov 21 2008, Richard Hadsell <hadsell-AT-blueskystudios.com> wrote:
Dave Handley wrote:
I'm going to have to very strongly disagree here. Depending on the usage of boost, checking a new version is often not a trivial process, and the vast majority of companies have other priorities for their software developers. My last company worked in shrink-wrapped software, and we had a policy that we would tag the new versions of all libraries just after our major annual release to give plenty of bed-in time before our next major release. In my current job though, using a new version of boost involves rebuilding an entire library stack, some of which is outside our direct control. Also stability is highly important, much more so that working on the latest and greatest. Therefore, we have a tendency to move to the latest version of boost when we actually need a new feature. As such we've skipped 1.30, 1.31, 1.32, 1.34, 1.35, 1.36. I totally agree with this.
Furthermore, Boost's current beta release schedule would only find bugs. It would be too late for beta testers to argue against intentional changes in the libraries.
Boost libraries should either maintain backward compatibility or mark themselves with a "user beware -- for experimental use only" caveat.
Of course backward compatibility is desirable, but maintaining it rigidly prevents forward progress. Judicious breakage does not necessarily mean that the library is "experimental" in any meaningful way. Nobody really has a problem with the stability of shared_ptr, for example, and yet look at its list of breaking changes over the years: http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/compatibility.htm -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
Of course backward compatibility is desirable, but maintaining it rigidly prevents forward progress.
This is one side of the medal. Don't call it backward compatibility but maturity and stability. The aim of the critique probably is clear distinction in maturity and stability for different parts of boost. Example: In case of spirit we have the following situation: spirit2x (nomen est omen) is a *completely* different library with a completely different interface written on a different base and a really inferior stability compared to spirit 1 (Even though it is ultimate high quality code and I begin to like it). Now that I became aware of what it means for me that good old spirit gets dropped and reworked this way I wish its new name was boost::ghost or whatever and spirit left in the state of 1.34.1: It works, it is fine, it has - of course - some limitations. So what? The parsers I have written with spirit are those parts of my code I never had to touch again (except once, see below). Sometimes no change is good. Also because I know most of spirit-1 oddities by heart and can fiddle small parsers within minutes I do not want to switch to 2x now. I acknowledge the hard work done to keep spirit1 in the distro, but I still dislike the way it was solved, because I'd prefer spirit-1 to be a first class citizen for at least 3 more years.
Judicious breakage does not necessarily mean that the library is "experimental" in any meaningful way.
Yes and no. If you touch it you probably will break one thing or another (and agile as you are fix it in 5 minutes after bug report). IMHO this also is a communication issue. On this list several people (me included) have already proposed to introduce stability labels. E.g. spirit2x *should* be tagged highly experimental pre-alpha code *despite* Joel's programming skills until many many users confirm its correct behaviour in Real World code. We have to separate the quality label of the library from the quality label of its authors. Maybe that helps.
Nobody really has a problem with the stability of shared_ptr, for example, and yet look at its list of breaking changes over the years:
http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/compatibility.htm
Most of these were extensions, bugfixes or improvements, not interface or silent breakage, right? The counter example: I had hard times with the rather silent change in spirit concerning trailing whitespaces and enforcing end_p. (http://www.nabble.com/Re%3A-grammar-rules-problem-p15635719.html) I agree with the change decision, but the change could have been advertized in big red letters on the main web page. It took me several months to detect _and_ understand the rather subtle errors it generated and this prevented migration to a new version of boost for a long time. This is OK for me, since Joel saved me a lot of time, but yes, this *change* broke all my code at once - silently. Something I do not like at all. The question is: can we work around this kind of problem easily? I guess, no. In another post you ask:
So what happens to the iterators library when it's time for the rewrite I've been planning? I intend, as much as possible, to maintain compatibility with the old interfaces, of course. Is that still a "stable" library?
Considering the interface: no. I'd prefer you advertise and introduce a new library as replacement candidate for the old library and have them both, the old and the new one, live together in boost for at least one year before the switch and the deprecation of the old one takes place. By this you have 2 things at a time: Fast release process *and* satisfied customers. Markus P.S.: I am on my knees again: I managed to *use* iterator_adaptors without understanding them at all. It works and I never had to touch the code again for 3 years now. Thank You. I now forgot everything I once read and learned about iterators. Please don't change it ... please ... :-)

Markus Werle wrote:
Example: In case of spirit we have the following situation: spirit2x (nomen est omen) is a *completely* different library with a completely different interface written on a different base and a really inferior stability compared to spirit 1 (Even though it is ultimate high quality code and I begin to like it). Now that I became aware of what it means for me that good old spirit gets dropped and reworked this way I wish its new name was boost::ghost or whatever and spirit left in the state of 1.34.1: It works, it is fine, it has - of course - some limitations. So what? The parsers I have written with spirit are those parts of my code I never had to touch again (except once, see below). Sometimes no change is good. Also because I know most of spirit-1 oddities by heart and can fiddle small parsers within minutes I do not want to switch to 2x now. I acknowledge the hard work done to keep spirit1 in the distro, but I still dislike the way it was solved,
What in particular do you dislike?
because I'd prefer spirit-1 to be a first class citizen for at least 3 more years.
And it will be. We value backwards compatibility. That is why we took pains to keep the 1.8 code in the distro. And I think it will remeain there for years to come. It would be cruel to expect, say Robert Ramey's Serialization, to be ported in a short period of time.
Judicious breakage does not necessarily mean that the library is "experimental" in any meaningful way.
Yes and no. If you touch it you probably will break one thing or another (and agile as you are fix it in 5 minutes after bug report).
IMHO this also is a communication issue. On this list several people (me included) have already proposed to introduce stability labels. E.g. spirit2x *should* be tagged highly experimental pre-alpha code *despite* Joel's programming skills until many many users confirm its correct behaviour in Real World code.
It was tagged 2 years ago as highly experimental pre-alpha. It is now tagged as beta. When it finally gets released as final, hopefully before BoostCon 09, it would have taken an ample 3 years to reach that level of maturity. True enough, many people are using it now in projects. Look: http://www.boost.org/doc/libs/1_37_0/libs/spirit/classic/index.html what do you see? That's still 1.8.x. There's no drastic change there. Spirit 1.8.x is, and always will be, first class. Isn't the name "classic spirit" testament to that fact?
We have to separate the quality label of the library from the quality label of its authors. Maybe that helps.
Nobody really has a problem with the stability of shared_ptr, for example, and yet look at its list of breaking changes over the years:
http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/compatibility.htm
Most of these were extensions, bugfixes or improvements, not interface or silent breakage, right?
The counter example: I had hard times with the rather silent change in spirit concerning trailing whitespaces and enforcing end_p. (http://www.nabble.com/Re%3A-grammar-rules-problem-p15635719.html) I agree with the change decision, but the change could have been advertized in big red letters on the main web page. It took me several months to detect _and_ understand the rather subtle errors it generated and this prevented migration to a new version of boost for a long time.
This is OK for me, since Joel saved me a lot of time, but yes, this *change* broke all my code at once - silently. Something I do not like at all.
I agree. That was !BAD! (in all caps). It's one of the moves that I regret. If I was to turn back time, I'd do it differently. People make mistakes. I am sorry for this lapse in judgement. I assure you, it won't happen again. Now it is in bold red: spirit.sf.net Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

Joel de Guzman wrote:
Markus Werle wrote:
[...] I acknowledge the hard work done to keep spirit1 in the distro, but I still dislike the way it was solved,
What in particular do you dislike?
Well, I had difficulties with the fact that _before_ spirit 2 is stable I am forced to change my headers and touch my code when upgrading to a new boost version. I also think that spirit-2 must not be called spirit. See below. Of course migration was less pain than first thought, but only due to what I learned from 3 different mailing lists. Maybe my approach to spirit-2 was accompanied by wrong expectations. I got confused when I found out that spirit-2 was officially released and shipped with a regular boost release, but the docs still were incomplete at that time and this and that was still missing or not as smooth as before. A classical case of failed communication, maybe with failures on both sides, sender and receiver of the message. Take my statements as feedback for how it was perceived from the outside, not as "everything is bullshit". I really appreciate the work you do - especially your documentation style is great. I still have the impression that we have not found the perfect approach to migration between versions yet. The number of libraries grows and with it the number of interdependencies in an exponential way. We face the classical configuration management dilemma.
because I'd prefer spirit-1 to be a first class citizen for at least 3 more years.
And it will be. We value backwards compatibility.
Ah, I understand. My definition of "first class" is a little bit different: First class is the recommended version and that's the one which has its docs at the standard path libs/<library>/doc. I think that spirit-2 is at the wrong directory right now.
That is why we took pains to keep the 1.8 code in the distro.
All this pain because spirit-2 does not have its own name ... Just give it another name and everything is clear for everyone. What do you think about boost::esprit? And for spirit-N | N > 3 another 3000 languages left for a lifetime: geist, ruach, esperto, espiritu, hafidha, ...
And I think it will remain there for years to come. It would be cruel to expect, say Robert Ramey's Serialization, to be ported in a short period of time.
Then again: spirit-2b or spirit-3 is a *completely* different (and better) thing compared to spirit-1. You reworked even details of the interface ("_p" has gone, etc.). My question: Why not give it another name?
IMHO this also is a communication issue. On this list several people (me included) have already proposed to introduce stability labels. E.g. spirit2x *should* be tagged highly experimental pre-alpha code *despite* Joel's programming skills until many many users confirm its correct behaviour in Real World code.
It was tagged 2 years ago as highly experimental pre-alpha. It is now tagged as beta. When it finally gets released as final, hopefully before BoostCon 09, it would have taken an ample 3 years to reach that level of maturity. True enough, many people are using it now in projects.
Those tags you are speaking of are not found on http://www.boost.org/doc/libs/1_37_0 where they belong. Tagging of course is a lot easier if - guess what? - spirit-2 had its own name (This point should be clear by now :-))
Look: http://www.boost.org/doc/libs/1_37_0/libs/spirit/classic/index.html what do you see? That's still 1.8.x.
sed -es ,/classic,,g and I am fine
There's no drastic change there. Spirit 1.8.x is, and always will be, first class. Isn't the name "classic spirit" testament to that fact?
This is what I misunderstood. I did not take this label as something that is "first class". I am happy to hear about your plans to keep it.
The counter example: I had hard times with the rather silent change in spirit concerning trailing whitespaces and enforcing end_p. (http://www.nabble.com/Re%3A-grammar-rules-problem-p15635719.html) I agree with the change decision, but the change could have been advertized in big red letters on the main web page. It took me several months to detect _and_ understand the rather subtle errors it generated and this prevented migration to a new version of boost for a long time.
This is OK for me, since Joel saved me a lot of time, but yes, this *change* broke all my code at once - silently. Something I do not like at all.
I agree. That was !BAD! (in all caps). It's one of the moves that I regret. If I was to turn back time, I'd do it differently. People make mistakes. I am sorry for this lapse in judgement. I assure you, it won't happen again.
That is nearly too much of excuse. Especially since I found out the change solved a problem I faced before. Therefore forgiven and forgotten now. One last question: Which new name will you give to spirit-2? ;-) best regards, Markus

on Fri Nov 21 2008, "Dave Handley" <dave-AT-dah.me.uk> wrote:
Version 1.33.1 is from the stone age (remember boost is moving faster than light[ning]) and I always expect things to be broken the next time (which is not nice, but compared to the problems solved by boost this still can be neglected).
What I would personally like to see is boost split into 2 parts, something like boost core, and boost general. Boost core would contain all the stable libraries and the core libraries that other people build libraries off. Shared_ptr, bind, lambda, iterator, operators, range, ublas, etc.
So what happens to the iterators library when it's time for the rewrite I've been planning? I intend, as much as possible, to maintain compatibility with the old interfaces, of course. Is that still a "stable" library? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Fri, Nov 21, 2008 at 12:59 PM, David Abrahams <dave@boostpro.com> wrote:
So what happens to the iterators library when it's time for the rewrite I've been planning? I intend, as much as possible, to maintain compatibility with the old interfaces, of course. Is that still a "stable" library?
Maybe put the new library in its own namespace and retain the old version in its own namespace for a release or two with it being marked deprecated in the documentation? A macro could be provided that alternately brought the different versions into the boost namespace. Of course it would bring the new library into the boost namespace by default. This may be too much of a burden on the library writer, and it's also getting into specifics when I think the discussion is mostly about processes at a high level, but I do think the idea has some merit. --Michael Fawcett

Dave Handley skrev:
Comments inlined:
Markus Werle writes:
<snip>
I've got one final point to make here. I went through and reviewed the code changes in boost.range that Tom is referring to. I wouldn't be happy putting this type of code change through in my own libraries. Changing the functionality of a default constructed object just to get rid of a single test against bool in a couple of functions (ostensibly for performance) seems to me misguided.
That is of course a valid view. But take to the extreame, it means we would have to give up the "you don't pay for what you don't use" mantra.
Furthermore, having different functionality in debug and release, for most major users of a library, is just dangerous. The size and empty functions for example assert in debug, but just silent fail in release.
"Silently fail" is a bit strong here. I mean, if there are any unit-test set up, I would expect them to trigger an assert in debug-mode. I don't consider that "silent".
The issingular function is even worse, it tells you whether a range is singular in debug, but always returns false in release.
IIRC, is_singular is not documented. So using it is on your own risk. It could disappear in the next release or whatever. -Thorsten

Thorsten Ottosen wrote:
Dave Handley skrev:
Comments inlined:
Markus Werle writes:
<snip>
I've got one final point to make here. I went through and reviewed the code changes in boost.range that Tom is referring to. I wouldn't be happy putting this type of code change through in my own libraries. Changing the functionality of a default constructed object just to get rid of a single test against bool in a couple of functions (ostensibly for performance) seems to me misguided.
That is of course a valid view. But take to the extreame, it means we would have to give up the "you don't pay for what you don't use" mantra.
It doesn't mean that at all. All this discussion is doing is persuading me that I shouldn't use boost.range in my own code because breaking changes will wreck my own code base. If I want functionality like boost.range, I should probably go and write my own version. I would prefer this not to be the case - unfortunately, so much of the discussion here and in the other thread is reinforcing that view. This sort of thing has the pernicious side effect of marginalising boost.
Furthermore, having different functionality in debug and release, for most major users of a library, is just dangerous. The size and empty functions for example assert in debug, but just silent fail in release.
"Silently fail" is a bit strong here. I mean, if there are any unit-test set up, I would expect them to trigger an assert in debug-mode. I don't consider that "silent".
Read that again - I said silently fail in release. When you are dealing in an environment with several million lines of code, it isn't beyond the realm of imagination that every code path isn't covered by unit tests. In that case, a silent fail in release is pretty much unacceptable since you are risking not the stability of your production code, but the correctness of it.
The issingular function is even worse, it tells you whether a range is singular in debug, but always returns false in release.
IIRC, is_singular is not documented. So using it is on your own risk. It could disappear in the next release or whatever.
I can't tell what the state of the documentation said before 1.35 so I can't comment here. Can someone please explain how to get versioned documentation on boost? The documentation that gets included in the download zips appears to me to be only partial (I can't find any documentation for range there for example). Dave

On Sun, Nov 23, 2008 at 10:04:06AM -0500, Dave Handley wrote:
I can't tell what the state of the documentation said before 1.35 so I can't comment here. Can someone please explain how to get versioned documentation on boost?
See http://www.boost.org/doc/ and http://www.boost.org/doc/libs/1_34_0 in particular. Is this really news to everyone? I'm just a kibitzer in this thread but it's been very surprising to read some folks who I assume would know better (Dave A, for one) arguing about what was documented without showing any evidence of having taken the time to read the old docs. -S

on Sun Nov 23 2008, "Steve M. Robbins" <steve-AT-sumost.ca> wrote:
On Sun, Nov 23, 2008 at 10:04:06AM -0500, Dave Handley wrote:
I can't tell what the state of the documentation said before 1.35 so I can't comment here. Can someone please explain how to get versioned documentation on boost?
See http://www.boost.org/doc/ and http://www.boost.org/doc/libs/1_34_0 in particular.
Is this really news to everyone? I'm just a kibitzer in this thread but it's been very surprising to read some folks who I assume would know better (Dave A, for one) arguing about what was documented without showing any evidence of having taken the time to read the old docs.
No, I've been short of time, so I never did go look at the old docs. However, I don't think I ever pretended to know for sure what was documented in the old version. I have sprinkled "if"s liberally throughout my writings in this thread. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Dave Handley skrev:
Thorsten Ottosen wrote:
Dave Handley skrev:
Comments inlined:
Markus Werle writes:
<snip>
I've got one final point to make here. I went through and reviewed the code changes in boost.range that Tom is referring to. I wouldn't be happy putting this type of code change through in my own libraries. Changing the functionality of a default constructed object just to get rid of a single test against bool in a couple of functions (ostensibly for performance) seems to me misguided.
That is of course a valid view. But take to the extreame, it means we would have to give up the "you don't pay for what you don't use" mantra.
It doesn't mean that at all. All this discussion is doing is persuading me that I shouldn't use boost.range in my own code because breaking changes will wreck my own code base. If I want functionality like boost.range, I should probably go and write my own version. I would prefer this not to be the case - unfortunately, so much of the discussion here and in the other thread is reinforcing that view. This sort of thing has the pernicious side effect of marginalising boost.
Furthermore, having different functionality in debug and release, for most major users of a library, is just dangerous. The size and empty functions for example assert in debug, but just silent fail in release.
"Silently fail" is a bit strong here. I mean, if there are any unit-test set up, I would expect them to trigger an assert in debug-mode. I don't consider that "silent".
Read that again - I said silently fail in release. When you are dealing in an environment with several million lines of code, it isn't beyond the realm of imagination that every code path isn't covered by unit tests. In that case, a silent fail in release is pretty much unacceptable since you are risking not the stability of your production code, but the correctness of it.
The issingular function is even worse, it tells you whether a range is singular in debug, but always returns false in release.
IIRC, is_singular is not documented. So using it is on your own risk. It could disappear in the next release or whatever.
I can't tell what the state of the documentation said before 1.35 so I can't comment here. Can someone please explain how to get versioned documentation on boost?
I have looked it up, and its not documented. Period. Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost. FWIW, boost.range is not changing anymore. -Thorsten

I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour. Dave

----- Original Message ----- From: "Dave Handley" <dave@dah.me.uk> To: <boost@lists.boost.org> Sent: Sunday, November 23, 2008 9:43 PM Subject: Re: [boost] Breaking existing libraries
I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour.
Hi, I would want toknow what we can do in cases like this one. There is some people that think that an evolution is need (in this case commig baclk to an olv bhavior). The library maintainer do not accepts this evolution. Can someone propose a new library to Boost using other workspace and namespace (e.g. range2) which is a copy of the original one, adding the requested functionality? (I'm not sure this was the case for the Signals2 library) Thanks, Vicente

Dave Handley skrev:
I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour.
If the compromise does not include going back to the old behavior for boost::iterator_range, then I'm open to suggestions (If we did that, how would we explain that situation to all those that want the current behavior?). -Thorsten

----- Original Message ----- From: "Thorsten Ottosen" <thorsten.ottosen@dezide.com> To: <boost@lists.boost.org> Sent: Sunday, November 23, 2008 11:50 PM Subject: Re: [boost] Breaking existing libraries
Dave Handley skrev:
I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour.
If the compromise does not include going back to the old behavior for boost::iterator_range, then I'm open to suggestions (If we did that, how would we explain that situation to all those that want the current behavior?).
Some one has already proposed boost::old_iterator_range and if I remember well you have proposed boost::deprecated::iterator_range. "I guess The old behavior could be supplied in <boost/range/deprecated/iterator_range.hpp> in namespace boost::deprecated. Again, it is a matter of time." Is this a good compromise for all? Vicente

Vicente Botet wrote:
----- Original Message ----- From: "Thorsten Ottosen" <thorsten.ottosen@dezide.com> To: <boost@lists.boost.org> Sent: Sunday, November 23, 2008 11:50 PM Subject: Re: [boost] Breaking existing libraries
Dave Handley skrev:
I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour.
If the compromise does not include going back to the old behavior for boost::iterator_range, then I'm open to suggestions (If we did that, how would we explain that situation to all those that want the current behavior?).
Some one has already proposed boost::old_iterator_range and if I remember well you have proposed boost::deprecated::iterator_range.
"I guess The old behavior could be supplied in <boost/range/deprecated/iterator_range.hpp> in namespace boost::deprecated. Again, it is a matter of time."
Is this a good compromise for all?
Not really - as a library user you can't rely on deprecated functionality. If my code was broken by this change, and the change was reverted in a deprecated version, I would probably just drop the library out of the (valid?) fear that the deprecated interface would be dropped at some point. The proposal that has been made multiple times in the other thread is that both types of functionality are valid, and that there should just be 2 classes. One could easily be made to inherit off the other, both would be useful for different use cases. As far as I can tell, no-one has made a solid critique against that proposal, but on the other hand, there still doesn't appear to be a consensus. I really wouldn't be surprised if the sum total of all this discussion in about 4 different threads on 2 different mailing lists is that absolutely nothing happens. I would like that not to be the case, but by past experience, I'm not holding my breath. Dave

----- Original Message ----- From: "Dave Handley" <dave@dah.me.uk> To: <boost@lists.boost.org> Sent: Monday, November 24, 2008 2:08 AM Subject: Re: [boost] Breaking existing libraries
Vicente Botet wrote:
----- Original Message ----- From: "Thorsten Ottosen" <thorsten.ottosen@dezide.com> To: <boost@lists.boost.org> Sent: Sunday, November 23, 2008 11:50 PM Subject: Re: [boost] Breaking existing libraries
Dave Handley skrev:
I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour.
If the compromise does not include going back to the old behavior for boost::iterator_range, then I'm open to suggestions (If we did that, how would we explain that situation to all those that want the current behavior?).
Some one has already proposed boost::old_iterator_range and if I remember well you have proposed boost::deprecated::iterator_range.
"I guess The old behavior could be supplied in <boost/range/deprecated/iterator_range.hpp> in namespace boost::deprecated. Again, it is a matter of time."
Is this a good compromise for all?
Not really - as a library user you can't rely on deprecated functionality. If my code was broken by this change, and the change was reverted in a deprecated version, I would probably just drop the library out of the (valid?) fear that the deprecated interface would be dropped at some point.
Can I conclude that you don't think that libraries evolve and for that some functionalities must be deprecated. Note that the name of the class be boost::old_iterator_range or boost::deprecated::iterator_range doesn't matter.
The proposal that has been made multiple times in the other thread is that both types of functionality are valid, and that there should just be 2 classes. One could easily be made to inherit off the other, both would be useful for different use cases. As far as I can tell, no-one has made a solid critique against that proposal, but on the other hand, there still doesn't appear to be a consensus.
I haven't the backgraund on this domain to prononce myself.
I really wouldn't be surprised if the sum total of all this discussion in about 4 different threads on 2 different mailing lists is that absolutely nothing happens. I would like that not to be the case, but by past experience, I'm not holding my breath.
This will depend on all the participants. If they are unable to find a compromise there is no reason to change. Please could you reconsider your possition? A deprecated interface will give you the opportunity to have again the fonctionality, and let you time to switch to the new one. How many time would be enough for you? Best regards, Vicente

----- Original Message ----- From: "vicente.botet" <vicente.botet@wanadoo.fr> Newsgroups: gmane.comp.lib.boost.devel To: <boost@lists.boost.org> Sent: Monday, November 24, 2008 2:06 AM Subject: Re: Breaking existing libraries
----- Original Message ----- From: "Dave Handley" <dave@dah.me.uk> To: <boost@lists.boost.org> Sent: Monday, November 24, 2008 2:08 AM Subject: Re: [boost] Breaking existing libraries
Vicente Botet wrote:
----- Original Message ----- From: "Thorsten Ottosen" <thorsten.ottosen@dezide.com> To: <boost@lists.boost.org> Sent: Sunday, November 23, 2008 11:50 PM Subject: Re: [boost] Breaking existing libraries
Dave Handley skrev:
I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour.
If the compromise does not include going back to the old behavior for boost::iterator_range, then I'm open to suggestions (If we did that, how would we explain that situation to all those that want the current behavior?).
Some one has already proposed boost::old_iterator_range and if I remember well you have proposed boost::deprecated::iterator_range.
"I guess The old behavior could be supplied in <boost/range/deprecated/iterator_range.hpp> in namespace boost::deprecated. Again, it is a matter of time."
Is this a good compromise for all?
Not really - as a library user you can't rely on deprecated functionality. If my code was broken by this change, and the change was reverted in a deprecated version, I would probably just drop the library out of the (valid?) fear that the deprecated interface would be dropped at some point.
Can I conclude that you don't think that libraries evolve and for that some functionalities must be deprecated. Note that the name of the class be boost::old_iterator_range or boost::deprecated::iterator_range doesn't matter.
My argument all along is that I think both functionalities are equally valid. And I don't think there is a sensible migration path from one to the other. As such, both classes should be in boost. However, during the discussion on this I ran into some rather intractable brick walls which mean I've just given up on the library.
The proposal that has been made multiple times in the other thread is that both types of functionality are valid, and that there should just be 2 classes. One could easily be made to inherit off the other, both would be useful for different use cases. As far as I can tell, no-one has made a solid critique against that proposal, but on the other hand, there still doesn't appear to be a consensus.
I haven't the backgraund on this domain to prononce myself.
I really wouldn't be surprised if the sum total of all this discussion in about 4 different threads on 2 different mailing lists is that absolutely nothing happens. I would like that not to be the case, but by past experience, I'm not holding my breath.
This will depend on all the participants. If they are unable to find a compromise there is no reason to change.
Please could you reconsider your possition? A deprecated interface will give you the opportunity to have again the fonctionality, and let you time to switch to the new one. How many time would be enough for you?
This would be useless - there isn't a sensible migration path, so without the original functionality available and supported in some form, we might as well drop the library and use something that will be stable in the future. Thanks for your help on the Vicente, you are one of the few pragmatic types on the list - and I wish you the best with your effort for documenting breaking changes. It's just a shame that discussions on this list get bogged down in irrelevancies - that stopped me from posting to this list 3 or 4 years ago, and my experience this time hasn't helped persuade me to get involved again. Dave

Dave Handley skrev:
Vicente Botet wrote:
----- Original Message ----- From: "Thorsten Ottosen" <thorsten.ottosen@dezide.com> To: <boost@lists.boost.org> Sent: Sunday, November 23, 2008 11:50 PM Subject: Re: [boost] Breaking existing libraries
Dave Handley skrev:
I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour.
If the compromise does not include going back to the old behavior for boost::iterator_range, then I'm open to suggestions (If we did that, how would we explain that situation to all those that want the current behavior?).
Some one has already proposed boost::old_iterator_range and if I remember well you have proposed boost::deprecated::iterator_range.
"I guess The old behavior could be supplied in <boost/range/deprecated/iterator_range.hpp> in namespace boost::deprecated. Again, it is a matter of time."
Is this a good compromise for all?
Not really - as a library user you can't rely on deprecated functionality. If my code was broken by this change, and the change was reverted in a deprecated version, I would probably just drop the library out of the (valid?) fear that the deprecated interface would be dropped at some point.
The proposal that has been made multiple times in the other thread is that both types of functionality are valid, and that there should just be 2 classes. One could easily be made to inherit off the other, both would be useful for different use cases. As far as I can tell, no-one has made a solid critique against that proposal, but on the other hand, there still doesn't appear to be a consensus.
I'm fine with having a non-deprecated boost::range<T> with the old behavior. I don't know if there is concensus for this? Let me just comment on the critiue there has been of the new concepts. The concepts where changed after lengthy discussions here on this list, initiated by real problems in using Boost.Range other parts of boost. I think it is fair to say that the new concepts are also much cleaner and minimal, and hence puts lets burden on the user. The docs should also have a "Upgrading from 1.32" section. As to whether the old concepts should still be documented, then I don't know. The old docs are on our website, but I guess we could link directly to them. As for time, then it is a problem currently. But I guess 1.38 is some time away anyway. -Thorsten

on Mon Nov 24 2008, Thorsten Ottosen <thorsten.ottosen-AT-dezide.com> wrote:
I'm fine with having a non-deprecated boost::range<T> with the old behavior. I don't know if there is concensus for this?
I'm totally fine with it, except for the name. I would prefer to keep the name "range" in namespace boost usable for something that isn't considered a dead end or a design mistake. I guess it's a testament to the weirdness of the old design that I can't think of a good descriptive name. boost::nonsigular_range comes to mind, except of course anything that invalidates its contained iterators (e.g. throwing out the underlying container) makes it singular again. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 24 Nov 2008, at 14:43, David Abrahams wrote:
on Mon Nov 24 2008, Thorsten Ottosen <thorsten.ottosen-AT- dezide.com> wrote:
I'm fine with having a non-deprecated boost::range<T> with the old behavior. I don't know if there is concensus for this?
I'm totally fine with it, except for the name. I would prefer to keep the name "range" in namespace boost usable for something that isn't considered a dead end or a design mistake. I guess it's a testament to the weirdness of the old design that I can't think of a good descriptive name.
boost::nonsigular_range
comes to mind, except of course anything that invalidates its contained iterators (e.g. throwing out the underlying container) makes it singular again.
Could I suggest "boost::container_view", the idea being that the type is at much like a container as possible, except it gives a view of other data rather than containing it's own data. I am working on a library in this area myself, which pushes this idea further (allowing push_back and other mutating members) on a similar view, but this simpler type branches the gap between ranges and full- blown containers. Chris

On Sun, Nov 23, 2008 at 5:58 PM, vicente.botet <vicente.botet@wanadoo.fr> wrote:
From: "Thorsten Ottosen" <thorsten.ottosen@dezide.com> "I guess The old behavior could be supplied in <boost/range/deprecated/iterator_range.hpp> in namespace boost::deprecated. Again, it is a matter of time."
Is this a good compromise for all?
This is fine with me. But one thing more... While we're at it, could we please have something like the Range concept definitions that were established in the review/release for 1.32, i.e. something with empty(r), size(r), etc. They are a superset of the requirements in the current definitions, so reintroducing them won't effect code that was written since their untimely demise in 1.35. If time is an issue and you need help, just ask. Even though, lately, I've been shamefully slow at submitting code, I might be able to pitch in. Daniel Walker

Some one has already proposed boost::old_iterator_range and if I remember well you have proposed boost::deprecated::iterator_range.
"I guess The old behavior could be supplied in <boost/range/deprecated/iterator_range.hpp> in namespace boost::deprecated. Again, it is a matter of time."
IMHO, I don't think the behaviour should be classed as "deprecated". Deprecated means "it's been superceded". In this case, the old behaviour is just gone, it's not superceded by something else.

on Sun Nov 23 2008, Thorsten Ottosen <thorsten.ottosen-AT-dezide.com> wrote:
Dave Handley skrev:
I have looked it up, and its not documented. Period.
Anyway, I'm sorry you feel the way you do. I don't intentionally try to break people's code, and I have put an enourmous effort into the code I've submitted to boost.
FWIW, boost.range is not changing anymore.
Unfortunately, you've already broken my confidence - unless of course, we can come up with a decent compromise on this which seems further away by the hour.
If the compromise does not include going back to the old behavior for boost::iterator_range, then I'm open to suggestions (If we did that, how would we explain that situation to all those that want the current behavior?).
I think the best thing you can do at this point is: a. Write a good, complete transition guide that is included in the library docs, describing all the changes. b. Include an example that shows how to build your own iterator_range that has the old behavior. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Tomas Puverle skrev:
If the compromise does not include going back to the old behavior for boost::iterator_range, then I'm open to suggestions
(Joke intended) This really doesn't seem to meet the criteria for a "compromise". Just sounds like you're getting your way.
Why? I'm open to including a new class with the old behavior, even though I think it has little purpose. Wha compromise did you have in mind? -Thorsten

Thorsten, I think the majority of opinions on this thread have voiced a preference for the old behaviour because singularity is a property of an iterator, not a range. Adding the validity constraint imposes too many restrictions upon otherwise valid uses of default constructed iterator_ranges where the iterator provides stronger guarantees. In my opinion, the Range concept should not have 'singular'. I appreciate that there were previous discussions prior to your change, but under firther scrutiny it appears that the wrong conclusion was reached. On Tue, Nov 25, 2008 at 3:30 PM, Thorsten Ottosen <nesotto@cs.aau.dk> wrote:
Tomas Puverle skrev:
If the compromise does not include going back to the old behavior for
boost::iterator_range, then I'm open to suggestions
(Joke intended) This really doesn't seem to meet the criteria for a "compromise". Just sounds like you're getting your way.
Perhaps erroneous use of singular iterators could be added through improvements to iterator debugging facilities?
Why? I'm open to including a new class with the old behavior, even though I think it has little purpose.
I don't think two classes that are almost identical is worthwhile. The singularity validation does not serve enough useful purpose to justify the limitations, and space overhead. Singularity debugging does not belong here.
Wha compromise did you have in mind?
-Thorsten
Neil Groves
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Sent from my iPhone On Nov 25, 2008, at 10:40 AM, "Neil Groves" <neil@grovescomputing.com> wrote:
Thorsten,
I think the majority of opinions on this thread have voiced a preference for the old behaviour because singularity is a property of an iterator, not a range. Adding the validity constraint imposes too many restrictions upon otherwise valid uses of default constructed iterator_ranges where the iterator provides stronger guarantees.
You don't need the old behavior (which attempted to provide those guarantees even when the underlying iterators can't, at the cost of space and time) to have that.
In my opinion, the Range concept should not have 'singular'.
Protecting users from singular iterators at the cost of space and time, especially in those cases when the iteratirs themselves already provide a nonsingular default-constructed state, of a bad idea.
I appreciate that there were previous discussions prior to your change, but under firther scrutiny it appears that the wrong conclusion was reached.
On Tue, Nov 25, 2008 at 3:30 PM, Thorsten Ottosen <nesotto@cs.aau.dk> wrote:
Tomas Puverle skrev:
If the compromise does not include going back to the old behavior for
boost::iterator_range, then I'm open to suggestions
(Joke intended) This really doesn't seem to meet the criteria for a "compromise". Just sounds like you're getting your way.
Perhaps erroneous use of singular iterators could be added through improvements to iterator debugging facilities?
Why? I'm open to including a new class with the old behavior, even though I think it has little purpose.
I don't think two classes that are almost identical is worthwhile. The singularity validation does not serve enough useful purpose to justify the limitations, and space overhead. Singularity debugging does not belong here.
Wha compromise did you have in mind?
-Thorsten
Neil Groves
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Tue, Nov 25, 2008 at 4:43 PM, David Abrahams <dave@boostpro.com> wrote:
Sent from my iPhone
On Nov 25, 2008, at 10:40 AM, "Neil Groves" <neil@grovescomputing.com> wrote:
Thorsten,
I think the majority of opinions on this thread have voiced a preference for the old behaviour because singularity is a property of an iterator, not a range. Adding the validity constraint imposes too many restrictions upon otherwise valid uses of default constructed iterator_ranges where the iterator provides stronger guarantees.
You don't need the old behavior (which attempted to provide those guarantees even when the underlying iterators can't, at the cost of space and time) to have that.
In my opinion, the Range concept should not have 'singular'.
Protecting users from singular iterators at the cost of space and time, especially in those cases when the iteratirs themselves already provide a nonsingular default-constructed state, of a bad idea.
I absolutely agree even though my original post may appear to indicate otherwise. I am in agreement that we simply shouldn't be checking for singularity at the range level. It appears that I may have misunderstood the old behaviour due to my failure to browse the old versions of the code. The whole singularity 'thing' should be dropped from ranges. In summary I think that there should be one class iterator_range without the checking. <snip>
I don't think two classes that are almost identical is worthwhile. The singularity validation does not serve enough useful purpose to justify the limitations, and space overhead. Singularity debugging does not belong here.
</snip>
Neil Groves

Markus Werle wrote:
[Sidenote: I'd prefer boost::spirit to stay as it is and spirit2c be renamed to boost::ultimate_parser, since it is a *completely* *different* library.]
I think the same has to be said for boost as a whole. As there is no guarantee to make two subsequent boost versions compatible with each other, I think it is only fair to consider them two distinct products. As unfortunate as that is for us users, it's the reality we have to face. Regards, Stefan -- ...ich hab' noch einen Koffer in Berlin...

Tomas Puverle skrev:
You may or may not have noticed a thread I started on boost.users about the breaking changes to Boost.Range. Here’s a short summary: We are currently (firmwide) using boost 1.33.1. I am in the process of trying to migrate and test some of our apps with boost 1.37. In 1.35 there was a breaking change to Boost.Range with respect to how singular ranges behave. This brings up several issues:
1) The breakage was silent. The interface stayed the same but the behavior changed, and drastically so.
But clealy any test would not fail silently if it was run in debug mode. You would get an assertion in your code. Let my just say that your code example was legal in the sense it used a documented behavior of Boost.Range which I had chosen to change. However, It was not legal generic code in the sense that you could not parse any range to function: template<class Range> void foo(const Range & r_) { if (r_.empty()) {...} } You'd had to write it like this: template<class Range> void foo(const Range & r_) { if (boost::empty(r)) {...} }
2) No communation: While I don’t usually post to boost.devel/boost.user, I and my colleagues still read it. Nobody recalls any mention of this on the list. Searching gmane brings up nothing, either. 3) No documentation on the boost website. As far as I can see, this change was introduced in 1.35 this March. On http://www.boost.org/users/news/version_1_35_0, there is no mention of a breaking change to Boost.Range.
That is of course my fault, that I didn't used more of my spare time to document this properly. The initial design was not optimal, and I prioritzed fixing it higher than documenting the changes.
4) The new Boost.Range behaves differently in debug and release builds. The public function is_singular() always returns false in release builds even when it would return true in debug builds.
IIRC, this is not a documented function, and hence you cannot expect it to be there in the next release etc.
Apart from the fact that this change breaks a lot of our code and obsoletes several useful (necessary?) idioms, the manner in which it happened is far below the standards that one has come to expect from boost.
At the moment, I have to say I don’t have a good answer to how to fix our code. However, I would at least like to try to make sure this kind of silent breakage
I guess The old behavior could be supplied in <boost/range/deprecated/iterator_range.hpp> in namespace boost::deprecated. Again, it is a matter of time. At the end of the day, I think the change was right, but I also sympathesize with the view of stability. It would be a good thing if we could improve the communication between end-users and developers, and find guidelines that allow libraries to move forward, while not breaking too much code silently/unintentionally. best regards -Thorsten
participants (28)
-
Christopher Jefferson
-
Daniel Walker
-
Dave Handley
-
David Abrahams
-
Dean Michael Berris
-
Edward Diener
-
Henrik Sundberg
-
Hrvoje Prgeša
-
joaquin@tid.es
-
Joel de Guzman
-
Johan Nilsson
-
Markus Werle
-
Michael Fawcett
-
Michael Marcin
-
Mika Heiskanen
-
Neil Groves
-
Ravi
-
Richard Hadsell
-
Robert Jones
-
Stefan Seefeld
-
Steve M. Robbins
-
Thijs van den Berg
-
Thorsten Ottosen
-
Thorsten Ottosen
-
Tomas Puverle
-
Vicente Botet Escriba
-
vicente.botet
-
Vladimir Prus