Suppose you have a collection of Strings. You want to put all Strings that start with "Foo" in one List and all Strings that start with "Bar" in another list.
Here is a bad way to write the code:
List<String> foos = new ArrayList<String>();
List<String> bars = new ArrayList<String>();
for(String word : words) {
if (word.startsWith("Foo"))
foos.add(word);
if (word.startsWith("Bar"))
bars.add(word);
}One reason this is bad is because it's difficult to refactor. Let's say this is just one part of method and it's taking up space. Naturally you want to
extract it into its own method. This is not a straight forward task because the result of this method would need two return values. There are many ways you
could solve this problem.
*You could make a method with this signature: public void populateFoosAndBars(List<String> foos, List<String> bars)
*You could make foos and bars instance variables
These two solutions are very bad for other reasons even though they solve the problem at hand (the reasons are explained in other sections). The best solution
by far is to break this loop up into two separate loops. Here's how the resulting code would look:
//this is what remains of the code above
List<String> foos = getFoos(words);
List<String> bars = getBars(words);
...
//this is refactored code
public List<String> getFoos(List<String> words) {
List<String> foos = new ArrayList<String>();
for(String word : words)
if (word.startsWith("Foo"))
foos.add(word);
return foos;
}public List<String> getBars(List<String> words) {
List<String> bars = new ArrayList<String>();
for(String word : words)
if (word.startsWith("Bar"))
bars.add(word);
return bars;
}Better, yet, this can be reduced to this:
//this is what remains of the code above
List<String> foos = getWordsThatStartWith(words, "Foo");
List<String> bars = getWordsThatStartWith(words, "Bar");
...
//this is refactored code
public List<String> getWordsThatStartWith(List<String> words, String startsWith) {
List<String> resultList = new ArrayList<String>();
for(String word : words)
if (word.startsWith(startsWith))
resultList.add(word);
return resultList;
}loops_should_have_one_output, Rev. 1, Last changed on 2008-01-10 01:56, 121 page hits