Category ArchiveLanguages
Agile & Code Quality & Languages & Scala 16 Oct 2008 07:15 am
Rules of structured programming and Scala
Recently I have been reading “Clean Code A Handbook of Agile Software Craftsmanship” by Robert C. Martin. I was originally inspired to read this book after attending a talk given by Robert Martin at JAOO earlier this year in Brisbane where he talked about “Clean Code”.
With my current focus being on Scala, I find myself constantly thinking about some of the opinions and ideas expressed in the book in the context of the Scala Language.
While discussing techniques defining functions in “Clean Code”, Robert Martin refers to Edsger Dijkstra’s rules of structured programming.
Dijkstra said that every function, and every block within a function, should have one entry and one exit. Following these rules means that there should only be one return statement in a function, no break or continue statements in a loop, and never, ever, any goto statements.
… an excerpt from “Clean Code A Handbook of Agile Software Craftsmanship” by Robert C. Martin.
Why does this make me think of Scala? While the Scala language has both the for and while control structures built-in, the implementers of the language have chosen not to include the break or continue commands as part of the language.
I think it is a brave decisions for language designers to make the decision to exclude such entrenched concepts as the break or the continue command from a language. This exclusion will force coders to think a little harder about the best way to describe their intent in code. I think Scala have got it right.
Languages & Scala 14 Oct 2008 09:15 pm
Implicit Conversions in Scala
In the Ruby programming language, one of its most powerful features is the concept of open classes. In Ruby, classes are never closed: you can always add methods to an existing class to augment its behaviour.
An example of this taken from http://www.ruby-lang.org/en/documentation/ruby-from-other-languages is shown below.
class Fixnum
def hours
self * 3600 # number of seconds in an hour
end
alias hour hours
end# 14 hours from 00:00 January 1st
# (aka when you finally wake up )
Time.mktime(2006, 01, 01) + 14.hours # => Sun Jan 01 14:00:00
Scala, while not offering open classes does have a feature that allow you to achieve something similar. Though I will be the first to admit it does make you jump through a few more hoops to achieve the same effect.
Implicit conversion in Scala allows us to extend the behaviour of pre-existing classes without actually changing them.
Imagine we would like to extend the String class with some of the functionality offered by the StringUtils class in the Apach Commons Lang library. Despite this being a java library we can seamlessly use this in Scala due to the tight interoperability with Java.
StringUtils offers a method called abbreviate that will replace a part of a string with ellipsis if the string is longer than specified length.
For example:
StringUtils.abbreviate("abcdefg", 6) = "abc..."
StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
StringUtils.abbreviate("abcdefg", 4) = "a..."
To begin with, lets write a simple utility class in Scala that will delegate to the Apach Commons Lang library that will allow us to abbreviate a string value. Since I have a strong TDD background I would like to start with a simple spec test to illustrate what I am trying to achieve.
package com.gigantiq.helloworld
import org.specs._
object RichStringSpecification extends Specification {
"A Rich String" should {
"abbreviate a long string to a specified length" in {
new RichString("abcdefg").abbreviate(6) mustMatch "abc..."
}
}
}
From this test you can see that I intend on implementing a simple class called RichString which will take a String argument on its constructor and provide an abbreviate method which will delegate to the Apach Commons Lang library.
Implementation RichString gives us a class that looks like this:
package com.gigantiq. implicitconversion
import org.apache.commons.lang.StringUtils
class RichString(original: String) {
def abbreviate(length: Int) = {
StringUtils.abbreviate(original, length)
}
}
Running our spec test will give us a satisfying output.
Specification "RichStringSpecification"
A Rich String should
+ abbreviate a long string to a specified length
Total for SUT "A Rich String":
Finished in 0 second, 36 ms
1 example, 1 assertion, 0 failure, 0 error
This class provides us with the functionality that we are after but not in the seamless way we would ultimately like. In this form every time we wish to abbreviate a String we would need to write code that looked like this:
new RichString("abcdefg").abbreviate(6)
This is not great… actually I might as will stick to Java if this is what i am stuck with.
What I would really like is for my interaction with the abbreviate method to be a little more elegant. In fact, it would be nice if I could seamlessly treat a String as if it was a RichString. This would mean I could write something like this:
“abcdefg”.abbreviate(6)
It gets better than this. If I achieved the above then I could actually get away with syntax that would look more like this:
“abcdefg” abbreviate 6
I would be able to do this since “.” notation before the method call is optional in Scala as is the parenthisis on a method with a single parameter.
Lets rewrite our test with this new expectation.
package com.gigantiq.implicitconversion
import org.specs._
object RichStringSpecification extends Specification {
"A Rich String" should {
"abbreviate a long string to a specified length" in {
“abcdefg" abbreviate 6 mustMatch "abc..."
}
}
}
This looks much nicer. How do we do this? The answer is through the use of an Implicit conversion.
We can declare an implicit conversion in Scala with the following syntax:
implicit def stringToRichString(original: String) = new RichString(original)
The “implicit” key word tells the Scala compile that the method “stringToRichString” can be used as an implicit converter. When the compiler sees a line like “abcdefg" abbreviate 6 it will actually translate the code in to (new RichString(“abcdefg").abbreviate(6)).
Once we have declared the above implicit conversion and run our test we will see everything pass once again.
Specification "RichStringSpecification"
A Rich String should
+ abbreviate a long string to a specified length
Total for SUT "A Rich String":
Finished in 0 second, 36 ms
1 example, 1 assertion, 0 failure, 0 error
Nice ![]()
Scala 06 Oct 2008 09:15 pm
Testing Scala using specs
As I mentioned in an earlier post, Scala offers many alternatives for unit testing. With its Java interoperability using JUnit or TestNg is no more difficult than using the purpose built testing frameworks for Scala such as ScalaTest, Rehersal, specs, and ScalaCheck.
My personal favourite is specs. The specs testing framework, is a Behaviour-Driven-Design testing tool written in Scala by Eric Torreborre.
Below is a very simple example of a specs test.
package com.gigantiq.thing
import org.specs._
object ThingSpecification extends Specification {
”A Thing” should {
”have a name equal to the passed value” in {
val thing = new Thing(”myThing”)
thing.name mustMatch “myThing”
}
”throw an IllegalArgumentException if passed a blank name” in {
new Thing(”") must throwA(new IllegalArgumentException)
}
}
}
The import org.specs._ statement is importing everything from the import org.specs package. The _ is equivalent to * in a java import statement.
Next we declare a specification with the following syntax…
object ThingSpecification extends Specification {
…
}
They object key word in Scala declares a singleton object. So in this case we have declared a singleton called ThingSpecification that extends the abstract class called Specification as provided by the specs library.
The specs library utilizes Scala’s flexibility to define a DSL that allows us to construct a very human readable specification.
"A Thing" should {
”have a name equal to the passed value” in {
val thing = new Thing(”myThing”)
thing.name mustMatch “myThing”
}
”throw an IllegalArgumentException if passed a blank name” in {
new Thing(”") must throwA(new IllegalArgumentException)
}
}
Looking at this example we can see clearly that we are expecting the following behavior from our application that we are writing.
- A Thing should have a name equal to the passed value.
- A Thing should throw an IllegalArgumentException if passed a blank name.
Before we can run this Specification we need the Thing class otherwise our tests will fail. So in the conciseness of Scala, here it is:
package com.gigantiq.thing
class Thing(val name: String) {
require(name.length > 0)
}
We can now compile our application. Once we have done that we can run our specification using the scala command.
andytrigg$ scala -cp specs-1.3.1.jar com.gigantiq.thing.ThingSpecification
Upon execution of this specification we receive the following output to our console.
Specification "ThingSpecification"
A Thing should
+ have a name equal to the passed value
+ throw an IllegalArgumentException if passed a blank name
Total for specification “ThingSpecification”:
Finished in 0 second, 49 ms
2 examples, 2 assertions, 0 failure, 0 error
Just for completeness I would like to show what happens in the event of a test failing. If we remove the precondition check(require(name.length > 0)) from our Thing class and rerun our specification, we will get the following output.
Specification "ThingSpecification"
A Thing should
+ have a name equal to the passed value
x throw an IllegalArgumentException if passed a blank name
java.lang.IllegalArgumentException should have been thrown (ThingSpecification.scala:12)
Total for specification “ThingSpecification”:
Finished in 0 second, 49 ms
2 examples, 2 assertions, 1 failure, 0 error
In the above examples I illustrated the use of two of the matchers that specs offers out of the box. Matchers are used for specifying the assertion being made in the specifications. The ones we have used here are:
mustMatch: used for asserting matching stringsmust throwA: used to evaluate that an expected exception is thrownIn addition to these, specs offers many matchers and it is very easy to write your own if none of the standard matchers suffice.
As you can see, unit testing doesn’t get much simpler than that. I love those specs.
Scala 05 Oct 2008 05:26 pm
IDE and Ant support for Scala
If I intend on writing even a smallish application there are two things I look for in regards to the tool support of the language.
- I hope the language has reasonable IDE support. By reasonable it should offer me a moderate number of code refactorings as a minimum.
- The language should integrate nicely with an automated build system so that i can incorparate the build in to a continuous integration environment.
One of the factors that can make or break the success of a language is the IDE support. Currently Scala’s IDE options are not great. Nothing that i have seen in regards to Scala’s IDE support has rocked my world. The main two I have explored is Intelli’s Scala plugin and the Scala plugin for Eclipse.
Normally my editor of choice would be IntelliJ for authoring Java. When it comes to writing Scala the IntelliJ plugin available is buggy at best and completely unusable on the Mac. I am sure this will improve over time. I am quietly hopeful that by the time IntelliJ 8 is released, many of the issues surrounding the Scala plugin will be resolved.
The Eclipse plugin, while quite limited in features seems less buggy than the IntelliJ equivalent. It is still not great though, so be prepared for some ugliness.
Both of the IDE’s mentioned above offer little more than the most basic refactoring support for Scala.
Fortunately Scala fairs better when it comes to an automated build environment. Scala offers great support for Apache Ant out of the box.
To illustrate an Ant build, lets get a simple application running. Here is a hello world application.
package com.gigantiq.helloworld
object HelloWorld extends Application {
println("Hello world!")
}
To show this application running we can either use the Scala compiler called “scalac” or the Scala compiler daemon called “fsc” to compile the application. For example:
andytrigg$ fsc com/gigantiq/helloworld/HelloWorld.scala
andytrigg$
Now that the application has been compiled to Java byte code, we can run the application by using the scala command:
andytrigg$ scala com.gigantiq.helloworld.HelloWorld
The output looks something like this:
andytrigg$ scala com.gigantiq.helloworld.HelloWorld
Hello world!
andytrigg$
Now that we have proven that the application runs, lets write a simple Ant script to automate this.
<?xml version="1.0" encoding="UTF-8"?>
<project name="hello world" basedir="." default="run">
<property name="scala.home" value="/Users/andytrigg/dev/scala/scala-2.7.1.final"/>
<property name="scala-compiler.jar" value="${scala.home}/lib/scala-compiler.jar"/>
<property name="scala-library.jar" value="${scala.home}/lib/scala-library.jar"/>
<property name="build.dir" value="${basedir}/build"/>
<property name="src.dir" value="${basedir}/src"/>
To make use of the built in Ant targets that Scala offers both “scala-compiler.jar” and “scala-library.jar” need to be on the classpath.
<path id="scala.classpath">
<pathelement location="${scala-compiler.jar}"/>
<pathelement location="${scala-library.jar}"/>
</path>
<path id="build.classpath">
<pathelement location="${scala-library.jar}" />
<pathelement location="${build.dir}" />
</path>
Add the Scala task definitions to this Ant project.
<taskdef resource="scala/tools/ant/antlib.xml">
<classpath refid="scala.classpath"/>
</taskdef>
Use the “scalac” compiler to build the project.
<target name="-compile">
<mkdir dir="${build.dir}"/>
<scalac srcdir="${src.dir}" destdir="${build.dir}" classpathref="build.classpath" force="changed">
<include name="**/*.scala"/>
</scalac>
</target>
Once the project is compiled to Java byte code, the application can be executed as a java application.
<target name="-run">
<java classname="com.gigantiq.helloworld.HelloWorld" classpathref="build.classpath">
</java>
</target>
<target name="--run" depends="-compile, -run"/>
<target name="run" depends="--run"/>
</project>
Now that we have an Ant build we can run the following from the command line:
andytrigg$ ant run
The result looks like this …
Buildfile: build.xml
-compile:
-run:
[java] Hello world!
–run:
run:
BUILD SUCCESSFUL
Total time: 0 seconds
andytrigg$
As you can see it is pretty simple to get a Scala application being built using Ant.
Scala 05 Oct 2008 02:48 pm
Introduction to Scala
For quite some time now a number of people whom I respect highly have been talking quite consitently about the Scala programming language. It has also been mentioned a number of times on “The Java Posse” pod cast. As a result my interest in Scala was sparked and I figured it is time I get my hands dirty and explore why there is so much buzz about the language.
My plan is to document what I learn about the language on my blog as a self-reference. Hopefully others will find my postings useful… or at the very least spark more interest.
What is scala?
Scala is a Sca(lable) la(nguage). Many sites about Scala talk about the language being scalable since it can lend itself to writing small scripts or to building large systems. To be honest I am not convinced I would use it for writing small scripts. I think there are better suited technologies available. When it comes to building larger systems I think it has a lot of promise … more so than Ruby. Ruby has some serious issues that makes writing large systems difficult. I am not going to discuss those issues here though.
An application written in Scala compiles into Java byte code and runs inside the JVM. As a result it offers interoperability with Java that few other languages offer.
Scala is both an object orientated, and functional language. Taken from the scala web site (http://www.scala-lang.org/)
Scala is object-oriented: Scala is a pure object-oriented language in the sense that every value is an object. Types and behavior of objects are described by classes and traits. Classes are extended by subclassing and a flexible mixin-based composition mechanism as a clean replacement for multiple inheritance.
Scala is functional: Scala is also a functional language in the sense that every function is a value. Scala provides a lightweight syntax for defining anonymous functions, it supports higher-order functions, it allows functions to be nested, and supports currying. Scala’s case classes and its built-in support for pattern matching model algebraic types used in many functional programming languages.
While Scala is statically typed, its type system is highly advanced and resolves many of the issues that people site as problems of type strong languages. I shall discuss a little more about this later.
Through the use of a unique combination of language mechanisms Scala is highly extensible. Its ability to add new language constructs makes it ideal for developing domain-specific languages.
Why scala?
For me, Scala’s main attraction is its interoperability with Java. From Scala you can call Java methods, access Java Fields, inherit from Java classes, and implement Java interfaces. Scala code can also be invoked from Java code. This level of interoperability opens up a huge world or open source and commercial libraries that are available to the Java community also available to the Scala community. It also means that existing Java systems can be extended with Scala with out much effort.
Like Ruby and Groovy, Scala allows programs to be written concisely and expressively. A common example for illustrating Scala’s conciseness is the declaration of a class.
Consider the following Java class:
class Person {
private final String firstName;
private final String lastName;
private final int age;
public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
}
If we were to rewrite this class in Scala, it could be written like this:
class Person(firstName: String, lastName: String, age: Int)
As I have mentioned already, Scala’s type system is highly advanced. The local type inference mechanism of Scala means redundant type information does not have to be explicitly annotated.
For example:
val y: Int = 1 + 3
val y = 1 + 3
These two statements are equivalent. In both cases y is an integer but on the second line the type of Int is inferred by its usage.
For me another good reason of why Scala is worth investigation is its testability. With its close interoperability with Java, well established test frameworks such as JUnit and TestNg can easily be used for unit testing. In addition there are a number of Scala specific testing frameworks such as ScalaTest, Rehersal, specs, and ScalaCheck.
In recent days I have started to use specs as my unit testing framework of choice and will discuss its use in a future blog about unit testing Scala.
Gigantiq & Java 27 Aug 2007 09:42 pm
Gigantiq are Looking for Skilled Java Developers
Gigantiq has a number of exciting opportunities we are exploring at the moment. We are looking for smart Java developers to join the Melbourne team.
If you think that you can fit into a team of skilled, passionate Software Developers then drop us a line and tell us about yourself.
We are happy to engage the right people on a contract or permanent basis.
jobs@gigantiq.com
www.gigantiq.com
Code Quality & Java 01 Aug 2007 01:30 pm
Enforcing Package Dependencies (Part 4)
Macker is my prefered tool for java package dependency enforment. It is a free tool licenced under GPL.
While Macker is not as simple as Japan to configure, it is not difficult and is considerably more powerful. Like Japan, Macker is configured via XML and is designed to be integrated into an ant build.
Here is a sample macker configuration file.
<?xml version="1.0"?>
<macker>
<ruleset name="Module dependency checking rules">
<var name="base" value="com.gigantiq.bedrock"/>
<pattern name=”root”>
<include class=”${base}.**”/>
</pattern>
<pattern name=”model”>
<include class=”${base}.model.**”/>
</pattern>
<pattern name=”ui”>
<include class=”${base}.ui.**”/>
</pattern>
<pattern name=”util”>
<include class=”${base}.util.**”/>
</pattern>
<!– Dependency rules –>
<access-rule>
<message>model package class ${from} cannot use class ${to}</message>
<deny><from pattern=”model”/><to pattern=”root”/></deny>
<allow><to pattern=”model”/></allow>
<allow><to pattern=”ui”/></allow>
</access-rule>
<access-rule>
<message>ui package class ${from} cannot use class ${to}</message>
<deny><from pattern=”ui”/><to pattern=”root”/></deny>
<allow><to pattern=”ui”/></allow>
</access-rule>
<access-rule>
<message>util package class ${from} cannot use class ${to}</message>
<deny><from pattern=”util”/><to pattern=”root”/></deny>
<allow><to pattern=”util”/></allow>
<allow><to pattern=”model”/></allow>
<allow><to pattern=”ui”/></allow>
</access-rule>
</ruleset>
</macker>
The pattern element allows us to define patterns that can be re-used in the macker rules that we define. In this example I have used the pattern elements to define the packages that will be referred to in the macker rules.
We can now define our package dependencies using the access-rule element. For example:
<access-rule>
<message>model package class ${from} cannot use class ${to}</message>
<deny><from pattern="model"/><to pattern="root"/></deny>
<allow><to pattern="model"/></allow>
<allow><to pattern="ui"/></allow>
</access-rule>
In this fragment I define that the model and ui packages are the only packages that can depend on the model package. I have also used the ${from} and ${to} in the message element to ensure that a readible message is produced on an access rule voilation. The message produced will contain the names of the classes responsible for the voilation.
The macker site contains plenty of examples that illustrate some of the capabilities of macker.
Like Japan, Macker includes a built in ant target that makes integration with an ant build very simple. The added time introduced to your build by adding macker should be minimal even on a large code base (less than 10 seconds).
Something I considered trying at one stage was to use XSLT to produce a GraphML file from the macker configuration file so that the defined package dependencies could be viewed in graphical manner using tools such as yEd. I have not had an opportunity to try this yet to see if it would work. If I do, I will post the results on this blog.
Code Quality & Java 30 May 2007 11:07 am
Enforcing Package Dependencies (Part 3)
Japan is another open source tool that can be used for enforcing package dependencies. It comes with an IntelliJ plugin as well as an ant task. The ant task makes it trivial to incorporate into an ant build.
The real beauty of Japan is how simple it’s configuration is despite being a dreaded XML file.
<japan-config base-package="com.gigantiq.bedrock" ignore-indicator="// JAPAN:IGNORE">
<dependency-set name="module" package-depth="4" transitive="true">
<dependency from="model" to="ui"/>
<dependency from="ui" to="model,ui"/>
<dependency from="util" to=""/>
</dependency-set>
</japan-config>
The document element, japan-config, defines an attribute called base-package. This allows the base package of the project to be defined. In this case the base-package is com.gigantiq.bedrock.
The dependency-set defines the allowed dependencies at specified depth. It is here that Japan exhibits it’s biggest limitation. Japan assumes that the dependencies you wish to enforce are all at the same level within the package hierarchy.
In the above example, since the dependencies we are enforcing are all below the package com.gigantiq.bedrock, we state that the package-depth for this dependency-set is 4. This can become problematic if you are retrofitting Japan to an existing project whose package structure is not very uniform. Japan’s work-around for this is that it allows multiple dependency-set elements to be defined all with different values for the package-depth attribute. Too many dependency-set elements though, lead to an overly complicated configuration file.
Since Japan comes with a Ant task it can be added to your existing ant build very easily.
<taskdef classname="net.sourceforge.japan.ant.JapanTask" name="japan" classpath="build/lib/ant/japan-0.1.jar:build/lib/ant/jdom.jar"/>
<target name="dependency-check" >
<japan sourcePath="source/java.main;" japanConfigFile="japan-config.xml" />
</target>
The error reporting that results from the ant task is very easy to interpret. Both ends of a violation are clearly highlighted.
So what are the biggest problems with Japan? There two main issues I have with Japan one of which I have already mentioned.
First is the flexibility that is lost with a dependency-set only allowing dependencies to be defined at a single level with in a package. The second is the absence of any tools for analysing an applications package dependencies.
The biggest thing that Japan has going for it, is that it is incredibly simple to use and trivial to include in my build.
Code Quality & Java 26 May 2007 12:46 pm
Enforcing Package Dependencies (Part 2)
JDepend is probably the best known of the package dependency tools. It has certainly been around for quite a while.
JDepend allows you to analyse java package metrics, dependencies, and cycles and allows you to visualise the analysis in a graphical UI, textual UI, and XML UI. I won’t go into detail on how to do this since it would largely require me to regurgitate what is already documented at the JDepend web site. My real interest is how can I integrate this into my build and have my build break when certain dependencies break.
JDepend allows you to right JUnit tests that codify the dependency constraints you wish to enforce. If any of these dependency constraints are broken, the unit test will fail. An example of such a unit test can be seen below.
package com.gigantiq;
import jdepend.framework.DependencyConstraint;
import jdepend.framework.JDepend;
import jdepend.framework.JavaPackage;
import jdepend.framework.PackageFilter;
import static junit.framework.Assert.assertEquals;
import org.junit.Test;
import java.io.IOException;
/**
* Copyright Gigantiq Pty Ltd
*/
public class EnforcePackageDependenciesTest
{
@Test
public void testMatch() throws IOException
{
PackageFilter filter = new PackageFilter();
filter.addPackage(”java.*”);
filter.addPackage(”javax.*”);
JDepend jdepend = new JDepend(filter);
jdepend.addDirectory(”/Path/To/Classes/”);
DependencyConstraint constraint = new DependencyConstraint();
JavaPackage model = constraint.addPackage(”com.gigantiq.bedrock.model”);
JavaPackage ui = constraint.addPackage(”com.gigantiq.bedrock.ui”);
JavaPackage util = constraint.addPackage(”com.gigantiq.bedrock.util”);
ui.dependsUpon(model);
ui.dependsUpon(util);
model.dependsUpon(util);
jdepend.analyze();
assertEquals(”Dependency mismatch”, true, jdepend.dependencyMatch(constraint));
}
}
To implement such a unit test, the first step is to create an instance of JDepend. In our exmpale we inject the JDepend instance with a package filter to ensure the java.* and javax.* packages are ignored during the analysis.
PackageFilter filter = new PackageFilter();
filter.addPackage("java.*");
filter.addPackage("javax.*");
JDepend jdepend = new JDepend(filter);
Our dependencies are then coded into the unit test by setting up a DependencyConstraint defining the allowed dependencies between packages.
DependencyConstraint constraint = new DependencyConstraint();
JavaPackage model = constraint.addPackage("com.gigantiq.bedrock.model");
JavaPackage ui = constraint.addPackage("com.gigantiq.bedrock.ui");
JavaPackage util = constraint.addPackage("com.gigantiq.bedrock.util");
ui.dependsUpon(model);
ui.dependsUpon(util);
Once our dependencies are coded up into such a unit test, it is a simple manner to include the execution of this test into our build since it can be treated like any other JUnit test in our system. Adding any new code that violates the defined constraints will result in a failing unit test.
There a number of issues with this approach of enforcing package dependencies that I really do not like.
- Enforcing the package dependencies is important enough that it should be treated as a seperate target with in the build. The danger of treating it as “just” another unit test is that we lose the sense of importance it should retain. Defining a seperate target in the build that just runs the JDepend unit tests would go a long way towards addressing this issue.
- One of my driving forces behind enforcing package dependency, is that I can better understand the applications structure and thus be able to improve my ability to understand the impact that a code change is going to have on the rest of the system. I do not find JDepend’s approach of defining dependencies particularly easy to ready. A JDepend test for a complex applicaion with a lot of dependencies defined can become very difficult to read.
- Error reporting is really poor. If my unit test fails, I get a message printed to the console that looks something like this…
junit.framework.AssertionFailedError: Dependency mismatch expected:<true> but was:<false>. What dependency has been breached? I could structure my test in such a way that makes determining the cause of such errors much easier, but I would prefer a tool that just offered better reporting with out much effort.
So while JDepend will give me an approach for enforcing package dependencies with in my application, it is far from being ideal.
Code Quality & Java 22 May 2007 09:44 pm
Enforcing Package Dependencies (Part 1)
While a code base remains small with only a few smart individuals responsible for changes, it can be relatively easy to maintain the architectural qualities. A project does not need to grow by much before the maintainability, flexibility, and modularity of the system can become hard to retain.
The cohesive aspects of an application’s architecture tend to be reflected in its package structure. Analyzing and enforcing package dependencies can be a very useful technique to assist in maintaining the architectural traits. Understanding the package dependencies also assists with understanding the impact of code changes as they occur.
I am a big advocate for automating everything I possibly can. Ensuring code quality is no exception. Over the next few blog entries, I plan to discuss a number of approaches I have encountered for automating the enforcement package dependencies.
JDepend, Japan, and Macker are all tools that can be incorporated into an ant build and be used for enforcing package dependencies. Each of these tools have their pros and cons that I will discuss in detail over the next few postings.

