Подтвердить что ты не робот

Рекомендации по обслуживанию кода

Я работаю в своем университете этим летом в лаборатории изображений/видео. Совсем недавно мой профессор дал мне программу, написанную студентом-градиентом, который просто оставил программу "исправить", потому что это "давало некоторые ошибки".

Проект был написан на С++ (кажется, это повторяющийся плохой знак в коде студента). Я открыл проект в VS08 и запустил проект, и, оказывается, "ошибки" были bad_alloc. Разумеется, проблема была связана с управлением памятью или, точнее, ее отсутствием.

Программисту, казалось, нравилось смешивать mallocs, news и new [] s на протяжении всего кода, без каких-либо свободных, удаленных или удаленных []. Чтобы усугубить ситуацию, все объекты, по-видимому, делают по крайней мере 4-5 несвязанных вещей. И в довершение всего, здесь комментарий программиста:

//do not delete objects, it seems to cause bugs in the segmenter

Из того, что я вижу, есть хорошее нездоровое сочетание ссылок указателей и ссылок, и все значения изменяются путем передачи по ссылке на монолитные функции класса, которые также могут быть статическими. Во время компиляции было около 23 предупреждений --- такие вещи, как возможная потеря данных при конвертации из double в char, около 17 неиспользуемых переменных и т.д. Это время, когда я хотел бы, чтобы С++ никогда не существовало в университетах, и что вся лаборатория работа была выполнена в виде python или matlab...

Итак, профессор хочет, чтобы я "возился" с программой, чтобы она могла работать на наборах данных примерно в 10 раз больше, чем она была использована. Я признаю, что я немного боюсь сказать ей, что код - это мусор.

StackOverflow, вы, ребята, никогда не проваливались, давая хорошие советы, поэтому теперь я умоляю, любой совет по работе с подобными ситуациями был бы очень оценен.

ИЗМЕНИТЬ Код составляет около 5000 LoC

EDIT2 Профессор решил пойти с самым легким подходом. Который получал больше ОЗУ. Yay за то, что собирался бросить деньги на проблему...

4b9b3361

Ответ 1

Во-первых, плохой код - это плохой код. Python, Java, Matlab или что-то еще собранное мусором не является хорошим кодом. Вы могли бы так же легко потратить свое время на отладку плохого кода Python.

С учетом сказанного, будьте абсолютно откровенны с профессором. Скажите ей, что код плох и покажите ей несколько примеров. Самое худшее, что вы можете сделать, это попытаться скрыть проблему. Если вы это сделаете, проблема не только обязательно приземлится у вас на коленях, но и будет зависеть от вас.

Подумайте, какое лучшее решение и предложите это ей. Это может быть исправление этого кода, привлечение помощи отдела компьютерных наук или его переписывание либо на С++, либо на другом языке. Скорее всего, у нее нет других возможностей и с радостью примет любое решение, которое вы предлагаете.

Ответ 2

Рефакторинг кода, по одному изменению за раз, пока это не будет иметь для вас смысл. Самое главное - не точная стратегия кодирования, а то, что вы понимаете, что она делает и почему.

Вероятно, вы в конечном итоге трогаете каждую строку кода, поэтому не пытайтесь делать что-либо в каком-либо конкретном порядке - исправьте первое, что сначала выпрыгивает на вас, а затем переходите к следующему, и так далее. Исключение: если предыдущий человек не использовал согласованную стратегию форматирования кода, запустите все это через автоинденент в качестве вашего первого действия.

Напишите тестовый пакет, когда идете.

Ответ 3

Будьте честны. Немедленно сообщите своему профессору, что код дерьмо и почему так. Если то, что вы указали в своем вопросе, верно, код действительно дерьмо.

Сколько у вас времени? Вы понимаете реализованный алгоритм (ы)?
5kLoC не так уж много, особенно когда все это происходит на низкоуровневом уровне. Когда вы знаете основные алгоритмы и имеете достаточное время под рукой, переписывать, то на 2k строки легко понятного кода может быть лучше, чем пытаться его исправить.

Ответ 4

5000 LoC не так уж плохо. Считайте себя счастливым.

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

  • Замените каждое использование malloc на new.
  • Исправить предупреждения компилятора.
  • Замените массивы векторами (или более подходящими структурами данных).
  • Замените необработанные указатели на переменные/ссылки стека, когда это возможно, и умные указатели, если нет. Не волнуйтесь об основных изменениях архитектуры или 100% преобразовании - сосредоточьтесь на низких висящих фруктах и ​​очистите некоторые из основных утечек памяти.
  • Начните реконструировать приложение.
    • Выберите дискретное поведение/задачу в приложении.
    • Выясните, как это работает.
    • Выясните, как вы хотите, чтобы он работал (концентрируясь на интерфейсе).
    • Разработка плана перехода.
    • Выполните свой план.
    • Повтор.

