Borland Package Library - special kind of object-oriented DLL with enforced type-safety
Delphi is component-based IDE for its proprietary dialect of Pascal language.
Differing from its competitor Visual Basic, it could "eat its own food" - create those components to extend itself.
Up to 1996 to install them one need to recompile part of IDE, similar to installation in Lazarus/FCL IDE. That resulted in two problems:
- The more components you install - the heavier IDE becomes, and computers back then had significantly less memory. You could not arrange different components subsets per project.
- If some component proved cruelly broken and crashed IDE, reconfiguring and rebuilding it without the component becomes less obvious task w/o using IDE.
It also made little help to deploy large programs: one either had to deploy large monolithic EXE which could cause problems in OSes with 16-bit kernel (Windows 9x/ME), or develop traditional Windows DLL sacrificing all type safety and complex types (passing objects and strings on EXE/DLL or DLL/DLL boundary would be extremely fragile, practically impossible for average programmer).
With the release of Delphi 3 in 1997 Borland introduced specific type of DLL, the one with enforced type safety (dependencies are codified at compile-time and checked at load time) and changed one letter: DLL -> DPL - Delphi Package Library
.
Next year Borland C++ Builder
1 was released (with built-in Delphi 3.5) and those libraries were renamed again: DPL -> BPL - Borland Package Library
.
BPL remains the basement for component-based RAD Studio
IDE design up to today.
Drawbacks of BPL:
- Increases "implementation leakage" problem of Turbo Pascal, source Units of which where introduced before OOP trend. That forces private members and datatypes (worker classes) used be promoted into public unit interface. Later Delphi language designer fixed the problem by introducing
partial classes
into C#, but in Delphi this feature is missing. Since BPL publishes allinterface
sections of all the contained units, even internal "worker" units, there is no way to make stable contained API and spaghetti dependencies may easily happen unnoticed. - Since every unit is public by definition - and since BPL may be re-used by other apps - the
Smart Linker
is defeated. If you only need 1% of the library - you either re-work it or you deploy the whole library with 99% of slab. In monolithic EXE mode compiler would record XRefs and theSmart Linker
would eliminate unused 99% of the library. - This also means you can not have several unit with the same name, like you can with DLLs. It is not big issue but may be inconvenient.
- This also means that if you re-work some class like adding new internal method (virtual or not) - the class signature changes and all the depending BPLs have to be re-compiled and re-deployed. It is especialyl annoying when you need some fix in stock RTL
- If you change compiler options or version, this change affects internal classes/functions ABI and all dependent packages should be re-build and re-deployed.