The Benefits of Modular Programming: Chapter Two
The Benefits of Modular Programming: Chapter Two
The Benefits of Modular Programming: Chapter Two
2.1
Distributed Development
11
12
Chapter 2
2.2
2.2
Modular Applications
13
Modular Applications
2.2.1
Versioning
14
Chapter 2
JDK version. A module could require JDK >= 1.5, xmlparser >= 3.0, and
webbrowser >= 1.5. At runtime, the code responsible for starting the application must ensure that the requested dependencies are satisedthat the
XML parser is available in a version 3.0 or newer, the Web browser is in version
1.5 or higher, and so forth. The NetBeans Module System does that.
Using such dependency schemas to maintain dependencies between
components in a modular system can work only if certain rules are obeyed.
The rst rule is backward compatibilitythat if a new version is released, all
contracts that worked in the previous version will work with the new one as
well. This is easier to say than to achieve. Rule number two is that components
of the system need to accurately say what they need. When a modules set of
dependencies changes, it needs to say so, so that the system can accurately
determine if they are satised. So if a piece of a modular system starts to rely
on new functionality, such as an HTML editor, it needs to add a new dependency (e.g., htmleditor >= 1.0). And if you start to use a new interface to
the HTML editor componentone which was only added in version 1.7 of
the componentthe dependency needs to be updated to require htmleditor
>= 1.7. The NetBeans Module System makes this second part relatively simple
in practice, since a modules compile-time classpath will only include modules
it declares a dependency on. So unless the modules list of dependencies is
updated, it will not compile.
2.2.2
2.3
2.2.3
15
Dependency Management
The system of versions and dependencies needs a manager that makes sure all
requirements of every piece in the system are satised. Such a manager can
check at each pieces install time that everything in the system remains consistentthis is how RPMs or Debian packages work in Linux distributions.
Metadata about such dependencies is also useful at runtime. Such metadata
makes it possible for an application to dynamically update its libraries without
shutting down. It can also determine if the dependencies of a module it is
asked to dynamically load can be satisedand if not, it can describe the
problem to the user.
NetBeans IDE is a modular application. Its modulesits constituent librariesare discovered and loaded at runtime. They can install various bits
of functionality, such as components, menu items, or services; or they can run
code during startup to initialize programmatically; or they can take advantage
of declarative registration mechanisms that various parts of the platform and
IDE offer to register services and initialize them on demand. The NetBeans
Module System uses the declared dependencies of the installed components
to set up the parent classloaders for each modules own classloader, determining what JARs will be searched when a module tries to load a class. This ensures
that any one modules classpath excludes any module JARs which are not
above it in its dependency tree and enforces the declared dependencies of each
componenta module cannot call code in a foreign module unless it declares
a dependency on that foreign module, so it will not be loaded at all if some of
its dependencies cannot be satised.
2.3
No one is surprised anymore that operating systems and distributions are designed in a modular way. The nal product is assembled from independently
developed components. Modularity is a mechanism to coordinate the work
of many people around the world, manage interdependencies between their
parts of the project, and assemble very complex systems in a reasonably
reliable way.
16
Chapter 2
The value of this approach is nally ltering down to the level of individual applications. Applications are getting more and more complicated, and
they are increasingly assembled from pieces developed independently. But
they still need to be reliable. Modular coding enables you to achieve and
manage that complexity. Since applications are growing in size and functionality, it is necessary to separate them into individual pieces (whether you call
them components, modules, or plugins). Each such separated piece
then becomes one element of the modular architecture. Each piece should be
isolated and should export and import well-dened interfaces.
Splitting an application into modules has benets for software quality. It
is not surprising that a monolithic piece of code, where every line in any source
le can access any other source le, may become increasingly interconnected,
unreadable, and ultimately unreliable. If you have worked in software for a
few years, you have probably been on a project where there was some piece
of code which everyone on the team was afraid to touchwhere xing one
bug always seemed to create two new bugs. That is the entropy of software
development. There is economic pressure to x problems in the most expedient way possiblebut the most expedient way is not necessarily in the longterm interest of the codebase. Modular software limits the risk of creeping
coupledness by requiring that different components of the system interoperate
through well-dened API contracts. Its not a silver bullet, but it makes it
considerably harder to have the sort of decay that eventually dooms many
complex pieces of software.
Comparing modular design and traditional object-oriented design is a lot
like the comparisons of structure programming with spaghetti code from the
1960s. Spaghetti code was the name given to Fortran or BASIC programs where
every line of code could use a GOTO statement to transfer execution to another
place in the program. Such code tended to be written in such a chaotic way
that often only the author of a program could understand the programs logic.
Structured programming tried to reduce this disorder by introducing
blocks of code: for loops, while loops, if statements, procedures, and calls
to procedures. Indeed, this improved the situation and the readability and
2.3
17
1. Except for boundary conditions where it may never return, throw an exception, etc.
18
Chapter 2
The initial step in designing a complex application is to design its architecture. For this, it is necessary to dene and understand the dependencies between parts of the application. It is much easier to do this in case of modular
applications.
Thus it is always wise to start designing any application in a modular way.
Doing so creates an infrastructure that will let you build more robust applications and avoid a great deal of manual bookkeeping. Rewriting messy, interconnected traditional object-oriented applications to give them a good
modular design is a hard task. And it is not often that a project can afford the
time it takes to be rewritten or rearchitected. Often, programmers have to live
with old, monolithic code with ever-increasing maintenance costsbecause
the code is known to work.
Modular design starts you out in an environment where the architecture
cannot slowly decay into unmaintainability without anyone noticing. If you
create a new dependency between two parts of a modular application, you
need to do some explicit gestures to set up that dependency. It cannot happen
by accident. While that is not a cure for messy designs, it is an environment
that encourages well-thought-out ones.
Modularity gives systems clearer design and control of module interdependencies; it also gives developers more exibility in maintenance. Consider that
when starting any new projectregardless of the projects initial scope.
Modular design will have large benets for the architecture of the entire application as it grows from its infancy. The real benets of modular programming
might not be apparent in the rst version of an application. But they will become obvious later with the reduced cost of creating the 2.0 and 3.0 versions.
Since modular programming does not add signicant cost to creating the 1.0
version of an application, there is little reason not to use this approach on all
projects. Many programmers are surprised (even sometimes horried) to nd
something they wrote fteen years ago still in use. Since we cannot predict the
future of our code, we might as well architect it to last from the start.
2.4
2.4
19
20
Chapter 2
Modules/Module Suite in the New Project wizard. Then follow the steps in
the wizard. After clicking OK, a new project be visible in the Projects window.
In contrast to the regular project, a suite does not have its own sources. It is
merely a project to bind together other, interdependent NetBeans module
projects. So, choose Suite/Modules, invoke a popup menu on that node, and,
using the Add Existing menu item, add the previously created module into
the suite.
A suite can contain more than one module. To demonstrate that, we can
convert an existing library into a module in the suite. Choose New Project
2.4
21
22
Chapter 2