Золотое правило дизайна API
(В оригинале - The Golden Rule of API Design)
Проектирование API – это сложно, особенно больших API. Если вы проектируете API, который будут использовать сотни или тысячи людей, то вы должны подумать о том, как вы будете его менять в будущем и не приведут ли эти изменения к тому, что код ваших клиентов перестанет работать. Кроме этого, вам нужно подумать, как пользователи вашего API будут влиять на вас. Если один из ваших API классов использует собственный метод, то помните, что пользователь может унаследовать свой класс от вашего, перекрыв этот метод, и это может привести к катастрофе. Вы не сможете поменять этот метод, потому что кто-то из ваших пользователей его переделал. И ваша внутренняя реализация начинает зависеть от ваших пользователей.
Разработчики API решают эту проблему по-разному, но самый простой способ – блокировка API. Так, на Java вы можете сделать большинство ваших классов final. В C# таким ключевым словом будет sealed. Независимо от языка вы можете захотеть, чтобы API предоставлялось через singleton или через статические фабричные методы с целью защитить себя от переопределения поведения и использования вашего кода, которое может вас ограничить в будущем. Это все звучит логично, но реально ли это все сделать?
В течении последнего десятилетия мы постепенно осознали всю важность модульного тестирования, но это знание еще не полностью распространилось в отрасли. Подтверждение этому вокруг нас. Возьмите любой непротестированный класс, использующий какой-нибудь сторонний API, и попытайтесь написать для него юнит-тест. Практически наверняка вы столкнетесь с проблемами. Вы обнаружите, что код, использующий API, буквально приклеен к этому API. Окажется практически невозможным отделить API так, чтобы отследить, как код взаимодействует с ним и перехватить возвращаемые значения для проверки.
Со временем состояние может улучшиться, но только если мы в процессе проектирования API начнем смотреть на тестирование как на реальный пример его использования. И речь здесь не о тестировании только нашего кода. Здесь начинается Золотое Правило Проектирования API: «Недостаточно написать тесты для разрабатываемого вами API, нужно написать тесты для кода, использующего ваш API». Когда вы это проделаете, вы на себе испытаете все те проблемы, с которыми столкнутся те, кто будет использовать ваш API и писать тесты для своего кода.
Не существует простого способа сделать API удобным для тестирования кода тех, кто этот API будет использовать. Static
, final
и sealed
по сути неплохие конструкции и могут использоваться при необходимости. Однако кроме этого нужно иметь в виду процедуру тестирования и пройти через нее самому. Испытав это на себе, вы сможете учитывать ее тонкости при проектировании.
Автор оригинала - Michael Feathers