Dynamic Languages
Archived Posts from this Category
Archived Posts from this Category

The easyb team is pleased to announce the release of easyb 0.9, baby!
The 0.9 release has:
narrative supportdescription supporteasyb supports capturing additional hip information regarding stories, such as a story’s description and some detail regarding the features, benefits, and roles of a persona related to a story. For instance, the DSL now supports a description syntax that takes a String value — single quote or Groovy’s triple quote trick.
description "some description"
scenario "text"
or
description """some long description that requires
multiple lines, etc
"""
scenario "text"
What’s more, you can provide additional details of a story via the narrative syntax:
description "text"
narrative "description", {
as_a "role"
i_want "feature"
so_that "benefit"
}
scenario "text"
Both the narrative and description keywords are optional and they don’t have to be used together– i.e. you can use the narrative one without providing a description. These aspects will be captured in the output (i.e. story report) of an easyb run too.
From a fixture standpoint, easyb supports both one time fixtures (before) and for each scenario (before_each). Of course, you can add tearDown-like behavior in after and after_each.
You can download the latest release from easyb’s Google code page.
2 comments Tuesday 01 Jul 2008 | Andy | Developer Testing, Groovy
Back in the Age of Aquarius, a popular pattern emerged in the Java world dubbed “the data access object“, which essentially
“separates a data resource’s [hip] client interface from its data access mechanisms”
meaning that clients to a particular domain object were shielded from the actual implementation of communicating with a particular database. Provided that clients worked with the interface type, implementations could be switched out (the database could migrate from DB2 to Oracle, for instance or one DAO type could leverage Hibernate, another IBATIS). This pattern had the bogue consequence, though, of logically dividing up a data layer into two types– DAOs and individual domain objects.

