An Introduction to Managing Projects
With Developer/2000

An Oracle White Paper
October 1996


For developers working in large, complex projects, managing the files that comprise those projects is inevitably a difficult and time consuming task. Managing files contributes nothing to productivity, yet it is a necessary part of the development process. This is no less true of projects built using Developer/2000 than it is of other environments.

A typical Developer/2000 project might consist of tens or hundreds of files, and the largest projects might consist of thousands. These files will be of many different types, for example:
· Forms documents and their corresponding executables
· Reports documents
· Graphics documents
· PL/SQL libraries
· Icons and bitmaps
· DLLs built from C source files
· Text documents such as test scripts and specifications
· Test data
· SQL scripts
…and many more. The developer faced with these files must constantly ask herself questions such as:
· What files make up this project?
· How do files depend on each other?
· Which files have been modified and need to be recompiled?
· Which files are to be delivered to the deployment environment?
· What type of file is this, and how do I print, edit or compile it?
Many developer hours are wasted trying to resolve such issues of configuration and management. Project Builder brings these tasks under control as an integral part of the Developer/2000 product.
Introducing Project Builder

Project Builder, introduced with Developer/2000 Release 2.0, aims to simplify the task of answering these questions. It does so by providing the developer with a lightweight, flexible, yet powerful tool that provides:

· A graphical presentation of a project in a familiar "navigator" or "explorer" style that can be viewed by file type or by dependency. The developer can easily add, remove, locate and edit the files that make up her project.

· A visual representation of the relationships between the files that make up a project. The developer can immediately see the dependencies between, for example, PL/SQL libraries and a form document that calls them, and use those dependencies to ensure that executables are always up to date.


· A totally customizable environment that can be tightly integrated with other development tools such as version control, CASE, or project scheduling. The developer can add new file types, defining actions such as "edit" or "compile" for those file types, and customize existing ones, by adding new actions and modifying existing ones.

Figure 1. The Project Builder navigator in Dependency view

Through its extensive customizability, Project Builder provides a point of integration for all the development lifecycle tasks from design to delivery. Furthermore, because Project Builder tracks dependencies between files, a single menu command is sufficient to ask Project Builder to "rebuild" or "make" a project, recompiling only those files that have changed (or whose dependencies have changed), and automatically applying the correct compilers to build each different type of file.

Project Builder Terminology
To understand Project Builder, we first need to understand some terminology. Project Builder’s navigator tree contains types, connections, projects and entries (see figure 1). Types have properties, actions and macros.

Types
A type is the basis of every entry, and controls the actions that are available in Project Builder. A type determines what actions (see below) can be performed against a file, such as edit or compile. Many types are predefined for common kinds of files such as Forms documents (FMB), text files and C source files.

Connections
In a typical project the developer has a number of databases that he works against. For example, there might be a small "scratch" database where the developer can create any test data he needs; a large test database that contains the data for a formal test suite; and perhaps databases running different versions of Oracle to test backward compatibility or new features.

Project Builder allows the developer to define and save the connect strings associated with these various databases, and then easily associate those connections with the project’s files, simply by dragging a connection and dropping it on the entry for the file. For example, referring again to figure 1, simply pick up the connection called Personal Oracle7 and drag it to the form Storproc.fmb; now when the Form document is next opened from Project Builder, Form Builder will automatically connect to the database before opening the form.

Projects
A collection of component files that a developer is working on is organized into one or more projects. A project can be subdivided into subprojects if that is more convenient for the developer. In figure 1, the project "Benefits and Features" has been divided into "Forms" and "Media". Often, the organization into subprojects will mirror the organization of the files into subdirectories, but this is not a requirement (although it is often more convenient for the developer).

Entries
The components that make up a project are known as entries. An entry is simply a description of a file that is part of a project. The definition of an entry can be seen in a property palette (figure 2). The definition includes general information about the file, such as its type, its location in the file system, its size, and when it was last modified. The actions and macros (see below) available for the entry can also be seen.

It is important to remember that an entry is not the file itself; rather it is a description of the file. So when you delete an entry from a project, you are simply telling Project Builder that the file is not part of that project any longer. The file itself, referenced by that entry, of course is not deleted.

Actions
An action is a command string that applies to entries, such as print, edit or compile. The same action can be defined for many different file types, potentially with a different definition for each. For example, most types have an "Edit" action defined. For a text file type this might be defined to open the file in Notepad or Write; for a Form document it would open it in Form Builder. Actions can act on individual entries one at a time (for example, print) or on several entries together (for example, to create a Zip or tar archive).

In figure 2, the actions defined for a bitmap are shown. All of these actions are inherited from the type (as shown by the arrow icon).

