perlmodstyle
СОДЕРЖАНИЕ
- ИМЯ
- ВВЕДЕНИЕ
- КРАТКИЙ СПИСОК ПРОВЕРКИ
- ПЕРЕД НАЧАЛОМ НАПИСАНИЯ МОДУЛЯ
- ПРОЕКТИРОВАНИЕ И НАПИСАНИЕ ВАШЕГО МОДУЛЯ
- ДОКУМЕНТИРОВАНИЕ ВАШЕГО МОДУЛЯ
- УЧЕТ ПРИ ВЫПУСКЕ
- ОБЩИЕ ОШИБКИ
- СМОТРИТЕ ТАКЖЕ
- АВТОР
ИМЯ
perlmodstyle - Справочник по стилю Perl-модулей
ВВЕДЕНИЕ
В данном документе описываются «лучшие практики» Perl-сообщества для написания Perl-модулей. Он расширяет рекомендации, приведенные в perlstyle, которые следует считать обязательными к прочтению перед изучением данного документа.
Хотя этот документ предназначен для всех авторов модулей, он особенно ориентирован на авторов, желающих опубликовать свои модули в CPAN.
Внимание уделяется элементам стиля, которые видны пользователям модуля, а не тем частям, которые видны только разработчикам модуля. Однако многие из приведенных в этом документе рекомендаций можно экстраполировать и успешно применять к внутренним частям модуля.
Данный документ отличается от perlnewmod тем, что является руководством по стилю, а не учебником по созданию CPAN-модулей. Он предоставляет контрольный список, с помощью которого модули можно сравнивать, чтобы определить, соответствуют ли они лучшим практикам, без необходимости подробного описания того, как этого добиться.
Все советы, содержащиеся в этом документе, были получены из обширных бесед с опытными авторами и пользователями CPAN. Каждый совет, данный здесь, является результатом предыдущих ошибок. Эта информация поможет вам избежать тех же ошибок и дополнительных затрат, которые неизбежно потребовались бы для их исправления.
В первой части этого документа представлен перечень пунктов контрольного списка; последующие разделы содержат более подробное обсуждение пунктов списка. В заключительном разделе «Общие ошибки» описываются некоторые из наиболее распространенных ошибок, совершаемых авторами CPAN.
КРАТКИЙ СПИСОК ПРОВЕРКИ
Для получения более подробной информации по каждому пункту данного списка см. ниже.
Перед началом
-
Не переизобретайте колесо
-
Когда возможно, внесите правки, расширьте или используйте подкласс существующего модуля
-
Делайте одну вещь и делайте ее хорошо
-
Выберите подходящее имя
-
Получите обратную связь перед публикацией
API
-
API должен быть понятен среднему программисту
-
Простые методы для простых задач
-
Разделение функциональности от вывода
-
Согласованное именование подпрограмм или методов
-
Используйте именованные параметры (хэш или хэшариф), когда параметров больше двух
Стабильность
-
Убедитесь, что ваш модуль работает в
use strictи-w -
Стабильные модули должны поддерживать обратную совместимость
Документация
-
Напишите документацию в POD
-
Документируйте назначение, область применения и целевые приложения
-
Документируйте каждый публично доступный метод или подпрограмму, включая параметры и возвращаемые значения
-
Приводите примеры использования в вашей документации
-
Предоставьте файл README, а также, возможно, заметки о выпуске, журнал изменений и т. д.
-
Предоставьте ссылки на дополнительную информацию (URL, электронная почта)
Учет при выпуске
-
Укажите предварительные требования в Makefile.PL или Build.PL
-
Укажите требования к версии Perl с помощью
use -
Включите тесты в свой модуль
-
Выберите разумную и согласованную схему нумерации версий (X.YY — это распространенная схема нумерации Perl-модулей)
-
Увеличивайте номер версии при каждом изменении, независимо от его размера
-
Упакуйте модуль с помощью «make dist»
-
Выберите подходящую лицензию (GPL/Artistic — хороший вариант по умолчанию)
ПЕРЕД НАЧАЛОМ НАПИСАНИЯ МОДУЛЯ
Постарайтесь не бросаться сразу в разработку модуля, не потратив некоторое время на обдумывание. Небольшое предварительное планирование может сэкономить вам массу усилий позже.
Было ли это сделано ранее?
Возможно, вам даже не нужно писать модуль. Проверьте, не было ли этого сделано в Perl ранее, и избегайте переизобретения колеса, если у вас нет веской причины.
Хорошие места для поиска существующих модулей — MetaCPAN и обращение на module-authors@perl.org (https://lists.perl.org/list/module-authors.html).
Если существующий модуль почти выполняет то, что вам нужно, подумайте о написании патча, создании подкласса или ином расширении существующего модуля, а не о его переписывании.
Делайте одну вещь и делайте ее хорошо
Рискуя сказать очевидное, модули предназначены для модульности. Perl-разработчик должен быть способен использовать модули для сборки строительных блоков своего приложения. Однако важно, чтобы блоки были правильной формы, и разработчику не нужно было использовать большой блок, когда ему нужен только небольшой.
Ваш модуль должен иметь чётко определённую область применения, не превышающую одного предложения. Можно ли разбить ваш модуль на семейство связанных модулей?
Плохой пример:
«FooBar.pm предоставляет реализацию протокола FOO и связанного стандарта BAR».
Хороший пример:
«Foo.pm предоставляет реализацию протокола FOO. Bar.pm реализует связанный протокол BAR».
Это означает, что если разработчик нуждается только в модуле для стандарта BAR, он не должен быть вынужден устанавливать библиотеки для FOO.
Что в имени?
Убедитесь, что вы выбрали подходящее имя для своего модуля на ранней стадии. Это поможет людям найти и запомнить ваш модуль и сделает программирование с вашим модулем более интуитивным.
При выборе имени модуля, обратите внимание на следующее:
-
Будьте описательными (т. е. точно описывайте назначение модуля).
-
Будьте последовательными с существующими модулями.
-
Отражайте функциональность модуля, а не реализацию.
-
Избегайте создания новой иерархии верхнего уровня, особенно если уже существует подходящая иерархия, в которую можно поместить ваш модуль.
Получить обратную связь перед публикацией
Если вы никогда раньше не загружали модуль в CPAN (даже если это уже делали), вам настоятельно рекомендуется получить обратную связь от людей, уже знакомых с областью применения модуля и системой именования CPAN. Авторы похожих модулей или модулей с похожими именами могут быть хорошим началом, как и сообщества, такие как Perl Monks.
ПРОЕКТИРОВАНИЕ И НАПИСАНИЕ ВАШЕГО МОДУЛЯ
Соображения по проектированию и программированию модулей:
ОРИЕНТИРОВАТЬСЯ НА ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ?
Ваш модуль может быть объектно-ориентированным (ООП) или нет, или он может иметь оба типа интерфейсов. Есть плюсы и минусы каждого метода, которые следует учитывать при проектировании вашего API.
В «Perl Best Practices» (авторство 2004 г., издательство O'Reilly Media, Inc.) Damian Conway предоставляет список критериев, которые следует использовать при решении вопроса о том, подходит ли ООП для вашей проблемы:
-
Разрабатываемая система большая или, вероятно, станет большой.
-
Данные можно сгруппировать в очевидные структуры, особенно если в каждой структуре много данных.
-
Различные типы данных, формирующие группы, образуют естественную иерархию, которая облегчает использование наследования и полиморфизма.
-
У вас есть данные, к которым применяются многие разные операции.
-
Вам необходимо выполнять одни и те же общие операции над похожими типами данных, но с небольшими вариациями в зависимости от конкретного типа данных, к которым применяются операции.
-
Вероятно, вам придется добавить новые типы данных позже.
-
Типичные взаимодействия между данными лучше всего представляются операторами.
-
Реализация отдельных компонентов системы, вероятно, изменится со временем.
-
Дизайн системы уже объектно-ориентированный.
-
Ваш код модулей, вероятно, будут использовать много программистов.
Внимательно подумайте, подходит ли ООП для вашего модуля. Необоснованное применение объектно-ориентированного программирования приводит к сложным API, которые сложно понять или использовать среднему пользователю модуля.
Проектирование вашего API
Ваши интерфейсы должны быть понятны среднему программисту Perl. Следующие рекомендации помогут вам оценить, достаточно ли прост ваш API:
- Написание простых процедур для выполнения простых задач.
-
Лучше иметь множество простых процедур, чем несколько монолитных. Если поведение вашей процедуры существенно изменяется в зависимости от ее аргументов, это признак того, что вам следует иметь две (или более) отдельные процедуры.
- Разделение функциональности от вывода.
-
Возвращайте результаты в максимально обобщенной форме и позвольте пользователю выбрать, как их использовать. Наиболее обобщенной формой обычно является структура данных Perl, которая затем может быть использована для генерации текстового отчета, HTML, XML, запроса к базе данных или чего-либо еще, что требуется вашим пользователям.
Если ваша процедура итерирует по списку (такому как список файлов или записей в базе данных), вы можете рассмотреть возможность предоставления обратного вызова, чтобы пользователи могли манипулировать каждым элементом списка по очереди. File::Find предоставляет пример этого с его
find(\&wanted, $dir)синтаксисом. - Предоставление разумных сокращений и значений по умолчанию.
-
Не требуйте от каждого пользователя модуля проходить одни и те же сложности для достижения простого результата. Вы всегда можете включить необязательные параметры или процедуры для более сложного или нестандартного поведения. Если большинству ваших пользователей приходится набирать несколько почти одинаковых строк кода, когда они начинают использовать ваш модуль, это признак того, что вы должны сделать это поведение значением по умолчанию. Другим хорошим показателем того, что вы должны использовать значения по умолчанию, является то, что большинство ваших пользователей вызывают ваши процедуры с одинаковыми аргументами.
- Конвенции именования
-
Ваше именование должно быть последовательным. Например, лучше иметь:
display_day(); display_week(); display_year();чем
display_day(); week_display(); show_year();Это также относится к именам методов, именам параметров и всему остальному, что видно пользователю (и большинству того, что не видно!).
- Передача параметров
-
Используйте именованные параметры. Гораздо удобнее использовать хэш, как это:
$obj->do_something( name => "wibble", type => "text", size => 1024, );... чем иметь длинный список неименованных параметров, как это:
$obj->do_something("wibble", "text", 1024);Хотя список аргументов может прекрасно работать для одного, двух или даже трех аргументов, любое большее количество аргументов затрудняет запоминание пользователю модуля и управление автором модуля. Если вы хотите добавить новый параметр, вам нужно будет добавить его в конец списка для обратной совместимости, и это, вероятно, сделает ваш порядок списка неинтуитивным. Кроме того, если многие элементы могут быть неопределёнными, вы можете увидеть следующие некрасивые вызовы методов:
$obj->do_something(undef, undef, undef, undef, undef, 1024);Устанавливайте разумные значения по умолчанию для параметров, которые их имеют. Не заставляйте пользователей указывать параметры, которые почти всегда одинаковы.
Вопрос о том, передавать ли аргументы в хэш или в хэшреф, в значительной степени является вопросом личного стиля.
Использование ключей хэша, начинающихся с дефиса (
-name) или полностью заглавных букв (NAME) — это пережиток более ранних версий Perl, в которых обычные строчные буквы не обрабатывались корректно оператором=>. Хотя некоторые модули сохраняют заглавные или дефисные ключи аргументов по историческим причинам или по личным предпочтениям, большинство новых модулей должны использовать простые строчные буквы. Какой бы вариант вы ни выбрали, будьте последовательны!
Строгость и предупреждения
Ваш модуль должен успешно работать с плейном «strict» и без генерации предупреждений. Ваш модуль также должен обрабатывать проверку на заражение там, где это уместно, хотя это может вызвать трудности во многих случаях.
Обратная совместимость
Модули, которые являются «стабильными», не должны нарушать обратную совместимость без, по крайней мере, длительного переходного периода и значительного изменения номера версии.
Обработка ошибок и сообщения об ошибках
Когда ваш модуль сталкивается с ошибкой, он должен сделать одно или несколько из следующих:
-
Возвратить неопределенное значение.
-
установить
$Module::errstrили аналогичное (errstr— распространённое имя, используемое модулями DBI и другими популярными модулями; если вы выберете что-то другое, обязательно четко это документируйте). -
warn()илиcarp()сообщение в STDERR. -
croak()только тогда, когда ваш модуль абсолютно не может понять, что делать. (croak()— лучшая версияdie()для использования внутри модулей, которая сообщает об ошибках с точки зрения вызывающей стороны. См. Carp для получения подробностей оcroak(),carp()и других полезных процедурах.) -
В качестве альтернативы вышеперечисленному, вы можете предпочесть бросать исключения с использованием модуля Error.
Настраиваемая обработка ошибок может быть очень полезна для ваших пользователей. Подумайте о предоставлении выбора уровней для сообщений об ошибках и отладки, о возможности отправки сообщений в отдельный файл, о способе указания процедуры обработки ошибок или о других подобных функциях. Убедитесь, что все эти параметры по умолчанию настроены на наиболее распространенное использование.
ДОКУМЕНТИРОВАНИЕ ВАШЕГО МОДУЛЯ
POD
Ваш модуль должен включать документацию, предназначенную для разработчиков Perl. Вы должны использовать «простую документацию» (POD) Perl для общей технической документации, хотя вы можете захотеть написать дополнительную документацию (белые книги, учебные пособия и т. д.) в другом формате. Вам необходимо охватить следующие темы:
-
Синопсис общих способов использования модуля
-
Цель, сфера применения и целевые приложения вашего модуля
-
Использование каждого публично доступного метода или подпрограммы, включая параметры и возвращаемые значения
-
Примеры использования
-
Источники дополнительной информации
-
Адрес электронной почты для автора/администратора
Уровень детализации в документации модуля Perl обычно варьируется от менее подробного к более подробному. Ваш раздел SYNOPSIS должен содержать минимальный пример использования (возможно, всего одну строку кода; пропустите необычные варианты использования или что-либо, что не требуется большинству пользователей); раздел DESCRIPTION должен описывать ваш модуль в общих чертах, обычно в нескольких абзацах; более подробная информация о процедурах или методах модуля, длинные примеры кода или другая подробная информация должны быть предоставлены в последующих разделах.
В идеале, тот, кто немного знаком с вашим модулем, должен иметь возможность освежить свои знания, не нажимая «вниз по странице». По мере продвижения читателя по документу, он должен получать всё больше знаний.
Рекомендуемый порядок разделов в документации Perl-модуля:
-
ИМЯ
-
СИНОПСИС
-
ОПИСАНИЕ
-
Один или несколько разделов или подразделов, предоставляющих более подробную информацию о доступных методах и процедурах и любой другой релевантной информации.
-
ОШИБКИ/ПРИМЕЧАНИЯ/др.
-
АВТОР
-
СМОТРИТЕ ТАКЖЕ
-
АВТОРСКИЕ ПРАВА и ЛИЦЕНЗИЯ
Держите документацию рядом с кодом, который она документирует («встроенная» документация). Включайте POD для заданного метода прямо над подпрограммой этого метода. Это упрощает обновление документации и позволяет избежать повторного документирования каждого фрагмента кода (раз в POD и раз в комментариях).
README, INSTALL, заметки к выпуску, журналы изменений
Ваш модуль также должен включать файл README, описывающий модуль и дающий ссылки на дополнительную информацию (сайт, электронная почта автора).
Файл INSTALL должен быть включен и содержать простые инструкции по установке. При использовании ExtUtils::MakeMaker это обычно будет:
- perl Makefile.PL
- make
- make test
- make install
При использовании Module::Build это обычно будет:
- perl Build.PL
- perl Build
- perl Build test
- perl Build install
Заметки к выпуску или журналы изменений должны создаваться для каждого выпуска вашего программного обеспечения, описывая видимые пользователю изменения в вашем модуле в терминах, релевантных для пользователя.
Если у вас нет веских причин использовать какой-либо другой формат (например, формат, используемый в вашей компании), принято называть файл журнала изменений Changes, и следовать простому формату, описанному в CPAN::Changes::Spec.
РАЗМЫШЛЕНИЯ О ВЫПУСКЕ
Нумерация версий
Номера версий должны указывать, по крайней мере, основные и второстепенные версии, а также, возможно, подвторостепенные версии. Основной выпуск — это выпуск, в котором большинство функциональных возможностей изменилось или в котором добавлено существенное новое функциональное обеспечение. Второстепенный выпуск — это выпуск, в котором небольшое количество функциональных возможностей было добавлено или изменено. Подвторостепенные номера версий обычно используются для изменений, которые не влияют на функциональность, такие как исправления документации.
Наиболее распространённая схема нумерации версий на CPAN выглядит так:
1.00, 1.10, 1.11, 1.20, 1.30, 1.31, 1.32 Правильный номер версии CPAN — это число с плавающей точкой с, по крайней мере, двумя цифрами после десятичной точки. Вы можете проверить, соответствует ли он CPAN, используя
perl -MExtUtils::MakeMaker -le 'print MM->parse_version(shift)' \
'Foo.pm' Если вы хотите выпустить «бета» или «альфа» версию модуля, но не хотите, чтобы CPAN.pm указывал её как последнюю, используйте знак «_» после обычного номера версии, за которым следуют, по крайней мере, две цифры, например 1.20_01. В этом случае рекомендуется следующий подход:
our $VERSION = "1.12_01"; # so CPAN distribution will have
# right filename
our $XS_VERSION = $VERSION; # only needed if you have XS code
$VERSION = eval $VERSION; # so "use Module 0.002" won't warn on
# underscore С этой хитростью MakeMaker будет читать только первую строку и, таким образом, читать знак подчеркивания, в то время как интерпретатор Perl будет оценивать $VERSION и преобразовывать строку в число. Позднее операции, которые обрабатывают $VERSION как число, смогут делать это, не вызывая предупреждение о том, что $VERSION не является числом.
Никогда не выпускайте ничего (даже исправление документации в одном слове) без инкремента номера. Даже исправление документации в одном слове должно привести к изменению версии на подвторостепенном уровне.
После выбора важно придерживаться вашей схемы версий, не уменьшая количество цифр. Это связано с тем, что «нижестоящие» инструменты, такие как система портов FreeBSD, интерпретируют номера версий по-разному. Если вы измените количество цифр в вашей схеме версий, вы можете сбить с толку эти системы, поэтому они получат версии вашего модуля в неправильном порядке, что, очевидно, плохо.
Предварительные требования
Авторы модулей должны тщательно оценить, следует ли полагаться на другие модули и на какие именно.
Самое главное, выбирайте модули, которые максимально стабильны. В порядке предпочтения:
-
Ядро Perl
-
Стабильные модули CPAN
-
Нестабильные модули CPAN
-
Модули, недоступные из CPAN
Указывайте требования к версии других модулей Perl в предварительных требованиях в вашем Makefile.PL или Build.PL.
Убедитесь, что вы указали требования к версии Perl как в Makefile.PL или Build.PL, так и с require 5.6.1 или аналогичным. См. документацию по use VERSION для получения подробностей.
Тестирование
Все модули должны быть протестированы перед распространением (с использованием «make disttest»), а тесты также должны быть доступны пользователям, устанавливающим модули (с использованием «make test»). Для Module::Build вы бы использовали эквивалент make test %%%CODE_BLOCK_37%%.
Значение этих тестов пропорционально предполагаемой стабильности модуля. Модуль, который претендует на стабильность или надеется получить широкое применение, должен придерживаться максимально строгого режима тестирования.
Полезные модули для написания тестов (с минимальным влиянием на ваш процесс разработки или время) включают Test::Simple, Carp::Assert и Test::Inline. Для более сложных наборов тестов существуют Test::More и Test::MockObject.
Упаковывание
Модули должны быть упакованы с помощью одного из стандартных инструментов упаковки. В настоящее время у вас есть выбор между ExtUtils::MakeMaker и более независимым от платформы Module::Build, что позволяет модулям устанавливаться последовательно. При использовании ExtUtils::MakeMaker вы можете использовать «make dist», чтобы создать свой пакет. Существуют инструменты, которые помогут вам создать модуль в стиле MakeMaker. К ним относятся ExtUtils::ModuleMaker и h2xs. См. также perlnewmod.
Лицензирование
Убедитесь, что ваш модуль имеет лицензию, и что полный текст лицензии включен в распространяемый пакет (если это не распространенная лицензия и условия лицензии не требуют ее включения).
Если вы не знаете, какую лицензию использовать, двойная лицензия под GPL и Artistic (аналогичная Perl) — хорошая идея. См. perlgpl и perlartistic.
ОБЩИЕ ОШИБКИ
Переизобретение колеса
Существуют определенные области применения, которые уже очень хорошо поддерживаются CPAN. Один пример — системы шаблонов, другой — модули даты и времени, и их много. Хотя написание собственной версии этих вещей является ритуалом посвящения, пожалуйста, тщательно подумайте, действительно ли Perl-миру нужно ваше опубликованное решение.
Попытка сделать слишком много
Ваш модуль будет частью инструментария разработчика. Он сам по себе не будет составлять весь инструмент. Искушение добавить дополнительные функции до тех пор, пока ваш код не станет монолитной системой вместо набора модульных строительных блоков.
Неподходящая документация
Не попадайтесь в ловушку написания документации для неправильной аудитории. Ваша основная аудитория — опытный разработчик, по крайней мере, с умеренным пониманием предметной области вашего модуля, который только загрузил ваш модуль и хочет как можно быстрее начать его использовать.
Учебники, документация для конечных пользователей, научные статьи, часто задаваемые вопросы и т. д. не подходят для основной документации модуля. Если вы действительно хотите написать их, включите их как поддокументы, такие как My::Module::Tutorial или My::Module::FAQ, и предоставьте ссылку в разделе «См. также» основной документации.
СМОТРИТЕ ТАКЖЕ
- perlstyle
-
Общие руководства по стилю Perl
- perlnewmod
-
Как создать новый модуль
- perlpod
-
Документация POD
- podchecker
-
Проверяет правильность вашей документации POD
- Инструменты упаковки
- Инструменты тестирования
-
Test::Simple, Test::Inline, Carp::Assert, Test::More, Test::MockObject
- https://pause.perl.org/
-
Сервер загрузки авторов Perl. Содержит ссылки на информацию для авторов модулей.
- Любая хорошая книга по разработке программного обеспечения
АВТОР
Кириллы "Скуд" Роберт <skud@cpan.org>
© 1993–2023 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.38.0/perlmodstyle