Wednesday, October 27, 2010

InfoQ: Sharpening the Tools

This is a very nice presentation very well led by Dan North. It offers several insights and hints, but I'd like to quote a couple of things.

At a certain point Dan says he doesn't like learning lunches too much, as the fact that you don't commit completely to learning but do it while you're eating somehow implies that education is not important, while it should be part of the job you're (hopefully) being paid for. It is sadly true, yet we have to work with what we've got: it will come as no surprise that I attend all these presentations in my lunchtime, but I found that given the circumstances it's much more effective than trying to reserve a full hour during the rest of the day.

The most important advices are found in the conclusive slide:
  • always assume you're out of date
  • you owe it to yourself to keep current
So... how much do you know what you don't know?

Thursday, October 21, 2010

Registrations are open!

It is now possibile to register for the 7th Italian Agile day which will be held in Genova on November 19. Hurry up!

The proposed program is very interesting as usual, and as usual I'd like to follow many talks at the same time... I wonder what I would do if I weren't ubiquitous...

Wednesday, October 20, 2010

InfoQ: Danger! Software Craftsmen at Work

I never liked presentations in which the presenter reads too much, or at least gives that impression; this is one of the reasons for which I found this presentation on InfoQ way too long. Furthermore, I think David Harvey takes things to the limit a little bit.

Yet, there is a sentence that I'd like to quote:

The customer is always right, but sometimes they need a little help... and we need to learn about the customer's world.


So there is a real danger here, and it lies within us. Mark the second part of the sentence, because that's the real important one: customers pay us because we provide value for their business, not because we write beautiful code. Customers don't care at all about the quality of our work as far as their business is concerned. To businessmen only business is important, not code.

