"I have a
SortedCollection of Teams. Now I need to convert *it*
to a line like ...".
Well, no. You need to
convert *each team* separately to such a
line. So something
like
aStream nextPutAll:
'...header line...'; cr.
mySortedTeams do:
[:eachTeam |
-write a
formatted line describing eachTeam to aStream].
Now it gets
interesting. Whose responsibility is it to write
a representation of a
Team instance to a stream? Should it be
done by the Team
instance, or should it be done outside?
Question 1: is there
obviously one and only one format, or do
you think that in a
more realistic example there might be more
than one way to print
a Team object? I concluded that there
might be many
different ways to do it. (I personally dislike
putting variable
length fields on the left.)
Question 2: *Can* it
be done from the outside or *must* it be
done inside? Is there
any information in the printed representation
that the caller cannot
ask the team object for? In this case, all
of the information is
available through Team's public interface.
Question 3: Should
Teams and printing be *coupled*? Should a Team
know about details
like the dividing line between columns? In this
case, I decided that
putting the formatting code inside the Team
object was highly
undesirable coupling.
Question 4: Is it
*possible* for a Team object to do the formatting
without knowing about
all the other Teams in the collection? In this
case, the
specification is rather vague. It seemed to me that all
the numeric columns
should be the same width and should be wide enough
to hold the largest
number with a space on each side.
In answer to question
4, my Tournament code contains
w := mySortedTeams
inject: 1 into: [:acc :team |
(team matchCount
max: team points) printString size max: acc].
and this clearly
requires knowledge of all the teams, so it makes no
sense to put it in
Team. (Of course, if the column widths are fixed,
this argument fails,
but such a choice makes no sense for large problems.)
So now you need
something like
aStream nextPutAll:
team name; space: 30 - team name size.
and then a numeric
value might be written as
aStream nextPutAll:
' | '; space: w - team points printString size;
print: team
points.
Please do not use
<< . Historically, << had no meaning in Smalltalk.
In some Smalltalks it
means leftwards bit shift. It is just too
confusing. (In a
shell, you would use > for output, not <<, which
is used for a kind of
input.) It is really weird to use s << String cr
instead of s cr. So
idomatic Smalltalk would be
s nextPutAll: t
name; cr.
Why are you writing to
(an output stream over) an Array?
Surely you want a String?
But in any case, I
would split this into two methods:
printTeams: teams
on: aStream
-- print heading
--
-- print each team
--
printTeamsAsString:
teams
^String
streamContents: [:s | self printTeams: teams on:s]