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


Исходный код

char hex[16];
int i;

for (i = 1; i<=len; i++)
{
    hex[1]="0";hex[2]="1";hex[3]="2";hex[4]="3";
    hex[5]="4";hex[6]="5";hex[7]="6";hex[8]="7";
    hex[9]="8";hex[10]="9";hex[11]="A";hex[12]="B";
    hex[13]="C";hex[14]="D";hex[15]="E";hex[16]="F";

    printf ("%c", hex[buff[i-1]>>4<<4/16-1]);
    printf ("%c", hex[buff[i-1]>>4<<4 ^ buff[i-1]-1]);
}

Очевидно, код представляет собой образец лабораторной работы, так как в реальном проекте должен быть реализован гораздо проще. Мне он интересен исключительно для демонстрации возможных способов рефакторинга.

Что не так в исходном коде

  1. Обработка данных привязана к месту хранения данных (смешаны знания о хранении числа, которое нужно отобразить, и о собственно алгоритме отображения).
  2. Довольно запутанный способ получения старшей и младшей четвёрки бит из каждого байта.
  3. Присвоение значения по сути константе происходит внутри цикла.
  4. Инициализация по сути строки выполняется посимвольно.
  5. Первый элемент массива hex остался незадействованным.
  6. Счётчик циклапо байтам buf начинается со второго байта.

Как можно отрефакторить исходный код

constchar* hex = "0123456789ABCDEF";

void printByteHex(unsigned char byte) {
    unsignedchar lowQuartet = byte & 0xF;
    unsignedchar highQuartet = (byte & 0xF0) >> 4;
    printf ("%c%с", hex[lowQuartet], hex[highQuartet]);
}
for (int i = 0; i < len; i++) {
    printByteHex(buf[i]);
}

Получившаяся версия функции printByteHex по прежнему объединяет в себе два знания: как преобразовать однобайтовое число в его шестнадцатиричное представление, и как с ним потом следует поступить. Разъединение этих знаний оставляю заинтересованному читателю в качестве упражнения.

Теория