Actions are normally defined as part of a type definition, but the developer can also add actions to a project or subproject; these actions are then inherited by every entry in the project. Actions can even be added directly to a specific entry, in which case they apply only to that entry. Inherited actions can also be overridden at each level of the hierarchy, as we will see later.
Some actions, notably Build and Deliver, have a special meaning for Project Builder and we will return to them later.

Macro
A macro is a kind of variable defined within Project Builder that can be used to customize and extend actions. Just as you might use environment variables in scripts or batch files to allow you to conveniently modify a script’s actions without editing the script itself, so you can use macros to customize actions without having to edit the actions themselves. For example, you might define a macro to determine whether to compile your application in Debug mode or Optimized mode. To switch off debug in preparation for building the deployment version of the application, you would simply change one macro definition, rather than having to find and modify every type whose Build command made use of the Debug flag.

There are several pre-defined macros in Project Builder, such as the name and location of the file, and you can add new macros as you need them. Just as for actions, macros can be defined for types, projects and individual entries, and are inherited in the same way.

Figure 2. The Property Palette

The Project Builder User Interface
Project Builder has three main components to its user interface: the project navigator, the property palette and the launcher toolbar. The first two of these will be immediately familiar to any user who is familiar with the other components of Developer/2000.

The Project Navigator
The Project Navigator was briefly introduced earlier. This is the main window for managing and organizing the entries in a project. You also launch actions against entries from here: simply select the entry, click the right mouse button, and the actions available are shown in the popup menu (figure 3).

Figure 3. Example actions available on the popup menu

The navigator can be displayed in one of two views, Project view and Dependency view.

Project View
In this view, the entries in a project are organized by project and subproject, then by type. This is useful to see all of the entries of a particular type, for example all of the PL/SQL libraries, used in a project.

Dependency View
In this view, the entries in a project are organized by dependencies between files; for example, an object file depends on a source file and a number of header files. We will describe below how those dependencies are determined, and how Project Builder exploits them.

The Property Palette
In figure 2, an example of a property palette is shown. The property palette is common to all of the Developer/2000 tools. Project Builder has property palettes for connections, types, entries and projects. In the property palette the user can view and modify the properties, actions and macros. The user can also add new actions and macros to types, entries and projects.

Inheritance in Project Builder
The property palette shows not only the properties, actions and macros, but also whether they are inherited or overridden. An entry inherits properties, actions and macros both from its type and from its project.
· An entry inherits from its type the properties, actions and macros associated with that type.
These include properties such as whether the file is text or binary and the actions to edit or compile an entry of that type.
· An entry also inherits properties, actions and macros from the project.

Properties inherited from the project include the Author of an entry. If actions or macros are added to the project, they are inherited by all entries in the project.

Some properties, actions and macros can be inherited from both the project and the type. In this case, setting the value at the project level overrides the type.

There are also two "generic" types: <Any File>, whose properties, actions and macros are inherited by every type and so by every entry, and Text File, whose properties, actions and macros are inherited by every type whose File Contents property is set to Text rather than Binary.

These two generic types allow a property such as Version Control File or an action such as the editor for all textual files to be easily set across many types without having to define it individually for each type.

The Launcher
The toolbar that appears at the top of the Project Builder navigator is known as the launcher. It can be customized to provide immediate access to the tools and editors that you use most often. This toolbar can include "group" items that cascade to provide access to more tools, much like the Start menu in Windows95.

Building and Delivering Projects in Project Builder
The aim of Project Builder is not merely to provide a graphical tool that allows the developer to locate, organize, and edit the files that make up a project. The greatest benefits of using Project Builder will be realized when you use its ability to build and deliver projects.

Dependencies and Building Projects
Tracking dependencies is one of the most complex and time consuming tasks in any development environment. Determining which files depend on which others is crucial to determining when files need to be recompiled as the result of a change. It is also the key to managing the impact of changes; for example, if a library changes, which forms might be affected?

Figure 4. Dependency view and implied items
Standalone tools for building (or ‘making’) projects are available, but they are often difficult to use or integrate with other development tools. The scripts required by textual tools such as make are complex and difficult to interpret, and even graphical tools must be kept in synchronization with the other tools in the project environment. For example, whenever you add a file to the project you must also remember to add it to the make script.

Project Builder provides two major advantages over such tools:
· Dependencies can be seen directly and managed easily in the navigator; no scripting or expertise is required
· Dependency information is an integral part of the project environment; there is no need to maintain separate project information and dependency information

With this visual, integrated management of dependencies, Project Builder makes it easy to assess the impact of changes and to rebuild affected modules. Project Builder greatly simplifies the tasks of ensuring that you are always working with up to date executables, avoiding misconfiguration problems, and delivering the right set of files to the end user.