For instance, if you had a copasetic Customer domain object, you would also have a CustomerDAO interface type– your Customer object would essentially be a struct and the DAO type would handle CRUD (create, read, update, delete) operations. If you needed to find a particular customer, you’d ask the DAO type, for example, invoking the findCustomer(long id) method on the CustomerDAO object, which would return a fully populated Customer object.
This pattern seemed well and good at the time– I admit to using it extensively on a large project ages ago (after disco though); however, after a while it seemed to be a lot of work– if, because it was my bag, I wanted a Customer object, why did I have to ask the CustomerDAO for it? Why couldn’t I just ask the Customer itself? On top of that, if I wanted to create a new Customer, I had to first populate a Customer object and then pass it to the DAO type and invoke the create method.
I’m sure at the time a lot of smart people eschewed this uptight pattern and designed more natural domain objects; but for me, the tides changed when I read an interesting article about Naked Objects and then looked deeply at Rails (and subsequently, Grails) as they came to mature– these frameworks have no notion of a DAO type– your domain object (Customer) does everything for you– you can create new Customers, save instances, find instance, etc.
I recently found myself building a domain model in Java without the luxury of Grails or GORM; however, I did employ Hibernate and Spring. My initial effort starting going down the traditional DAO-domain object pairing but I quickly found myself disgusted– as a result I started playing around with combining the duo into something as hip (and polished) as what Grails/Rails would give you. My goal, of course, to provide a domain object that handled everything rather than having clients of the domain object have to work with two different trippin’ objects.
In the end, I still have two different objects and an interface type to link them (via Spring); however, clients need only work with one hip type– the domain object. My domain objects support instance methods like create, remove, and update and class methods for find-like methods.
I nonetheless still have a DAO object– it’s essentially a Spring wired HibernateTemplate– this object supports the true CRUD logic and is directly bound to Hibernate. For example, given a Race domain object, the DAO looks like this (minus some instance and class methods, but you’ll get the point):
class RaceDAOImpl implements RaceDAO {
private SessionFactory sessionFactory;
public RaceDAOImpl() {
super();
}
public void setSessionFactory(final SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void create(final Race race) {
final HibernateTemplate tmplte =
new HibernateTemplate(this.sessionFactory);
tmplte.save(race);
}
//...
public Race findByName(final String name) {
final HibernateTemplate hibernateTemplate = new HibernateTemplate(this.sessionFactory);
return (Race) hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
return session.createQuery(
"from ... name = ?")
.setString(0, name.trim())
.uniqueResult();
}
});
}
//...
}
Note that this class isn’t public– it isn’t intended for outside consumption– the only client to this class (which will be shown shortly) is the domain object (which lives in the same package).
With this DAO object, I extracted an interface type– RaceDAO. This interface is the link between the domain object (Race) and the DAO (that is, the domain object will work with the interface type not the implementation or because it’s everyone’s bag to describe things in terms of coupling– the domain object is loosely coupled to the DAO implementation).
interface RaceDAO {
Collection<Race> findAll();
Race findById(long id);
Race findByName(String name);
//...other finders...
void create(Race race);
void update(Race race);
void remove(Race race);
}
The domain object (which clients rely on) then relies on Spring (which basically acts as a factory) and composition to expose instance and class methods that indirectly (i.e. delegate via composition) leverage Hibernate to manipulate persistence.
For instance, the Race domain object looks like a normal, hip domain object– it contains various properties (and consequentially getters and setters) related to races (races have runners and results, etc) like so:
public class Race {
private long id;
private String name;
private Date date;
private double distance;
private Set<Runner> participants;
private Set<Result> results;
private String description;
//.....more to come
}
The next step could have unfolded in a number of different ways; however, I kept on truckin’ and ended up with something that works– there are certainly pros and cons associated with my choices though (I will point those out shortly).
The DAO interface is linked via Spring in a static block in the domain object like so:
private final static RaceDAO dao;
static {
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
dao = (RaceDAO) context.getBean("race_dao");
}
Note that the type in the domain object is the interface (RaceDAO) not the implementation — Spring is returning some type that is bound to the String race_dao, which in my case is the Hibernate template type shown earlier.
Thus, because the RaceDAO is a static type, I can then expose a series of class methods on the domain object for finding particular race instances like so:
public static Collection<Race> findAll(){
return dao.findAll();
}
public static Race findById(long id) {
return dao.findById(id);
}
//...others...
Plus, instance methods on the domain object also delegate to the interface type:
public void create() {
dao.create(this);
}
Now clients of a particular domain object don’t need to handle or work with various copasetic objects– they work exclusively with a domain object (much like you would in Grails, for instance). For example, the following easyb scenario demonstrates the behavior of a Race instance:
scenario "Race should support finding races by name", {
when "the find by name method is called", {
race = Race.findByName("Leesburg Marathon")
}
then "the race should have 100 runners", {
race.participants.size().shouldBe 100
}
}
As you see in the Groovy code above, the findByName method is a class method– it returns a Race instance, which clients can then work with.
Instance methods on the domain object work too, for example, creating a new race instance and persisting it is as easy as invoking the create method:
scenario "the domain object should faciliate creating new instances", {
given "a new race is created", {
new Race("SML 10K", new Date(), 6.2,
"race the hills of Smith Mountain lake").create()
}
then "the domain class should actually find it by name", {
race = Race.findByName("SML 10K")
race.description.shouldBe "race the hills of Smith Mountain lake"
}
}
As I mentioned earlier, there are some bogue disadvantages to this strategy– that is, because it’s its bag, the static block forces clients to load some instance of the DAO– without mocking that instance out, the domain object becomes somewhat heavy. For instance, loading the Race class with a Hibernate wired DAO means that a database must be up and running. Thus, without some mocking of the DAO interface type (and subsequent wiring of Spring) these domain objects can be hard to truly unit test.
The advantage of this strategy is that clients don’t have to deal with a DAO type– they have a more neat-o-natural interface to work with– that being the business object itself (i.e. Customer or Race or Runner, etc). There are still two objects (and a binding type) to work with; however, the DAO is hidden. And in keeping with the spirit of the original DAO pattern, implementers are free to create varying instances of the DAO (should they actually need more than one– unit testing certainly comes to mind for a need to create at least one other instance).
The data models offered by frameworks like Grails and Rails are pretty hippingly sophisticated as well as elegant; what’s more they are easy to learn and natural to use. At this point, however, GORM (Grails magic data layer sauce) isn’t available as a stand alone project for Java developers; consequently, hip developers are left to rolling their own models (which leverage Hibernate, JDBC, IBATIS, etc), modeled after said project’s elegance.
The DAO pattern as it was authored (and implemented) back in the day is heavy, man; however, by applying a bit of Spring (or some other IOC framework) and leveraging a restrictive class modifier (to thus hide objects from clients), you can create more natural domain objects that still live up to the promised flexibility of the DAO pattern. Can you dig it, baby?
18 comments Tuesday 17 Jun 2008 | Andy | Groovy, Software Development
My friend Venkat Subramaniam, who played a role in shaping early versions of easyb’s hip DSL, has recently published an article dubbed “Creating DSLs in Java, Part 1: What is a domain-specific language?” on JavaWorld. This is an excellent article that demystifies DSLs and demonstrates that you probably use them daily.
One of my favorite points Venkat makes is:
Simplicity is critical to the success of a DSL. A person familiar with the language’s domain must easily understand it.
He goes on to add:
Creating a good DSL is like cooking a nutritious meal; just like you want kids to eat vegetables without realizing and fussing over them, you want clients to use your DSL without worrying about its syntax.
Because it’s their bag, this notion of simplicity has been a guiding principle for the easyb team; yet, striving for clarity, conciseness, and expressiveness (other points Venkat goes on to make) within a DSL is harder than you think! You only need look at a classic make file to see, in my opinion, a DSL that creates a lot of fuss, baby.
Check out Venkat’s copasetic article and while you are at it, don’t forget to check out easyb, man!
0 comments Saturday 14 Jun 2008 | Andy | Dynamic Languages, Groovy, Software Development
One of my favorite features in Groovy is its hip ? operator, which facilitates Nullpointer navigation safety– while this feature isn’t available directly in Java, there is a handy Java operator that I’ve found myself using more and more these days (in Java, man) based upon my dynamic language conditioning of preferring code terseness: the ternary operator.
The ternary operator doesn’t directly relate to the ? operator in Groovy; however, its bag is similar– that is, reducing typing. This operator enables you to succinctly assign a value to a variable based on one or more boolean decisions like so:
this.location = (location != null ? location : DEFAULT_LOC_NAME);
In the code above, the location member variable (this.location) is being set to a location local variable or a static constant (DEFAULT_LOC_NAME) if the location local variable is null. Thus, the code to the left of the ? operator must be a boolean expression and the value to the left of the : operator is returned if true and the value to the right of the : is returned if the expression is false.
The single line of Java code facilitated by the ternary would be roughly equivalent to a conditional like so:
if(location != null){
this.location = location;
}else{
this.location = DEFAULT_LOC_NAME;
}
Of course, the {}’s are optional (thus, the code could be reduced somewhat); however, the point being that a copasetically placed ternary reduces typing and a bit of redundancy (in this case), baby.
In the past, I used to eschew the ternary due to its terseness– I found myself using conditionals to more clearly express my intent; however, after years of dynamic language conditioning, I’ve found myself reserving my stance on the ternary.
If you find yourself typing too much Java, baby, then consider employing the ternary– you may find its laconic nature refreshingly simple. Can you dig it, man?
5 comments Saturday 17 May 2008 | Andy | Groovy, Software Development
The hip team over at easyb.org has been diligently working towards a 1.0 release and recently added the notion of fixtures for stories; that is, the DSL has been updated to include:
before_eachafter_eachThese constructs operate much the same as JUnit’s original fixtures in that code in the before_each closure is executed before each scenario and after_each, after.
As an example of how fixtures can be copasetic, over on testearly.com, easyb was utilized in combination with Selenium to create a more human readable functional story.
The first scenario attempted to capture a sunny day:
Yet in realizing this story (as Selenium was utilized) additional aspects related to using Selenium were mixed into the prose. For instance, for every scenario, the following given was needed to fire up a Selenium instance:
given "selenium is up and running", {
selenium = new DefaultSelenium("localhost",
4444, "*firefox", "http://acme.racing.net/greport")
selenium.start()
}
What’s more, because it’s Selenium’s bag, the following then was also required to clean things up:
then "selenium should be shutdown", {
selenium.stop()
}
These are obviously candidates for pushing into a fixture type construct, right? Consequently, if you need copasetic logic that is repeated for a scenario, you can place it into either a before_each or a after_each construct like so:
before_each "initialize an instance of selenium", {
given "selenium is up and running", {
selenium = new DefaultSelenium("localhost", 4444,
"*firefox", "http://acme.racing.net/greport")
selenium.start()
}
and "given a person is at the race report page", {
selenium.open("http://acme.racing.net/greport/personracereport.html")
}
}
Selenium requires some clean up; accordingly, the following construct will be executed post a scenario:
after_each "shut down selenium", {
then "selenium should be shutdown", {
selenium.stop()
}
}
Given this fixture logic, the corresponding scenarios become more concise as their intent is more clearly expressed (without too much selenium mixed in):
scenario "an invalid person should return an error message", {
given "a form with a first and last name entered and sumbitted", {
selenium.type("fname", "Merlin")
selenium.type("lname", "Paine")
selenium.click("submit")
}
then "the report should have a list of races for that person", {
selenium.waitForPageToLoad("5000")
selenium.getText("//b").shouldBeEqualTo "no races found for this person"
}
}
Remember, these fixture constructs are executed for each scenario in a story– at this point, one time fixture logic can be easily added to a story by placing it outside the construct of a scenario. If you haven’t taken easyb for a test drive yet, go for it, man!!
1 comment Friday 16 May 2008 | Andy | Developer Testing, Groovy

