Etikettarkiv: guava

Preconditions in Google Guava

Detta inlägg finns även att läsa på HRM Softwares teknikblogg!

While the Guava project from Google comes packed with goodies for Java developers there is one thing in particular that I tend to use over, over and over again. Actually there used to be two of those, but since Java 8 comes with their own implementation of Optional I have shifted over towards that implementation instead. Anyway, the topic of this short text is Preconditions in Google Guava.

You can think of preconditions in Guava (as the word suggests) as a way to express and enforce preconditions that must be true in order for the execution to continue. A natural fit for these would be at the beginning of a method or a constructor, acting as guard statements of sorts that throw exceptions when violated.

To make things a bit more concrete we turn to code. First off we take a look at the ”normal” way to achieve precondition-like functionality without relying on Guava:

public class SomeClass {  
   private final String aString;  
   private final String anotherString;  
   private final int anInteger;  

   public SomeClass(String aString, String anotherString, int anInteger) {  
     if (aString == null) {  
       throw new NullPointerException("aString was null");  
     }  
     if (anotherString == null) {  
       throw new NullPointerException("anotherString was null");  
     }  
     if (anInteger <= 0) {  
       throw new IllegalArgumentException(  
           String.format("Expected anInteger to be > 0, got %s", anInteger));  
     }  
     this.aString = aString;  
     this.anotherString = anotherString;  
     this.anInteger = anInteger;  
   }  
   // more code here..  
 }  

In the SomeClass constructor we want to a) enforce that the strings passed as arguments are not null and that the integer argument is greater than zero and b) assign the arguments to their respective class member variable. Throughout the 16 lines of code in the constructor body we spend 12 lines of code just enforcing the correctness of the supplied arguments. One word that comes to my mind is verbose.

Another thing to note is that in each of the if-statements we check if the argument has a value that we do not accept. In plain english we can say ”if aString is null, then throw an exception” or ”if anInteger is equal to or lower than zero, throw an exception”.

We now turn to preconditions in Guava. An implementation of the constructor with the same functionality would then look as follows:

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

public class SomeClass {  
   private final String aString;  
   private final String anotherString;  
   private final int anInteger;  

   public SomeClass(String aString, String anotherString, int anInteger) {  
     checkArgument(anInteger > 0, "Expected anInteger to be > 0, got %s", anInteger);  
     this.anInteger = anInteger;  
     this.aString = checkNotNull(aString);  
     this.anotherString = checkNotNull(anotherString);  
   }  
   // more code here..  
 }  

In this version of the class constructor we make use of two static methods in the Preconditions class, namely checkArgument and checkNotNull. In order to make the code more readable these two methods have been statically imported, as seen above the class definition. Let’s walk through the lines in the constructor one by one.

The first line calls the checkArgument precondition to check that anInteger is greater than zero, otherwise an IllegalArgumentException will be thrown. A second and third argument can be supplied to the method – this is optional as the method is overloaded – that provides the exact same functionality as the String.format method used in the former version of the constructor. The most important thing to note on this line is that we check if the argument has a value that we accept. This is the complete opposite to what we did in the former version of the constructor, where we checked if the argument had a value we did not accept. In plain english we can now say ”anInteger must be greater than 0 or an exception will be thrown”.

The second line in the constructor is just an assignment, nothing more to say about that. The fourth and the fifth lines are however much more interesting. Here we use a precondition on each line to check that the string is not null, otherwise a NullPointerException will be thrown. If the precondition is enforced successfully, the argument supplied to the checkNotNull method is assigned to its member variable. In plain english we can now say ”aString cannot be null or an exception will be thrown”. Again, the way we express this is completely inverted from the former version of the constructor, where we say ”if aString is null, then throw an exception”.

Aside from making the code more compact – we have now effectively reduced the code from 16 lines down to 5 – it is also in my strong opinion that the latter version of our constructor is easier to understand. With preconditions in Guava we have the ability to state how things must be rather than how things must not be in order to proceed with the execution. This might seem like a trivial improvement to code readability, but with each small improvement to readability we add to our code base we also make it more maintainable.