Ответ 5

Я бы предложил следующие шаги, описанные Майклом Персоном в книге "Работа эффективно с устаревшим кодом". А именно: как можно скорее получите код под контролем.

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

Я знаю, однако, что это гораздо проще сказать, чем на самом деле сделать это. Прочтите эту главу "Швы" (части кода, которые вы можете переопределить/подключить, чтобы вы могли легче получить код): http://www.informit.com/articles/article.aspx?p=359417&seqNum=3 Смотрите также это на CppUnit и CppUnitLite, платформе для модульного тестирования на С++: http://c2.com/cgi/wiki?CppUnitLite

Запустите код через профайлер памяти. См. Эту ссылку SO: https://stackoverflow.com/questions/818673/memory-profiler-for-c Это поможет вам отследить места, которые вам нужны, чтобы начать добавлять инструкции delete/free. Я также начал бы пытаться сделать распределение памяти по крайней мере непротиворечивым в используемом им API.

Ответ 6

На мой взгляд, самое лучшее, что вы можете сделать, это сказать профессору, что код беспорядок, и не будет работать должным образом, если некоторые части не будут перезаписаны. Предложите небольшой рефакторинг кода, переписывая только те части, которые ему нужны (не вся программа).

Не рассказывая об этом, может дать вам больше проблем, чем у вас уже есть:)

Ответ 7

Как промежуток остановки, вы можете попытаться использовать какую-то сборку памяти, собранную с помощью мусора, такую ​​как dlmalloc, чтобы узнать, позволяет ли вам временно преодолеть препятствие на пути к памяти.

В долгосрочной перспективе вам придется разобраться в беспорядок управления памятью - этого просто нет. Из вашего описания вам, вероятно, также придется решать проблемы с дизайном объекта, но вы, вероятно, можете уйти с выполнением некоторой очистки управления памятью в первую очередь.

Вот как я подхожу к этому:

  • Найдите все места в коде, вызывающем malloc(). Посмотрите на них очень хорошо и попробуйте заменить их на вызовы new, поэтому вам нужно иметь дело только с одним типом управления памятью, что упростит переход на следующий шаг.
  • Найдите все те места, которые вызывается new, и посмотрите, можете ли вы заменить необработанные указатели, которым присваиваются результаты new, с помощью boost::shared_ptr<>. Это должно по крайней мере дать вам какую-то белую мусорную коллекцию мусора; конечно же, вы должны также изменить все прототипы функций функций, получающих эти указатели, вместо shared_ptr<> вместо обычных указателей, иначе вы просто нарядили беспорядок и ничего не улучшили. Я бы на самом деле утверждал, что вы изменили ситуацию к худшему...

Как только вы устраните проблемы с непосредственным управлением памятью, вы можете начать реорганизацию объектов и улучшить дизайн. Я бы не начал, сначала исправляя дизайн, вам лучше работать с программным обеспечением, улучшая понимание его работы, а затем сортируя дизайн, иначе вы, вероятно, замените один беспорядок на другой.

Ответ 8

Звучит как полный беспорядок. Рефакторинг - это самое меньшее, что вам нужно сделать. Смесь новых и malloc - это рецепт катастрофы!

Думаю, вам придется переписать почти все. К счастью, 5000 SLOC не огромны и не должны занять слишком много времени.

Звучит как хорошее упражнение!

Ответ 9

Объясните профессору вопрос, который вы видите. И никогда не представляйте проблему без решения. Помните об этом, когда вы пишете свой отчет вместе с вашими предложениями. Вы можете предложить несколько возможностей и позволить им выбрать ту, которую они хотят взять. И в этот момент вы сделаете свою работу - время для их выполнения!

Ответ 10

Было дано много хороших предложений о том, как обращаться с самим кодом. Мне кажется, что одна из основных проблем может заключаться в том, что это было (понятно) написано для не-компьютерного класса не-программистом. Вы можете посоветовать своему профу, что в будущем она получит кого-то в классах потокового программирования (в сотрудничестве с cs prof), чтобы выполнить фактическую реализацию в этих случаях.

Теперь, конечно, это имеет потенциал роста и вниз для всех участников. Конечный пользователь (ваш профессор) должен иметь возможность создать спецификацию или, по крайней мере, сформулировать ее потребности. Ей, возможно, необходимо убедиться в том, что есть смысл отнять время от того, что она предпочла бы сделать, чтобы сделать это. Команда внедрения должна иметь возможность работать с этой спецификацией и обмениваться данными с конечными пользователями. Команда внедрения гарантирует, что код достаточно хорошо написан, если на самом деле это команда, а не человек.

