Initializer Build idiom – facts and fallacies

Nowadays, most Java developers are quite familiar with the so called Initializer Build idiom. It’s meanwhile a well known idiom for building hierarchical structures, especially when creating formations which follow the composite pattern.

In short, you mostly want to avoid building those structures in a verbose way by instantiating each element separately and assembling the elements afterwards (that is defining the parent – child relationships), but combine both (instantiation and assembling) within one step in a more concise way.

I applied the idiom the other day, only to detect some fallacies (i was falling for) that will come with that idiom, if you don’t attend to the given specialities. The following sections will give a brief overview of the specific facts that will come with that idiom along with some of the more severe fallacies you have to be aware of.

Setting up the stage – the Announcement composite

Let’s start with a simple example for a better understanding.
Imagine we have an application where we can post some announcements. So here’s what an announcement should look like (remember, it’s a very simple example, that will only serve for emphasizing the specialities of the idiom we’ll use afterwards).


import java.util.List;

public interface Announcement {

    public String getHeader();

    public List<Announcement> getAnnouncements();
}

As you can see, an Announcement has a header (we won’t look at the content of an announcement in this example) and can provide some ‘child’ announcements (so there might be some type of announcements that act as a kind of ‘container’ for some other announcements. Looks like we have a kind of composite in here …).

Leafs

Let’s look at a specific type of an announcement – an Article:


import java.util.Collections;
import java.util.List;

public class Article implements Announcement{

	private String header;

	public Article( String header ){
		this.header = header;
	}

	@Override
	public String getHeader() {
		return header;
	}

	@Override
	public List<Announcement> getAnnouncements() {
		return Collections.emptyList();
	}
}

You can see, that Article adheres to the syntactic ‘contract’ of an Announcement. When asked about it’s provided (contained child) announcements, Article will hand over an empty list, so an Article must be a Leaf within the composite scenario.

Let’s say we have another Leaf (that is another concrete type of an announcement) called Advert. I will not show you the code for this class, since it is almost similar to Article (of course we could have come up with an abstract superclass for leafs).

Composites

Now’s time for a composite type, so we can group some announcements. Let’s call it a Category:

import java.util.ArrayList;
import java.util.List;

public class Category implements Announcement{

	private String header;

	private List<Announcement> announcements = new ArrayList<Announcement>();

	public Category( String header ){
		this.header = header;
	}

	@Override
	public String getHeader() {
		return header;
	}

	public void add( Announcement announcement ){
		this.announcements.add( announcement );
	}

	@Override
	public List<Announcement> getAnnouncements(){
		return announcements;
	}
}

As you can see, a Category is an Announcement which carries a header of it’s own. In addition to that, we can assign an arbitrary number of announcements into a Category, making it a composite.

Composing Announcements – the ‘verbose’ way

If we now want to come up with a hierarchy of announcements (say a category ‘Sports News’ with some more general Articles and some sub categories especially for ‘Soccer News’ and ‘Basketball News’, also containing some Articles and Adverts) we could do this by first instantiating each individual Announcement and composing the sub categories (resp. the covered Articles and Adverts) afterwards:

		Category sportsNews = new Category( "Sports News" );

		sportsNews.add(  new Article( "Bloopers" ) );
		sportsNews.add( new Advert( "Get in shape with ..." ) );

		Category soccerNews = new Category( "Soccer News" );
		sportsNews.add( soccerNews );

		soccerNews.add( new Article( "Yellows beat Greens" ) );
		soccerNews.add( new Advert( "Buy the new soccer shoes" ) );

		Category basketballNews = new Category( "Basketball News" );

		basketballNews.add( new Article( "Most points ever by Bryawitzki" ) );
		basketballNews.add( new Advert( "I love this game" ) );

You may have seen, that this kind of composing is a little bit verbose in respect to the arrangement of categories and sub categories. Worse, the formatting of the code gives no hint about the hierarchic structure of the composition. You may have spot, that we’ve forgotten to add the ‘Basketball News’ as a sub category of ‘Sports News’.

Composing Announcements using the Initializer build idiom

The Initializer build idiom combines the creation and composition of announcements within one step. It’s based on the idea of using an class initializer on the fly and composing the announcements within that initializer while ‘instantiating’. This mechanism comes with a specific cost: you have to create a new anonymous class on the fly, where you can put and define your initializer. Let’s look at the same composition from the last example, now using the initializer build idiom:

		Category sportsNews = new Category( "Sports News" ){{

			add( new Article( "Bloopers" ) );
			add( new Advert( "Get in shape with ..." ) );

			add( new Category( "Soccer News" ){{
				add( new Article( "Yellows beat Greens" ) );
				add( new Advert( "Buy the new soccer shoes" ) );
			}} );

			add( new Category( "Basketball News" ){{
				add( new Article( "Most points ever by Bryawitzki" ) );
				add( new Advert( "I love this game" ) );
			}} );
		}};

At first sight, the many curly braces look a little bit odd since we have some ceremony within here that comes with the idiom, but as soon as you concentrate on the essence, you kind of lose sight of it.
Note the formatting of the composition – you can see the parent – child relationship between the different parts of the whole hierarchy simply by looking at the natural intendation and – more demanding – by looking at the nesting of the given statements. Furthermore, it’s simply impossible to forget a child (like we did with ‘Basketball News’ within the example before).

Anonymous subclass