Gant is a Groovy-based build system that uses Ant’s extensive collection of flower power tasks without all of the nasty XML– this enables you to leverage greater flexibly when it comes to hiply assembling software. Capitalizing on this flexibility within a CI process, however, can be somewhat challenging, unless, that is, you happen to be using Hudson, baby!
Hudson is an open source CI server that is particularly interesting given its ease of configuration and its compelling plug-ins, which provide increased visibility into such aspects as test result trends, for instance. What’s more, because it’s Hudson’s bag, baby, it has a copasetic Gant plug-in that enables you to easily employ Gant as a build process for any CI project.
Setting up the Gant plug-in is easy too– all it takes is 5 steps.
First, download the plug-in.

Next, you need to upload the smokin’ plug-in into Hudson– to do this, you need to go to your Hudson server’s home page and select the Manage Hudson link. This link is on the upper left corner of the page. Once you hit that link, you’ll be presented to with a list of options for managing Hudson. Select the Manage Plugins link, baby.

Once you’ve hit that link, you should see a small form that allows you to select the plug-in on your local machine and upload it. Do that!

So far, pretty easy, eh? Don’t worry, it doesn’t get any more difficult either– the next step is to globally configure the plug-in. This involves doing one thing– pointing Hudson to your installation of Gant, which if you’re following Gant’s instructions, is essentially is your Groovy installation. Therefore, go back to the Manage Hudson link and click the System Configuration link.

