Friday, June 18, 2010

Property interfaces and Guava functional programming

Something that I’ve been thinking about lately is how I can make it easier to use Guava’s methods that operate on Functions, Predicates, etc.

One simple use for Functions is to get properties of objects, allowing you to (among other things) create a transformed view of a collection containing a certain property from each element. For example, transforming a list of Person objects to a String collection of names. Any time you want to do something with a collection of objects based on a certain property of those objects, this is useful.

However, it's rather ugly and awkward to have to create an anonymous inner class inline when calling a method that uses a Function. While you can create static final instances of such functions and methods that return instances of functions, with many classes you could end up with many such instances and methods. One good way to reduce the number of Function objects you need to create and make it easy to work with certain common properties (such as IDs, names, etc.) on many objects is to create interfaces that each expose a single such property:

Not only does this help add consistency to your classes, it allows you to collect behavior that can work on any type of object that has the property the interface exposes. I'd probably name such classes as the plural of the property name ("Ids" and "Names", for example).

This makes working with the IDs of a list of things with IDs as easy as possible:

The GET function is exposed to allow its use for anything you might want a function for, not just tranform. For example, with a HasName interface and Names class similar to the code for IDs, I could do something like this:

This would of course filter a list of people to an iterable that only includes people with the name Bob. It uses static imports (because they make this stuff read a lot nicer), and the methods are:

I think this approach can make working with the properties of objects using Functions a lot easier and cleaner, while also encouraging more consistency between classes in general, which is nice.

Thursday, March 25, 2010

Get your UI out of my logic

I really don't like seeing something like this used in a domain object.

I've also seen a list of objects retrieved from the database and put into an Object array with "Select" as array[0] and the rest of the objects being actual objects someone might care about. Let's just have everyone remember what type of objects are in this array, and they should also remember that the first element isn't one of those!

I can't imagine what people find so hard about producing a new list or whatever to base their combo box model on at the time that the combo box is actually created. Furthermore, with something like the enum above, the enum constants use lowercase letters because it'll look nicer when they're rendered in the UI using the default toString(). The use of toString() to produce the text for the UI in general bothers me. I want it to produce text that's helpful to me in error messages... use some other means for rendering it to users.

I guess what I want to say is: keep user interface concerns where they belong, near the user interface!

Friday, January 22, 2010

What's the issue with @Inject?

Reading Uncle Bob's recent post about dependency injection frameworks, I noticed that quite a few people seemed to be treating the use of Guice's @Inject annotation in their application code as a reason to prefer other DI frameworks to Guice. For the most part, none of them provided any explanation for why using the annotation in application code was a problem other than "I don't like it". Even ignoring the fact that JSR-330 standardizes the only annotations and the one interface from Guice that are used in application code and will be usable with Guice 2.1, I find it difficult to understand these points of view. What's the issue people have with it?

Why it's good

@Inject is just one annotation that, in a typical concrete class, will be used on one constructor and MAYBE a couple setters. It allows dependencies to be injected without any explicit configuration of the Spring XML form while retaining safe and predictable behavior by ensuring that injections always take place using the exact constructors and methods you want to use. It saves you from ever having to specify anything using strings, making it possible to refactor and rename classes and methods without any risk of breaking your DI configuration... I think this is an extremely important point. It generally doesn't allow anything unexpected to happen.

Tied to the framework?

I feel like the knee-jerk reaction to using @Inject in classes is that by doing that, you're somehow tying yourself to Guice. As Uncle Bob put it,

I don’t want to write a Guice application. Guice is a framework, and I don’t want framework code smeared all through my application. [...] I don’t want to have @Inject attributes everywhere [...]
I understand that when he says this, Uncle Bob is arguing against using DI frameworks in general. Ignoring that argument for now and accepting that DI frameworks are worth using, the fact is that if you're using a DI framework, you are tying yourself to it. It's how your application is configured, unless you're doing all the work to create an alternate way of wiring the application together in which case... why? If you choose to switch to another DI framework or stop using a DI framework entirely (and how likely are either of these, really?) it is going to involve some work to remove the existing configuration and write the new configuration. And removing a bunch of @Inject annotations would be an absolutely trivial part of that.

Annotations are not code

I think it's important to note that annotations are not code. By themselves, they do nothing. You can use a class even without the annotations on its elements available on the classpath. When writing tests, you can completely ignore them. Guice's annotations will also never be in the body of your code, meaning you should generally be able to ignore them when reasoning about how a class behaves. One comment I read (from a Spring XML user) stated that the commenter considered annotations "just as bad" as code and likened the @Inject annotation to providing your classes with the ApplicationContext (Spring's central container interface). This is, of course, way off base. Providing programmatic access to the central container ties the code itself to the DI framework. The class can then use the framework's code directly to get access to any object it wants, anywhere in its code. Testing the class would require configuring a container and looking through the class to see what needs to be in it. The framework becomes a Service Locator framework. The @Inject annotation imposes no such thing.

In general, I think the benefits provided by Guice and the configuration safety provided by the use of @Inject far outweigh the at most minor annoyance of placing an annotation or so per injectable class. In future posts I'd like to talk more about what I like about dependency injection and Guice.