Mega Code Archive

 
Categories / Delphi / Examples
 

Why use Packages

Title: Why use Packages ? Question: Packages offer a structural library approach to developing applications and offers a precondition for package diagrams. In Delphi/Kylix a Package is a combination, collection of units, which have dependencies. Answer: The goal is to provide some notions about runtime packages and why use packages at all in a "designed" project? Runtime packages, which are optional in a project, offer several advantages over a conventional programming. By compiling reused and modular code into a runtime library, we can share it among Delphi/Kylix applications. Package diagrams are used to describe parts of a system at a high level, such as 'report generator' or 'single sign on ckecker'. These will have internal structure, and many tools will allow you to jump from the package to a detailed view of its structure. Remember: Packages could be nested. Two types can be made by Delphi/Kylix: - design time packages used to install components in the IDE and to create special property editors, experts etc. for custom components this type is used only by IDE and is never distributed with your app - run time packages provide functionality when we run an application they operate much like DLL's Rule: Design time packages need run time packages to work but not the other way round. In this article we deal with run timers. First Decision -------------------- Packages allow also a faster compilation cause only code concerning the "small" application is compiled with each build. In comparison with a DLL, packages provide an easier approach with forms or method calls cause packages are owner of the application so they interact better with other classes. On the other side a DLL is more "other language friendly" and less IDE dependent. Advantages of Packages: - packages are specific to Delphi - packages are UML conform - faster compilation, less parsing - packages save memory for many applications - testing becomes more plannable (DUnit) - better installation, setup's and deployment possible - scalable in product, e.g. a light- or professional version The first decision we should make is: Do we put components in a package or do we modularize a whole application with a lot of forms, data-modules, multi-language or ressources? That means dependencies between classes should be stronger (inner coupling) than dependencies between packages. Imagine a scheduling system for public transports with an optional messaging system or an optional reporting system. Some installation need only the schedSystem and others will install the ME and REP modul too. Build the Package ----------------------- Ok., let's start with a simple application with two forms (form1 and form2), form2 should become a package, means we modularize the app within a reusable module. 1. Remove Form2 from the auto-created form list 2. The Event-Handler goes like this: with TForm2.Create(application) do begin try showModal; finally free; end; 3. Add Unit2 to Unit1 uses (implementation part) 4. Now we create a package with Form2... 5. View/Project Manager then right click on Project Group and select " Add New Project..." till the Package Editor arrives 6. We select Package from the New list 7. We select the "Contains" item and add Unit2.pas 8. It's time now to save and compile our package 9. Since our package is run-time only clicking on the Install buttton will not work The package is complete and we call it picinPac so the file generated is picinPac.bpl in the project order. Hint: If we rename the extension from bpl to dll and take a look with quickview, you can see the package like a DLL! We also define in the package editor/options the package as "Runtime only" so the property editors are wiped out (we don't need them at runtime). Second part is now to compile the app with our package: 1. We select Project Options/ Packages tab 2. Activate the checkbox "Build with runtime packages" 3. Add in the edit box below our package like vcl50;picinPac 4. Packages listed in the edit box are automatically linked to your app's 5. Recompile it After we compiled it, the app is about 17k but we need on a second machine the package and vcl50.bpl too, as we can see in the package editor "Requires". (But with multiple packages we need another check). The whole check for deployment is found within the compile-info from the Delphi Menu "Information and finally Package used". The mechanic get's Delphi by statically linking our package at compile time. Note: Like a DLL, also a package is able to load dynamically with LoadPackage() and UnloadPackage(). But either you choose static or dynamic, any changes in Form2 needs a rebuild within the package-editor (compile) after then Form1 is up to date. I can't say how many times we forget that. To prevent this add the package to the Project Manager Group so we can switch between compilations. Versioning Problem ------------------------ When we update a DLL (change function's implementation), we simply compile it, export some new routines and ship the new version. All the applications using this DLL will still work (unless, of course, you've removed existing exported routines). On the other hand, when updating a package, you cannot ship a new version of your package without also updating the executable. This is why we cannot use a unit compiled in Delphi 4 in a Delphi 5 project unless we have the unit's source; the compiler checks version information of DCU's and decides whether an unit has to be recompiled so any package that you provide for your application must be compiled using the same Delphi version used to compile the application. Note: You cannot provide a package written in Delphi 6 to be used by an application written in Delphi 5. Note: although the app is linked to run-time packages, the program's units must list all the units they require in the uses clause. Compiling with run time packages only tells the app where to find it's component code. Last check is the project-source *.bpg, sort of a editable make script, that shows our packages in a "well documented" way. Create project groups to handle related projects at once. In our example, you can create a project group that contains multiple executable or binary files such as two .BPL and an .EXE: #------------------------------------------------------------------------------ VERSION = BWS.01 #------------------------------------------------------------------------------ !ifndef ROOT ROOT = $(MAKEDIR)\.. !endif #------------------------------------------------------------------------------ MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$** DCC = $(ROOT)\bin\dcc32.exe $** BRCC = $(ROOT)\bin\brcc32.exe $** #------------------------------------------------------------------------------ PROJECTS = p_lcd.exe adopac.bpl picinPac.bpl #------------------------------------------------------------------------------ default: $(PROJECTS) #------------------------------------------------------------------------------ p_lcd.exe: ..\p_lcd.dpr $(DCC) adopac.bpl: adopac.dpk $(DCC) picinPac.bpl: picinPac.dpk $(DCC)