7 смертных грехов программного проекта

Original author: Yegor Bugayenko
  • Translation

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


Антипаттерны


К сожалению, все современные программные языки обладают слишком большой гибкостью. Они слишком много позволяют и слишком мало запрещают.
Например, Java не имеет ничего против того, чтобы вы вместили целое приложение в один единственный «class» с помощью 5000 разных методов. Технически приложение компилируется и запускается, но это хорошо всем известный антипаттерн, который называется Божественным объектом.


image

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


Как только вы допустили один антипаттерн, их сразу становится больше и больше, и эта «опухоль» только растет.


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


Всегда старайтесь относиться с достаточной долей скептицизма к своему проекту и не расслабляйтесь, если он «просто работает». Чем раньше вы диагностируете проблему, тем проще ее вылечить.


Неотслеживаемые изменения


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

image

Всегда используйте тикеты. Неважно, насколько мал проект или команда, которая его обслуживает — даже если вы работаете над ним в гордом одиночестве, всегда используйте тикеты для любой возникающей проблемы. Объясните в двух словах суть проблемы, зафиксируйте свои предположения. Используйте тикет-систему как временное хранилище для любой информации, имеющей отношение к проблеме. Фиксируйте все, что может в будущем иметь смысл, когда кто-то другой будет пытаться вникнуть в «что-то странное, что происходит с продуктом».


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


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


Ad Hoc релизы


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


image

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


image

Многие проекты далеки от этого. Процессы их релиза — это всегда что-то магическое, когда ответственный за это человек (также известный как DevOp) должен нажать на определнные кнопки здесь и там, где-то залогиниться, проверить определенные показатели и т. д. Такие релизы называются ad hoc релизами, они типичны для всей индустрии.


Здесь может быть только один совет: автоматизируйте процесс.


Волонтерский статический анализ


image

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


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


Неизвестное тестовое покрытие


Тестовое покрытие — это степень, в которой ПО прошло интеграционное тестирование. Чем больше покрытие, тем больший объем кода был выполнен во время тестирования. Очевидно, что высокое покрытие — хорошая штука.


image

Тем не менее, многие разработчики не знаю, каково их покрытие: они просто не измеряют этот показатель. Возможно, они и проводят какие-то тесты, но никто не знает, как глубоко тестируется ПО, а какие его участки не тестировались вовсе. Это гораздо хуже, чем плохое тестовое покрытие, о котором вы рассказали каждому встречному.


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


Непрерывная разработка


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


image

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


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


Недокументированные интерфейсы


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


image

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


Мы здесь говорим о документировании для пользователя, а не для разработчика. В общем и целом, мы против документации внутри ПО: работающее ПО гораздо лучше, чем понятная документация к нему. Но это не относится к «внешней» документации, которая предполагается для использования пользователями.


Взаимодействие конечного пользователя с ПО должно быть документировано в обязательном порядке. Если ваша программа — это библиотека, то ее конечные пользователи — разработчики, которые не развивают продукт, а просто используют его как «черный ящик».


Все эти критерии используются для проектов с открытым исходным кодом.

Cloud4Y
85.95
#1 Корпоративный облачный провайдер
Share post

Comments 13

    +1
    Спасибо за статью. Скажите, а что плохого в непрерывной разработке? И в тему: как в коде указывать, что планируется сделать и каким курсом идёт проект?
      +1
      Спасибо. Прочитал с удовольствием.

      Только одна неверная ссылка я думаю.

      «Ссылайтесь на тикеты в коммитах. Нет необходимости поучать, что каждый \»коммит"/ должен сопровождаться сообщением." — тут ссылка на коммит ведет в описание коммита SQL, хотя должно быть описание комита для Гита.
        0
        >Некоторые веб-сервисы для хостинга ИТ-проектов, например, Git

        Что? С каких пор git стал веб сервисом? Вот и возникает вопрос а стоит ли доверять мнению автора статьи который даже не в курсе что такое git и путает его с GitHub(BitBucket, etc)ю Плюс с некоторыми пунктами не согласен. Например с предпоследним. Имхо роллинг релиз ничем не хуже классической системы с периодическими релизами.
          0
          molchanoviv, про Git действительно опечатка. Спасибо, исправили!
          +3
          Тестовое покрытие — это степень, в которой ПО прошло интеграционное тестирование.

          Почему только интеграционное? Куда делось юнит-тестирование, компонентное тестирование и остальные?
          Очевидно, что высокое покрытие — хорошая штука.

          Не очевидно. Хорошая штука — достаточное покрытие. Слишком большое количество тестов приведет к тому, что вырастут издержки на поддержку тестов при изменении кода.
            0
            Бросилась в глаза фраза «Некоторые веб-сервисы для хостинга ИТ-проектов, например, Git, имеют сильные инструменты для создания такой информации». Решил посмотреть, как же там в оригинале. А там: «Git tags and GitHub release notes are two powerful instruments that provide me such information». И как это называется?
              0
              Недокументированные интерфейсы

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

              Пустил слезу…
              Апогей недокументированных интерфейсов — отсутствие интерфейсов
                0
                Не совсем понятна фраза «Волонтерский статический анализ». Подозреваю, что автор имел ввиду «добровольный анализ», который плох, потому что он должен быть обязательным.
                  0
                  Ну или анализ ради анализа и красивых отчетов. Без применения на практике в ежедневной разработке.
                  0
                  Объясните в двух словах суть проблемы, зафиксируйте свои предположения.

                  «Клиент жалуется, что ничего не работает».

                  Не «в двух словах» — гигантский paper на грани scientific на тему обнаруженной самовозбуждающейся системы из пяти системных компонент, каждая из которых работает правильно.
                    0
                    Какие-то части из оригинальной статьи пропущены?
                    Например это:
                    I've written about this in Strict Control of Java Code Quality. I use qulice.com in Java projects and rubocop in Ruby, but there are many similar tools for nearly every language.

                    Или это оригинал поменялся?
                      0
                      ...has been tested by unit or integration tests.
                      Перевод
                      … прошло интеграционное тестирование.
                      ?!
                      0
                      Например, Java не имеет ничего против того, чтобы вы вместили целое приложение в один единственный «class» с помощью 5000 разных методов

                      Технически у вас это ряд ли получится: вы упрётесь в размер пула констант класса.

                      Only users with full accounts can post comments. Log in, please.