Implicit Dependencies
Project Builder automatically deduces many dependencies from the Deliverable Type property and the Build action of an entry’s type. In figure 4, the developer has added a Form document (FMB) called Storproc.Fmb to the project. FMB files have a Deliverable Type of ‘Forms executable (FMX)’, so Project Builder automatically adds Storproc.Fmx to the project and shows that the FMX file is dependent on the FMB: if the FMB changes, it will be necessary to recreate the FMX using the Build action defined for the FMX. Notice that the implicit entry, Storproc.Fmx, is distinguished in the navigator by a lighter typeface.

The second file that the developer added was a Forms text file (FMT) called Dsktest.Fmt. The Deliverable Type for an FMT file is also Forms executable (FMX): the Deliverable Type tells Project Builder the type of file that, ultimately, is built for delivery to the end user. In this case Project Builder adds the FMX and automatically discovers the two steps necessary to reach an FMX from an FMT by examining the Build action defined for each type: the Build action for an FMX is to compile the corresponding FMB, and the Build action for an FMB is to convert from an FMT. Project Builder therefore adds two implicit entries, Dsktest.Fmb and Dsktest.Fmx. Project Builder can follow a chain of Build commands for as many steps as necessary to connect an entry to its final deliverable. (If more than one possible chain exists, it will find the shortest).

Manual Dependencies
Sometimes, you will have dependencies that cannot be determined automatically by Project Builder. For instance, your form may contain calls to program units in a PL/SQL library. If the interfaces to the program units in the library change, it will be necessary to rebuild the FMX.

To allow the developer to include such dependencies in the project definition, dependencies can be added manually. In figure 4, to indicate that Storproc.Fmx depends on a PL/SQL library called Navigate.Pll, as shown in figure 4, the developer selects the entry Storproc.Fmx then clicks Add Files from the menu or toolbar. The files chosen in the Add Files dialog that appears are then added as dependencies of the selected entry.

Notice that the dependency is added to the FMX, not to the FMB, as you might at first sight expect. Although the FMB contains the calls to the PL/SQL, and therefore the FMB will need to be recompiled, it is important to remember that dependencies tell Project Builder what target needs to be built, rather than what source needs to be recompiled. From one point of view, the FMB compiles to the FMX, but in Project Builder terms we say that the FMX is built from the FMB, the library, and any other dependencies we might add. Expressed in this way, it is much clearer that when any of the dependencies change, the FMX must be rebuilt.

Building Projects
One of the most tedious tasks in managing a project is ensuring that the ‘build’ is up to date: that everything that needs to be rebuilt, has indeed been rebuilt. It is rarely an acceptable solution to constantly rebuild everything.

With Project Builder, this process is greatly simplified. When you click the Compile Incremental command from Project Builder’s menu or the corresponding toolbar button, Project Builder determines from the dependency information which entries need to be built and the correct order to build them. Project Builder will examine the file timestamps of each entry and its dependencies to determine which files have been modified, and only rebuild those entries which are out of date. Project Builder determines the correct Build command to apply to each entry from the Build action defined for that entry.

You can also click Compile All if for any reason you want to force a rebuild of all the files in a project, or Compile Selection to rebuild particular entries.

Deploying Projects
Once a project is completed the remaining task is to deliver the executable files, help files, supporting media (such as sounds, images, videos or icons) and any other files that the end user will need to have installed. Typically, the delivery process involves creating an archive or "stage" of the required files. To simplify this task, Project Builder includes a property Deliver file which allows you to indicate which entries represent files to be delivered, or deployed, to the end user.

Usually the Deliver file property fill be inherited from the type, but for some files this may not be appropriate. In this case you can simply override the setting on individual entries, as with any other property. Alternatively, you might choose to organize all the deliverables into a separate subproject, then set Deliver file to Yes on that subproject, which will then be inherited by all the files in the subproject.

To deliver the project, simply click File->Adminstration->Deliver on the menu. Project Builder will apply the appropriate Package for delivery action to each file. These actions will usually be defined to accept "multiple files"; for example, if many entries have PkZip defined as the action, you normally don’t want to run PkZip once for each file. Instead, Project Builder runs PkZip once, passing all of the files to it at one go.

Team Development with Project Builder
In many cases you will want to use Project Builder in a team environment, so that many developers can be working together on the many files that make up a project. If one developer modifies a library that another depends on, you will want Project Builder’s dependency management to track that dependency, just as it would for a single user. In order to successfully use Project Builder in a team environment, it is necessary to understand a little of how Project Builder stores and shares information.

Project Builder makes use of three kinds of files, called registries, to store information: the Global Registry, the User Registry, and Project Registries. (In fact, Project Registries are simply what we have been calling Projects up to this point.) The contents of all three of these are visible in the navigator. To ensure that these registries remain consistent between developers, normally one member of the team will take on the role of Project Administrator.

