Like a good library writer, we have actually finessed this problem in the code we have written.
The way things are now set up, all of the separator characters have to be in the prefix argu-
ment that is passed in to the PlayerImpl constructor. But this means that any code calling
the constructor will have to be very careful, not only to make sure that they end the prefix
String with a filesystem separator but also to make sure that they don't hardcode in the kind
of separator used in their development system in the prefix, thus making their code nonport-
We can do a lot better than that. And in doing so, we can take a look at some of the mechan-
isms that the JVM offers to help us ensure that our code is actually portable, even in the face
of various changes in operating systems and environments. Our strategy will be to take some
of the pressure off the caller of our Player class. Rather than putting the onus on the caller to
supply a place in the filesystem for us to store the data for a player, we will do much of the
work ourselves. We will store the players in a directory that is determined by the team that the
player is on. The team directories, in turn, will be stored in a directory that is determined when
the program is run rather than by some code that we will write. This means that we are going
to have to do something about the file separator character, since we will be building strings
that include that character, and we will need to do that in a way that is portable. Fortunately,
the JVM and the associated runtime environment give us ways to do this.
Actually, the JVM gives us a couple of ways to do this, which is more a statement about the
history and evolution of the platform than an example of good software design. In a perfect (or
even better) world, there would be one way to make our code portable with respect to things
like the separator used in the filesystem. But in the world we are in, there are at least two.
We should start by thinking about what the filesystem organization should be for our Player
data. Since we are naming the files using the unique identifiers that we are associating with
the Player objects, we could just keep all of the files containing the data in a single directory,
knowing that they will all have a unique name. But that would lead to a messy directory, so
we would like to impose some grouping of the objects. Since we are talking about baseball
players, the obvious grouping is by the team the player is on, which is information that we are
already tracking in the Player object. So we will create a directory for each team and store
the data for the players on that team in files within that directory. We can't assume that the
names of the players are unique, but we can assume that the names of the teams are unique,
so there is no need to add a unique identifier to the Team object.
Using this approach, constructing the filename is easy enough. We just have to concatenate
the String that is the team name with the String that can be generated from the player ID.
Between the two, we need to have the file path separator. This last is the operating-system-de-