Программирование перестановкой
Эта статья в значительной степени или полностью опирается на один источник . ( декабрь 2019 г. ) |
Программирование путем перестановок , иногда называемое «случайным программированием» или «обстрелом», представляет собой подход к разработке программного обеспечения, при котором проблема программирования решается путем итеративного внесения небольших изменений ( перестановок ) и тестирования каждого изменения, чтобы увидеть, ведет ли оно себя желаемым образом. Этот подход иногда кажется привлекательным, когда программист не до конца понимает код и считает, что одна или несколько небольших модификаций могут привести к созданию правильного кода.
Эта тактика неэффективна, если:
- Не хватает легко выполняемых автоматических регрессионных тестов со значительным охватом кодовой базы:
- серия небольших модификаций может легко внести в код новые необнаруженные ошибки, что приведет к «решению», которое будет даже менее правильным, чем исходная точка.
- Без разработки через тестирование редко можно путем эмпирического тестирования измерить, будет ли решение работать во всех или значительной части соответствующих случаев.
- Не используется система контроля версий (например, GIT , Mercurial или SVN ) или она не используется во время итераций для сброса ситуации, когда изменение не имеет видимого эффекта.
- прежде чем будет достигнут удовлетворительный конечный результат, обычно происходит множество фальстартов и корректировок.
- в худшем случае исходное состояние кода может быть безвозвратно потеряно
Программирование путем перестановки практически не дает или вообще не дает гарантий качества создаваемого кода — это полная противоположность формальной верификации .
Программистам часто приходится программировать путем перестановки, когда API недостаточно документирован. Эта неясность заставляет других копировать и вставлять из эталонного кода, который считается правильным, но сам был написан в результате программирования путем перестановки.
В некоторых случаях, когда программист может логически объяснить, что именно один из небольшого набора вариантов должен работать, программирование путем перестановки приводит к правильному коду (который затем можно проверить) и избавляет от необходимости думать о других (неправильных) вариантах.
Пример
[ редактировать ]Например, следующий пример кода на языке C (предназначенный для поиска и копирования ряда цифр из более крупной строки) имеет несколько проблем:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
const char* buffer = "123abc";
char destination[10];
int i = 0;
int j = 0;
int l = strlen(buffer);
while (i < l) {
if (isdigit(buffer[i])) {
destination[j++] = buffer[i++];
}
++i;
}
destination[j] = '\0';
printf("%s\n", destination);
}
Во-первых, это не дает правильного ответа. С заданной начальной строкой он выдает результат «13», когда правильный ответ — «123». Программист, не осознающий структурных проблем, может ухватиться за одно утверждение, говоря: «Ага, есть еще одно приращение». Строка «++i» удалена; но тестирование кода приводит к бесконечному циклу. «Ой, неправильное приращение». Предыдущий оператор добавляется обратно, а строка над ним изменяется, чтобы удалить пост-инкремент переменной i:
if (isdigit(buffer[i])) {
destination[j++] = buffer[i];
}
Тестирование кода теперь дает правильный ответ: «123». Программист удовлетворенно вздыхает: «Вот и все. Теперь все готово». Дополнительное тестирование с различными другими входными строками подтверждает этот вывод.
Конечно, остаются и другие проблемы. Поскольку программист не утруждает себя полным пониманием кода, они остаются незамеченными:
- Если входные данные содержат несколько чисел, разделенных нецифровыми символами, например
"123ab456"
, пункт назначения получает все цифры, объединенные вместе - Если входная строка больше целевого массива, произойдет переполнение буфера.
- Если входная строка длиннее, чем
INT_MAX
, поведение не определено, поскольку strlen() возвращает значение типаsize_t
которое представляет собой целое число без знака и может быть шире, чемint
. - Если
char
является знаковым типом, и входная строка содержит символы, не входящие в диапазон0
..UCHAR_MAX
после целочисленного продвижения вызовisdigit()
имеет неопределенное поведение.
Хотя решение является правильным для ограниченного набора входных строк, оно не является полностью правильным, и, поскольку программист не удосужился разобраться в коде, ошибки не будут обнаружены до более позднего этапа тестирования, если вообще будут обнаружены.
Также известен как «Проб и ошибка», «Создать и проверить», «Тыкать и надеяться». [ 1 ] «Метод Birdshot» и «Стиль программирования миллиона обезьян».
Ссылки
[ редактировать ]- ^ Катания, Энтони (1987). " "всегда, хотя есть некоторые алгебраические навыки, темы по факторизации, рациональные." " . Математика и компьютерное образование . 21 . Мичиганский университет : 74.