Day 28: Frequently Repackage Code Into Smaller Libraries
A problem that is common to many programming projects is the deficient separation of code into distinct packaging units, such as libraries and modules or assemblies. Languages such as Java, Python, and C++ provide great flexibility for users to create such modules.
Despite this, many developers, especially beginners, misuse this flexibility by packing as much code as possible in individual source files and libraries. The result of these practices is source code that is difficult to manage and maintain.
Packaging and Interfaces
In a sense, packaging functionality into modules and libraries is an extension of the problem of devising good classes and interfaces. However, it is directed at a higher level: not the lower level of programming elements, such as functions and types, but at the level of source code packaging, linking, and distribution.
A typical example occurs when a new team starts to develop a large application. Lots of functionality are created, and for simplicity this functionality is hosted in a single executable. This is fine for the first iterations of a product, and it really streamlines the process of building and distributing software.
What happens over time, however, is that interfaces inside the product become easily intertwined, even when developers are careful about it. What is worse, however, is that a change in a module that processes network connections, for example, will prompt a rebuild of the whole project.
Depending on the language this may become a problem sooner or later. In C++, for instance, building processes may sometimes take hours. Python, on the other hand, doesn’t suffer from building time issues, but even then it is a hassle to test and make sure that the whole project is OK, just because one of the modules was changed.
The ideal goal is to create libraries and other higher level modules (depending on the language), such that a routine change in that module doesn’t need to force the repackaging, testing, or even building of other parts of the software.
An ideal situation, for example, is what happens when an operating system has a regular update (for example, a security fix). When that happens, application software will not need to be recompiled or even retested. And that is true even though every application depends heavily on the APIs provided by the operating system.
Clearly this level of separation is much harder to achieve for normal application code, simply because an OS kernel has been painstakingly designed to reduce coupling. But this doesn’t mean that we should’t strive to achieve some level of separation.
The most basic way of improve code organization in this sense is to create independent libraries to handle common application concerns as soon as possible. For example, a library to handle networking operations can be added to the project, and all interactions with the network routed to that module. As a side note, a lot of open source projects were started exactly in this way. For example, the now ubiquitous Gtk+ widget set was initially just another library developed by the creators of Gimp.
Advantages for Compiled Languages
Another great advantage of repackaging code in this way in a statically typed language such as C++ is the reduction in compilation and link time.
Large code bases in C++ tend to create huge dependencies due to the file inclusion system, which is based on a preprocessor. When not handled properly, such a system creates link time dependencies that are hard to break. By separating modules into libraries as soon as possible, one can reduce the dependencies in the long run.
In summary, code packaging is an important skill that you should strength by making thoughtful decisions during the design phase of a project. Creating libraries make it easier to handle dependencies in application code. In languages with long compile times such as C++, this practice can save you a lot of time and reduce dependency issues that may arise during future development.
About the Author
Carlos Oliveira holds a PhD in Systems Engineering and Optimization from University of Florida. He works as a software engineer, with more than 10 years of experience in developing high performance, commercial and scientific applications in C++, Java, and Objective-C. His most Recent Book is Practical C++ Financial Programming.