0% found this document useful (0 votes)
39 views

rc166 010d ModularityPatterns - 0 PDF

Uploaded by

miromarko
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views

rc166 010d ModularityPatterns - 0 PDF

Uploaded by

miromarko
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

#127

Get More Refcardz! Visit refcardz.com

Getting Started with


CONTENTS INCLUDE:
n
Whats New in JPA 2.0

JPA 2.0
n
JDBC Properties
n
Access Mode
n
Mappings
n
Shared Cache
n
Additional API and more... By Mike Keith
Getting Started with JPA 2.0

DZone, Inc. | www.dzone.com


#166
Get More Refcardz! Visit refcardz.com

CONTENTS INCLUDE:

Patterns of Modular Architecture


❱ Base Patterns
❱ Dependency Patterns
❱ Usability Patterns
❱ Extensibility Patterns
❱ Utility Patterns By Kirk Knoernschild
❱ Hot Tips... and More!

The Two Facets of Modularity


ABOUT THE MODULARITY PATTERNS There are two facets of modularity.

Module frameworks are gaining traction on the Java platform. Though The runtime model focuses on how to manage software systems at
modularity isn’t a new concept, it promises to change the way we runtime. A module system, such as OSGi, is required to take advantage of
develop software applications. You’ll only be able to realize the benefits the runtime model.
of modularity if you understand how to design more modular software
systems. The development model deals with how developers create modular
software. The development model can be broken down into two sub-
The modularity patterns lay the foundation necessary to incorporate categories. The programming model is how you interact with a module
modular design thinking into your development initiatives. No module framework to take advantage of the runtime benefits of modularity. The
framework is necessary to use these patterns, and you already have many design paradigm is the set of patterns you apply to design great modules.
of the tools you need to design modular software. This refcard provides a
quick reference to the 18 modularity patterns discussed in the book Java A module framework gives you runtime support and a programming
Application Architecture: Modularity Patterns with Examples Using OSGi. model for modularity. But a module framework won’t help you design
great software modules. The patterns in this refcard address the design
The modularity patterns are not specific to the Java platform. They can paradigm and help you design modular software.
be applied on any platform by treating the unit of release and deployment
as the module. Each pattern, except for base patterns, includes a diagram Module Defined
description, and implementation guidance. A software module is a deployable, manageable, natively reusable,
composable, stateless unit of software that provides a concise interface
Base Patterns: Fundamental modular design concepts upon which several to consumers. On the Java platform, a module is a JAR file, as depicted in
other patterns exist. the diagram. The patterns in this refcard help you design modular software
and realize the benefits of modularity.
Dependency Patterns: Used to help you manage dependencies between
modules.

Usability Patterns: Used to help you design modules that are easy to use.

Extensibility Patterns: Used to help you design flexible modules that you
can extend with new functionality.

Utility Patterns: Used as tools to aid modular development.

Logical vs. Modular Design


Almost all well-known principles and patterns that aid software design
address logical design. Identifying the methods of a class, relationships
between classes, and the system package structure are all logical design
issues. The vast majority of development teams spend their time dealing
with logical design issues. A flexible logical design eases maintenance and
increases extensibility.
Patterns of Modular Architecture

Logical design is just one piece of the software design and architecture
challenge, however. The other is modular design, which focuses on
the physical entities and the relationships between them. Identifying
the entities containing your logical design constructs and managing
dependencies between the units of deployment are examples of modular
design. Without modular design, you may not realize the benefits you
expect from your logical design. The modularity patterns help you:

• Design software that is extensible, reusable, maintainable, and


adaptable.

• Design modular software today, in anticipation of future platform


support for modularity.

• Break large software systems into a flexible composite of


collaborating modules.

• Understand where to place your architectural focus

• Migrate large-scale monolithic applications to applications with


a modular architecture.

DZone, Inc. | www.dzone.com


2 Patterns of Modular Architecture

BASE PATTERNS DEPENDENCY PATTERNS

The base patterns are the fundamental elements upon which the other The dependency patterns focus on managing the relationships between
patterns exist. They establish the conscientious thought process that modules. They provide guidance on managing coupling that increase the
goes into designing systems with a modular architecture. They focus on likelihood of module reuse.
modules as the unit of reuse, dependency management, and cohesion.
Acyclic Relationships
Module relationships must be acyclic.
Manage Relationships
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:

Hot If changing the contents of a module, M2, may impact the contents
of another module, M1, we can say that M1 has a physical
Tip dependency on M2.

