You get a bonus - 1 coin for daily activity. Now you have 1 coin

Subroutine Libraries: Static, Dynamic, Object and Class Libraries

Lecture



A library (from the English Library ) is a collection of objects or subroutines for solving tasks that are related in subject matter. Depending on the programming language, libraries contain object modules or source code and data that assist in the use and integration of new capabilities into software solutions.

A library can mean the same thing as a module or several modules.

From the point of view of computer science, libraries are divided into static and dynamic ones.

In some programming languages (for example, in Python) it is the same as a module, while in others it means several modules. From the point of view of the operating system (OS) and application software, libraries are divided into dynamic and static.

The term «subroutine library» was apparently among the first to be mentioned by Wilkes M., Wheeler D., and Gill S. as one of the forms of organizing computations on a computer. Based on what is set out in their book, a library was understood to be a set of «short, pre-prepared programs for individual, frequently occurring (standard) computational operations».

History

The earliest programming concepts analogous to libraries were intended to separate data definitions from the program's implementation. The JOVIAL company brought the concept of COMPOOL (communication pool) to public attention in 1959, although it borrowed the idea from the SAGE software for large systems. Following the computer science principles of separation of concerns and information hiding, «the goal of the Comm Pool was to allow system data to be shared among many programs by providing a centralized description of the data».

COBOL also included «primitive capabilities for a library system» in 1959, but Jean Sammet in retrospect characterized them as «inadequate library capabilities».

Another important contribution to the concept of the modern library was made by the innovative FORTRAN subroutine. FORTRAN subroutines can be compiled independently of one another, but the compiler lacked a linker. Thus, before the introduction of modules in Fortran-90, type checking between FORTRAN subroutines [NB 1] was impossible.

Finally, historians of the concept must recall the influential Simula 67. Simula was the first object-oriented programming language, and its classes were almost identical to the modern concept used in Java, C++, and C#. The class concept of Simula was also the ancestor of the package in Ada and the module in Modula-2. Even in its initial development in 1965, Simula classes could be included in library files and added at compile time.

Static libraries

They can take the form of source text, which the programmer includes in their program at the writing stage (for example, for the Fortran language there is an enormous number of libraries for solving various tasks precisely in the form of source texts), or in the form of object files that are attached (linked) to the executable program at the compilation stage (in Microsoft Windows such files have the extension .lib, in UNIX-like operating systems they usually have the extension .a). As a result, the program includes all the necessary functions, which makes it self-contained but increases its size.

A static library is an object file in the form of a file (it may often be supplied together with the source code), the code from which is selectively or fully inserted into the program at the linking stage.

Libraries distributed in the form of source code are converted by the translator into object files. Then the linker combines the object files of the libraries and the object files of your program into a single executable file.

For example, the following are distributed as source texts:

  • libraries for the Fortran language;
  • the Boost library for the C++ language.

Libraries distributed in the form of object files are already ready for linking. The linker combines the object files of the libraries and the object files of your program during the creation of the executable file.

Extensions of the object files of static libraries in different operating systems.

Extension OS
«a» UNIX
«lib» Microsoft Windows

The standard libraries of many compiled programming languages (Fortran, Pascal, C, C++, and others) are distributed in the form of object files.

Advantages:

  • all necessary functions are included in a single executable file.

Disadvantages:

  • the executable file takes up more space on disk and in memory (if it attaches the code from the object library files in full rather than selectively);
  • when errors are found in the library, all programs need to be rebuilt.

Dynamic libraries

They are also called shared libraries (English Shared library ), or dynamically linked libraries (English Dynamic Link Library , DLL). These are separate files that provide a program with a set of functions to be used, downloaded at the execution stage when the program turns to the OS with a request to execute a function from the library. If the required library is already loaded into RAM, the program will use the loaded copy of the library. This approach makes it possible to save time and memory, since several programs use a single copy of the library that is already loaded into memory.

Dynamic libraries are usually stored in a specific location and have a standard extension. For example, .library files in the logical volume Libs: in AmigaOS; in Microsoft Windows and OS/2 shared-use library files have the extension .dll; in UNIX-like operating systems they usually have .so; in MacOS they have .dylib.

When writing a program, it is enough for the programmer to indicate to the programming language translator (compiler or interpreter) that such-and-such a library should be linked and that a particular function from the specified library should be used. Neither the source text nor the executable code of the function is included in the program.

A dynamic library is a file containing machine code. It is loaded into the process's memory by the operating system's program loader either at the time the process is created or upon the request of an already running process, that is, dynamically.

File name extensions of dynamic libraries in different operating systems
Extension OS Meaning Note
so UNIX English shared object
dylib Mac OS English dynamic library
library AmigaOS Stored in the logical volume Libs:
dll Microsoft Windows, OS/2 English dynamic link library

Depending on their purpose, a distinction is made between:

  • Libraries used by a single program and containing functions critical to the program's operation. Disadvantage: in the absence of the library, the program will not be able to work;
  • Libraries used by a single program and containing additional functions. For example, plugin libraries are used to extend the program's functionality;
  • Shared-use libraries (English shared library). They contain functions used by several programs. They can be loaded into the OS address space (English system library) to save memory: a single copy of the library will be used by several processes. Because of this last circumstance, such libraries are often called shared.

