Resource leakages: command pattern to the rescue
Over the years of performance monitoring with Plumbr I have faced hundreds of performance issues caused by resource leakages. In this post I would like to describe one of the simplest ways to approach resource clean-up and avoid the problem.
Let me first describe the problem by using a movie player application as an example. The primary feature for such an application would naturally be playing the movie itself. As is a custom nowadays, we don’t want to store the whole movie collection on the device used for playing the movie. Instead, we will download a movie to a local temporary file, play it and then remove that file to free the space for the next one. A naive implementation for such workflow would look like the following:
public class MoviePlayer { private final Catalog catalog = new Catalog(); public void play(String movieName, String screen) { Movie movie = catalog.find(movieName); try { movie.fetch(); movie.play(screen); } finally { movie.release(); } } } class Catalog { Movie find(String name) { return new Movie(name); } }
As you see, the MoviePlayer class, being a client to the Catalog class, has to take care of the whole lifecycle of the movie playing. Finding, downloading, playing and removing the file all belong to the MoviePlayer class implementation.
Herein lies the first problem: if at least one of such clients was written by some careless developer who forgets to call movie.release() method, the downloaded file will be left on your local disk. Every movie you play will thus add one more file and the disk space on the device would eventually be exhausted.
The second problem with such “jack-of-all-trades” code is exposed when additional functionality is introduced. For example, imagine you would need to add the possibility to log the actual movie playing time.
Currently the only way to do it is to change MoviePlayer class. If there were other clients for the Catalog class, the change would need to be introduced in each and every one of them. As a result, the MoviePlayer grows bigger and bigger with each additional feature, handling more and more separate concerns. As a result the code will eventually be difficult to understand and change.
Considering the MoviePlayer should be mainly just dealing with the movie playback, it surely sounds like too much additional hassle. Indeed, so let us try to move all this clutter from the MoviePlayer to make sure we have a class with single responsibility. Command design pattern, a 20 years old technique is best suited for the task at hand.
Alleviating the pain: command pattern to the rescue
The basic idea behind the approach is first to abstract away piece of action that varies from use-case to use-case in order to distinguish it from more stable parts of the algorithm. In our case this could involve movie playback or re-encoding with different video codec. The boilerplate, including the boring steps of “find a movie-download-do something-remove local file” sequence would be thus isolated from the particular use case. In our example, we can do this with the following simple interface:
interface MovieCommand { void execute(Movie movie); }
The change above includes introducing a new method with one additional parameter of type MovieAction. In this method the entire algorithm is executed:
- Movie is located.
- Movie is downloaded.
- Action or command passed to the method is executed on the movie. Specific action is now the only variable part changing from use case to use case.
- And finally, file handle to the movie is released and cleanup to temporary files is carried out.
Now, if we need to alter the algorithm in any way, we will do it in exactly one place, not affecting any of the clients who are still concerned only with their specific action, like movie playing or encoding. Our MoviePlayer example would now be as simple as:
class Catalog { private Movie find(String name) { return new Movie(name); } void withMovie(String movieName, MovieCommand action) { Movie movie = find(movieName); try { movie.fetch(); action.execute(movie); } finally { movie.release(); } } }
The technique is extremely powerful and widespread. If you have not recognized any uses for this, think about JDBC access to relational databases. All the boilerplate related to acquiring a database connection, preparing a statement, acquiring a resultset and closing the resources in particular order used to be a nightmare to handle before Spring Templating came to the rescue.
Similarly, different aspects, such as security checks or caching can be implemented in your custom codebase by using command pattern, cleaning your code from the unnecessary boilerplate and simplifying the codebase a lot.
Reference: | Resource leakages: command pattern to the rescue from our JCG partner Nikita Salnikov Tarnovski at the Plumbr Blog blog. |
That’s the Strategy Pattern, not the Command Pattern. They’re easy to mix up, but they are different.
Thanks a lot. Enjoyed yours 70+ articles.