From there, find the Gant section. There are two form elements that require information– the name of your Gant instance and GROOVY_HOME (which is where you installed Groovy, man).
You’ll notice that you can multiple instances of Gant configured; hence, I usually make the name the version number of the underlying Gant instance in use.
Lastly, you’ve got to configure a particular job to use that version of Gant. During a job setup, you’ll note in the Build section, you can now select the Invoke Gant script checkbox. What a trip!

Once you select the checkbox, you’ll be presented with two form elements– which Gant version to use (this is drop down list with the various names from your global configuration) and which commands to invoke. By the way, you’ll note that the form says “Ant Version”– don’t be fooled though– simple typo, man. Once you are done configuring the job, don’t forget to hit the save button. I usually like to force a build to verify things are copasetic.
That’s it, baby! You are all done and ready to go with Gant and Hudson. Can you dig it?
2 comments Thursday 15 May 2008 | Andy | Continuous Integration, Groovy
On more than one occasion, I’ve been asked by various hip developers if there was a conversion script for transforming existing Ant build files into Gant build files. Russel Winder, the copasetic guru behind Gant updated the Gant website with a link to a trippin’ script (dubbed ant2gant.groovy) that’ll do just that, baby!
I tested it out with a normal Ant build file and it worked like a charm– just make sure you have in your classpath:
ant.jar (I used 1.7.0)ant-launcher.jar (I used 1.7.0 as well)commons-cli.jar (I used 1.1)Also too, my Ant build.xml file had a path element living outside of a target like so:
<path id="build.classpath">
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</path>
This was causing the script (really Ant’s Project object) to blow up; consequently, I moved it into an initializing target and things worked copasetically from there.
If you haven’t tried Gant yet and you find yourself beating your head against the wall when it comes to adding behavior to Ant (such as looping, etc), then give your head a rest and take a look at Gant– this is a smokin’ tool that adds a refreshing level of flexibility and expressiveness to Ant (using Groovy, man!).
2 comments Monday 28 Apr 2008 | Andy | Build Process, Groovy
The hip folks over at easyb.org have released version 0.8 of easyb. If you haven’t seen easyb yet, then you are in a for a real treat as easyb is the coolest thing since sliced bread, baby. As a BDD framework for the Java platform, easyb makes it super easy to craft executable documentation for software requirements by leveraging a flexible (and easy) story based domain specific language.
What’s particularly copasetic about the 0.8 release is the inclusion of a new IntelliJ plug-in, which makes working with easyb, well, even easier (if that’s possible, man). Many thanks to Rod Coffin for his hard work on this and the Maven 2 plug-in!
The DSL has been refined slightly to permit adding a description phrase (way to go Rodrigo Urubatan!); plus, because it’s everyone’s bag, you can chain phrases via and now– the DSL now permits a second repeated phrase substitute and instead as follows:
scenario "text",{
given "text", {}
and "given text", {}
when "text", {}
then "text", {}
and "then text", {}
}
Abstract stories are now possible; thus, the proceeding closure to any phrase is now optional– easyb will make the story as pending. Kudos to Ken Brooks for this and the vast reporting improvements!
Other noteworthy changes:
shouldNotHaveIf you haven’t had a chance to check out easyb, then start lookin’ baby! See the mailing list or be a copasetic disco dancer and just download it!
1 comment Thursday 03 Apr 2008 | Andy | Developer Testing, Groovy
New to Groovy? Fear not, hip daredevil! While “Groovy in Action” is undoubtedly your vade mecum as it is for countless other madcaps, the copasetic folks at IBM developerWorks have recently published “Fluently Groovy” to quell your Groovy thirsts, baby.
This tutorial is for hip developers unfamiliar with Groovy and who want a quick and copasetic introduction to the basics, man. Get started with Groovy’s simplified variation of the Java syntax and learn about essential features like native collections and closures. Write your first Groovy class, and then see how easily you can use JUnit to test it, baby.
Because it’s your bag, you’ll walk (no, dance!) away from this one-hour tutorial with a fully functioning Groovy development environment and the skills to use it. Right on! Best of all, you’ll have learned first-hand how to use Groovy and Java code together in your everyday Java application development. How’s that sound for a party, baby?! What are you waiting for? Read on!
2 comments Monday 31 Mar 2008 | Andy | Articles, Groovy
Software metrics are objective measurements of particular aspects of code– for instance, Cyclomatic complexity measures complexity without any regard for why code contains a certain number of paths. For metrics to be useful, baby, they must be applied subjectively. In the case of complexity, there may be circumstances that warrant such code (although, I’ve yet to find complex code that still can’t benefit from refactoring). I’ve also found that, on the whole, metrics are more copasetic when combined with other metrics and trended– for instance, complexity alone is somewhat interesting, but pairing complexity with code coverage paints a much more detailed metric that bears understanding. High complexity with low coverage is clearly more risky than the same complexity with high code coverage– even the CRAP metric holds this relationship.
One particular hip metric that I find helpful is the ratio of copy and pasted code within a code base as unknown copy and pasted code will haunt you, man. For instance, copy and pasted code replicates bugs and poorly coded algorithms to name a few nefarious aspects; consequently, understanding what code has been replicated can help teams refactor offending code. Having run various copy and paste analyzers on more code bases than I care to admit, (and because it’s my bag) I’ve found that all code bases have a certain level of offending code that triggers a copy and paste detection. One particular tool, CPD, is nice enough to create a report containing the offending code like so:
<duplication lines="7" tokens="53">
<file line="36" path="cbd4/blackjack/src/com/stelligent/blackjack/Hand.java"/>
<file line="42" path="cbd4/blackjack/src/com/stelligent/blackjack/Hand.java"/>
<file line="48" path="cbd4/blackjack/src/com/stelligent/blackjack/Hand.java"/>
<codefragment>
<![CDATA[
} else if (first.equals("Jack")) {
if(!second.equals("King") && !second.equals("Queen") && !second.equals("Jack")){
return Integer.parseInt(second) + 10;
} else {
return 20;
}
}else if(first.equals("9")){
]]>
</codefragment>
</duplication>
As you can see, CPD reports the total number of lines of copy and pasted code and where that bogue code can be found. This data is certainly helpful; however, it doesn’t paint the entire story– while 7 lines doesn’t seem like all that much code, you’d probably reconsider if it were 7 lines of code in a 30 line code base or more realistically– 700 lines in a few thousand line code base. Therein lies the catch– CPD’s data is really only helpful when viewed on the whole (or a ratio– that is, total lines of copy and pasted code over total lines of code). Unfortunately, CPD doesn’t report the total lines of code scanned– only the total lines of copy and pasted code. For instance, in this sample code base, there were 9 suspected copy and pasted code fragments totaling about 120 lines of code (or CPLOC).
Luckily, there’s another handy tool which reports the total lines of code (or LOC) in a code base– JavaNCSS. Running JavaNCSS yielded a value of about 610 LOC; therefore the ratio of copy and pasted code is CPLOC/LOC or 120/610, which is roughly 20%.
20% CPLOC is probably a bad thing– at a minimum is is worth knowing about. 20% today might not be too important to know, but knowing that it increased to 25% next week would be an indication that things are degrading– likewise, seeing a value decrease over time indicates the code base is actively being improved. Yet, how can teams possibly monitor this trippin’ data?
Reports are hip, but in truth, reports by tools like CPD are essentially read once– the first time they are generated. After that, it’s anyone’s guess when someone will actively read the report again. Hence, I find it particularly helpful to essentially throw the report out and let the build itself proactively tell me when a particular metric gets out of hand. This essentially means that my build has to monitor a particular metric– and in the case of the CPLOC ratio, my build has to gather data from two sources– JavaNCSS’s report and CPD’s.
Fortunately, this is easy with Groovy– if your instance, you are using Ant for builds, you can first generate the two reports as follows:
<target name="cpd">
<mkdir dir="target/reports"/>
<taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask"
classpathref="classpath"/>
<cpd minimumTokenCount="10" outputFile="target/reports/cpd.xml" format="xml">
<fileset dir="src">
<include name="**/*.java"/>
</fileset>
</cpd>
</target>
The code above generates a CPD XML report from all the code in a src directory and the following code creates a JavaNCSS report from the same code base:
<target name="javancss">
<taskdef name="javancss" classname="javancss.JavancssAntTask"
classpathref="classpath" />
<javancss srcdir="src" generateReport="true"
abortOnFail="true" ccnPerFuncMax="100"
outputfile="target/reports/javancss_metrics.xml" format="xml" />
</target>
The only high-level step left to do is to put the two metrics together; however, this step actually takes a few sub-steps, baby. For instance, obtaining the total lines of CPLOC requires iterating over a collection of duplication elements in the CPD xml file. Consequently, the following steps detail the effort required to obtain this metric:
Groovy, by the way, is particularly well suited for such a task (as if you didn’t know that, man?)– parsing XML with Groovy is practically effortless– like disco dancing, eh? For instance, obtaining the total LOC from JavaNCSS’s xml file is as easy as
int ncss = Integer.parseInt(jncssroot.packages.total.ncss.text())
Note, I’m coercing integer values as I’d like to divide (and round) my result– if I don’t explicitly specify int’s I’ll be left with String division, which doesn’t work so well.
Parsing CPD’s xml document is slightly more complex– slightly in that it takes 3 times as much code:
def cpdtot = 0
cpdroot.duplication.each { elem ->
cpdtot += Integer.parseInt(elem.@lines.text())
}
Again, parsing an XML document yields String values; accordingly, I need to use Integer’s parseInt method.
Next, all I need to do is divide the two and, in my case, I’m aggressively rounding up via Java’s ceiling call as follows:
def ratio = Math.ceil((cpdtot / ncss) * 100)
Multiplying the result by 100 gives me a percentage value, of course, and lastly, I compare that to a threshold value:
if(ratio > Double.parseDouble(properties.cpd_threshold)){
ant.fail(message:
"cut and paste ratio was greater than ${properties.cpd_threshold}%, it was ${ratio}%")
}
Puttin’ it all together, baby, yields a groovy Ant script with a hip target:
<target name="cpd-threshold" depends="metrics">
<groovy>
def jncssroot = new XmlSlurper().parse("target/reports/javancss_metrics.xml")
int ncss = Integer.parseInt(jncssroot.packages.total.ncss.text())
def cpdroot = new XmlSlurper().parse("target/reports/cpd.xml")
def cpdtot = 0
cpdroot.duplication.each { elem ->
cpdtot += Integer.parseInt(elem.@lines.text())
}
def ratio = Math.ceil((cpdtot / ncss) * 100)
if(ratio > Double.parseDouble(properties.cpd_threshold)){
ant.fail(message:
"cut and paste ratio was greater than ${properties.cpd_threshold}%, it was ${ratio}%")
}
</groovy>
</target>
Reports are hip, but they are usually only read once– the first time they are generated. Rather than waiting to find out that there’s a problem, proactively analyzing a hip metric (such CPLOC/LOC) enables rapid feedback and rapid corrections– is that unambiguous or what?
0 comments Thursday 20 Mar 2008 | Andy | Code Metrics, Groovy