Independent Deployment
by kirk knoernschild
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. Some module are naturally more independent than others. For instance, it would be relatively easy to create an indepdent module to perform various mathematical and statistical functions, mainly because there are few external forces that impact how the module needs to behave. However, you cannot always expect to eliminate all outgoing dependencies. In most interesting systems, cohesive objects collaborate and work together to provide the complex behavior exhibited by business applications, and there are many more forces that can affect how an object behaves. While we strive to reduce coupling as much as possible, there must be some coupling that exists in order for a network of objects to work together. Without some coupling, your system would not be very interesting.
Given that some degree of coupling is necessary, it’s also very likely that collaborating objects are spread throughout and across many different modules. To obtain high degrees of maintainability, and a glimmer of hope for reusability, it’s important to minimize the coupling between modules. Since the purpose of the Dependency patterns is to help manage dependencies between modules, we’ll sepnd our time here exploring where and why independently deployable modules are important. Techniques discussed later will help show you how.
As with any principle, pattern, guideline, or heuristic, you might use it judiciously. While they usually offer a flexible solution, that solution typically comes with the pricetag of complexity. Using a complex solution when a more simple one will suffice is a classic example of overarchitecting, which can contribute to your maintenance and reuse problems as much as neglecting to apply a flexible, though more complex, solution when one is warranted.
So how might you know when a module needs to be independently deployable? I suppose the driving force behind the need to make a module independently deployable is how frequently that module is reused. Modules not intended for reuse don’t need their dependencies managed as carefully. This isn’t to say that dependency management is less important for these modules, because managing dependencies is always important. However, if you’re not planning to reuse the module, the driving force behind dependency management becomes maintainability. And when you want higher degrees of maintainability, your best option is to usually focus on testability. I digress, however, so let’s get back to why it’s so difficult to create reusable modules.
‘The problem we’ll quickly encounter with developing reusable modules is that it’s very difficult to create a reusable module until that module has been used a number of different times in a variety of different contexts. This prevents a chicken and egg scenario. Do you attempt to develop a module so that’s it’s reusable right away, or do you design the module only for it’s initial use and then refactor that module as additional reuse is necessary? The challenge in designing a reusable module initially is that you are forced to predict how others are going to want to use that module. You’ll find that you’re either paralyzing your development by attempting to fight through problems to which you cannot yet know the answer, or worse yet,that you’re solving the wrong problems altogether.
That’s not to say that refactoring is always the answer, though I do consider it a more feasible approach. Instead of attempting to predict reuse, you’ll choose to develop the module for it’s specific initial need, and as other uses are identified and known, you can modify the module to accommodate these needs. While not perfect, you’ll find it’s easier to take something simple that works and make it work better than it is to take something that is insanely complex and difficult to understand, and try to reuse it. It’s likely you’re going to find that you have to modify the module anyway, resulting in the same type of refactoring that you’d do wth a simpler approach, except that your refactoring is going to be more difficult because of the initial complexity. To summarize, it’s better to start simple and grow the module as the need arises rather than starting complex based on a perceived need.
Implementation Variations
Modules need to interact because it’s the sum of these interactions that result in a system’s desired behavior, and in many cases, you cannot simply take these interactions away. If it’s required that you allow one module to interact with another, you can create an interface or abstract class within the module that defines the dependent module’s view of the world. Implementations can be plugged into the module at run-time. I’ll show an exampleof how to do this in the sample code.
After you’ve eliminated the physical dependencies between modules, the idea of plugging the implementation into the module is referred to as wiring. You’ll need to wire these modules together at run-time if you want two physically independent modules to interact with each other. There are two ways to do this wiring. First, you can progammatically wire them by configuring the classes of a module with implementations that implement or extend an abstraction defined by the module. Another way is to externalize the wiring using ExternalConfiguration.
AcyclicRelationships introduces escalation, demotion, and callback , which are three different ways to break cyclic relationships among modules. Escalation and demotion can also be used to break a dependency altogether. Since demotion pushes the dependency to a lower level module, it cannot be used to break a dependency, though it can be used to lessen a heavier weight dependency.
Consequences
Independence comes with a price. It can make your modules harder for other developers to use, and that can be frustrating. Of course, the complexity incurred because of the additional flexibility isn’t all bad, since without the flexibility, other developers wouldn’t have the option of using your module since it wouldn’t give them what they need anyway. At the end of the day though, in a lot of situations, you ‘ll want to make sure that most modules are as independently deployable as possible. This is especially important for lower level modules. Taken to an extreme, however, you could make almost every module in your application standalone. However, the complexity such a solution would require would likely outweigh any advantage.
Sample Code
Heavyweight dependencies are very costly. They inhibit reusability and restrict testability. Let’s consider a payroll system where an Employee class has a pay method on it that will calculate the pay for that instance of Employee. This seems pretty logical, however, it can also get pretty messy. The pay method needs to interact with a legacy payroll system that feeds downstream financials systems, generates a paystub, and stores an image of the paystub in an enterprise document management system. Figure 1 shows the diagram for this system.

