The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
Поддерживаемость является самым ценным достоинством современной разработки программного обеспечения. Поддерживаемость может быть измерена как время, необходимое новому разработчику для изучения программного обеспечения перед тем, как он сможет начать вносить серьезные изменения в него. Чем больше время, тем ниже поддерживаемость. В некоторых проектах это требование времени близко к бесконечности, что означает, что оно буквально неподдерживаемо. Я считаю, что существуют семь фундаментальных и смертных грехов, которые делают наше программное обеспечение неподдерживаемым. Вот они.
Anti-Patterns
К сожалению, языки программирования, которые мы используем, слишком гибкие. Они позволяют слишком много и запрещают слишком мало. Например, в Java нет ничего против того, чтобы поместить всё приложение в один единственный “класс” с несколькими тысячами методов. Технически, приложение скомпилируется и запустится. Но это известный анти-паттерн, который называется объект-бог.
Таким образом, анти-паттерн - это технически приемлемый способ проектирования, который общепринято считается неправильным. В каждом языке существует множество анти-паттернов. Их наличие в вашем продукте подобно опухоли в живом организме. Как только они начинают расти, очень сложно остановить процесс. В конечном итоге, весь организм умирает. В конечном итоге, весь программный продукт становится неподдерживаемым и приходится переписывать.
Как только вы допустите несколько анти-паттернов, в конечном итоге их станет больше, а “опухоль” будет только расти.
Это особенно верно для объектно-ориентированных языков программирования (Java, C++, Ruby и Python), главным образом, потому что они наследуют многое от процедурных языков (C, Fortran и COBOL). И потому что разработчики ООП, как правило, мыслят процедурно и императивно. К сожалению.
Кстати, в дополнение к существующему списку известных анти-паттернов, я также считаю эти несколько вещей довольно плохими подходами к кодированию.
Мой единственный практический совет здесь - читайте и учитесь. Возможно, эти книги помогут вам или моя книга “Elegant Objects.” Всегда старайтесь быть скептическими по поводу качества вашего программного обеспечения и не расслабляйтесь, когда оно “просто работает”. Как и с раком, чем раньше вы его диагностируете, тем больше шансов на выживание.
Untraceable Changes
Когда я смотрю на историю коммитов, я должен иметь возможность определить для каждого изменения что было изменено, кто внес изменение и почему было сделано это изменение. Более того, время, необходимое для получения ответов на эти три вопроса, должно измеряться в секундах. В большинстве проектов это не так. Вот несколько практических рекомендаций:
Всегда используйте тикеты. Независимо от размера проекта или команды, даже если это только вы один, создавайте тикеты (задачи на GitHub) для решения каждой проблемы. Кратко объясните проблему в тикете и задокументируйте свои мысли там. Используйте тикет как временное хранилище для всей информации, связанной с проблемой. Опубликуйте все, что может иметь смысл в будущем, когда кто-то другой попытается понять, о чем были эти “несколько странных коммитов”.
Ссылочные билеты в коммитах. Само собой разумеется, что каждый коммит должен иметь сообщение. Коммиты без сообщений - очень плохая практика; я даже не буду обсуждать, почему. Но простое сообщение недостаточно. Каждое сообщение должно начинаться с номера билета, над которым вы работаете. GitHub (я уверен, что вы его используете) автоматически связывает коммиты и билеты, увеличивая отслеживаемость изменений.
Не удаляйте ничего. Git позволяет нам выполнять «принудительную» отправку (forced push), которая перезаписывает всю ветку, которая ранее существовала на сервере. Это всего лишь один пример того, как вы можете уничтожить историю разработки. Многократно я также видел, как люди удаляют свои комментарии в обсуждениях на GitHub, чтобы заявки выглядели более «чистыми». Это просто неправильно. Никогда не удаляйте ничего; позвольте вашей истории оставаться с вами, несмотря на то, насколько плохо (или беспорядочно) она может выглядеть для вас сейчас.
Ad Hoc Releases
Каждый программный продукт должен быть упакован перед его доставкой конечному пользователю. Если это библиотека Java, она должна быть упакована в файл .jar
и выпущена в какой-либо репозиторий; если это веб-приложение, оно должно быть развернуто на определенной платформе и т.д. Независимо от размера продукта всегда существует стандартная процедура, которая выполняет тестирование, упаковку и развертывание.
Идеальным решением было бы автоматизировать эту процедуру, чтобы ее можно было выполнить из командной строки с помощью одной команды.
$ ./release.sh
...
DONE (took 98.7s)
Большинство проектов далеки от этого. Их процесс выпуска всегда включает в себя некую магию, где ответственное лицо за него (также известное как DevOp) должно нажимать кнопки там и тут, входить в систему, проверять некоторые метрики и так далее. Такой ad hoc процесс выпуска все еще является типичной греховной практикой в индустрии программной инженерии.
Я могу дать только один практический совет: Автоматизируйте это. Я использую rultor.com для этого, но вы можете использовать любые инструменты, которые вам нравятся. Важно, чтобы весь процесс был полностью автоматизирован и мог выполняться из командной строки.
Volunteer Static Analysis
Статический анализ делает наш код визуально лучше. И делая его лучше визуально, мы неизбежно делаем его лучше работать. Но это происходит только тогда, когда вся команда принуждена (!) следовать правилам, навязываемым статическим анализатором(ами). Я рассказывал об этом в статье Strict Control of Java Code Quality. В Java-проектах я использую qulice.com, а в Ruby - rubocop, но есть много похожих инструментов для практически каждого языка.
Вы можете использовать любой из них, но сделайте это обязательным! В большинстве проектов, где используется статический анализ, разработчики просто создают красиво выглядящие отчеты и продолжают писать код так, как делали раньше. Такой “добровольный” подход не приносит никакой пользы проекту. Более того, он создает иллюзию качества.
То, что я говорю, это то, что статический анализ должен быть обязательным шагом в вашем процессе развертывания. Сборка не может быть завершена, если нарушается какое-либо правило статического анализа.
Unknown Test Coverage
Простыми словами, охват тестирования - это степень, до которой программное обеспечение было протестировано с помощью модульных или интеграционных тестов. Чем выше показатель охвата, тем больше “количества” кода было выполнено во время выполнения тестов. Очевидно, что высокий уровень охвата - это хорошая вещь.
Однако многие разработчики проектов просто не знают охват своего кода. Они просто не измеряют этот показатель. У них могут быть некоторые тесты, но никто не знает, насколько они проникают в программное обеспечение и какие его части вообще не проходят тестирование. Такая ситуация гораздо хуже, чем низкий уровень тестового покрытия, который измеряется и сообщается всем.
Высокое покрытие не гарантирует высокого качества. Это очевидно. Но незнакомое покрытие является явным индикатором проблем с поддержкой. Когда новый разработчик присоединяется к проекту, он должен иметь возможность внести некоторые изменения и увидеть, как покрытие меняется после них. В идеале, проверка покрытия тестами должна осуществляться так же, как и статический анализ, и сборка должна завершаться неудачно, если покрытие оказывается ниже определенного порога (обычно около 80 процентов).
Nonstop Development
То, что я имею в виду под “непрерывной” разработкой, означает отсутствие этапов и выпусков. Независимо от типа программного обеспечения, которое вы разрабатываете, вам необходимо часто выпускать и версионировать его. Проект без четкой истории релизов становится неподдерживаемым беспорядком.
Это в основном связано с тем, что поддерживаемость заключается в том, чтобы я мог понять вас, читая ваш код.
Когда я изучаю исходный код и его историю коммитов и релизов, я должен быть в состоянии понять, какой была цель автора или авторов, что проект делал год назад, куда он направляется сейчас, какова его дорожная карта и так далее. Вся эта информация должна быть представлена в исходном коде и, что самое важное, в истории Git.
Git tags и заметки о выпуске на GitHub - два мощных инструмента, которые предоставляют мне подобную информацию. Используйте их на полную мощность. Также, не забывайте о том, что каждая двоичная версия продукта должна быть доступна для немедленной загрузки. Я должен иметь возможность загрузить версию 0.1.3 и протестировать ее прямо сейчас, даже если проект в настоящий момент работает над 3.4.
Undocumented Interfaces
У каждой программы есть интерфейсы, через которые ее предполагается использовать. Если это Ruby-камень, то есть классы и методы, которые я буду использовать в качестве конечного пользователя. Если это веб-приложение, то есть веб-страницы, которые конечный пользователь увидит и управляет, чтобы использовать приложение. У каждого программного проекта есть интерфейсы, и их необходимо тщательно задокументировать.
Как и все вышеупомянутое, здесь также речь идет о поддерживаемости. Как новый программист в проекте, я начну изучать его через его интерфейсы. Я должен быть способен понять, что он делает, и попытаться использовать его самостоятельно.
Я говорю здесь о документации для пользователей, а не для разработчиков. В общем, я против документации внутри программного обеспечения. Здесь я полностью согласен с Agile Manifesto - рабочее программное обеспечение намного важнее подробной документации. Но это не относится к “внешней” документации, которая предназначена для чтения пользователями, а не разработчиками.
Таким образом, взаимодействие конечного пользователя с программным обеспечением должно быть четко задокументировано.
Если ваше программное обеспечение является библиотекой, то его конечными пользователями являются разработчики программного обеспечения, которые собираются использовать его — не вносить вклад в него, а просто использовать его как “черный ящик”.
These are the criteria being used to evaluate the open source projects entered in our award competition.
Translated by ChatGPT gpt-3.5-turbo/35 on 2023-09-20 at 21:02