Комментарии 50
Неоднократно встречался с подобной ошибкой и на своей шкуре почувствовал все раздражение, когда ошибка после нескольких часов поиска все-таки найдена.
Мне кажется интересна была бы идея самого отслеживания Copy/Paste на уровне среды. Включаем настройку компилятора и нам высвечиваются места, где было совершено копирования строки или нескольких строк кода, с подсветкой изменений сделанных во вставленной строке.
Мне кажется интересна была бы идея самого отслеживания Copy/Paste на уровне среды. Включаем настройку компилятора и нам высвечиваются места, где было совершено копирования строки или нескольких строк кода, с подсветкой изменений сделанных во вставленной строке.
+18
Хм, отличная идея. надо будет поискать в интернетах, или самому сесть разбираться с плагинами к эклипсу.
0
Заменять x на y и на z частенько приходится в вычислительной физике. Это наверное самая частая ошибка. Самое обидное, что понять, где баг, хотя бы примерно — довольно сложно. Видишь баг на графике или картинке — какой-то шум например, а где его в коде искать непонятно.
Очень бы хотел такую тулзу прикрутьить в линуксовой консольке к моей задаче. Такое возможно? Желательно с поддержкой С++0x.
Очень бы хотел такую тулзу прикрутьить в линуксовой консольке к моей задаче. Такое возможно? Желательно с поддержкой С++0x.
+2
Сам за собой замечал частенько такие «опечатки», поэтому стараюсь не копипастить без нужды. Одна строчка кода написаного с нуля за десяток-другой секунд может сэкономить десятки минут отладки и поиска неисправности.
Стоимость у Вашего продукта, конечно, не детская, но для больших проектов, думаю, такая цена вполне оправдана.
Стоимость у Вашего продукта, конечно, не детская, но для больших проектов, думаю, такая цена вполне оправдана.
0
Предлагаю посмотреть на наш новый инструмент — CppCat. Это облегчённый статический анализатор кода для Visual C++. $250 за лицензию.
0
Когда я был маленький junior, нам ведущие программисты наши нежные пальчики «отсушивали прикладами», когда видели еще на этапе правки кода, что мы пытаемся фрагмент скопипастить. Ну, в смысле, это было грубой ошибкой, влияющей на твои позиции в компании. Вполне успешно, кстати.
-7
Часть таких проблем таки решается выделением общих участков в маленькую вспомогательную функцию.
Просто лениться не надо…
Ну а часть действительно нет…
Просто лениться не надо…
Ну а часть действительно нет…
+1
Поворчу: Вы сделали багрепорты в проекты, указанные в Ваших примерах?
И зачем все ссылки через ваш сайт?
И зачем все ссылки через ваш сайт?
+4
Вы сделали багрепорты в проекты, указанные в Ваших примерах?
Да, делаем почти во все проекты:
www.codeproject.com/Messages/3707662/Mistakes.aspx
www.codeproject.com/KB/threads/MultiThreadSimpleQueue.aspx?fid=1590747&select=3707716#xx3707716xx
www.codeproject.com/KB/MFC/UltimateToolbox.aspx?fid=452557&select=3709822#xx3709822xx
www.codeproject.com/KB/MFC/UltimateToolbox.aspx?fid=452557&select=3709823#xx3709823xx
www.codeproject.com/KB/MFC/UltimateTCPIP.aspx?msg=3709454#xx3709454xx
www.codeproject.com/KB/IP/webem.aspx?msg=3709836#xx3709836xx
…
и так далее, и так далее…
Да, делаем почти во все проекты:
www.codeproject.com/Messages/3707662/Mistakes.aspx
www.codeproject.com/KB/threads/MultiThreadSimpleQueue.aspx?fid=1590747&select=3707716#xx3707716xx
www.codeproject.com/KB/MFC/UltimateToolbox.aspx?fid=452557&select=3709822#xx3709822xx
www.codeproject.com/KB/MFC/UltimateToolbox.aspx?fid=452557&select=3709823#xx3709823xx
www.codeproject.com/KB/MFC/UltimateTCPIP.aspx?msg=3709454#xx3709454xx
www.codeproject.com/KB/IP/webem.aspx?msg=3709836#xx3709836xx
…
и так далее, и так далее…
+15
2) И зачем все ссылки через ваш сайт?
Мы заботимся о своих читателя и отслеживаем перемещение статей, ресурсов и так далее.
Читать подробнее здесь — habrahabr.ru/company/intel/blog/101957/
Мы заботимся о своих читателя и отслеживаем перемещение статей, ресурсов и так далее.
Читать подробнее здесь — habrahabr.ru/company/intel/blog/101957/
+11
Мне думается, в ряде случаев ошибок можно было бы избежать вместе с копированием, применив другой подход:
— если вызывается два раза подряд функция — сделать этот вызов в цикле
— если копируется кусок куда, слишком небольшой, чтобы его выносить в отдельную функцию — всё же выделить в функцию.
Также помогает соображение, что повторяющийся (скопированный) код вообще выглядит подозрительным.
— если вызывается два раза подряд функция — сделать этот вызов в цикле
— если копируется кусок куда, слишком небольшой, чтобы его выносить в отдельную функцию — всё же выделить в функцию.
Также помогает соображение, что повторяющийся (скопированный) код вообще выглядит подозрительным.
-1
В топике имеются в виду как раз те ситуации, когда выделение однотипного кода в функции нелогично и неприемлимо из-за чрезмерной сложности полученного кода.
Пример:
GetMenu()->CheckMenuItem(IDC_ LINES_X, MF_BYCOMMAND | nState);
GetMenu()->CheckMenuItem(IDC_ LINES_Y, MF_BYCOMMAND | nState);
Можно выпендриться и запихнуть в функцию, но это будет уже мозгодробление.
Другое вопрос — имеет ли такой код вообще право на существование?
В таком случае лучше задуматься об архитектуре проекта в целом и понять причины появления однотипного повторяющегося кода.
Пример:
GetMenu()->CheckMenuItem(IDC_ LINES_X, MF_BYCOMMAND | nState);
GetMenu()->CheckMenuItem(IDC_ LINES_Y, MF_BYCOMMAND | nState);
Можно выпендриться и запихнуть в функцию, но это будет уже мозгодробление.
Другое вопрос — имеет ли такой код вообще право на существование?
В таком случае лучше задуматься об архитектуре проекта в целом и понять причины появления однотипного повторяющегося кода.
+3
Вынос в функцию не спасет!
MyCheck(IDC_ LINES_X);
MyCheck(IDC_ LINES_Y);
Также легко «скопипастить».
MyCheck(IDC_ LINES_X);
MyCheck(IDC_ LINES_Y);
Также легко «скопипастить».
+3
Foreach не так уж и сложен будет.
foreach (item; [IDC_LINES_X, IDC_LINES_Y]) {
GetMenu().CheckMenuItem(item, MF_BYCOMMAND | nState);
}
// D
foreach (item; [IDC_LINES_X, IDC_LINES_Y]) {
GetMenu().CheckMenuItem(item, MF_BYCOMMAND | nState);
}
// D
+1
лишний вызов функции (читай: смена окружения) садит производительность
это может быть критичным
это может быть критичным
-1
Принудительный inline?
+2
А может, к примеру, сократить размер используемой приложением памяти и выиграть на уменьшении свопа. На этапе написания кода это может определить только телепат.
Make it run, make it correct, make it fast, и только в таком порядке.
Make it run, make it correct, make it fast, и только в таком порядке.
+3
Знаете что Кнут называл корнем всех бед? То-то же.
+3
НЛО прилетело и опубликовало эту надпись здесь
Один из способов снизить вероятность такого рода ошибок: Code review.
Да заодно и те только такого рода…
Да заодно и те только такого рода…
+2
НЛО прилетело и опубликовало эту надпись здесь
> Нельзя запретить программистам копировать код. Это уже маразм.--Маразм — это старческое заболевание, сопровождающееся потерей памяти. Но если молодой здоровый начальник запретит копировать код, то где здесь маразм? Не понимайт.
-3
страшно жить с такой ограниченной клавиатурой!
+1
Идея форматирования кода хороша, и я её поддерживаю, но она идёт вразрез с автоформаттерами IDE, у которых часто своё представление о том, как выровнять строки и где сделать перенос строки. Не использовать их совсем тоже плохо, особенно новичкам в компании, если они привыкли к другому стилю кодирования. В компании может быть сделан шаблон автоформатирования, который соответствует внутренним требованиям. Кое-где он даже автоматически применяется при коммите кода ко всем файлам. С одной стороны можно не греть голову, правильно расставляя пробелы и скобки, но с другой стороны любой сотрудник может одной волшебной кнопкой испортить тщательную ручную расстановку переносов строк и пробелов в совсем другом фрагменте кода. Этого даже никто не заметит: код компилируется, тесты проходят.
В связи с этим возник вопрос: можно ли в популярных IDE пометить фрагмент кода, как не требующий автоформатирования? Или, скажем, разрешить автоформаттеру для фрагмента править отступы, но запретить править переносы строк?
В связи с этим возник вопрос: можно ли в популярных IDE пометить фрагмент кода, как не требующий автоформатирования? Или, скажем, разрешить автоформаттеру для фрагмента править отступы, но запретить править переносы строк?
+4
хм, а в чем тут ошибка?
void DXUTUpdateD3D10DeviceStats(...)
{
…
else if( DeviceType == D3D10_DRIVER_TYPE_SOFTWARE )
wcscpy_s( pstrDeviceStats, 256, L«WARP» );
else if( DeviceType == D3D10_DRIVER_TYPE_HARDWARE )
wcscpy_s( pstrDeviceStats, 256, L«HARDWARE» );
…
}
void DXUTUpdateD3D10DeviceStats(...)
{
…
else if( DeviceType == D3D10_DRIVER_TYPE_SOFTWARE )
wcscpy_s( pstrDeviceStats, 256, L«WARP» );
else if( DeviceType == D3D10_DRIVER_TYPE_HARDWARE )
wcscpy_s( pstrDeviceStats, 256, L«HARDWARE» );
…
}
+1
L«HARDWARE» — символы такого рода в списке параметров не будут интерпретированы как нечто иное?
0
А ЭТО ЕЩЕ ОДИН ПРИМЕР ОШИБКИ ПРИ COPY-PASTE! :))
Я не то скопировал при написании статьи. Вот правильный фрагмент:
else if( DeviceType == D3D10_DRIVER_TYPE_SOFTWARE )
wcscpy_s( pstrDeviceStats, 256, L«WARP» );
else if( DeviceType == D3D10_DRIVER_TYPE_HARDWARE )
wcscpy_s( pstrDeviceStats, 256, L«HARDWARE» );
else if( DeviceType == D3D10_DRIVER_TYPE_SOFTWARE )
wcscpy_s( pstrDeviceStats, 256, L«SOFTWARE» );
Два раза повторяется «DeviceType == D3D10_DRIVER_TYPE_SOFTWARE».
Я не то скопировал при написании статьи. Вот правильный фрагмент:
else if( DeviceType == D3D10_DRIVER_TYPE_SOFTWARE )
wcscpy_s( pstrDeviceStats, 256, L«WARP» );
else if( DeviceType == D3D10_DRIVER_TYPE_HARDWARE )
wcscpy_s( pstrDeviceStats, 256, L«HARDWARE» );
else if( DeviceType == D3D10_DRIVER_TYPE_SOFTWARE )
wcscpy_s( pstrDeviceStats, 256, L«SOFTWARE» );
Два раза повторяется «DeviceType == D3D10_DRIVER_TYPE_SOFTWARE».
+3
Столкнулся с проблемой копипаста при составлении простенького параметризатора для управления роботом — там 18 параметров, ко всем применяется одна и та же функция. Ошибку искал неделю в уже скомпилированной и поставленной на место работы программе. В конце концов плюнул, и вышел из положения, перегрузив функцию, которая устанавливала параметры, так, чтобы она обращалась не к одной переменной, а к специальной вспомогательной структуре — списку передаваемых параметров с некоторой «обвязкой». Такой подход немного позже привел меня (тогда еще зеленущего студента) к идейке пакетирования команд, так что проблема оказалась полезной.
+2
Copy-Paste это уже технология. О как!
+1
НЛО прилетело и опубликовало эту надпись здесь
Когда я делаю копипаст, то больше концентрируюсь на этом участке кода и проверяю несколько раз, что все правильно.
+1
Возможно оффтопик: именно за способность уйти от любого дублирования кода и любят языки семейства Lisp.
0
При этом здесь нет смысла говорить о дублировании кода. Как не думай, проще здесь написать невозможно. Подобных примеров можно привести огромное количество, взяв любую программу. Не нравится, что здесь пример касается GUI, так и в других задачах мы встретим аналогичное:
int texlump1 = Wads.CheckNumForName («TEXTURE1», ns_global, wadnum);
int texlump2 = Wads.CheckNumForName («TEXTURE2», ns_global, wadnum);
здесь можно предложить такой вариант: реализовать функцию, принимающую на вход массив (в данном случае на выходе тоже массив). Тогда кусок будет выглядеть как-то так:
char * textures[2] = { "TEXTURE1", "TEXTURE2" }; int texlump[2] = Wads.CheckNumForName(textures, ns_global, wadnum);
Да, и тут есть копипаст, но на мой взгляд выглядит намного лучше: проще рефакторить, проще увидеть ошибку. Да и красивее в конце концов :)
0
Читайте про новые проверки — Intel IPP Samples for Windows — работа над ошибками.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Последствия использования технологии Copy-Paste при программировании на Си++ и как с этим быть