Figure 1 – Initial Component Diagram for Employee Payroll System
In the Employee class shown in Listing 1, we import the Payroll class, which is the facade to the legacy payroll system. For the sake of exmaple, I’ve kept the pay method pretty simple, but it’s likely that there could be a number of other aspects to the pay method that we’d want to test.
package com.extensiblejava.employee;
import com.extensiblejava.payroll.Payroll;
import java.math.*;
public class Employee {
private Name name;
private BigDecimal salary;
public Employee(Name name, BigDecimal salary) {
this.name = name;
this.salary = salary;
}
public PayCheck pay() {
Payroll payroll = new Payroll(salary);
return new PayCheck(payroll.run());
}
}
Listing 1: The Employee Class With Payroll Import
About all that I can do is test that the PayCheck is not null, since I don’t know what to expect back from the Payroll system. To check for a specific value, I’d be required to understand the payroll calculation process, which I’m not interested in when testing only the Employee. Listing 2 shows the EmployeeTest class.
package com.extensiblejava.test;
import junit.framework.TestCase;
import com.extensiblejava.employee.*;
import java.math.BigDecimal;
public class EmployeeTest extends TestCase {
public static void main(String[] args) {
junit.textui.TestRunner.run(EmployeeTest.class);
}
public void testEmployeePay() {
Employee employee = new Employee(new Name(), new BigDecimal("20000.00"));
PayCheck payCheck = employee.pay();
assertNotNull(payCheck);
}
}
Listing 2: The EmployeeTest Class
Additionally, I’ve prevented the ability to reuse Employee without also bringing along Payroll and all of it’s dependencies. Ultimately, this design has some pretty severe limitations. To clean things up a bit, I want to eliminate the dependency of my Employee class, and more importantly my employee.jar component, from the legacy payroll system. To do this, I’ll create an interface named PayrollRunner that represents the Employee view of how pay must be calculated. The PayrollRunner class, shown in Listing 3, is in the employee.jar component.
package com.extensiblejava.employee;
import java.math.BigDecimal;
public interface PayrollRunner {
public BigDecimal runPayroll(BigDecimal salary);
}
Listing 3: The PayrollRunner class
Now, instead of Employee using the Payroll class directly, as it did previously, I’ll inject an implementation of the PayrollRunner into the pay method of Employee, as shown in Listing 4.
package com.extensiblejava.employee;
import com.extensiblejava.payroll.Payroll;
import java.math.*;
public class Employee {
private Name name;
private BigDecimal salary;
public Employee(Name name, BigDecimal salary) {
this.name = name;
this.salary = salary;
}
public PayCheck pay(PayrollRunner runner) {
return new PayCheck(runner.runPayroll(this.salary));
}
}
Listing 4: The Employee Class with PayrollRunner Injected
This effectively eliminates any outgoing dependency of my employee.jar, making it an independent component. It’s also a bit easier to test my Employee class, and ultimately my employee component, since I’m not forced to also test the heavier weight payroll process in conjunction with employee. I’m also able to create a mock implementation of the PayrollRunner that can be used in the test case, as shown in Listing 5.
package com.extensiblejava.test;
import junit.framework.TestCase;
import com.extensiblejava.employee.*;
import java.math.BigDecimal;
public class EmployeeTest extends TestCase {
public static void main(String[] args) {
junit.textui.TestRunner.run(EmployeeTest.class);
}
public void testEmployeePay() {
PayrollRunner runner = new PayrollRunner() {
public BigDecimal runPayroll(BigDecimal salary) { return new BigDecimal("500.00"); }
};
Employee employee = new Employee(new Name(), new BigDecimal("20000.00"));
PayCheck payCheck = employee.pay(runner);
assertEquals(payCheck.getPay(), new BigDecimal("500.00"));
}
}
Listing 5: The EmployeeTest Class with PayrollRunner
The final component diagram can be seen in Figure 6.2.

Figure 2 – Component Diagram with independent employee component
The newly created payfacade.jar modules contains a facade that implements the PayrollRunner interface, and controls the interaction with the legacy payroll system. The PayFacade class is shown in Listing 6.
package com.extensiblejava.facade;
import com.extensiblejava.employee.*;
import com.extensiblejava.payroll.*;
import java.math.BigDecimal;
public class PayFacade implements PayrollRunner {
public BigDecimal runPayroll(BigDecimal salary) {
Payroll payroll = new Payroll(salary);
return payroll.run();
}
}
Listing 6: The PayFacade Class
There are two interesting comments regarding the structure. First, we’ve used the PayrollRunner to allow the Employee class to callback on the implementation when the pay calculation must be performed. Second, by using this callback, we have eliminated any relationship between employee and payroll. Note that we could have placed the PayrollRunner implementation in the payroll component. However, this would have created a dependency from payroll to employee, which may be undesirable. To this end, the relationship between payroll and employee has been escalated to the payrollfacade.
Wrapping Up
It’s not possible for every module in your software system to maintain it’s independence. Some degree of coupling between modules is always necessary for any complex system. However, some modules are better reuse candidates for others, and it’s these modules where we should focus our efforts. Because we don’t always recognize which modules these might be early in the development lifecycle, it’s likely that we’ll need to refactor using some of the other patterns in the book to increase the independence of those modules.