Excessive dependencies will make your modules more difficult to maintain,


reuse, and test.
Description
Implementation Guidance Cyclic relationships complicate the module structure. Apply the following
• Avoid modules with excessive incoming and outgoing rule to identify cyclic relationships.
dependencies.

• Modules with many incoming dependencies should be stable.


If beginning with module A, you can follow the dependency
That is, they should change infrequently Hot relationships between the set of modules that A is directly or
indirectly dependent upon and you find any dependency on module
• Use module dependencies as a system of checks and balances. Tip A within that set, then a cyclic dependency exists between your
For instance, enforce relationships between software layers using
module structure.
modularity (see Physical Layers).
You should avoid cyclic dependencies.
Module Reuse Implementation Guidance
Emphasize reusability at the module level. • Escalation breaks cycles by moving the cause of the cyclic
Description dependency to a managing module at a higher level.
An oft-cited benefit of object-oriented development is reuse. Unfortunately,
objects (or classes) are not an adequate reuse construct. The Reuse • Demotion breaks cycles by moving the cause of the cyclic
Release Equivalence Principle explains why. dependency to a lower-level module.

• Callbacks break a cycle by defining an abstraction that is injected


Hot The unit of reuse is the unit of release. into the dependent module. This implementation resembles the
Observer [GOF] pattern.
Tip
Levelize Modules
Modules are a unit of release and are, therefore, an excellent candidate as
Module relationships should be levelized.
the unit of reuse.

Implementation Guidance
• Separate horizontal modules (those that span business domains)
from vertical modules (those specific to a business domain).

• Module granularity and weight play a significant role in reuse.


Carefully consider each.

• Fine-grained modules with external configuration come with a


higher likelihood of reuse. But beware, these modules may be
more difficult to use.

Cohesive Modules
Module behavior should serve a singular purpose.

Description
Cohesion is a measure of how closely related and focused the various
responsibilities of a module are. Modules that lack cohesion are more
difficult to maintain. Description
Levelization is similar to layering, but is a finer-grained way to manage
Implementation Guidance acyclic relationships between modules. With levelization, a single layer may
• Pay careful attention to how you allocate classes to their contain multiple module levels. To levelize modules, do the following:
respective modules.
Assign external modules level 0. Modules dependent only on level 0
• Classes changing at the same rate and typically reused together modules are assigned level 1. Modules dependent on level 1 are assigned
belong in the same module. level 2. Modules dependent on level n are assigned level n + 1.
• Classes changing at different rates and typically not reused
together belong in separate modules.

DZone, Inc. | www.dzone.com


3 Patterns of Modular Architecture

Implementation Guidance Independent Deployment


• Levels are more granular than the layers in your system. Use Modules should be independently deployable units.
levels to manage relationships within layers.

• Levelization demands module relationships be acyclic. You


cannot levelize a module structure with cycles.

• A strict levelization scheme, where modules are dependent


only on the level directly beneath it, is conceptually ideal but
pragmatically difficult.

Physical Layers
Module relationships should not violate the conceptual layers.

Description
The less outgoing dependencies a module has, the easier the module
is to reuse. A module with no outgoing dependencies is independently
deployable and can be reused without the worry of identifying which
additional modules might be necessary. Lower-level modules inherently
have fewer outgoing dependencies and increase the opportunity for reuse.

Implementation Guidance
• Not all modules can be independently deployable. Some module
dependencies are always necessary.
Description
Layering a system helps ease maintenance and testability of the • In addition to reducing outgoing dependencies, container
application. Common layers include presentation (i.e., user interface), dependencies must also be minimized for those modules that are
domain (i.e., business), and data access. Any conceptually layered software independently deployable.
system can be broken down into modules that correspond to these
conceptual layers. Physical layers helps increase reusability because each • Highly cohesive modules are easier to make independently
layer is a deployable unit. deployable units.

Implementation Guidance
• Begin by creating a single coarse-grained module for each layer. USABILITY PATTERNS

• Enforce the layers using Levelize Build. We want modules that other developers find easy to interact with. The
usability patterns help design modules that are easy to understand and
• Break out each layer into more cohesive modules and use use.
Levelize Modules to understand and manage the relationships
within the layer. Published Interface
Make a module’s published interface well known.
• It’s fine if modules within a layer have relationships between
them. These modules will be at different levels.

Container Independence
Modules should be independent of the runtime container.

