Limiting Length

Rule #4 tells us the Soundex code must be four characters.

c2/26/SoundexTest.cpp
 
TEST_F(SoundexEncoding, LimitsLengthToFourCharacters) {
 
ASSERT_THAT(soundex.encode(​"Dcdlb"​).length(), Eq(4u));
 
}

The code throws an exception when Google Mock runs this new test. No worries, because our test tool traps this exception, reports a test failure, and continues running any subsequent tests.

 
[ RUN ] SoundexEncoding.LimitsLengthToFourCharacters
 
unknown file: Failure
 
C++ exception with description "basic_string::_S_create" thrown in the test body.
 
[ FAILED ] SoundexEncoding.LimitsLengthToFourCharacters (1 ms)

By default, Google Mock swallows the problem and keeps running the rest of your tests. If you prefer to crash the tests on an uncaught exception, you can run Google Mock with the following command-line option:

 
--gtest_catch_exceptions=0

Looking at a backtrace in gdb (or a comparable debugging tool) tells us that our problem is in zeroPad. A web search reveals that the _S_create error occurs when you attempt to create a string larger than the maximum allowed size. With those two facts, we focus on the string construction in zeroPad. Aha! When the length of code exceeds MaxCodeLength, zerosNeeded overflows with a value that makes the string constructor unhappy.

TDD fosters an incremental approach that makes it easier to resolve problems, because it exposes them as soon as you create them. We didn’t need to debug to pinpoint our problem; a glance at the backtrace was all we needed.

(Yet, any time things crash, we always wonder about our approach. How might we have better test-driven to make the source of problem more explicit? Once we wrote zeroPad, we might have considered elevating it as a public utility method. At that point, our job would have been to more exhaustively test it in order to document to other developers how it could be used. We might have been more likely to stumble across the need to guard zeroPad against creating a string with an invalid length.)

For our solution to the problem, we could fix zeroPad. We could also change encodedDigits to stop once it encodes enough letters. We choose the latter—once encoding gets filled with encoded digits, we break out of the loop.

c2/26/Soundex.h
 
std::​string​ encodedDigits(​const​ std::​string​& word) ​const​ {
 
std::​string​ encoding;
 
for​ (​auto​ letter: word)
*
{
*
if​ (encoding.length() == MaxCodeLength - 1) ​break​;
 
encoding += encodedDigit(letter);
*
}
 
return​ encoding;
 
}

The new statement doesn’t clearly and directly declare its intent. We immediately extract it to the intention-revealing function isComplete.

c2/27/Soundex.h
 
std::​string​ encodedDigits(​const​ std::​string​& word) ​const​ {
 
std::​string​ encoding;
 
for​ (​auto​ letter: word) {
*
if​ (isComplete(encoding)) ​break​;
 
encoding += encodedDigit(letter);
 
}
 
return​ encoding;
 
}
 
*
bool​ isComplete (​const​ std::​string​& encoding) ​const​ {
*
return​ encoding.length() == MaxCodeLength - 1;
*
}
..................Content has been hidden....................

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