A word of caution: that doesn't means that we have to be sloppy, for at least a couple of reasons:
  • our personal pride on what we do (after all, we claim to be craftsmans, don't we?)
    • I know someone will not care about this point. I do.
  • customers will sooner or later notice that each and every simple functionality they ask for costs more and more as time passes and functionalities are added, thus throwing us out of their business.
    • This would probably be no good, because we would end up showing boards...

Sunday, October 17, 2010

Varargs for creating lists

I confess I am not so used to varargs yet, but sometimes they can be very useful, e.g. when you want to create a list and punch in some objects in one shot:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
Without the Arrays class you should use the old boring construct:
List<String> stooges = new ArrayList<String>
stooges.add("Larry");
stooges.add("Moe")
stooges.add("Curly");
The former is much better!

Waiting for JMock 2.6.0

JMock is a library that supports TDD of Java code with mock objects. To mock an object the actual syntax (version 2.5.1) is the following one:
final MyObject myObject = context.mock(MyObject.class)
This is plain vanilla code, but things are getting even better in 2.6.0 thanks to the @Mock annotation:
@Mock MyClass myClass
I think it will be difficult to shrink it more than this... looking forward to the release!

Friday, October 15, 2010

Meet Dozer

Integration between systems is one of the most typical reasons of failure in complex projects. Yet, we find ourselves doing it day after day, so after some strategic mapping you have to get your hands dirty and map your wonderful objects to that incredible garbage other vendors still insist to call code. Or was it the other way round?

Let's assume a simple interaction via web services exposed on, say, an i-Series platform. I don't know whether all RPGLE programmers work in the same way, but almost all services of that kind I've seen so far have a single port with a thousand parameters for a hundred of different purposes and it is up to you to try and understand which of them must be used in which occasion. If that was not enough (and for me it is) it seems there is a contest for the use of the most cryptic parameter names, for which vowels seem to be banished and six characters is considered more than ehough (when not a waste of space).

One of the many things you learn with DDD is that code should be as close as possibile to your mental representation of the domain: well, LDLSDC does not make me think of a list of documents, but maybe it's my fault.

That said, before I use those objects in my code I'll have to convert them. The typical mapper has a signature similar to the following one:
public MyObject convert(YourObject yours, MyObject mine)
or
public MyObject convert(YourObject yours, MyObject.class)
The implementation is normally something like this:
myObject.setPropertyOne(yourObject.getPropertyOne);
myObject.setPropertyTwo(yourObject.getPropertyTwoButHasDifferentName)
(repeat ad lib for each property to be mapped)

This is very frustrating and most of all error prone. This is where several libraries step forward, most of them based on reflection, each of them having pluses and minuses. So far, the most interesting one I've found is Dozer, a bean to bean mapper that recursively copies data from one object to another (of a different type, of course! where would the fun be otherwise?). By the way, integrating different systems is just one of many reasons you have for mapping between different objects.

Using Dozer is just as easy as downloading the jar file, adding it to the classpath (don't forget the dependencies!) and coding right away:
Mapper mapper = new DozerBeanMapper();
Destination destination = mapper.map(source, Destination.class);
(almost utterly copied from the official tutorial). That's it. All fields with the same name are automagically mapped, with Dozer taking care of the necessary conversions (at least the more common ones). Should you need to customize mappings you may add some xml files that define how Dozer should behave:
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net
http://dozer.sourceforge.net/schema/beanmapping.xsd">

<configuration>
<stop-on-errors>true</stop-on-errors>
<date-format>MM/dd/yyyy HH:mm</date-format>
<wildcard>true</wildcard>
</configuration>

<mapping>
<class-a>yourpackage.yourSourceClassName</class-a>
<class-b>yourpackage.yourDestinationClassName</class-b>
<field>
<A>yourSourceFieldName</A>
<B>yourDestinationFieldName</B>
</field>
</mapping>

other custom class mappings would go here.......

</mappings>
And this is copied from the official manual.

You can also introduce a custom converter that you can reuse through your application:
<converter type="org.dozer.converters.TestCustomConverter" >
<class-a>org.dozer.vo.CustomDoubleObject</class-a>
<class-b>java.lang.Double</class-b>
</converter>
and its corresponding class:
public class TestCustomConverter implements CustomConverter {

public Object convert(Object destination, Object source, Class destClass, Class sourceClass) {
if (source == null) {
return null;
}
CustomDoubleObject dest = null;
if (source instanceof Double) {
// check to see if the object already exists
if (destination == null) {
dest = new CustomDoubleObject();
} else {
dest = (CustomDoubleObject) destination;
}
dest.setTheDouble(((Double) source).doubleValue());
return dest;
} else if (source instanceof CustomDoubleObject) {
double sourceObj = ((CustomDoubleObject) source).getTheDouble();
return new Double(sourceObj);
} else {
throw new MappingException("Converter TestCustomConverter used incorrectly. Arguments passed in were:" + destination + " and " + source);
}
}
}
And now a personal reminder: if you have to map an array of objects, but you know the types that you will find in specified positions AND want to avoid class cast exceptions (and I guess you do), you can use this syntax:
<field>
<a>myObjects[0]</a>
<b>other.propOne</b>
<a-hint>java.lang.Long</a-hint>
</field>
<field>
<a>myObjects[1]</a>
<b>other.propTwo</b>
<a-hint>java.lang.Short</a-hint>
</field>
Next thing I'm gonna try is the mapping for POJOs and JAXB objects...

Spiderman busted!

This is the revenge of J.Jonah Jameson...


The picture is one of the most beautiful ones shot by Los Angeles Times Photographers in 2009; find the others here.

Tuesday, October 12, 2010

InfoQ: Agile Team Meets a Fixed Price Contract

I found another interesting article on fixed price contracts managed in an agile way. It also adds some considerations on budget spent, which you don't normally find in articles of the same kind.

Friday, October 8, 2010

Improved JUnit support in NetBeans 7.0

The 7.0 release of NetBeans will extend the support for the JUnit framework addind the following functionalities (I'm told some of them can already be found on Eclipse):
  • The 4.8.2 release of the JUnit library has been integrated.
  • You can now run or debug a single test case (method) in a suite (class) from the editor context menu.
  • It's now possible to rerun only failed tests.
  • The filtering of the test results view was improved. It' now allowed to select the result states (passed, failed, error) which will be hidden in the result view.
  • The tabbed output was implemented for the test results view.
All the relevant informations can be found on the official NetBeans site.

Thursday, October 7, 2010

Don't forget the content type

In one of our legacy projects all web services were exposed through SAAJ servlets; having to expose a new one we opted for a newer JAX-WS style, also thanks to everything that NetBeans gives you right out of the box.

So we created a new Web Service (you can check this tutorial to see how it is done) and wrote all the tests and code we needed. Everything went fine, until we tried to test the whole project (which should be mandatory before you commit).

At this point some of our old tests failed, all reporting the same error:
SAAJ0532: Absent Content-Type
The offending code builds a message that we use to test the parser:
private SOAPMessage buildMessage(String filename) throws IOException,  SOAPException {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(basepath + filename);
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage(new MimeHeaders(), resourceAsStream);
return message;
}
At first it caught me off balance because our additions and changes went nowhere near the code related to the failure. Then it must be something related to the environment, which is the fact that NetBeans added a dependency on the JAX-WS 2.1 library that probably has some conflicts with the SOAP jars we use.

As some manual tests seemed to confirm that the application is working normally, we deferred the investigations (not for very much longer!) and simply fixed the test:
private SOAPMessage buildMessage(String filename) throws IOException,  SOAPException {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(basepath + filename);
MessageFactory messageFactory = MessageFactory.newInstance();
MimeHeaders headers = new MimeHeaders();
headers.addHeader("Content-Type", "text/xml");
SOAPMessage message = messageFactory.createMessage(headers, resourceAsStream);
return message;
}
And now an afterthought. The test failed, yet the application did not. Does this mean our test was wrong? Actually it only means that the previous library was more forgiving, because the test has proved useful for a long time (also spotting a regression). It is better to have a not-so-perfect test than none at all.

Wednesday, October 6, 2010

InfoQ: Technical Debt a Perspective for Managers

Another interesting article on technical debt; the most important thing that emerges is that management must buy and support the need for getting rid of it.

The price you pay for technical debt is not on the barrelhead: it's all an hidden cost, and it grows in a non-linear manner with time. Think about it.