🔥

Тред (Осип Фаткуллин)


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

Для себя я принял за правило, что оформляю что-либо в библиотеку только если сам буду это использовать. Писать библиотеку, которая тебе не нужна и надеяться, что она будет нужна кому-то ещё - пустая трата времени.

Ещё хороший вариант обстучать идею об лида или других разработчиков

Чем шире целевая аудитория библиотеки, тем сложнее всё сделать хорошо. Не стоит сразу строить планы покорения мира, лучше сначала протестировать библиотеку на более узкой аудитории и отработать основной функционал.

Никому не нужна документация библиотеки на 10 языках, если библиотека при этом не работает как надо.

Хорошо. Представим, что делаем библиотеку для использования внутри компании - так будет проще.

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

Структура пакетов. Это не приложение и здесь никакой необходимости делать сложную структуру пакетов - она только запутает пользователя библиотеки. Ещё один бонус - чем проще структура, тем меньше мусора будет в импортах.

Отделяйте внешний API от деталей реализации, которые API не являются. Хороший подход - класть внутрянку в отдельный пакет, чтобы при импорте разработчик понимал что лезет куда-то не туда. Ещё лучше если язык позволяет ограничить видимость. В котлине пользуйте internal.

Не стоит затаскивать в библиотеку зависимости, которые нужны "для удобства": - DI? Пишем руками, ведь не известно какой DI-фреймворк у конечного пользователя. - Хочется реактивщины? Можно затащить, но только если реактивный подход является частью API.

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

Ещё хорошо бы вычищать лишние промежуточные зависимости. Например, библиотека зависит от kotlin-stdlib-jdk8, хотя использует только kotlin-stdlib. Или, пример хуже, тащим compose-foundation там ге достаточно compose-foundation-layout.

Дальше несколько kotlin-specific моментов. Модификатор доступа public по умолчанию это удобно, но так что-то лишнее может утечь в API. Включайте explicit API mode, тогда компилятор будет заставлять явно указывать модификаторы видимости и возвращаемые типы github.com/Kotlin/KEEP/bl…

Заранее стоит подумать нужна ли совместимость с Java. Проще сразу проставить нужные аннотации где надо, чем потом проходиться по всему проекту. kotlinlang.org/docs/java-to-k…

Осторожно относитесь к поведению по умолчанию. Оно должно быть не таким "как вам удобно", а наиболее очевидным для пользователя. Поведение по умолчанию сложно будет поменять после релиза так, не сломав обратную совместимость.

Если важна бинарная совместимость с прошлой версией, используйте валидаторы для проверки. Вот валидаторы для Java и Kotlin: lvc.github.io/japi-complianc… github.com/Kotlin/binary-…

Если бинарная совместимость не важна - всё равно используйте. Так вы точно не внесёте ломающие изменения "случайно".

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

Библиотека готова? Отлично! Теперь нужно чтобы другие разработчики поняли как её использовать. Первое, что они увидят - README, из него в первую очередь должно быть понятно: - Что это за покемон - Базовые сценарии использования - Как затащить в проект makeareadme.com

Если библиотека опенсорсная, то надо ещё лицензию указать и желательно readme писать сразу на английском. Лицензия скорее всего подойдёт MIT или Apache 2.0

Нужно ли писать wiki? По желанию. Моё мнение - гораздо важнее писать комментарии к функциям и классам, чтобы разработчик мог прямо из IDE получить ответы на интересующие его вопросы.

Ещё нашёл для себя крайне полезным постепенно заполнять changelog, по мере внесения изменений. Так меньше шансов не учесть какие-то изменения в release notes, особенно если новая версия готовилась долго. keepachangelog.com

Конечно, можно генерировать changelog из коммитов или из влитых PRов - круто, если вам подходит такой вариант!

Я ещё ничего не написал про CI, анализ кода и т.д. Потому что не стоит распыляться на инфрастуктуру пока библиотека не готова.

CI стоит настроить достаточно рано, чтобы не упустить сломавшиеся тесты, а стат. анализатор можно подключить и позже. Особенно полезен он будет когда появятся контрибьюторы (вы ведь и так идеальный код пишете, да? :D)

Если библиотека завирусилась и начала обрастать контрибьюторами, старайтесь упростить жизнь этим святым людям)

Можно уменьшить количество проблем на ревью настройками проекта. Например, настройки кодстайла можно пошарить с через файлик editorconfig. editorconfig.org

Кстати, ловите .editorconfig для Android-проектов. Рассортировал в нём все опции в таком порядке как они расположены в Android Studio и IDEA gist.github.com/osipxd/9a78649…

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

Ещё один важный пункт о котором забыл. Уменьшайте "API surface", чем меньше разработчику нужно классов/функций/абстракций, чтобы начать использовать библиотеку, тем лучше.

Даже если кажется, что сейчас библиотека идеальна и в ней всё очевидно, не верьте этому чувству. Автор не может объективно оценить понятный API или нет, т.к. сам его написал.

Ну и самое главное, как всегда
notion image

На сегодня всё, а завтра будет про...
🤔 37.3% Тулинг
🤔 62.7% Хочу мемы!

Надо было другие варианты ответа делать. - Тулинг - Полное отключение телеграмма в России

Осип ФаткуллинОсип Фаткуллин