Java Application Architecture
Modularity Patterns with examples using OSGi

Back

Modularity Patterns with examples using OSGi

Back

Modularity Patterns with examples using OSGi

Back

Even though we try hard not to, we all make mistakes. Except for Randy. I worked with him for a while. He was never wrong.

Anyway, if you do find mistakes on this website, or in the book, please do let me know.

  • In the Foreword by Peter Kriens, page xxiv, the second sentence of the second paragraph should refer to the end of Chapter 3, not the end of Chapter 4.
  • In Colocate Exception, Figure 12.1 and 12.2, the service.jar should be renamed to service-impl.jar and the and service-impl.jar should be renamed to service.jar. They should be swapped.
  • Modularity Patterns with examples using OSGi

    Back

    Kirk Knoernschild is a software developer who has filled most roles on the software development team. In 2002, Mr. Knoernschild wrote the book "Java Design: Objects, UML, and Process," published by Addison-Wesley and was a contributing author to "No Fluff Just Stuff 2006 Anthology." Kirk is an open source contributor, has written numerous articles, and is a frequent conference speaker. He has trained and mentored thousands of software professionals on topics including Java/J2EE, modeling, software architecture and design, component-based development, service-oriented architecture, and software process. You can visit his website.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 116 in Java Application Architecture.

    Manage Relationships

    Statement

    Design module relationships.

    Description

    A relationship between two modules exists when a class within one module imports at least a single class within another module. In other words:
    If changing the contents of a module, M2, may impact the contents of another module, M1, we can say that M1 has a Physical Dependency on M2. [JOUP02]

    Modularity Patterns with examples using OSGi
    data-theme="b"

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 125 in Java Application Architecture.

    Module Reuse

    Statement

    Emphasize reuse at the module level.

    Description

    One of the oft-cited benefits of object oriented development is reuse. A large part of its failure is because classes aren't the best reuse mechanism.
    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 139 in Java Application Architecture.

    Cohesive Modules

    Statement

    Module behavior should serve a singular purpose.

    Description

    There are two key elements that affect module cohesion. These follow: Based on these statements, it's easy to draw the following conclusion:

    Unfortunately, while logical, these general statements do not always apply.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 146 in Java Application Architecture.

    Acyclic Relationships

    Statement

    Module relationships should be uni-directional.

    Description

    When you define a relationship between two system modules, their coupling is increased. Some degree of coupling is necessary simply because modules need to work together to accomplish some task. But certain types of coupling should be avoided. There are rules that will help you identify bi-directional relationships between modules.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 157 in Java Application Architecture.

    Levelize Modules

    Statement

    Module relationships should be levelized.

    Description

    Levelized modules demand that module relationships be acyclic. Any cycles in module relationships therefore prevents levelization. To levelize modules relationships, there are several steps.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 160 in Java Application Architecture.

    Physical Layers

    Statement

    Module relationships must not violate logical layer relationships.

    Description

    It's common knowledge that when designing systems of any degree of complexity, the presentation, business logic, and data access should be separated into distinct layers. There are several important considerations when separating the layers.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 170 in Java Application Architecture.

    Container Independence

    Statement

    Modules should be independent of the runtime container.

    Description

    Modules with excessive runtime container dependencies are heavyweight modules that cannot execute outside the confines of the runtime container. Lightweight modules with no container dependencies have significant advantages.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 176 in Java Application Architecture.

    Independent Deployment

    Statement

    Modules should be as independently deployable as possible.

    Description

    For a module to be independently deployable, it cannot have any outgoing dependencies on any other module.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 187 in Java Application Architecture.

    Published Interface

    Statement

    Make a modules published interface well-known.

    Description

    A modules's PublishedInterface is the set of public methods on the public classes within the module that you expect developers using the module to invoke and work with. A PublishedInterface is subtly different from a modules public interface, which is simply the complete set of public methods on public classes within the module.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 200 in Java Application Architecture.

    External Configuration

    Statement

    Modules should be externally configurable.

    Description

    The ability to configure a module to it's usage context increases our ability to reuse the module across contexts, whereas tightly coupling configuration to the module prohibits reuse. External configuration allows a module to be reconfigured across environments, and even within it's existing environment, without demanding redeploying the module.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 206 in Java Application Architecture.

    Default Implementation

    Statement

    Provide modules with a default implementation.

    Description

    To maximize reuse, a module must be flexible enough so that it can function in variety of different operating environments. Yet, for a module to be usable, it must be independently deployable. To address this tension, a module can be given a Default Implementation with well-defined extension points so that the module can be extended when necessary.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 212 in Java Application Architecture.

    Module Facade

    Statement

    Create a facade serving as a coarse-grained entry point to the modules underlying implementation.

    Description

    We create fine-grained and lightweight modules to increase module reuse. Unfortunately, fine-grained modules can also be difficult to use because the user must understand the API of several different modules and use them in conjunction with each other to accomplish a particular task. Additionally, lightweight modules must also be configured to an environmental context. Because of this, fine-grained and lightweight modules are generally more difficult to use. A Module Facade is useful to provide a higher level API that coordinates the work of a set of fine-grained modules.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 222 in Java Application Architecture.

    Abstract Modules

    Statement

    Depend upon the abstract elements of a module.

    Description

    Modules heavily depended upon have many incoming dependencies. In other words, you may have many modules that all depend on a single module. On one hand, this is a good thing because you've managed to maximize reuse. But reuse has it's challenges. If the modules you're reusing heavily require a change, the ramifications of that change can ripple throughout all dependent modules. Changing a heavily reused module can be quite a maintenance headache. Abstract Modules helps you deal with this dilemma.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 229 in Java Application Architecture.

    Implementation Factory

    Statement

    Use factories to create a modules implementation classes.

    Description

    One of the challenges we face with Abstract Modules is how the object relationships are established at runtime. A class dependent on an abstraction should avoid referencing any of the implementing classes, otherwise anytime a new implementation class is defined, the class dependent on the abstraction also needs to be changed.
    If a class depending on an abstraction must be changed when creating a new implementation of the abstraction, the design is flawed.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 237 in Java Application Architecture.

    Separate Abstractions

    Statement

    Place abstractions and the classes that implement them in separate modules.

    Description

    You create an abstract class or interface to help reduce coupling between classes. This offers the ability to create new implementations of the abstraction without impacting clients dependent on that abstraction. In this sense, abstract coupling allows you to add new classes to your system without modifying existing classes, and it does so by reducing the dependency relationship between classes.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 246 in Java Application Architecture.

    Colocate Exceptions

    Statement

    Exceptions should be close to the class or interface that throw them.

    Description

    Sadly, dealing with exceptions in enterprise software systems is often an afterthought. But allocation of exceptions to modules has significant implications on the modularity, and more specifically the dependencies between modules, within our software system. Placing the exception close to a class that catches it will often cause a cyclic dependency between the module containing the class that throws the exception and the module containing the class that catches the exception. Exceptions should always be placed in a module closer to the class that throws the exception than a module closer to the class that catches the exception.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 253 in Java Application Architecture.

    Levelize Build

    Statement

    Perform the build in accordance with module levelization.

    Description

    An automated and repeatable build is a critical aspect to most successful development projects. First and foremost, an automated and repeatable build forces you to integrate early and integrate often, so you’re guaranteed to always have a system that works. But there are some rules you should follow to implement a Levelized Build.

    Modularity Patterns with examples using OSGi

    Back

    For the full description, implementation variations, consequences, and detailed sample, see Page 263 in Java Application Architecture.

    Test Module

    Statement

    Each module should have a corresponding test module.

    Description

    Writing tests is one of the most important activities you should perform as a developer. Create a robust suite of tests has significant advantages, both long and short term. Short term, tests help you verify that the code you write does as you intend. Creating tests also helps you design your system. Since classes should be independently testable, a natural by-product of test driven development is that your classes will exhibit lower degrees of coupling. Testing classes independently is valuable, but it's also valuable to test the integration aspect of multiple classes or modules.

    Modularity Patterns with examples using OSGi