When writing a program, it is enough for the programmer to specify to the translator (compiler or interpreter) the path to the library and the name of the function. Neither the source text of the function nor its executable code will be included in the program.

Advantages:

  • memory savings due to the use of a single library by several processes;
  • the ability to fix errors (it is enough to replace the library file and restart the running programs) without changing the code of the main program.

Disadvantages:

  • the possibility of breaking the API — when changes are made to the library, existing programs may stop working (they lose interface compatibility);
  • a conflict of dynamic library versions — different programs may require different versions of the library;
  • the availability of identical functions at identical addresses in different processes — this makes it easier to exploit vulnerabilities (to solve this problem, pic (English) was invented).

Libraries for interpreted languages

A library is a file containing either code in an interpreted language or bytecode for a virtual machine.

For example, libraries for the Python language can be distributed either in the form of source code files (extension «py») or in the form of bytecode files (extension «pyc», the letter «c» from the English compiled).

Libraries of objects and classes

Although dynamic linking was first applied in the 1960s, it did not spread to operating systems used by consumers until the late 1980s. By the early 1990s it was available in one form or another in most operating systems. During this same period, object-oriented programming (OOP) was becoming an important part of programming. OOP with binding at run time requires additional information that traditional libraries do not provide. In addition to the names and entry points of the code located within, they also need a list of the objects on which they depend. This is a side effect of one of OOP's main advantages, inheritance, which means that parts of the complete definition of any method may be located in different places. This is more than just listing what services one library requires from another: in a true OOP system the libraries themselves may be unknown at compile time and may vary from system to system.

At the same time, many developers were working on the idea of multi-tier programs, in which a «display» running on a desktop computer would use the services of a mainframe or minicomputer for storing or processing data. For example, a program on a computer with a graphical interface would send messages to a minicomputer to return small samples of a huge dataset for display. Remote procedure calls (RPC) already performed these tasks, but there was no standard RPC system.

Soon most minicomputer and mainframe manufacturers initiated projects to combine them, creating an OOP library format that could be used anywhere. Such systems were called object libraries or distributed objects if they supported remote access (not all did). Microsoft's COM is an example of such a system for local use. DCOM, a modified version of COM, supports remote access.

For a while, object libraries had the status of the «next big thing» in the programming world. A number of attempts were made to create systems that could work on different platforms, and companies competed, trying to lock developers into their own systems. Examples include IBM's System Object Model (SOM/DSOM), Sun Microsystems' Distributed Objects Everywhere (DOE), NeXT's Portable Distributed Objects (PDO), Digital's ObjectBroker, Microsoft's Component Object Model (COM/DCOM), and any number of CORBA-based systems.

