Here is my personal advice on how to create a successful library for Boost or otherwise. I don't lay claim be the originator of any of these. They are derived from many different source of software development ideas and methodologies. Many of these sources contain overlapping ideas with different terminology.
Incremental development
continual testing
Literate Programming - consideration of progam and documentation as "one thing".
Program development though Progam Derivation - correct program construction through composition of demonstrably correct components.
This is what we usually do to make a library or other body of code:
write all the code
write some tests
change all the code and tests until the tests to pass on our platform
start writing documentation and examples
upload it and ask people to try it out
This approach has a couple of problems.
Coding is fun, while the ancillary tasks can be very boring, tedious and frustrating. So leaving these other tasks as an afterthought results in poor and/or incomplete documentation, testing, and concept definition.
Conceptual errors are often discovered when writing documentation, tests and concepts. Discovery of these errors usually results in changed to the code which ripple through the whole library and create a lot of work.
Poor/Incomplete documentation/testing/concepts mean that fewer conceptual errors are discovered before code is made available to users.
Users will be shipped code which is weak on documentation, tests, and examples and has conceptual errors. Often the library writer doesn't do this intentionally, it's just an effect of the way the code has been developed. Users will discover these problems, reject the library and move on. If the library writer get's any feedback it is likely to be of limited usefulness.
So reworking code and documentation after everything is "done" results in a huge amount of extra work - if the work every get's done.
The basic problem is that the ancillary tasks create a lot of useful information and this needs to be cycled back into the library code before anything is shipped. Cycling this information back sooner saves wasted time.
Here is what I recommend instead:
write a small group of classes. functions, or templates.
use concepts - what are concepts?
write documentation for this group
write and newly required concept checking classes
write a program to test this code
Repeat above for the next group.
When there is enough to be truely useful to someone, upload the package as ask people to test it. The package may not have all the features planned for it, but it should have enough functionality to be useful.
Monitor feedback.
add features and make adjustments and repeat cycle above.
In contrast to the first approach.
Coding, testing, documentation, are divided into shorter tasks. So the tedium and frustration are much easier to deal with.
Information gleaned from documentation, testing, concepts, and user feedback is received sooner and saves much rework and back tracking.
The result is a higher quality library which:
Exhibits "conceptual integrity". That is, code with a clearly defined purpose which is explained in an way which makes it obvious what the code is meant to do and how to use it.
Motviates the user to take the code for a "test drive" by including the code in his own application. This should that convince the user that the library is bug free, useful, and easy to use.
Results in the user returning positive feedback and request for more features.
Motivates the library writer and perhaps other users to add features to the library.
include concept checks (also known as "parameter constraints") on template parameters to check template parameters. These provide compile time checks on the arguments used in template instatiation similar to the way that C++ type checking provides compile time checks on the arguments of function calls.
Boost Concept Checking Reference contains of list of widely used concepts checking classes. It's very easy to use these in your own class and function template definitions:
This will cause a compilation error whenever one invokes
my_class_template<T> on any T which is does not support
the == operator.
Be prepared to Create Concept Checking Classes classes when your library defines new concepts.
Many libraries have a section entitled "Rationale". This section is very helpful for anyone who want's to use the library. The problem is that if you wait until you're done to write this section, you can't remember what the key decisions were and why you made them. That is, you don't remember all the dead ends you discarded to get your final finished product. If your library gets to review, someone will suggest that it you should of done it using method X instead of method Y
"Easy" way - don't keep notes. Here's what happens.
At some point in the development, you discover that you want to change a design decision. This means you have to use method X instead of method Y. Generally this will occur more than once during the development.
Finally you get everything done, and submit your library for review.
Now some smart guy will make a good case for using method Y instead of method X which you used. Of course you know that since you've been down that road. But now you don't remember exactly why method Y couldn't be made to work.
So you sort of fake it with a glib response which only provokes your critic to make an even stronger case. Now everything has escalated to the point where you have to go back and make a really exahaustive explanation (maybe even involving sample code!). This sucks up a huge amount of time.
"Hard" way - keep notes on your decisions as you go:
When you discover you want to change a design decision, add an explanation to your log.
Keeping such notes diminishes the possibility that you accidently change a design decision back to one that has previously been determined to be a dead end. Don't laugh - this is not hard to do!
When writing documentation, take these notes, clean them up and include them in a section called "Rationale". This makes writing this very useful documentation trivial.
Users and library reviewers will be able to see your case before they make their "suggestions". This short circuits lot's of pointless discussions. There will likely still be differences of opinion, but all the issues will be visible to all parties at the same time.
If there's already a boost component which performs some function you need - use it.
If you're making a library which you hope to get accepted into Boost, it will very likely depend upon other boost library components. Do not test your code against the Boost Trunk. Consider the following:
You're using Boot Test Library to test your library.
The Boost Test author makes a change and tests it on his own system.
He uploads it to the trunk for testing on all other compilers/OS combination which Boost Supports.
Over the next few days it turns out that the code is broken on some platforms he couldn't test on. So he endeavors to make the code fixes required.
Meanwhile, you've updated your local copy and you test your new library. But now you get a number of subtle problems of unknown origin. You have to spend a lot of time tracking down errors which are not in your own code at all! This is a huge waste of time.
Eventually, the Boost Test Library author get's all the tests passing and the problem goes away - IF you happen to update your local copy from the trunk in the meantime.
This scenario supposes that you've only got one Boot Library dependency in your code. In reality, due to the nested library structure of all software libraries, you'll actually be dependent on dozens of other libraries which your are not even aware of.
Using the Boost Trunk copy of libraries is a huge waste of your time - don't do it!