Showing posts with label field. Show all posts
Showing posts with label field. Show all posts

Tuesday, September 13, 2011

Communicate code intention I: Nulls

It's all about communication... Really!

As programmer one thing you do is to communicate with the computer so it does whatever you want.
However the computer isn't the only one you interact with. Your code is is something you tell to the computer and the team. Is communication of actions and intentions what makes the computer do things.
And this is the key part of the communication: intentions.

While the language of your choice may be able to communicate some intentions very explicitly, some others don't. This is where you should put your effort. Communicating your intentions is essential for your team and for your future self. Yes, you think you will remember but you won't.
The more you code, the lesser the probabilities are you will remember what was the intention of each line.

So, how do you manage to communicate all the implicit decisions and knowledge that is used on the code? You don't! Because you cannot reflect all the implicit decisions. But at least, you try to express as much as is useful for you and your team.

Use annotations to communicate expected behavior with nulls

I use two extra annotations just for the purpose of communication. They don't change the behavior of the program nor are compiled. They are discarded on compilation but they help me and the team know what we should expect when using a method or passing parameters.

@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({ ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER, ElementType.METHOD })
public @interface CantBeNull {

}

@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({ ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER, ElementType.METHOD })
public @interface MayBeNull {

}
As you can see these annotations are only retained on the source level and can be used on parameters, methods, variables and class fields.

Of course, you can live without these, or make your own. The idea here is to communicate what your code expects as input and how it will behave as output. Communicating this information on the code has proved to be valuable for others and myself after months of coding.

Don't overuse
Remember the goal: communication. If you use them everywhere and without a second thought they will become noise, and people ignore noise. So all your extra effort will be in vain. Just use it when the code isn't clear or can be prone to errors.
If you use Hibernate or other frameworks that have similar annotations just use those. Don't add these mechanically as they are redundant in presence of similar annotations.

Uses
These are the main use cases

  • On methods: Indicate whether is safe to use the return value as null-impossible, or you should do extra checks
  • On method arguments: Indicate whether the method can handle null values or you may provoke a NullPointerException if careless.
  • On class fields: Indicate whether the class is designed to handle null on that field, or some parts of the class rely on the assumption of not null.
  • On local variable: This case is rare and I don't use it very much because I try to make short methods. But just in case, you can indicate whether or not a local variable can be made null during a loop or similar.



Tuesday, August 23, 2011

Don't use String literals for Reflection

Do you know what this line of code is for?


@OneToMany(mappedBy = "assignedInvoice")
private List<PurchaseOrderAssignment> purchaseOrders;



And this one?

Class.forName("java.lang.String")


Or this one?


Field nameField = Person.class.getField("name");


Ok, not so difficult.
First one is a Hibernate annotation for mapping a one-to-many relationship indicating wich field is the owner. The second one is how you obtain a reference to a class Object for String class. And the third one is how you obtain the "name" field of the class "Person" using reflection.
If you have been around Java long enough you should be familiar with of these forms of reflection.

Now. Can you tell what's wrong with them? (hint: the tittle of this article can help you)
Yes! There are using string literals to refer to class structure elements.

And why is that wrong?
Because doing so you loose the relationship with the referred element. Your code looses the information about structure dependencies.
Using string literals you cannot know where all the reflections references to some class field are, prior to a refactor.You cannot change the name of the field in one place and expect to automatically update all the references (remember DRY?).

In other words you are making implicit an existing dependency relationship between referred and referral code and you start to loose control over changes.

What should I do then?
Until the RFE(http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5043025) is implemented in the JDK, we will have to content ourselves with String constants.
We cannot honor the DRY principle, but at least we can repeat ourselves just once.

I propose you to declare a constant with the name of the field, or the class, or whatever you may need to refer using reflection, very near to the place where it is declared.

As an example to the one-to-many relationship counterpart:



  @ManyToOne
  private Invoice assignedInvoice;
  public static final String assignedInvoice_FIELD = "assignedInvoice";


Here I declare the field and below the constant to refer to it with reflection.
I then, use that constant (assignedInvoice_FIELD) to refer to the field using any form of reflection (annotations too).


@OneToMany(mappedBy = PurchaseOrderAssignment.assignedInvoice_FIELD)
private List<PurchaseOrderAssignment> purchaseOrders;




The sad part is that you have to update the constant every time you rename the field (or class), but luckily you won't be changing that too much and in case you do, you will have to change just one place.
The nice part is that now, you can see where all your reflections references are with most IDEs and if you happen to delete or rename the field carelessly, having that constant near is a reminder of the existing dependencies.

Of course this is not an ideal solution, but is good enough to keep you in control of your code.

Extra note
I prefer to use "_FIELD" as a suffix when the constant refers a field so that the IDE auto-completion capabilities offers me the constant and I know that is not a getter or setter method. I use "_GETTER" suffix when the property is not available as a field on the class.

Other interesting articles