I just started hating Java

By Confusion on Thursday 7 January 2010 15:42 - Comments (32)
Categories: Java, Python, Software engineering, Views: 8.245

A new year, a new hatred. I've just officially begun hating the language in which I do most of my work: Java. The tiresome verboseness finally got to me. Please compare with me:


Java:
1
2
3
4
5
6
7
8
9
10
11
12
private static String joinObjectFields(final List<SomeObject> objects, 
        final Character seperator, final SomeObject exclude) {

        String result = "";
        for (SomeObject object: objects) {
            if (!object.equals(exclude)) {
                result += object.someField + seperator;
            }
        }
        // Strip last ; (and see edit3)
        return result.substring(0, result.length() - 1);
    }




Python:
1
2
3
4
def joinObjectFields(objects, seperator, exclude):

  fields = [object.someField for object in objects if object != exclude]
  return seperator.join(fields)



To prevent "these pieces of code don't do the same thing", an alternate Java implementation, more like the Python one:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static String joinObjectFields(final List<SomeObject> objects, 
        final Character seperator, final SomeObject exclude) {

        final String[] fields = new String[objects.size()];
        for (int i = 0; i < fields.length; i++) {
            if (!object.get(i).equals(exclude)) {
                fields[i] = object.someField;
            }
            else {
                fields[i] = "";
            }
        }
        return StringUtils.join(fields, ';');
    }


Doesn't get much better, even if you would initialize the array to contain "" in every field using a utility method.

For extra hatred, consider the necessary changes to the code to enable the same method to join the contents of a different object field.

Edit: A colleague noted that cloning the list and removing the 'exclude' would make matters slightly better.

Edit2: And before someone starts calling me a Python fanboy: you can also do this in a much shorter fashion in Scheme, Ruby, Perl, Scala, Lisp/Clojure, etc.

Edit3: And of course I stupidly forgot to check whether result.length() is actually > 0 in the first implementation.

Edit4: As JanDM rightly points out, I shouldn't use curly braces in Python :P.

Edit 5: This version in Java, posted by Markus in the comments, is far superior: I wasn't making any sense here: the code does a different thing.

Avoid storing configuration data in your revision control system

By Confusion on Tuesday 20 October 2009 22:02 - Comments (3)
Categories: Java, Software engineering, XML, Views: 4.792

After a discussion with a colleague this afternoon, I thought I'd share the following: you should avoid storing configuration data in your revision control system. Especially authentication credentials should not be in there. Here's why:
  1. When securing servers and networks, things like the server hosting an RCS don't get the same priority as, say, your web facing production server. Mistakes are easy to make and you can simply use Google to find 'accidentally' web facing RCS's that expose passwords.
  2. There will be plenty of copies 'out there', outside of your control. How many developers have that data stored on their machine? How careful are they with their laptops and your production passwords?
  3. Access to the configuration is limited to those that should be able to change it: no accidental changes by a junior performing a careless check in.
  4. If you can use the exact same build for your development, test/staging and production environment, then you can cleanly separate between code problems and configuration problems. If you need to rebuild a distributable archive to have the build process include environment-specific configuration, there will always be the doubt that some other difference may have sneaked in.
  5. It's much easier to change the configuration if you don't have to make a new build to deploy the change.
Now I specifically say 'avoid' and not 'do not ever', because many frameworks do not make this separation particularly easy. In the Java world, standard frameworks like Maven, Spring and Hibernate all impose obstacles to succeed at keeping sensitive configuration data out of RCS's.

Maven is a build tool that offers all kinds of build-time placeholder substitution capabilities, which is diametrically opposed to this advice. Spring does dependency injection and the configuration to wire your application together strongly attracts other types of configuration data to be included with it. And if you are paranoid enough to give production databases different names, so you can never accidentally run a test against a production database: how do you get that name into your Hibernate OR mappings at startup time?

It takes careful thought and thorough understanding of the build and startup processes, but in my opinion it is well worth it. Every time I deploy a new version of the one application in which configuration and code are completely separated, where I just have to drop a new .jar and restart, I dance with joy.

A simple Java puzzler

By Confusion on Thursday 18 June 2009 14:59 - Comments (17)
Categories: Java, Software engineering, Views: 2.905


Java:
1
2
final long YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365;
        System.out.println(YEAR_IN_MS);


What will be printed?

Undecipherable product descriptions

By Confusion on Friday 12 June 2009 17:57 - Comments (4)
Categories: Java, Software engineering, Views: 2.527

Today I had to merge a Flex frontend into a Java project. Inside the Flex project, in a 'lib' directory, I found something called 'cairngorm.swc'. Having no experience with development in Flex, I had no clue what this file was. The person responsible was not available at the moment, so I did the only natural thing: Google it. That turned up Adobe's homepage for Cairngorm. The first section, which your eye falls onto when you view the page, is titled 'Overview' and reads:
Cairngorm is the lightweight micro-architecture for Rich Internet Applications built in Flex or AIR. A collaboration of recognized design patterns, Cairngorm exemplifies and encourages best-practices for RIA development advocated by Adobe Consulting, encourages best-practice leverage of the underlying Flex framework, while making it easier for medium to large teams of software engineers deliver medium to large scale, mission-critical Rich Internet Applications.
[..]
Ehmmm, yeah, right. Thanks for making me feel stupid. Now I still don't know whether it's a library that I need to include to get the application to run, a standalone Flex viewer/debugger or a collection of examples. By clicking "More information" and reading further, I didn't actually get more information. Only after a PgDn I finally encountered
The Cairngorm microarchitecture is intended as a framework for Enterprise RIA developers.
ah, framework. That's a word I know. So it's a library.

I have this kind of experience more often than I like to: I read an introduction to something and afterwards I still have no idea what the thing is. Is it just me or do you also feel introductions should start with the simple facts and purpose and maybe expand towards an all-encompassing vision of the developers towards the end, rather than starting out that way and leaving you at a plane of abstraction that causes you to miss the actual simplicity of the thing?

Nasty Java HashMap race condition

By Confusion on Tuesday 9 June 2009 22:03 - Comments (13)
Categories: Java, Software engineering, Views: 11.656

After reading this I think I need to check some applications I wrote in the past.

The piece is excellent and details matter, but I'll attempt a summary anyway:
if you use a regular HashMap in a multithreaded environment, it seems the worst that can happen is that you incur some additional cache misses due to race conditions. In a lot of situations that is perfectly acceptable and since wrapping the HashMap with Collections.synchronizedMap() incurs quite a performance penalty (and at that point, that was basically the choice), you are tempted to just leave the HashMap in. Don't. The 'put' operation may trigger a resize and redistribution of the internal data structure of the HashMap that can thoroughly hose it is concurrently accessed during the restructing , to the extent that your program goes into an infinite loop.

These days, there isn't any performance reason to decide in favor of the regular HashMap: the java.util.concurrent.ConcurrentHashMap has excellent performance, even in singlethreaded applications. However, I think I've made the mistake of using a regular HashMap somewhere in the past. However, the application has never malfunctioned (as far as I know), so it may well be that the chances of this bug occurring are so small that they are negligible for all practical purposes. Nevertheless, unless you want to do the math, replacing it by a ConcurrentHashMap is a safe bet.