After all, code is a form of communication, and code that communicates well is easier to understand and maintain.

P.S. An alternative to the Preconditions.checkNotNull method is the Objects.requireNonNull method available in Java 7.

Presentation om Guava

På jobbet har vi något som kallas ”utvecklarforum” där vi som utvecklare diskuterar saker som direkt eller indirekt berör vårt dagliga arbete. Nu i veckan har jag tagit initiativet och ska då prata lite som Guava i detta forum. Guava är en samling bibliotek som Google använder i sina egna Javaprojekt och som finns tillgängliga för allmänheten. Nu när jag ändå har en fancy blogg tänkte jag sprida mina slides här – enjoy!

APIer och null

På jobbet har det varit mycket diskussioner kring APIer på sistone och eftersom jag i och med det har ämnet på läppen tänkte jag lobba lite för en grej som jag tycker är fräck. Även om implementationen av det jag tänker på är i Java så borde konceptet vara applicerbart i vilket objektorienterat språk som helst. Here goes.

Föreställ dig att du som utvecklare arbetar mot ett API – låt oss kalla APIet för AnimalRepository – där metoden nedan är definierad:

Animal findAnimal(int id);

Föga förvånande syftar metoden till att slå upp ett visst objekt av typen Animal. Men vad händer om det inte finns något objekt som matchar det id man skickar in? Det står klart att det inte går att utläsa genom att bara titta på metodsignaturen. Som utvecklare får man då helt enkelt jaga fatt i dokumentationen och/eller gräva runt i källkoden för att förstå denna hantering, eftersom den kan se ut på lite olika sätt från API till API.

En vanlig förekommande design är att metoden helt enkelt returnerar null om det inte finns något resultat. Men null är problematiskt på så många sätt – det har skrivits spaltmeter om eländet och första bästa resultat när jag googlade kan man titta på här. En annan lösning som jag själv inte har testat men läst en del om är Null Object pattern. Grejen här är att man knackar ihop en implementation av typen som inte har något beteende. Men hur skulle det te sig? Ska man då kolla om objektet är tomt? Att metoden kan returnera tomma objekt framgår i vilket fall inte av dess signatur. En tredje möjlighet (som känns ganska knäpp) vore att kasta ett exception. Men en enkel fråga borde man väl ändå få ställa utan att världen går under? Exceptions är ju mer ”woop woop, hördu det brinner här borta”.

Nej det här blev omständigt. Vore det inte bättre om metodsignaturen helt enkelt kunde kommunicera hur man hanterar ett icke-resultat? Kan designern av APIet göra något här? Såklart han kan, varför skulle jag annars bemöda mig med att problematisera så pass? 🙂 Säg hej till Google Guava!

Man kan tycka vad man vill om Google men de har gjort en hel del bra grejer och Guava är en av dem. Guava är en samling utilities för Javautvecklare som hjälper oss i vår vardag. Här finns massor av matnyttigt (som det finns anledning att återvända till i ett framtida inlägg) men det jag vill lyfta fram i detta nu är något som kallas för Optional. Och varför inte börja med ett exempel? Vi tar samma metodsignatur som ovan fast med en ny twist:

Optional<Animal> findAnimal(int id);

Optional kan ses som en wrapper för saker som kan vara null. Och bara genom att använda det i metodsignaturen klargör vi för den som ska använda APIet att här kan det minsann returneras något som inte är något alls. Här har vi alltså ett enkelt och kraftfullt koncept som gör att koden nu kommunicerar bättre än tidigare. Men hur använder man sig av returvärdet? Det är ett ganska snyggt upplägg om jag får tycka till:

Optional<Animal> result = animalRepository.findAnimal(123);
if (result.isPresent()) {
  // we have a result
  Animal animal = result.get();
  ...
}

Kod som kommunicerar är fina grejer! 🙂 Det var allt för denna gången. Trevlig helg!