The Repertiore Project

Introduction to General Purpose Libraries

Reuse is good. Reusable code is nice because we can use something again without building a new one. It's also nice when one part can be used several times in the same program, since that keeps the program's size down and also makes it more maintainable.

But reuse of code goes beyond simple convenience. If a component was written to be reusable, it may be very well designed and carefully crafted. All the little details will be taken care of, and upon reuse you just don't have to worry about it anymore.

Consider a simple case of reusing a function: When creating a window, how many people just use a stock white brush for the background? The robust behavior is to look up the control panel settings for what window backgrounds ought to be. A small detail, but a function such as CreateWindow that has a zillion parameters has a lot of small details.

A reusable part to create a program's main window is a very simple part: a single function, perhaps half a page in length. However, by building such a part you put a great deal of attention into details that you might omit if you were just coding yet another call to CreateWindow in some program. The work pays off, because once built, you can get better functionality, in addition to being easier to use than writing yet another call to CreateWindow.

John's Principles of Library Design

So just what is a "class library", anyway? I've seen libraries that try to make C++ look like SmallTalk. I've seen specialized libraries for various purposes. But, for the most part, the "general purpose" libraries I've seen are actually programming religions. That is, to use the library, you have to adopt the library's way of doing things, throughout the entire program. It's like kudzu: once planted, it gets into everything. Microsoft's MFC is an example of this kind of system.

My feelings are somewhat different. A library should provide components that are useful in places such that you want to use it, as opposed to requiring the entire program to be written a certain way just so you can get some feature.

That is, the use of a library component in one place should not have an undue influence on how the program is written in other places.

Second, the library should be useful as separate parts, and the use of one simple part should not drag in the entire beast. This can be paradoxical, since if components are generally useful why can't you use then when writing other components in the library? This issue is thorny, and will be covered again in more detail.

Third, reusable code should be general and extensible. A good library needs to embody a compromise between being too flexible and being inflexible.

Why Use This Stuff?

With so many C++ libraries out there, including stuff that comes with the compiler, why look into another one? It boils down to two compelling reasons: features and robustness.

Some of the things in the Classics library are new, in the sence of not seeing them in other libraries. For example, the ustring class is a new concept, the smart pointers are more technically advanced than others, the multi-stanza exception objects provide superior error reporting, and the vararray collection offers handy copy-on-write features not found in traditional implementations.

Robustness is of primary importance if you are trying to write solid code yourself. Not a week goes by that I don't hear about Microsoft's STL implementation messing up in some way, or bugs in MFC, or Win32 primitives that are poorly documented or don't handle boundary conditions very well.

What might seem like a "thin" wrapper in Classics is often the necessary code to make a Win32 primitive robust. That is, it handles boundary conditions and checks for errors. Naïve code that simply calls functions like MultiByteToWideChar as shown in the numerous example programs and magazine articles will not be as robust as using Classics, because these functions often have subtle and surprising caveats.

The vararray class will work properly (unlike STL vectors) without bizzare failures at boundary conditions and some choices of template arguments. The string class will operate correctly (unlike MFC's CString) even when multiple threads are being used. Count on it. If I'm ever in a hospital, I'll take comfort in knowing that the medical imaging equitment uses Classics rather than MFC. Microsoft Word might lose work from time to time and users put up with it. But don't pull that stunt with a patient's brain scan!

Robustness

A reusable component should work correctly and reliably before you ever consider building anything with that component.

The Repertoire Project sets itself apart from other libraries because it's built like a tank. Furthermore, the code is extensivly tested, and the testing code is shipped along with the actual library, making it eay for you add new test cases if you suspect something, and to do full regression testing any time a change is made.

See Robust Code and Testing for more on robustness and testing issues.

Furthermore, thread-safety is designed into the code from the inception. This can be important when actually using the code in a multi-threaded environment. Other libraries (such as MFC's CString class) is full of race conditions, or worse yet, casual use of locking that leads to potential deadlocks.


Classics

ClassICs is a library of general purpose C++ components. This is actually the third major redesign of the library, so it ought to be called Classics 3. However, it was never widely distributed—it was just a (less than successful) attempt to gather my own useful objects together into a common place, and document them.

The name Classics has a double meaning. "Class ICs" brings to mind reusable components, such as electronic ICs. One meaning of classic is in accordance with established principles of excellence in the arts and sciences. Another is balanced, formal, objective, austere, regular, simple, etc.

In short, it perfectly describes the design principles embodied in this library, that of high quality, robustness, and simple elegance.


RatWin

RatWin stands for Rationalized Windows, and is a set of C++ header files as an alternative to the traditional WINDOWS.H file. They feature strong type checking, overloading, namespaces, and no macros.


Tomahawk

Tomahawk is an experimental Windows programming framework. It's still in the experimental stages.


Conquer

Conquer will be a library for multi-threaded programming. It is still in the planning stages.