Description
Description
Heavyweight modules are dependent upon a specific runtime environment
Modules should encapsulate implementation details so that other modules
and are difficult to reuse across contexts. Environmental dependencies also
don’t need to understand the implementation to use the module. A
negatively affect your ability to test modules. Modules independent of the
module’s published interface exposes the capabilities you want to make
runtime container are more likely reused, and are more easily maintained
available to other developers.
and testable.

Implementation Guidance A published interface consists of the public methods within the
• Avoid importing container-dependent packages in your module’s
code. Hot public classes within the “exported” packages that other modules
are able to invoke.

• Use External Configuration to configure a module so that it can


Tip
operate in different runtime environments.
In standard Java, there is no way to explicitly state which packages a
• Use dependency injection to abstract container dependencies. module exports, so it’s difficult to enforce a published interface. Module
frameworks, such as OSGi, shine in this situation.

DZone, Inc. | www.dzone.com


4 Patterns of Modular Architecture

Implementation Guidance Module Façade


• In standard Java, document the published interface you expect Create a façade serving as a coarse-grained entry point to another fine-
other clients to invoke. grained module’s underlying implementation.

• In standard Java, expose the published interface via abstractions


and discourage other developers from using the concrete
classes.

• Module frameworks, such as OSGi, allow you to export packages


and allow you to more easily enforce a published interface.

External Configuration
Modules should be externally configurable.

Description
Module initialization typically requires configuring the module to its Description
environmental context. Externalizing the configuration decreases context Fine-grained and lightweight modules are inherently more reusable.
dependencies and allows you to use the module across a wider array of But fine-grained modules are also typically dependent on several other
environments. External configuration increases a module’s reuse, but modules. A Module Façade defines a higher level API that coordinates the
makes it more difficult to use because developers must understand how to work of a set of fine-grained modules. The façade emphasizes ease of use
configure the module. while the finer-grained modules emphasize reuse.

Implementation Guidance Implementation Guidance


• Use External Configuration to eliminate a module’s environmental • Don’t emphasize reuse of the façade. Use it to wire together and
dependencies. configure multiple fine-grained modules.

• Include a configuration file within the module that defines a • Place context and environmental dependencies in the façade.
default configuration, making the module easier to use.
• Use the façade as an entry point for your integration tests.
• Remain cognizant of the tradeoff between increased reuse
and decreased usability. In other words, maximizing reuse
EXTENSIBILITY PATTERNS
complicates use.

Default Implementation We want software that is easy to extend without modifying the existing
Provide modules with a default implementation. codebase. We also want to deploy this new functionality without affecting
other areas of the system. The extensibility patterns help us achieve this
goal.

Abstract Modules
Depend upon the abstract elements of a module.

Description
Depending on the abstract elements of a module gives you greater
opportunities to extend the system by defining new modules with classes
Description
that implement or extend the abstraction. Any clients of the module also
To maximize reuse, a module must be flexible enough so that it can
have the ability to define their own implementations and to plug them into
function in a variety of different operating environments. Yet, making a
the module.
module easier to use leads us to incorporate more functionality into a
module so developers are required to do less when using the module. A
Implementation Guidance
default implementation with well-defined extension points helps address
• Use an Implementation Factory to create a module’s underlying
this tension.
implementation.
Implementation Guidance
• When defining a Default Implementation, depend upon the • Use Abstract Modules when you have many incoming module
abstract elements of a module (see Abstract Modules or Separate dependencies and you want the flexibility to swap out underlying
Abstractions). implementations.

• Include a default configuration in the module, but make the • Strive to make the abstraction within a module as stable as
module externally configurable, as well. possible. That is, avoid changes since it will have many many
other modules that are dependent upon it.
• Always create a Test Module to test the default implementation.

DZone, Inc. | www.dzone.com


5 Patterns of Modular Architecture

Implementation Factory
Use factories to create a module’s implementation classes. Hot Keep the abstraction closer to the classes that depend upon it and
further from the classes that extend or implement it.
Tip
Implementation Guidance

• If all classes that depend upon an abstraction live in a single


module, then place the classes and the abstraction in the same
module.

• If the classes dependent upon an abstraction live in separate


modules, place the abstraction in a module separate from the
classes that depend upon it.

• Separating abstractions lends the ultimate flexibility to extend


your system, but also increases its complexity.

UTILITY PATTERNS
Description
Any module whose classes depend upon the abstract elements of another The utility patterns are additional tools and techniques that aid modular
module should avoid referencing any implementation classes. Doing so development. They help you enforce your modular design and ensure
will compromise your module design. Consider the following rule. quality.