So what is going on here? As you can see, we’ve just ‘instantiated’ a ‘concrete’ class (like the category for our ‘Sports News’), building an anonymous subclass on top of it on the fly (that’s the first curly brace after the constructor call). So in fact, we didn’t instantiate an instance of class Category, but an anonymous subclass of it. You can simply test that fact using reflection:

		assertTrue( sportsNews.getClass().isAnonymousClass() );

		assertEquals( Category.class, sportsNews.getClass().getSuperclass() );

Equal … Not !

Of course, you have to be aware of that fact, especially when you try to compare that instance to other instances of class Category. Although the anonymous subclass can be used wherever a Category (or Announcement) is expected, it fails miserable when passing that subclass to the equals() method of Category (if comparing the class instances within equals() ):

		assertTrue( Announcement.class.isAssignableFrom( sportsNews.getClass() ) );
		assertTrue( Category.class.isAssignableFrom( sportsNews.getClass() ) );

		assertFalse( Category.class.equals( sportsNews.getClass() ) );

Initializer

There’s one thing left to explain – the second curly brace after the curly brace which introduced the anonymous subclass. This one now opens and defines a new initializer of the anonymous subclass. Within that initializer we can use all methods that are available in the given lexical scope of the surrounding subclass …

Lexical Scope

Let’s look at another composition. Although the compiler is happy with the following statements, there’s a big (semantic) flaw in it. Can you spot it?

		Announcement announcement =

			new Category( "Sports" ){{

				add( new Article( "NBA Saison Preview" ) );

				add( new Advert( "Do sports" ) );

				add( new Article( "Football's coming home" ){{

					add( new Advert( "Buy the new champions ball" ) );
				}} );
			}};

Have you seen it? Let’s take a closer look at Announcement ‘Football’s coming home’. We were able to add a child to an Article (yes, ‘Football’s coming home’ is an Article, not a Category) and although class Article doesn’t provide any method add(), the compiler didn’t complain about. Why’s that?

If you look at the whole construct, you can see, that this Article (or better it’s anonymous subclass that we’ve also defined on the fly within that composition, as we learned before) is constructed within the initializer of the surrounding anonymous class (for category ‘Sports’). This determines the lexical scope for our Article’s subclass. Since there is a method add() visible within that lexical scope (inherited from Category by the anonymous subclass of ‘Sports’), the compiler will call this method and is completely happy with that constellation.

In this case Advert ‘Buy the new champions ball’ is in fact added to Category ‘Sports’, since it’s the add() method from that anonymous subclass that is visible within the lexical scope. You can easily test this fact:

		assertEquals( 4, announcement.getAnnouncements().size() );

So in this special case, the given nesting of our add() calls is misleading! You wouldn’t fall into this trap if you would have chosen the ‘normal’ way without that idiom:

		Article footballsHome = new Article( "Footbal's coming home" );
		footballsHome.add( new Advert( "Buy the new championchip ball" ) );

In this case, the compiler would complain that ‘The method add(Advert) is undefined for the type Article’, since he can’t find any appropriate method within the lexical scope.

Conclusion

As you have seen, the initializer build idiom may be very dangerous in some situations. We may wouldn’t want to add more than three Announcements per Category within the given example. The given constellation may be a result that’s constructed by accident. Looking at the code gives you only a bad hint, that the given formatting and nesting doesn’t reflect the resulting nesting of the Announcements.

So as always – if you want to use a specific ‘weapon’, you have to know something about it’s inner ‘mechanics’, otherwise it may backfire in an unwanted way …

Advertisements
Posted in java. 4 Comments »

4 Responses to “Initializer Build idiom – facts and fallacies”

  1. Collin Says:

    If you wanted to avoid the sub classing you could create a constructor that took a variable number of Announcement arguments.


    public Article( String header Announcement … announcements){

    Category sportsNews = new Category( “Sports News”,
    new Article( “Bloopers” ),
    new Advert( “Get in shape with …” )
    new Category( “Soccer News”,
    new Article( “Yellows beat Greens” ),
    new Advert( “Buy the new soccer shoes” )
    ),
    new Category( “Basketball News”,
    new Article( “Most points ever by Bryawitzki” ),
    new Advert( “I love this game”)
    )
    );

  2. Axel Rauschmayer Says:

    Another possibility is to return in add() and then chain the methods:
    Category sportsNews = new Category( “Sports News” )
    .add( new Article( “Bloopers” ) )
    .add( new Advert( “Get in shape with …” ) )

    .add( new Category( “Soccer News” )
    .add( new Article( “Yellows beat Greens” ) )
    .add( new Advert( “Buy the new soccer shoes” ) )
    )

    .add( new Category( “Basketball News” )
    .add( new Article( “Most points ever by Bryawitzki” ) )
    .add( new Advert( “I love this game” ) )
    );

  3. Axel Rauschmayer Says:

    In the above post, the word “this” got swallowed (I used angle brackets):
    Another possibility is to return “this” in add().
    Thus, the method would look as follows:
    public Category add( Announcement announcement ){
    this.announcements.add( announcement );
    return this;
    }

  4. new roof shingles baltimore Says:

    The capacities of 8, 12, roofing baltimore maryland 16,
    and 20 quarts ensure you always have the right size pot for stews, soups, chili, and more.
    Hoffritz 4 Piece Nesting Aluminum Stockpot Set with Lids – This Hoffritz 4 Piece Nesting Aluminum
    Stockpot Set is perfect for preparing big family dinners, holiday meals,
    and large cookouts. The capacities of 8, 12, 16, and 20 quarts ensure you always have
    the right size pot for stews, soups, chili, and more.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: