Java Reference
In-Depth Information
assertEquals ( "richard>hai" , data . toString ());
bob . write ( "richard<oh its you!" );
});
bob . write ( "bob\n" );
vertx . setTimer ( 6 , id -> richard . write ( "bob<hai" ));
});
});
});
}
I connect two clients, richard and bob, then richard says “hai” to bob and bob replies “oh it's
you!” I've refactored out common code to make a connection, but even then you'll notice
that the nested callbacks are beginning to turn into a pyramid of doom . They are stretching
rightward across the screen, a bit like a pyramid sitting on its side (don't look at me—I didn't
come up with the name!). This is a pretty well known antipattern, which makes it hard for a
user to read and understand the code. It also stretches the logic of the code between multiple
methods.
In the last chapter, I discussed how we could use lambda expressions to manage resources by
passing a lambda expression into a with method. You'll notice in this test that I've used this
pattern in couple of places. We've got a withModule method that deploys the current Vert.x
module, runs some code, and shuts the module down. We've also got a withConnection
method that connects to the ChatVerticle and then closes down the connection when it's
done with it.
The benefit of using these with method calls here rather than using try-with-resources is
that they fit into the nonblocking threading model that we're using in this chapter. We can try
and refactor this code a bit in order to make it easier to understand, as in Example 9-8 .
Example 9-8. A test of whether two friends in our chat server can talk to each other, split in-
to different methods
@Test
public
public void
void canMessageFriend () {
withModule ( this
this :: messageFriendWithModule );
}
private
private void
void messageFriendWithModule () {
withConnection ( richard -> {
checkBobReplies ( richard );
richard . write ( "richard\n" );
messageBob ( richard );
});
Search WWH ::




Custom Search