After the marketing hype subsided, object libraries continued to be used both in object-oriented programming and in distributed information systems. Class libraries are the OOP-era rough equivalent of the older types of code libraries. They contain classes, which describe the characteristics and define the actions (methods) with objects. Class libraries are used to create instances, or objects, with certain characteristic values. In some OOP languages, such as Java, the distinction is obvious: classes are often contained in library files (for example, in Java's JAR file format), while created object instances reside only in memory (although they can potentially be made persistent in separate files). In others, such as Smalltalk, class libraries are merely a starting point for a system image that includes the entire state of the environment, the classes, and all created objects.

Remote libraries

Another solution to the library problem is to use completely separate executable files (often in some lightweight form) and to call them using remote procedure calls (RPC) over a network to another computer. This approach maximizes the reuse of the operating system: the code needed to support the library is the same code that is used to provide application support and security for any other program. In addition, such systems do not require the library to be present on the same computer, but can forward requests over the network.

However, this approach means that each library call requires considerable overhead. RPC calls are much more expensive than a call to a shared library that has already been loaded on the same computer. This approach is usually used in distributed architectures that make intensive use of such remote calls, especially in client-server systems and application servers such as Enterprise JavaBeans.

Code generation libraries

Code generation libraries are high-level APIs that can generate or transform bytecode for Java. They are used by aspect-oriented programming, by some data access frameworks, and for testing to create dynamic proxy objects. They are also used to intercept field access.

Independent Software Vendor (Vendor)

An Independent Software Vendor (English ISV, Independent Software Vendor) is a company that specializes in creating or selling software developed for sale on the mass market or in specialized (niche) markets. Such markets can be diverse, for example, software for realtors (real estate brokers), for working with schedules for hospital staff, for barcode reading, for warehouse management, and even software for childcare, and so on.

Specialized products usually give organizations higher productivity in their work than «boxed» software such as, for example, spreadsheets or databases as part of office suites. The largest software development companies, such as Microsoft and IBM, have special programs for ISVs. However, an ISV creates and sells software products that run on one or more computer hardware or operating system platforms. Companies that make platforms, such as Software AG, salesforce.com, BEA Systems, Microsoft, Novell, IBM, Sun Microsystems, Hewlett Packard, and Apple, encourage and provide support to ISV vendors, often with special «business partnership» programs.

In general, the more applications that run on a platform, the more valuable it is to customers. Of course, platform makers such as Microsoft and IBM also create applications, but they do not have the resources and, in many cases, the specialized knowledge required to create applications of all kinds.

Some ISVs focus on a specific operating system, such as IBM's AS/400 for small business, for which there are thousands of applications created by ISVs. Other ISVs specialize in some particular application area, such as supporting engineering workers, or develop software mainly for high-performance Unix-platform workstations.

ISVs create and sell software that is added to software platforms. OEM hardware manufacturers use hardware platform components to build products on their basis. Value-added resellers include platform software in their own software product packages.

Infrastructure code and core code

Earlier we considered the distinction between infrastructure code and non-infrastructure code, which is usually called core code. The difference between these two concepts can be summarized as follows: «everything in the vendor directory is infrastructure code». But I disagree with this, and here is why.

Is all vendor code infrastructure code?

You may disagree with such a statement, because everyone has their own definition of «infrastructure», which would turn this statement into an incorrect one. Let us look at the current version of this definition, which consists of two rules that define core code. Any code that does not simultaneously satisfy these two rules should be regarded as infrastructure code.

  • Rule 1: Core code does not directly depend on external systems and does not depend on code written to interact with a specific type of external system.
  • Rule 2: Core code does not require a specific environment in order to run, nor does it have dependencies intended to run only in a specific context.

Following this definition, we understand that as soon as a piece of code reaches out to something beyond the running application (for example, it connects to the network, touches the file system, requests the current time or random data), it should be regarded as infrastructure code. As soon as a piece of code can run only in a specific environment (a web application, a CLI application, etc.), it too should be regarded as infrastructure code.

These rules say nothing about whether the core code is located in the src/ or vendor/ directory, and that is fair. Imagine that you have a piece of code that you can call core code because it matches its definition. If you now move this code into a separate repository on GitHub, publish it as a package, and install it in the vendor/ directory of your project using Composer, will this piece of code suddenly become infrastructure code? Of course not. The location of the code does not determine what kind of code it is.

The fact that something is vendor code does not determine that it is infrastructure code. The difference lies in whether you can run this code in complete isolation, without providing external dependencies and without any preparation of the environment.

Unit tests and core code

This may remind you of Michael Feathers' definition of a unit test. A test is not a unit test if it:

  1. Talks to a database
  2. Communicates over the network
  3. Touches the file system

It cannot run at the same time as your other unit tests, or you have to do special things to your environment (for example, editing configuration files) in order to make the test work. Tests that do these things will not do any harm. Often they are worth writing, in a modular form. However, it is important to be able to separate them from real unit tests, so that we can maintain a set of tests that we can run quickly whenever we make our changes. In fact, following the stated definition of core code, we can conclude that core code is the only code that can be tested with a unit test. This does not mean that you cannot test infrastructure code; it merely means that such a test cannot be considered a unit test. Such tests are often called integral or integration tests.

Most, but not all, vendor code is infrastructure code

Thus, there is no strict connection between infrastructure code and a directory inside the vendor. However, there is a certain inverse relationship: most of your application's infrastructure code is located in the vendor directory. It can also be said that you write most of the core code yourself.

Let us look at some examples of code that is located in the vendor but would not (according to my rules) be called infrastructure code:

  • An event dispatcher library
  • An assertion library
  • A value object library

Libraries that deal only with data transformation (for example, a data converter or serializer) can also be regarded as non-infrastructure code. In practice, you can use the following checklist to find out whether code (wherever it is located, in src or in vendor) is non-infrastructure code:

  • The class is used anywhere and can be freely called by any of its methods
  • The code has no static dependencies (facades, service registries, etc.), no dependencies on global state ($_SERVER, $_POST, etc.). All of its dependencies are provided as constructor arguments. None of the dependencies are themselves infrastructure code.

The first rule guarantees that the code has no external dependencies (network, file system, etc.) that must be available when the code is called. The second rule guarantees that you do not need to prepare any special context in order to run this code. When all of this is true, it means that if you run the code and encounter a problem (in a test or during regular use), you will know that it is a problem with the code. It will not be related to any infrastructure problems, so you should be able to solve it by fixing the code that is running.

See also

  • Linker
  • Automatic linking
  • Code reuse
  • Linker (computing)
  • Loader (computing)
  • Dynamic-link library
  • Object file
  • Plugin - a software component that adds a specific function to an existing software application.
  • Prelinking, also known as prebinding
  • Static library
  • Runtime library
  • Visual Component Library (VCL)
  • Component Library for Cross Platform (CLX)
  • C standard library - the standard library for the C programming language
  • Java Class Library
  • Framework Class Library - the standard library of the Microsoft .NET Framework
  • Generic programming - a way of designing and writing programs in which algorithms are written in terms of parametric types that provide easy reuse (used by the C++ standard library)
  • soname - a data field in a shared object file
  • Stub function method

Comments

To leave a comment

If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Lectures and tutorial on "Software and information systems development"

Terms: Software and information systems development