Refactoring to Single-Responsibility Functions

The encodedDigits function continues to increase in complexity. We inserted blank lines in order to visually group related statements, a dead giveaway that a function does too much.

The single responsibility principle (SRP) tells us that each function should have one reason to change.[7] encodedDigits exhibits a classic violation of the SRP: it mixes high-level policy with implementation details.

Our encodedDigits function accomplishes its goal using a two-step algorithm. First append the encoded first letter to the encoding, and then iterate through the rest of the letters and append them. The problem is that encodedDigits also includes the low-level details to accomplish those two steps. encodedDigits violates SRP, because it must change for two reasons: if we want to alter implementation details or if we need to change the overall policy for encoding.

We can extract the two steps from encodedDigits into two separate functions, each containing implementation details for a simple abstract concept. What remains in encodedDigits declares our solution’s policy.

c2/37/Soundex.h
 
std::​string​ encodedDigits(​const​ std::​string​& word) ​const​ {
 
std::​string​ encoding;
 
encodeHead(encoding, word);
 
encodeTail(encoding, word);
 
return​ encoding;
 
}
 
 
void​ encodeHead(std::​string​& encoding, ​const​ std::​string​& word) ​const​ {
 
encoding += encodedDigit(word.front());
 
}
 
 
void​ encodeTail(std::​string​& encoding, ​const​ std::​string​& word) ​const​ {
 
for​ (​auto​ letter: tail(word)) {
 
if​ (isComplete(encoding)) ​break​;
 
 
auto​ digit = encodedDigit(letter);
 
if​ (digit != NotADigit && digit != lastDigit(encoding))
 
encoding += digit;
 
}
 
}

That’s better. Let’s go one step further and extract some of the body of the for loop in encodeTail.

c2/38/Soundex.h
 
void​ encodeTail(std::​string​& encoding, ​const​ std::​string​& word) ​const​ {
 
for​ (​auto​ letter: tail(word))
 
if​ (!isComplete(encoding))
 
encodeLetter(encoding, letter);
 
}
 
 
void​ encodeLetter(std::​string​& encoding, ​char​ letter) ​const​ {
 
auto​ digit = encodedDigit(letter);
 
if​ (digit != NotADigit && digit != lastDigit(encoding))
 
encoding += digit;
 
}

The resulting refactored code creates some visual similarity that suggests the possibility for more tightening of the algorithm. Is encoding a single character in encodeHead simply a special case of the encoding loop in encodeTail? Feel free to experiment—you can do so safely, because you’ve got tests! We think the algorithm is clear enough for now and choose to move on.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.122.127