There are ways we could refactor the displayCart function, but consider a second what the caller is doing each time it wants to use the function.
Consider this simple code example:
// caller
String shoppingCartMessage = displayCart("You have %s", cart.size());
String otherMessage = displayCart("You saved %s", saved.size());
// common function
String displayCart(String template, int size) {
if (size == 0) {
return String.format(template, "no items");
}
return String.format(template, size > 1 ? "a total of " + size + " items" :
" an item");
}
Each call requires the caller to calculate the size of the list that it’s holding. For two examples, that’s fine. If the caller has a variety of different sources of data, then it’s also fine.
But if it’s always the same source data, then getting each call site to do a wee calculation is not less efficient in terms of processing, but it’s less ideomatic and it’s more typing.
Given the object of the displayCart function is to describe a particular shopping cart, why is it not working out what data it needs from the cart itself?
This becomes more of a problem if the caller has to calculate several attributes of the source data in order to use a function on those data.
Conversely, this alternative:
String displayCart(String template, List<Item> cart) {
int size = cart.size();
...
}
… is only a reasonable thing to do if the common function:
◉ is really about the source data
◉ can be coupled with the types involved
◉ is suitably broken down so it doesn’t become a monolith with too many responsibilities
The way to identify this smell is a gang of callers all busily calculating the same inputs from the same types of source data.
Consider this simple code example:
// caller
String shoppingCartMessage = displayCart("You have %s", cart.size());
String otherMessage = displayCart("You saved %s", saved.size());
// common function
String displayCart(String template, int size) {
if (size == 0) {
return String.format(template, "no items");
}
return String.format(template, size > 1 ? "a total of " + size + " items" :
" an item");
}
Each call requires the caller to calculate the size of the list that it’s holding. For two examples, that’s fine. If the caller has a variety of different sources of data, then it’s also fine.
But if it’s always the same source data, then getting each call site to do a wee calculation is not less efficient in terms of processing, but it’s less ideomatic and it’s more typing.
Given the object of the displayCart function is to describe a particular shopping cart, why is it not working out what data it needs from the cart itself?
This becomes more of a problem if the caller has to calculate several attributes of the source data in order to use a function on those data.
Conversely, this alternative:
String displayCart(String template, List<Item> cart) {
int size = cart.size();
...
}
… is only a reasonable thing to do if the common function:
◉ is really about the source data
◉ can be coupled with the types involved
◉ is suitably broken down so it doesn’t become a monolith with too many responsibilities
The way to identify this smell is a gang of callers all busily calculating the same inputs from the same types of source data.
0 comments:
Post a Comment