Product Lead @ Pulse Energy
Practicing Agile/XP since 2000
Formerly an agile coach with ThoughtWorks
Conference organizer for original Agile India conference
.WAR
.DLL
.GEM
characterized by massiveness, total uniformity, rigidity, invulnerability, etc.
http://michaelfeathers.typepad.com/michael_feathers_blog/2009/06/canalizing-design.html
function askHAL(action) {
if (isReadMe(action) {
return "Affirmative, Dave. I read you.";
} else if (isReadMessage(action)) {
return "It is dangerous to remain here. You must leave within two days.";
}
return "I'm sorry, Dave. I'm afraid I can't do that.";
}
Use tests to enforce package structure and support decoupling effort
@Test
public void corePackageShouldOnlyDependOn_util() throws Exception {
Set<String> valid = ImmutableSortedSet.of("com.pulseenergy.util");
assertThat(findInternalDependencies("com.pulseenergy.core"), is(valid));
}
@Test
public void systemPackageShouldOnlyDependOn_core_util() throws Exception {
Set<String> valid = ImmutableSortedSet.of(
"com.pulseenergy.core", "com.pulseenergy.util");
assertThat(findInternalDependencies("com.pulseenergy.system"), is(valid));
}
@Test
public void securityPackageShouldOnlyDependOn_core_springSecurity_system_util() {
Set<String> valid = ImmutableSortedSet.of(
"com.pulseenergy.core", "com.pulseenergy.spring.security",
"com.pulseenergy.system", "com.pulseenergy.util");
Set<String> invalid = ImmutableSortedSet.of("com.pulseenergy.web.filter"); // invalid dep
assertThat(findInternalDependencies("com.pulseenergy.security"),
is(ImmutableSortedSet.of(valid, invalid)));
}
@Test
public void fooShouldDependOnX() {
assertThat(findInternalDependencies("com.pulseenergy.foo"),
is(Collections.emptySet()));
}
@Test
public void fooShouldDependOnX() {
assertThat(findInternalDependencies("com.pulseenergy.foo"),
is(ImmutableSortedSet.of("com.pulseenergy.bar", "com.pulseenergy.baz")));
}
@Test
public void fooShouldDependOnBar() {
Set<String> valid = ImmutableSortedSet.of("com.pulseenergy.bar");
Set<String> invalid = ImmutableSortedSet.of("com.pulseenergy.baz");
assertThat(findInternalDependencies("com.pulseenergy.foo"),
is(Iterables.concat(valid, invalid)));
}
@Test
public void fooShouldDependOnBar() {
Set<String> valid = ImmutableSortedSet.of("com.pulseenergy.bar");
assertThat(findInternalDependencies("com.pulseenergy.foo"), is(valid));
}
private Collection<JavaPackage> analyzePackage(String targetPackage) throws IOException {
final JDepend jDepend = new JDepend();
jDepend.addDirectory(IntrospectionHelper.findClassesDirectory().getAbsolutePath()
+ "/" + convertPackageToPath(targetPackage));
@SuppressWarnings("unchecked")
final Collection<JavaPackage> allPackages = jDepend.analyze();
final List<JavaPackage> filteredPackages = Lists.newArrayList();
for (JavaPackage aPackage : allPackages) {
if (aPackage.getName().startsWith(targetPackage)) {
filteredPackages.add(aPackage);
}
}
return filteredPackages;
}
private Set<String> findInvalidDependencies(JavaPackage javaPackage) {
final Set<String> packageViolations = Sets.newTreeSet();
@SuppressWarnings("unchecked")
Collection<JavaPackage> efferents = javaPackage.getEfferents();
for (JavaPackage efferentPackage : efferents) {
if (isInternalDependency(efferentPackage)) {
packageViolations.add(efferentPackage.getName());
}
}
return packageViolations;
}