Я работаю разработчиком программного обеспечения уже много лет. По моему опыту, проекты становятся более сложными и неосуществимыми, так как все больше разработчиков вовлекаются в разработку продукта.
Кажется, что программное обеспечение на определенной стадии разработки имеет тенденцию становиться «хакерским» и «хакерским», особенно когда никто из членов команды, которые определяли архитектуру, больше не работает в компании.
Я нахожу разочаровывающим, что разработчику, который должен что-то изменить, трудно получить общее представление об архитектуре. Следовательно, существует тенденция исправлять проблемы или вносить изменения таким образом, чтобы это противоречило исходной архитектуре. В результате получается код, который становится все более сложным и еще более сложным для понимания.
Есть ли полезные советы о том, как сохранить исходный код действительно поддерживаемым на протяжении многих лет?
Ответы:
Единственное реальное решение, позволяющее избежать гниения кода - это хорошо кодировать!
Как правильно писать код - это другой вопрос. Это достаточно сложно, даже если вы отличный программист, работающий один. В разнородной команде все становится намного сложнее. В сторонних (суб) проектах ... просто молись.
Обычные хорошие практики могут помочь:
источник
Модульные тесты - твой друг . Реализация их заставляет слабую связь. Это также означает, что «хакерские» части программы могут быть легко идентифицированы и подвергнуты рефакторингу. Это также означает, что любые изменения можно быстро протестировать, чтобы убедиться, что они не нарушают существующую функциональность. Это должно побудить ваших разработчиков модифицировать существующие методы, а не дублировать код из-за страха поломки.
Модульные тесты также работают как дополнительная часть документации для вашего кода, описывая, что должна делать каждая часть. Благодаря обширным модульным тестам вашим программистам не нужно знать всю архитектуру вашей программы, чтобы вносить изменения и использовать существующие классы / методы.
В качестве приятного побочного эффекта, модульные тесты также помогут уменьшить количество ошибок.
источник
Все здесь быстро упоминают гниль кода , и я полностью понимаю и согласен с этим, но здесь все еще не хватает общей картины и существующей проблемы. Гниение кода не просто происходит. Кроме того, упоминаются юнит-тесты, которые хороши, но на самом деле они не решают проблему. Можно иметь хороший охват модульных тестов и относительно безошибочный код, однако все еще имеет гнилой код и дизайн.
Вы упомянули, что разработчик, работающий над проектом, испытывает трудности с реализацией функции и пропускает общую картину общей архитектуры и, таким образом, осуществляет взлом системы. Где техническое руководство, чтобы обеспечить и повлиять на дизайн? Где проверки кода в этом процессе?
Вы на самом деле не страдаете от гниения кода, но вы страдаете от командной гнили . Дело в том, что это не должно иметь значения, если первоначальные создатели программного обеспечения больше не в команде. Если технический руководитель существующей команды полностью и верно понимает основополагающую конструкцию и хорош в роли технического лидера, то это не проблема.
источник
Мы можем сделать несколько вещей:
Дайте одному человеку общую ответственность за архитектуру. Выбирая этого человека, убедитесь, что у него есть видение и умение разрабатывать и поддерживать архитектуру, и что у них есть влияние и полномочия, чтобы помочь другим разработчикам следовать архитектуре. Этот человек должен быть опытным разработчиком, которому доверяет руководство и которого уважают его коллеги.
Создайте культуру, в которой все разработчики становятся владельцами архитектуры. Все разработчики должны быть вовлечены в процесс разработки и поддержания целостности архитектуры.
Разработайте среду, в которой легко сообщаются архитектурные решения. Поощряйте людей говорить о дизайне и архитектуре - не только в контексте текущего проекта, но и в целом тоже.
Лучшие практики кодирования делают архитектуру более понятной из кода - требуется время на рефакторинг, комментирование кода, разработку модульных тестов и т. Д. Такие вещи, как соглашения об именах и методы чистого кодирования, могут очень помочь в общении архитектуры, поэтому вам нужна команда выделять время для разработки и следования своим собственным стандартам.
Убедитесь, что вся необходимая документация ясна, лаконична, актуальна и доступна. Сделайте как высокоуровневые, так и низкоуровневые архитектурные схемы общедоступными (закрепление их на стене может помочь) и общедоступными.
Наконец (как естественный перфекционист) я должен признать, что архитектурная целостность - это достойное стремление, но могут быть и более важные вещи - например, создание команды, которая может хорошо работать вместе и фактически доставить работающий продукт.
источник
Способ, которым я решаю эту проблему, заключается в том, чтобы снять ее с корня:
Мое объяснение будет использовать термины из Microsoft / .NET , но будет применимо к любой платформе / панели инструментов:
источник
Очистите сгнивший код путем рефакторинга при написании модульных тестов. Выплачивайте (этот) долг за весь код, к которому вы прикасаетесь, когда вы:
Значительно ускорите цикл разработки в первую очередь с помощью:
Код рефакторинга для использования слабой связи (высоко внутренне связанных элементов) посредством:
Органический рост это хорошо; большой авангардный дизайн - это плохо.
Иметь лидера, который осведомлен о текущем дизайне. Если нет, прочитайте код проекта, пока вы не будете осведомлены.
Читайте книги по рефакторингу.
источник
Простой ответ: вы не можете .
Вот почему вы должны стремиться к написанию небольшого и простого программного обеспечения. Это не просто.
Это возможно только в том случае, если вы достаточно долго думаете о своей, казалось бы, сложной проблеме, чтобы определить ее максимально простым и лаконичным образом.
Решение действительно больших и сложных проблем часто можно решить, опираясь на маленькие и простые модули.
Другими словами, как отмечали другие, простота и слабая связь являются ключевыми составляющими.
Если это невозможно или невозможно, вы, вероятно, проводите исследования (сложные проблемы без известных простых решений или вообще без известных решений). Не ожидайте, что исследования непосредственно произведут ремонтопригодные продукты, это не то, для чего исследование.
источник
Я работаю над базой кода для продукта, который постоянно совершенствуется с 1999 года, так что, как вы можете себе представить, он сейчас довольно сложный. Самый большой источник хакерства в нашей кодовой базе - это многочисленные случаи, когда нам приходилось переносить его с ASP Classic на ASP.NET , с ADO на ADO.NET, с обратных передач на Ajax , переключения библиотек пользовательского интерфейса, стандартов кодирования и т. Д.
В целом мы проделали разумную работу по поддержанию поддерживаемой базы кода. Главные вещи, которые мы сделали, которые способствовали этому:
1) Постоянный рефакторинг - если вам нужно прикоснуться к фрагменту кода, который является хакерским или трудным для понимания, вы должны уделить дополнительное время на его очистку, и вам предоставят свободу действий в расписании. Модульные тесты делают это намного менее страшным, потому что вы можете легче тестировать регрессии.
2) Сохраняйте аккуратную среду разработки - будьте бдительны в отношении удаления кода, который больше не используется, и не оставляйте резервные копии / рабочие копии / экспериментальный код в каталоге проекта.
3) Согласованные стандарты кодирования для жизни проекта. Посмотрим правде в глаза, наши взгляды на стандарты кодирования со временем меняются. Я предлагаю придерживаться стандарта кодирования, с которого вы начали, на всю жизнь проекта, если у вас нет времени, чтобы вернуться и модифицировать весь код, чтобы соответствовать новому стандарту. Здорово, что вы перешли к венгерской нотации , но примените этот урок к новым проектам, а не просто переключитесь на этот новый проект.
источник
Так как вы пометили вопрос с управлением проектами, я попытался добавить некоторые не кодовые пункты :)
Планируйте текучесть кадров - предположите, что вся команда разработчиков исчезнет к тому времени, когда она достигнет своей фазы обслуживания - ни один разработчик, достойный их соли, не хочет застрять, поддерживая свою систему навсегда. Начните готовить материалы для передачи, как только у вас будет время.
Последовательность / однородность не могут быть подчеркнуты достаточно. Это будет препятствовать культуре «иди в одиночку» и побудит новых разработчиков спросить, сомневаются ли они.
Держите это в курсе - используемые технологии, шаблоны проектирования и стандарты - потому что у нового разработчика в команде (на любом уровне) будет больше шансов быстро приступить к работе.
Документация - особенно архитектура - почему были приняты решения, и стандарты кодирования. Также сохраняйте ссылки / заметки / дорожные карты при документировании бизнес-домена - вы будете удивлены, насколько трудно корпоративному бизнесу объяснить, что они делают, разработчику без опыта работы с доменом.
Четко сформулируйте правила - не только для вашей текущей команды разработчиков, но и подумайте о будущих разработчиках обслуживания. Если это означает размещение гиперссылки на соответствующую документацию по оформлению и кодированию на каждой странице, пусть будет так.
Убедитесь, что архитектура и особенно слои кода четко разграничены и разделены - это потенциально позволит заменить слои кода по мере появления новых технологий, например, заменить интерфейс Web Forms на HTML5 jQuery UI и т. Д., Что может купить год или около того дополнительного долголетия.
источник
Одним из свойств кода с высокой степенью доступности является чистота функции .
Чистота означает, что функции должны возвращать один и тот же результат для одних и тех же аргументов. То есть они не должны зависеть от побочных эффектов других функций. Кроме того, это полезно, если они не имеют побочных эффектов сами.
Это свойство легче увидеть, чем свойства сцепления / сцепления. Вам не нужно делать все возможное, чтобы достичь этого, и я лично считаю это более ценным.
Когда ваша функция чиста, ее тип сам по себе является очень хорошей документацией. Кроме того, написание и чтение документации с точки зрения аргументов / возвращаемого значения намного проще, чем упоминание некоторого глобального состояния (возможно, доступ к которому осуществляется другими потоками O_O).
В качестве примера широкого использования чистоты для удобства сопровождения вы можете увидеть GHC . Это большой проект, которому около 20 лет, в котором проводятся масштабные рефакторинги и все еще вводятся новые важные функции.
Наконец, мне не очень нравится пункт «Не усложняйте». Вы не можете держать свою программу простой, когда моделируете сложные вещи. Попробуйте создать простой компилятор, и ваш сгенерированный код, скорее всего, будет работать очень медленно. Конечно, вы можете (и должны) сделать отдельные функции простыми, но в результате вся программа не будет простой.
источник
В дополнение к другим ответам, я бы порекомендовал слои. Не слишком много, но достаточно для разделения разных типов кода.
Мы используем модель внутреннего API для большинства приложений. Существует внутренний API, который подключается к базе данных. Затем слой пользовательского интерфейса . Разные люди могут работать на каждом уровне, не нарушая и не нарушая другие части приложений.
Другой подход - заставить всех прочитать comp.risks и The Daily WTF, чтобы они узнали о последствиях плохого дизайна и плохого программирования, и они будут бояться увидеть свой собственный код, опубликованный на The Daily WTF .
источник
Поскольку многие из этих ответов, похоже, сосредоточены на больших командах, даже с самого начала, я собираюсь представить свою точку зрения как часть команды разработчиков из двух человек (три, если вы включаете дизайнера) для стартапа.
Очевидно, что простые проекты и решения являются лучшими, но когда у вас есть парень, который буквально платит вашей зарплатой, дыша вам на шею, у вас не обязательно есть время подумать о самом элегантном, простом и удобном в обслуживании решении. Имея это в виду, мой первый важный момент:
Документация Не комментарии, код должен в основном самодокументироваться, но такие вещи, как проектные документы, иерархии и зависимости классов, архитектурные парадигмы и т. Д. Все, что помогает новому или даже существующему программисту понимать базу кода. Кроме того, может помочь документирование тех странных псевдобиблиотек, которые в конечном итоге всплывают, например, «добавить этот класс в элемент для этой функциональности», поскольку это также мешает людям переписывать функциональность.
Тем не менее, даже если у вас есть серьезные ограничения по времени, я считаю, что еще одна хорошая вещь, чтобы иметь в виду:
Избегайте взломов и быстрых исправлений. Если быстрое исправление не является фактическим исправлением, всегда лучше выяснить основную проблему, а затем устранить ее. Если у вас буквально не будет сценария «заставить это работать в ближайшие 2 минуты, или вы уволены», лучше сделать исправление сейчас, потому что вы не собираетесь исправлять код позже, вы просто собираетесь перейти к следующему заданию, которое у вас есть.
И мой личный любимый совет - больше цитата, хотя я не могу вспомнить источник:
«Кодируйте, как будто человек, который идет за вами, является психопатом-убийцей, который знает, где вы живете»
источник
/** Gets the available times of a clinic practitioner on a specific date. **/
или/** Represents a clinic practitioner. **/
.Один принцип, который не был упомянут, но который я считаю важным, - это принцип открытого / закрытого типа .
Вы не должны изменять код, который был разработан и протестирован: любой такой кусок кода запечатан. Вместо этого расширяйте существующие классы с помощью подклассов или используйте их для написания оберток, классов декораторов или с помощью любого шаблона, который вы считаете подходящим. Но не меняйте рабочий код .
Просто мои 2 цента.
источник
Будь разведчиком . Всегда оставляйте код чище, чем вы его нашли.
Исправить разбитые окна . Все эти комментарии «изменяются в версии 2.0», когда вы используете версию 3.0.
Когда есть серьезные хаки, разработайте лучшее решение в команде и сделайте это. Если вы не можете исправить взлом как команда, то вы недостаточно хорошо понимаете систему. «Попроси взрослого о помощи». Старейшие люди вокруг, возможно, видели это раньше. Попробуйте нарисовать или извлечь диаграмму системы. Попробуйте нарисовать или извлечь сценарии использования, которые особенно полезны в качестве диаграмм взаимодействия. Это не исправляет это, но по крайней мере вы можете видеть это.
Какие предположения больше не соответствуют действительности, которые подтолкнули дизайн в определенном направлении? Там может быть небольшой рефакторинг, скрывающийся за некоторыми из этого беспорядка.
Если вы объясните, как работает система (хотя бы один случай использования), и вам снова и снова придется извиняться за подсистему, это проблема. Какое поведение будет делать остальную часть системы проще (независимо от того, насколько сложно это реализовать по сравнению с тем, что есть). Классическая подсистема для перезаписи - это та, которая загрязняет каждую другую подсистему своей операционной семантикой и реализацией. «О, вы должны собрать значения перед тем, как передать их в подсистему froo, а затем снова отключить их при получении вывода из froo. Может быть, все значения должны быть сброшены при чтении из пользователя и хранилища, и остальная часть системы не так? Это становится более захватывающим, когда есть два или более различных grozification.
Проведите неделю в команде, удаляя предупреждения, чтобы увидеть реальные проблемы.
Переформатировать весь код в стандарт кодирования.
Убедитесь, что ваша система контроля версий привязана к вашей системе отслеживания ошибок. Это означает, что будущие изменения приятны и подотчетны, и вы можете решить ПОЧЕМУ.
Занимайтесь археологией. Найдите оригинальные проектные документы и просмотрите их. Они могут быть на этом старом компьютере в углу офиса, в заброшенном офисе или в шкафу, который никто никогда не открывает.
Переиздание проектной документации в вики. Это помогает институционализировать знания.
Напишите процедуры, похожие на контрольные списки для выпусков и сборок. Это мешает людям думать, чтобы они могли сосредоточиться на решении проблем. Автоматизируйте сборки, где это возможно.
Попробуйте непрерывную интеграцию . Чем раньше вы получите неудачную сборку, тем меньше времени проект сможет потратить с рельсов.
Если руководитель вашей команды не делает этого, это плохо для компании.
Постарайтесь убедиться, что весь новый код проходит правильные юнит-тесты с измеренным покрытием. Так что проблема не может стать намного хуже.
Попробуйте выполнить модульное тестирование некоторых старых битов, которые не были протестированы. Это помогает сократить страх перемен.
Автоматизируйте интеграционные и регрессионные тесты, если можете. По крайней мере, есть контрольный список. Пилоты умны, им платят много, и они используют контрольные списки. Они также облажались довольно редко.
источник
Прочитайте, а затем перечитайте Code Complete от Стива Макконнелла. Это похоже на библию хорошего написания программного обеспечения, от начального дизайна проекта до одной строки кода и всего, что между ними. Что мне больше всего нравится в этом, так это то, что он подкреплен десятилетиями надежных данных; это не просто следующий лучший стиль кодирования.
источник
Я пришел, чтобы назвать это «эффектом мистического дома Винчестера». Как и в доме, все начиналось достаточно просто, но с годами многие разные работники добавили так много странных функций без общего плана, что никто его больше не понимает. Почему эта лестница никуда не ведет и почему эта дверь открывается только в одну сторону? Кто знает?
Способ ограничить этот эффект - начать с хорошего дизайна, который сделан достаточно гибким, чтобы справиться с расширением. Несколько предложений уже были предложены по этому вопросу.
Но часто вы берете на себя работу, где ущерб уже нанесен, и уже слишком поздно для хорошего дизайна без проведения дорогостоящего и потенциально рискованного перепроектирования и переписывания. В таких ситуациях лучше всего попытаться найти способы ограничить хаос, в то же время охватывая его. Это может раздражать ваши дизайнерские ощущения, что все должно пройти через огромный, некрасивый, одноэлементный «менеджерский» класс или уровень доступа к данным тесно связан с пользовательским интерфейсом, но научитесь справляться с этим. Защищайтесь в этих рамках и старайтесь ожидать неожиданного появления «призраков» программистов прошлого.
источник
Рефакторинг кода и модульное тестирование прекрасно. Но так как этот длительный проект ведет к взлому, это означает, что руководство не ставит ногу, чтобы убрать гниль. Команда обязана внедрять хаки, потому что кто-то не выделяет достаточных ресурсов для обучения людей и анализа проблемы / запроса.
Поддержка долгосрочного проекта является такой же ответственностью менеджера проекта, как и отдельного разработчика.
Люди не вводят хаки, потому что им это нравится; они вынуждены обстоятельствами.
источник
Я просто хочу поставить нетехническую проблему и (возможно) прагматический подход.
Если ваш менеджер не заботится о техническом качестве (управляемый код, простая архитектура, надежная инфраструктура и т. Д.), Становится сложно улучшить проект. В этом случае необходимо обучить указанного менеджера и убедить его «вкладывать» усилия в ремонтопригодность и решение технических проблем .
Если вы мечтаете о качестве кода в этих книгах, вам также нужен начальник, который обеспокоен этим.
Или, если вы просто хотите приручить «проект Франкенштейна», вот мои советы:
По моему опыту, программирование скорее энтропийно, чем эмерджентно (по крайней мере, в популярной парадигме с императивной структурой). Когда люди пишут код для «просто работы», возникает тенденция потерять свою организацию. Теперь для организации кода требуется время, иногда гораздо больше, чем просто заставить его работать.
Помимо реализации функций и исправления ошибок, не торопитесь с очисткой кода.
источник
Я был удивлен, обнаружив, что ни один из многочисленных ответов не выдвинул очевидного: сделать программное обеспечение состоящим из множества небольших независимых библиотек. Имея множество небольших библиотек, вы можете создавать большое и сложное программное обеспечение. Если требования меняются, вам не нужно выбрасывать всю кодовую базу или исследовать, как изменить большую звуковую кодовую базу, чтобы сделать что-то другое, чем то, что она делает в настоящее время. Вы просто решаете, какие из этих библиотек будут актуальны после изменения требований, и как объединить их, чтобы получить новую функциональность.
Используйте любые методы программирования в тех библиотеках, которые облегчают использование библиотеки. Обратите внимание, что, например, любой не объектно-ориентированный язык, поддерживающий указатели функций, поддерживает фактически объектно-ориентированное программирование (ООП). Так, например, в C, вы можете сделать ООП.
Вы даже можете рассмотреть возможность совместного использования этих небольших независимых библиотек между многими проектами (подмодули git - ваши друзья).
Излишне говорить, что каждая небольшая независимая библиотека должна быть проверена модулем. Если определенная библиотека не тестируется модулем, вы делаете что-то не так.
Если вы используете C или C ++ и вам не нравится идея иметь много маленьких файлов .so, вы можете связать все библиотеки вместе в больший файл .so или, в качестве альтернативы, вы можете сделать статическое связывание. То же самое относится и к Java, просто измените .so на .jar.
источник
Просто: уменьшите расходы на обслуживание большей части вашего кода до нуля, пока у вас не будет достаточного количества движущихся частей. Код, который никогда не нужно менять, не требует затрат на обслуживание. Я рекомендую стремиться к тому, чтобы код действительно имел нулевую стоимость обслуживания, а не пытался снизить стоимость по сравнению с множеством мелких и суетных рефакторинговых итераций. Сделать это стоить ноль сразу.
Хорошо, по общему признанию, это намного, намного сложнее, чем кажется. Но это не сложно начать. Вы можете взять часть кодовой базы, протестировать ее, создать над ней красивый интерфейс, если дизайн интерфейса беспорядок, и начать наращивать части кодовой базы, которые являются надежными, стабильными (как в случае отсутствия оснований для изменения), и одновременно сжатие деталей, которые ненадежны и нестабильны. Кодовые базы, которые нужно поддерживать как кошмар, часто не отличают движущиеся части, которые должны быть заменены, от частей, которые этого не делают, поскольку все считается ненадежным и подверженным изменениям.
Я на самом деле рекомендую пройти весь путь, чтобы разделить организацию вашей кодовой базы на «стабильную» и «нестабильную» части, причем стабильные части - это огромная PITA для восстановления и изменения (что хорошо, так как им не нужно быть изменены и перестроены, если они действительно принадлежат к «стабильному» разделу).
Это не размер кодовой базы, которая усложняет обслуживание. Это размер кодовой базы, который необходимо поддерживать. Я использую миллионы строк кода, когда, скажем, использую API операционной системы. Но это не способствует затратам на обслуживание моего продукта, поскольку мне не нужно поддерживать исходный код операционной системы. Я просто использую код, и он работает. Код, который я просто использую и никогда не должен поддерживать, не требует никаких затрат на обслуживание с моей стороны.
источник