Пример рефакторинга «извлечение функции» при вычислении кода


Исходный код

switch (*p)
{
    case '0': id += 0; break;
    case '1': id += 1; break;
    case '2': id += 2; break;
    case '3': id += 3; break;
    case '4': id += 4; break;
    case '5': id += 5; break;
    case '6': id += 6; break;
    case '7': id += 7; break;
    case '8': id += 8; break;
    case '9': id += 9; break;
    case 'a': case 'A': id += 10; break;
    case 'b': case 'B': id += 11; break;
    case 'c': case 'C': id += 12; break;
    case 'd': case 'D': id += 13; break;
    case 'e': case 'E': id += 14; break;
    case 'f': case 'F': id += 15; break;
    case 'g': case 'G': id += 16; break;
    case 'h': case 'H': id += 17; break;
    case 'i': case 'I': id += 18; break;
    case 'j': case 'J': id += 19; break;
    case 'k': case 'K': id += 20; break;
    case 'l': case 'L': id += 21; break;
    case 'm': case 'M': id += 22; break;
    case 'n': case 'N': id += 23; break;
    case 'o': case 'O': id += 24; break;
    case 'p': case 'P': id += 25; break;
    case 'q': case 'Q': id += 26; break;
    case 'r': case 'R': id += 27; break;
    case 's': case 'S': id += 28; break;
    case 't': case 'T': id += 29; break;
    case 'u': case 'U': id += 30; break;
    case 'v': case 'V': id += 31; break;
    case 'w': case 'W': id += 32; break;
    case 'x': case 'X': id += 33; break;
    case 'y': case 'Y': id += 34; break;
    case 'z': case 'Z': id += 35; break;
}

Нарушение принципа единственного знания

Этот фрагмент кода знает о двух вещах: какой числовой код соответствует каждому символу, и каким способом применяется числовой код.

Полученим числового кода должен заниматься отдельный метод, который будет знать только об этом и ни о чём другом.

Извлечение метода для вычисления числового кода

int GetLetterCode(char letter)
{
    switch (letter)
    {
        case '0': return 0;
        case '1': return 1;
        case '2': return 2;
        case '3': return 3;
        case '4': return 4;
        case '5': return 5;
        case '6': return 6;
        case '7': return 7;
        case '8': return 8;
        case '9': return 9;
        case 'a': case 'A': return 10;
        case 'b': case 'B': return 11;
        case 'c': case 'C': return 12;
        case 'd': case 'D': return 13;
        case 'e': case 'E': return 14;
        case 'f': case 'F': return 15;
        case 'g': case 'G': return 16;
        case 'h': case 'H': return 17;
        case 'i': case 'I': return 18;
        case 'j': case 'J': return 19;
        case 'k': case 'K': return 20;
        case 'l': case 'L': return 21;
        case 'm': case 'M': return 22;
        case 'n': case 'N': return 23;
        case 'o': case 'O': return 24;
        case 'p': case 'P': return 25;
        case 'q': case 'Q': return 26;
        case 'r': case 'R': return 27;
        case 's': case 'S': return 28;
        case 't': case 'T': return 29;
        case 'u': case 'U': return 30;
        case 'v': case 'V': return 31;
        case 'w': case 'W': return 32;
        case 'x': case 'X': return 33;
        case 'y': case 'Y': return 34;
        case 'z': case 'Z': return 35;
    }
    return 0;
}
id += GetLetterCode(*p);

Теперь можно дополнительно укоротить функцию GetLetterCode на основе знания о том, что в кодировке ASCII символы цифр и букв идут подряд, и символами можно оперировать как числами.

int GetLetterCode(const char letter)
{
    if ('0' <= letter && letter <= '9') {
        return letter - '0';
    }
    if ('a' <= letter && letter <= 'z') {
        return letter - 'a' + 10;
    }
    if ('A' <= letter && letter <= 'Z') {
        return letter - 'A' + 10;
    }
    return0;
}

Теория