The Global Registry
Commonly, the Global Registry will be shared by all developers. It contains the type definitions that are shared across the network. To make it accessible to everybody, the project administrator may place it on a shared network drive. Because this registry is shared by the whole team, to avoid conflicting changes only the Project Administrator should make changes to it. The recommended way to ensure this is to use the network file system’s file permissions and access control to ensure that, although the whole team can read this file, only the project administrator can modify it.

(You might ask why Project Builder itself does not provide some mechanism of its own to protect the Global registry from conflicting updates. The answer is simply that if the file is not protected at the level of the network file system, then any "internal" scheme, however clever it might be, can be subverted by any developer who creates and copies another registry file over the top of the Global Registry. So the registry file should always be protected at the file system level anyway, and once the file is protected in the file system, an internal mechanism would be redundant. Furthermore, by relying on the network file system for protection, we also allow you to use whatever network file system you choose; we do not impose a scheme that might not be supported by particular network file systems.)

Locking the Global Registry
Whenever the Project Administrator is making changes to the Global Registry, the registry file is briefly locked, to ensure that other users do not inadvertently read inconsistent information. Normally these locks are released so quickly that other users will be completely unaware of their existence.

Occasionally, however, perhaps due to a very busy network, the Global Registry will be locked just at the instant when another user needs to read it (for example, at startup). Project Builder will automatically retry reading the Global Registry, but if it still cannot succeed, the user will then see a dialog explaining that the Global Registry is unavailable. Clicking the Retry button will usually be sufficient to continue - unless the Project Administrator or the network is extremely busy!

Project Builder will repeatedly offer the option to Retry until the file becomes available. Very occasionally, perhaps due to a network server being down, Project Builder will not be able to read the Global Registry even after several clicks on the Retry button. In such a case the user is best advised to click the Exit button and try again later when the Global Registry is available. Because the Global Registry contains the basic information about types, Project Builder cannot work without it.

The User Registry
As its name suggests, the User Registry is private to each individual user, and it will normally be placed either on a local drive on each user’s PC, or on a private directory on a network drive. (Under Unix it is placed under the user’s home directory).

Because each user has their own User Registry, they can edit it freely, for example to add private types or to override the definitions of types in the Global Registry.

If the User Registry is placed on a network drive, there is, as with the Global Registry, the risk that the file may be unavailable due to network problems. As with the Global Registry, you will not be able to run Project Builder if the User Registry is unavailable due to a network failure.

Project Registries
Projects are each stored in their own Project Registry file. Projects may be private to an individual developer, or shared among several.

If a project is shared, the Project Administrator may decide to provide each developer with a private copy of the Project registry, or they may share a single copy via a shared network drive. The best choice depends on whether all or only one developer is allowed to modify the project.

(Note that we are talking here about modifying the project itself; that is, adding and removing entries, or changing properties, actions or macros of an entry. All users may modify the files that the entries point to, just as if they were accessing the files directly through the file system rather than through Project Builder).

If only one developer is allowed to modify a particular project, the simplest approach is to place the Project Registry on a file server, and protect the file against update in the same way as for the Global Registry.

If more than one user is allowed to modify a project, the recommended way to share these changes is for the project administrator to provide each user with a private copy of the project. The users’ individual changes can then be shared using Project Builder’s export and import commands.

In some cases the project administrator may decide to share a Project Registry and allow more than one user to update it. Although this is permitted by Project Builder, it can be a risky strategy if many developers attempt to update the same project: sometimes a developer will not be able to save changes to the project. If a developer attempts to change a project, adding an entry for example, Project Builder will first check whether the project has changed since it was last read; if it has changed, Project Builder will notify the developer that his changes cannot be saved, and will reread the latest version of the project. The developer can then attempt to make his changes again. Project Builder will never overwrite one developer’s changes with another’s, avoiding "last write wins" problems. If your change is accepted by Project Builder, you can be confident that nobody will overwrite it without seeing your change. (This is directly analogous to what happens when two users of a database application attempt to update the same record in a RDBMS: the first to update commits successfully, the second must query an up-to-date version of the record before he can make changes).

As with the Global and User Registries, there will be occasions when Project Builder cannot open a particular project. Unlike the case of those two registries, however, this is not a severe problem. Project Builder will simply notify the developer and continue. The developer can work in any other open project, and attempt to reopen the project at some later time.

Summary
Project Builder is a significant addition to the Developer/2000 product’s capabilities. It provides an easy-to-use, graphical environment for the management of projects that simplifies development and delivery of both simple and complex projects. It is equally suitable for the individual developer as for the team. The extensive customizability makes it simple to integrate Project Builder with all the other tools that comprise the development environment.