Programming libraries abound but very few are good. A good library works, is easy to use and is easy to learn.
For a library to be easy to learn it must include good documentation. Good documentation has neither too little nor too many words. It should be optimized so a programmer can learn it in the shortest possible time. The type of documentation will change depending on the kind of library it is. Some will require extensive documentation on all features while others just need a few simple examples. When you write a library, imagine using it then picture the best possible documentation that would help you do that.
A good library works, which means it must create the correct output for every possible input. It will ideally have no bugs. While this may seem easy, it takes many years to develop the skills needed to accomplish this. To help with this, automated testing is required. Automated testing is its own subject.
A good library must be easy to use. It must be consistent, which helps programmers learn it. It should never take control and only provides tools. The calling code should always have complete control. If a library takes control then it can’t easily be used with other libraries. There can be tricky parts to library development, such as memory management. The language choice also determines if the library is easy to use.
Many libraries are written in c. Even though c++ has existed for decades, it isn’t widely used for libraries. This is due to an oversight in the c++ specification. C++ introduced new ideas such as polymorphism. However polymorphism isn’t supported in object files. To fix this, c++ compilers adjust the function names so each polymorphic function has a unique name. This conversion is called name wrangling, because it wrangles the name into a form that linkers can understand. There’s nothing wrong and many programmers are completely unaware of it. Name wrangling happens behind the scenes so programmers don’t even notice. The issue comes about because there is no c++ specification for name wrangling, which means a library can’t be used by a different c++ compiler. C does not have this limit, which is why so many libraries are still written in c.
Next is memory management, which can be tricky. This is due to how libraries are handled by the operating system or compiler. Static libraries have the fewest problems. A static library is compiled into the application, so it uses the same memory segments and language libraries. Shared libraries are stored in separate files. They’re loaded as needed. The goal of shared libraries is to reduce memory use. This works by taking a library that many applications use and only loading it once.
Shared libraries use less memory so are good from that respect. Unfortunately they also have inherent problems. The first issue involves bug fixes. A shared library is loaded into memory but can’t easily be unloaded and replaced. So when a library is updated the system often has to restart. Other problems arise from shared memory or security issues. Newer types of shared libraries address these issues, but problems remain. There are also issues around memory allocation, especially when the shared library is compiled with a different compiler. Memory allocated by the shared library should also be reallocated or freed with the library. This means some structures, like dynamically growing structures, should be avoided. If a library fails to do this, it may work on some systems or with some applications only to fail on others. Another issue is version problems. Older shared libraries may require other older shared libraries to function. In the end, there could be so many on the system that the memory benefits virtually vanish.
Both static and shared libraries have their time and place. Other factors also affect library development, such as if the library is open source. To gain the benefits of open sorce, the source code must be well commented. This is easy to do, and makes it easier to maintain, but it takes more work. However not all libraries are pre-compiled. There are also source code libraries.
Source code libraries also exist for compiled languages, like c or c++. These can replace static libraries. They often work best when gathered into one source and one header file. That way they don’t clutter a project. A source code library can provide simple rather than comprehensive functionality and the programmer can expand it as needed. This lets the programmer customize the library to meet current needs.
Libraries should have a good well thought-out interface. It should simplify the use as much as possible. Sample code should have a few library calls at most to do simple tasks. Another thing to consider is future or backward compatibility. If developers can upgrade the library to the latest version without having to change their code then they are far more likely to use it.
Some libraries have special requirements. For example, a library made for an embedded system is written differently than a library for a PC. Embedded systems have less memory and a lot less stack space, so recursion or memory-intense algorithms should be avoided. If the library is built for these kinds of applications ensure it’s mentioned in the documentation.
The open source adds another wrinkle to libraries. Some libraries force any code using it to also be open source. Consider the outcomes before deciding on a license model for your library. A closed source library is perfectly acceptable. If it’s good then people don’t mind paying for it. Often times great libraries are neither open source nor closed source, they give it out for free. These libraries are written to fill a need then released afterwards. Their license model translates to, ‘Here’s the code. Use it for whatever just don’t bug me.’ There are specific versions of this, such as the MIT or Apache license.
In conclusion, a good library works, has no bugs, it is easy to use and has efficient documentation. If you develop libraries using these simple principals then your library is more likely to be used.