Это отличная подготовка к "реальному миру", а также возможность междисциплинарного сотрудничества с теми, кто понимает проблемную область, работающую с теми, кто понимает инструменты.

Он предлагает студентам cs "реальный", а не надуманное упражнение, и с их стороны должен проявлять больше энтузиазма. (Разумеется, в зависимости от ведомственного соперничества и малой политики, это также может быть проблемой в создании или без стартера, но эй, я оптимист...)

Ответ 11

Там ничего не получается, скрывая проблему от проф. Да, жалуясь на то, что вам дали груз мусора, на котором можно работать, может звучать как нытье, но скрывая этот факт, и попытка исправить его сбоку заставит его выглядеть, как будто вы в лучшем случае медленный рабочий и в худшем случае некомпетентный. Я думаю, что первое, что нужно сделать, это попытаться вежливо сказать профессору, что есть много проблем с этой программой, которые нужно будет очистить и привести примеры... знает ли профессор о чем-нибудь о программировании? Я не думаю, что это было изложено в вопросе... но так или иначе объясняет проблему и говорит, что, по вашему мнению, потребуется, чтобы исправить ее.

Тем не менее, следующий большой вопрос, который приходит мне на ум: Являются ли плохое управление памятью и преобразованием плохого типа единственными большими проблемами, или это те примеры, которые вы выбрали из сотни серьезных проблем? То есть, основная структура и логика программы в основном звучат, или все это беспорядок? (Я бы догадался, что все это беспорядок, но, очевидно, я не видел программу.)

Ключевое решение, которое необходимо предпринять, - это: (а) Пройти через программу и исправить кучу подробных ошибок по одному за раз? (b) Провести серьезную реструктуризацию и очистку? Или (c) выбросить его и переписать с нуля. Я часто испытываю соблазн к выбору (c) в таких случаях, потому что кажется, что переписывание будет меньше работы, чем очистка беспорядка, но вполне вероятно, что в существующий код встроено много подробных логических решений. Если у вас нет детальной, актуальной документации о требованиях, что является такой маловероятной возможностью, что я сразу же увожу ее из-за смеха над самой мыслью - единственный способ узнать все правила - прочитать существующий код и выяснить, что это такое. В какой момент (a) или (b) становится намного более эффективным, чем (c).

Желаю, чтобы я сказал "просто делай Х", к сожалению, с объемом информации, которую можно разумно разместить в сообщении, я думаю, что мы все ограничены словами "Вот некоторые правдоподобные варианты для рассмотрения..."

Ответ 12

Ключи к обслуживанию:

  • SCM. В Windows я бы рекомендовал нечто вроде Mercurial. Сделайте центральный блаженный репозиторий, где от других можно получить программное обеспечение и где исправления будут получены из частных репозиториев разработчика.

  • Отслеживание ошибок/ошибок. Если у вас его еще нет, получите его. Это должно быть легко продать проф. Не могу дать никаких рекомендаций для Windows. Друзья используют Mantis.

  • Управление выпуском. Часто входит в систему отслеживания проблем. Но процесс создания самого релиза - это скорее организационно-политическая, а не техническая проблема. По сути, речь идет о предоставлении публичного имени определенным внутренним версиям программного обеспечения. В реальной жизни он становится очень политическим, когда его решают, что фактически попадает в выпуск.

5K LoC немного. Наличие SCM помогает отслеживать изменения и возвращаться в случае регрессий. Отслеживание проблем помогает команде работать над проблемами. Выполняйте небольшие выпуски при устранении проблем (например, ваш malloc против новых или утечек памяти). Сделайте основные выпуски для более крупных исправлений и функций (например, для поддержки больших наборов данных).

Важно не торопиться и начинать с небольших изменений. Современный SCM допускает множество мелких коммитов (например, отслеживание проблем с деревьями зависимостей проблем), и это следует использовать. Это позволяет отслеживать, как изменяется поведение программного обеспечения и какое изменение точно вводит регрессию. Довольно часто это самое невиновное изменение.

Ответ 13

Заменить все:

Type* data = (Type*)malloc(123*sizeof(Type));

с

std::vector<Type> data(123);

Удалено все управление памятью! Легко, как пирог. Затем просто обходите векторы по значению.

Ответ 14

Эта проблема может быть легко устранена путем добавления большего количества оперативной памяти. 1-2GB должен сделать трюк.