Статьи

Как определить предстоящие регрессии или разрывы API

Что такое регрессия?

Регрессии происходят из-за изменений в коде или его зависимостях, но иногда также из-за изменений среды. Мы не будем говорить об этом последнем пункте в этом посте.

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

Как я могу получить регрессии в моем коде?

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

+ Изменить регрессия
Compile времени Подпись метода изменена / удалена Код, использующий этот метод, больше не будет соответствовать
Удалено наследование интерфейса / абстрактного класса Реализация классов теряет поведение и больше не может быть приведена в супертипе
Добавлен интерфейс / абстрактный класс наследования Компилятор запросит реализацию абстрактных / сигнатурных методов
Во время выполнения Реализация метода изменена Непредсказуемое поведение
Загруженный код времени выполнения с другой версией API (RMI, Spring и т. Д.) Если API-интерфейсы не совместимы, код будет зависать по любой из предыдущих причин.

 

Я приведу пример, скажем, класс Foo реализует интерфейс Bar

public interface Bar
{
    // Cool signatures inside
}

public class Foo implements Bar
{

    private UnserializableType boo;

    Foo(UnserializableType boo) {

        this.boo = boo;// Nothing to do with DBZ

    }

    // Cool methods implementations doing stuff with boo 

}

Кажется, все хорошо, пока это не произойдет!

public interface Bar extends Serializable
{
    // Still cool signatures inside
}

Интерфейс становится Serializable, но моя реализация не может быть правильно сериализована из-за поля boo, которое само не сериализуемо. Отсюда регрессия во время выполнения! Этот случай интерфейсов, расширяющих новый тип, является особым, потому что интерфейс Serialization не имеет ограничений метода для добавления поведения для Java. Но будет регрессия времени компиляции для любого нового метода, добавленного к интерфейсу.

Может ли что-то помочь мне определить регрессию до того, как она произойдет?

Некоторые регрессии почти невозможно предсказать, однако для большинства из них вы можете по крайней мере иметь подсказку о том, где проверять регрессии. Конечно, регрессии во время компиляции можно легко идентифицировать по сравнению с регрессиями во время выполнения. Если вы работаете только с собственным кодом в одном проекте, то регрессии во время компиляции часто идентифицируются вашей IDE одной рукой (Eclipse, Netbeans, Visual Studio и т. Д.). И из-за вашей ситуации вы можете сделать это и просто Ctrl + Z, чтобы вернуть все в порядок.

Однако, если вы работаете с несколькими зависимостями, это другая игра. Вы не знаете о регрессии при обновлении зависимости, скажем, с версии 1.2 до более новой. Соответствует ли 1.3 или 1.4? обе? Вам придется проверить вручную, изменив зависимость, а затем скомпилировать код. Это не очень смешно и не сексуально. И когда дело доходит до регрессий во время выполнения, вам придется снова пройти всю цепочку тестирования. Так что теперь вот способы предсказать регресс, прежде чем они произойдут!

  • Сравните сигнатуры разных версий API. Изменены ли некоторые методы или поля? Наследование нарушено? Создано? На самом деле это реально выполнимо, особенно в Java, благодаря Reflection API
  • Обнаружение изменений реализации: нет необходимости вносить изменения в исходный код, а только указывать, что байт-код / ​​скомпилированный код изменился для этого метода. Тогда у вас будет подсказка, где проверять регрессию без необходимости профилировать весь ваш код.
  • Определите использование API в вашем коде: изменения повлияют на ваш код? Или вы не используете эту часть?

Инструменты и ссылки

  • Для Java Это много инструментов, которые могут выполнять проверку соответствия API, ACC является одним из этих инструментов. Доступно по адресу http://ispras.linuxbase.org/index.php/Java_API_Compliance_Checker.
  • ABI Compliance Checker — это инструмент, который выполняет аналогичный процесс, но для библиотек C / C ++. Проверьте это здесь http://ispras.linuxbase.org/index.php/ABI_compliance_checker
  • Этот веб-сайт отслеживает разрывы API библиотек C / C ++ http://upstream-tracker.org/ . Интересно наблюдать явление довольно распространенное и непредсказуемое.

Что дальше ?

Соответствие версий между API-интерфейсами является очень важным вопросом и источником множества перегрузок тестирования и регрессии. Поэтому наша компания заинтересована в том, чтобы этот процесс проверки не был обременительным в повседневной жизни программиста. Tocea поставляется с плагином maven для проверки соответствия с открытым исходным кодом, который может быть интегрирован в цепочку инструментов анализа кода. Оставайтесь в курсе.