If a class depending on an abstraction must be changed in order to Colocate Exceptions


Exceptions should be close to the class or interface that throws them.
Hot instantiate a new implementation of the abstraction, the design is
flawed.
Tip
Furthermore, if a module must be changed to accommodate the
instantiation, the module design is compromised.

Implementation Guidance

• The factory must be separated from the module containing the


class instances it creates as well as the module dependent upon
the abstractions.

• Externalize the creation of a module’s implementation to a


configuration file.

• Consider using a dependency injection framework like Spring, Description


OSGi Blueprint, or OSGi Declarative Services. These will serve as Allocation of exceptions to modules has implications on module
your factory to wire together the appropriate implementations at dependencies. Putting exceptions close to the classes that catch them
runtime. creates a dependency from the module that throws the exception to
the module containing the exception. Because invoking a method can
Separate Abstractions introduce a module dependency, exceptions should be in the same module
Place abstractions and the classes that implement them in separate as the class containing the method that throws the exception.
modules.
Implementation Guidance
• Throw the exception on the interface or abstract class you’re
bound to and place the exception in the same module as the
interface or abstract class.

• If abstractions across several modules throw the same exception,


demote the exception to a completely separate module at a lower
level.

Levelize Build
Execute the build in accordance with module levelization.

Description
Separating abstractions from their implementation offers the greatest
flexibility to provide new implementations that completely replace existing
implementations. With Separate Abstractions, you can define new behavior
and plug it into your system without affecting existing system modules.
Separate Abstractions can be used to develop a plug-in architecture. As a
general guideline, apply the following rule.

DZone, Inc. | www.dzone.com


6 Patterns of Modular Architecture

Description Description
Enforcing module relationships is difficult. Though conceptually you may Test modules contain all of the tests for the classes in a specific module.
believe you have an acyclic module structure and fully comprehend the They allow you to test a module’s underlying implementation. A Test
module relationships, a single build target with everything on the classpath Module may contain unit tests that test a module’s classes, as well as
allows undesirable cycles and dependencies to creep in. A levelized build integration tests that test the entire module’s functionality.
helps you enforce your module dependencies. Any dependencies that
violate your defined module structure will result in a build failure. Implementation Guidance
• Depending on Abstract Modules makes it easier to define mocks
Implementation Guidance
and stubs for testing a module independently.
• Avoid a full classpath build, where all classes are built using a
single compile target.
• For larger test suites, or situations where performance is
paramount, separate different types of tests (i.e., unit tests,
• Define separate build targets for modules in different levels. Level
integration tests, performance tests, etc.) out into separate test
1 modules can be built with only external level 0 modules. At
modules.
higher levels, include only the modules from lower levels that are
required for a successful build.
• Ideally, you’ll only include the test module and the module under
test in the classpath when executing the tests. Pragmatically,
• Defining new module dependencies will require modifying the
some modules may require other dependent modules.
build for that module. This is not necessarily undesirable.

Test Module
Each module should have a corresponding test module.

ABOUT THE AUTHOR RECOMMENDED BOOK


Kirk is a software developer with a passion for building This isn’t the first book on Java application
great software. He takes a keen interest in design, architecture. No doubt it won’t be the last. But rest
architecture, application development platforms, agile assured, this title is different. The way we develop
development, and the IT industry in general, especially Java applications is about to change, and this title
as it relates to software development. His recent book, explores the new way of Java application architecture.
“Java Application Architecture: Modularity Patterns
with Examples Using OSGi” was published in 2012 and
presents 18 patterns that help you design modular BUY HERE
software systems.

Browse our collection of over 150 Free Cheat Sheets


Upcoming Refcardz
HTTP

Free PDF MongoDB


Cypher
Apache HTTPD

DZone, Inc.
150 Preston Executive Dr.
Suite 201
Cary, NC 27513
DZone communities deliver over 6 million pages each month to 888.678.0399
more than 3.3 million software developers, architects and decision 919.678.0300
makers. DZone offers something for everyone, including news,
Refcardz Feedback Welcome
$7.95

tutorials, cheat sheets, blogs, feature articles, source code and more.
“"DZone is a developer's dream",” says PC Magazine. [email protected]

Copyright © 2012 DZone, Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval Sponsorship Opportunities
system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior
[email protected]
Version 1.0
written permission of the publisher.

You might also like