Seven Deadly Sins of a Software Project

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

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

К сожалению, языки программирования, которые мы используем, слишком гибкие. Они разрешают слишком многое и запрещают слишком мало. Например, в Java ничего не мешает разместить всё приложение в одном единственном “классе” с несколькими тысячами методов. Технически приложение будет компилироваться и работать. Но это хорошо известный анти-паттерн, называемый божественным объектом.

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

Как только вы позволяете появиться нескольким анти-паттернам, они будут появляться всё чаще, и “опухоль” будет только расти.

Это особенно верно для объектно-ориентированных языков (Java, C++, Ruby и Python), в основном потому, что они наследуют многое от процедурных языков (C, Fortran и COBOL). И потому что разработчики ООП часто мыслят в процедурном и императивном стиле. К сожалению.

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

Мой единственный практический совет здесь - читайте и учитесь. Возможно, вам помогут эти книги или моя книга “Elegant Objects.” Всегда будьте скептически настроены по отношению к качеству вашего программного обеспечения и не расслабляйтесь, когда оно “просто работает”. Как и с раком, чем раньше вы его диагностируете, тем больше шансов на выживание.

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

Всегда используйте тикеты. Независимо от того, насколько маленьким является проект или его команда, даже если это только вы один, создавайте тикеты (задачи GitHub) для каждой проблемы, которую вы решаете. Кратко объясните проблему в тикете и задокументируйте свои мысли там. Используйте тикет как временное хранилище для всей информации, связанной с проблемой. Опубликуйте все, что может иметь смысл в будущем, когда кто-то другой попытается понять, о чем были эти “несколько странных коммитов”.

Упоминайте тикеты в коммитах. Само собой разумеется, что каждый коммит должен иметь сообщение. Коммиты без сообщений - очень плохая практика, не буду даже обсуждать, почему. Но только сообщение недостаточно. Каждое сообщение должно начинаться с номера тикета, с которым вы работаете. GitHub (я уверен, что вы его используете) автоматически свяжет коммиты и тикеты, увеличивая отслеживаемость изменений.

Не удаляйте ничего. Git позволяет нам делать “принудительную” отправку, которая перезаписывает всю ветку, которая ранее существовала на сервере. Это всего лишь один пример того, как можно уничтожить историю разработки. Многократно я также видел, как люди удаляют свои комментарии в обсуждениях на GitHub, чтобы тикеты выглядели более “чистыми”. Это просто неправильно. Никогда ничего не удаляйте; пусть ваша история остается с вами, несмотря на то, как плохо (или беспорядочно) она может выглядеть для вас сейчас.

Каждое программное обеспечение должно быть упаковано перед его доставкой конечному пользователю. Если это библиотека Java, она должна быть упакована в файл .jar и выложена в репозиторий; если это веб-приложение, оно должно быть размещено на определенной платформе и т.д. Независимо от размера продукта всегда существует стандартная процедура тестирования, упаковки и размещения.

Идеальным решением было бы автоматизировать эту процедуру, чтобы ее можно было выполнить из командной строки одной командой:

Большинство проектов далеки от этого. Их процесс выпуска всегда включает некую магию, где ответственное лицо за это (также известное как DevOp) должно кликнуть здесь и там, войти куда-то, проверить некоторые метрики и т.д. Такой ад-хок процесс выпуска все еще является очень типичным грехом всей индустрии программной инженерии.

Я могу дать только один практический совет: Автоматизируйте это. Я использую для этого rultor.com, но вы можете использовать любые инструменты, которые вам нравятся. Важно, чтобы весь процедура была полностью автоматизирована и могла быть выполнена из командной строки.

Статический анализ придает нашему коду лучший вид. И, сделав его лучше выглядящим, мы неизбежно делаем его лучше работающим. Но это происходит только тогда, когда вся команда (!) вынуждена следовать правилам, установленным статическим анализатором (или анализаторами). Я писал об этом в статье “Строгий контроль качества кода на Java”. Я использую qulice.com в Java-проектах и rubocop в Ruby, но существует множество аналогичных инструментов для практически каждого языка.

Вы можете использовать любой из них, но сделайте это обязательным! В большинстве проектов, где используется статический анализ, разработчики просто создают красиво выглядящие отчеты и продолжают писать код так, как делали раньше. Такой “добровольный” подход не приносит проекту никаких преимуществ. Более того, он создает иллюзию качества.

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

Простыми словами, тестовое охватывание - это степень протестированности программного обеспечения с помощью модульных или интеграционных тестов. Чем выше охват, тем больше “кода” было выполнено во время выполнения тестов. Очевидно, что более высокий охват - это хорошо.

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

Высокий охват не гарантирует высокое качество. Это очевидно. Но неизвестный охват - это явный показатель проблем с поддержкой. Когда новый разработчик приступает к проекту, он должен иметь возможность вносить изменения и видеть, как это влияет на охват. Идеально, тестовое охватывание должно проверяться также, как и статический анализ, и сборка должна завершаться с ошибкой, если оно оказывается ниже определенного заранее установленного порога (обычно около 80 процентов).

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

Это в основном связано с тем, что поддерживаемость заключается в моей способности понимать ваш код, читая его.

Когда я изучаю исходный код, его коммиты и историю выпусков, я должен понимать намерения его авторов, что проект делал год назад, куда он движется сейчас, какова его дорожная карта и так далее. Вся эта информация должна присутствовать в исходном коде и, что самое важное, в истории Git.

Теги Git и заметки о выпусках GitHub - это два мощных инструмента, которые предоставляют мне такую информацию. Используйте их в полной мере. Также не забывайте, что каждая бинарная версия продукта должна быть доступна для немедленной загрузки. Я должен иметь возможность загрузить версию 0.1.3 и протестировать ее прямо сейчас, даже если проект в данный момент работает над версией 3.4.

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

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

Я говорю здесь о документации для пользователей, а не для разработчиков. В общем, я против документации внутри программного обеспечения. Здесь я полностью согласен с Agile Manifesto—рабочее программное обеспечение гораздо важнее всесторонней документации. Но это не относится к “внешней” документации, которая должна быть прочитана пользователями, а не разработчиками.

Таким образом, взаимодействие конечного пользователя с программным обеспечением должно быть ясно задокументировано.

Если ваше программное обеспечение является библиотекой, то его конечными пользователями являются программисты, которые собираются использовать его—не вносить вклад в него, а просто использовать его как “черный ящик”.

Вот критерии, которые используются для оценки проектов с открытым исходным кодом, участвующих в нашем конкурсе наград.

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-15 at 06:42

sixnines availability badge   GitHub stars