вторник, 24 сентября 2013 г.

Perl best practices на русском (часть 1)

Данная статья является первой частью свободного перевода выдержек из книги “Perl Best Practices Standards and Styles for Developing Maintainable Code” (Damian Conway). В статье я постарался в максимально сжатом виде пересказать основные тезисы и рекомендации, приводимые в книге. К сожалению, книги на русском я не нашел, именно поэтому привожу здесь данный перевод. Если какой-то из пунктов покажется вам непонятным, советую обратиться непосредственно к книге, или пишите комментарии. Со многими приведенными здесь рекомендациями я сам не согласен, но оставляю их в неизменном виде.

Форматирование кода

1. Все скобки должны быть в стиле K&R
2. Разделяйте операторы и круглые скобки пробелом
3. Не разделяйте процедуры и круглые скобки, массивы и квадратные скобки, хэши и фигурные скобки пробелами
4. Всегда пишите круглые скобки при вызове операторов и подпрограмм
5. Отделяйте сложные ключи хэшей от окружающих скобок пробелами
6. Отеляйте операторы от операндов пробелами
7. Ставьте точку с запятой в конце каждого выражения
8. Ставьте запятую после каждого значения в многостроковом списке(после последнего элемента – тоже)

9. Используйте ширину экрана в 78 колонок
10. Используйте отступ в 4 пробела
11. Используйте для отступов пробелы, не табы
12. Никогда не ставьте на одной строке два выражения
13. Разделяйте код на блоки
14. Не пишите else на одной строке с закрывающей фигурной скобкой
15. Выравнивайте связанные элементы по вертикали
16. Разбивайте длинные строки на отдельные перед операторами (например, в длинном арифметическом выражении перенос строки надо ставить перед знаком +)
17. Выносите длинные выражения в отдельные строки
18. Отделяйте вызовы операторов в длинных выражениях отступами
19. Разделяйте длинные выражения на отдельные строки перед знаком равно (по аналогии с п.16)
20. Оформляйте каскадные тернарные операторы в колонки
21. Для инициализации длинных списков не используйте запятые, используйте qw или q
22. Доведите свой стиль форматирования кода до автоматизма

Конвенции именования

23. Используйте осмысленные имена переменных
24. Логические (булевы) переменные должны идти после значеий с которыми они сравниваются
25. Помечайте ссылки префиксом _ref
26. Именуйте массивы во множественном числе, а хэши – в единственном
27. Для разделения слов в именах переменных используйте подчеркивание
28. Модули в camel-нотации, перменные и функции – с маленькой буквы через подчеркивание
29. Аббрувиатуры необходимо разделять знаком подчеркивания
30. Сокращайте имена переменных по первым буквам
31. Избегайте двусмысленных слов при именовании
32. Для приватных методов используйте в качестве префикса двойное подчеркивание __

Значения и выражения

34. Используйте интерполируемые операторы только для тех строк, которые должны быть интерполированы
35. Не используйте “” или ” для определения пустых строк, лучше писать: q{}
36. Используйте модуль charnames для специальных ASCII-символов, не числовые представления и не шестнадцатеричные
37. Не используйте в выражениях числа напрямую, лучше помещайте их в константы (например, с помощью модуля Readonly)
38. Десятеричные числа не должны начинаться с нулей, иначе они будут интерпретированы как восьмеричные
39. Используйте подчеркивания для улучшения читабельности длиных чисел (123_234_000_000_000)
40. Разбивайте длинные строковые литераты на несколько строк
41. Используйте heredoc для помещения в переменную многострочных литералов
42. Используйте theredoc когда heredoc конфликтует с вашим выравниванием
43. Каждую heredoc-метку пишите в верхнем регистре
44. При открытии heredoc, заключайте метку heredoc’а в кавычки
45. Не используйте возможность писать строковые литераты без кавычек (barewords)
46. Используйте ‘=>’ для формирования хэшей
47. Не используйте запятые для последовательностей значений ???
48. Не смешивайте высокоприоритетные и низкоприоритетные булевы операторы (&&,|| и and, or)
49. Заключайте списки в скобки
50. Используйте grep для проверки присутствия строки в массиве, для проверки любого другого значения в массиве используйте any() из модуля List::MoreUtils

Переменные

51. Избегайте использования нелексических переменных. Все свои переменные определяйте с my и постарайтесь не пересекаться с множеством зарезервированных perl переменных
52. Не используйте переменные из пакетов в своем коде
53. Если необходимо изменить переменную из пакета, локализуйте ее (local)
54. Инициализируйте все переменные только в локальной области видимости
55. Используйте полноценные английские слова для именования переменных
56. Если вам необходимо изменить пунктуационную переменную, изменяйте ее в локальной области видимости (пунктуационные переменные: $_, $., $|, …)
57. Не используйте regex match variables ???
58. Остерегайтесь модификации через $_
59. Используйте отрицательные индексы для получения последних элементов массива
60. Используйте упрощенное получение среза для массивов и хэшей (для массива: получить элементы со 2-го по 7-ой: @arr[2..7], для хэшей: @hash{‘alice’, ‘alex’, ‘ben’} )
61. Используйте табуляцию при получении срезов:
@frames[ -1, -2, -3 ]
= @active{‘top’, ‘prev’, ‘backup’};
62. Слишком длинные наборы ключей выносите из операций среза в отдельные переменные

Управляющие структуры

63. Старайтесь не использовать постфиксный if
64. Оставьте постфиксный if для исключительный условий (die, last, next)
65. Не используйте постфиксные for, while, unless или until
66. Никогда не используйте unless и until
67. Избегайте C-подобного синтаксиса при написании циклов (плохо: for (my $n=4; $n<=$MAX; $n+=2), хорошо: for my $n (4..$MAX))
68. Избегайте изменения массивов или хэшей внутри циклов
69. Никогда не вызывайте одну и ту же подпрогамму несколько раз в пределах одной итерации
70. Используйте для переменных циклов осмысленные имена
71. Всегда объявляйте для for переменную-итератор с my
72. При генерации нового списка взамен старого используйте map
73. Используйте grep и first при поиске элементов в массивах
74. Используйте for вместо map при изменении массива и сохранении его в новую переменную
75. Используйте подпрограммы для сложных преобразований над списками
76. Никогда не изменяйте $_ в функциях со списковым контекстом
77. Избегайте каскадного нагромождения if
78. Используйте таблицы поиска (table-lookup) вместо каскадной проверки if
79. Используйте тернарный оператор в случае неизбежности каскадной проверки
80. Не используйте do..while циклы
81. Отвергайте как можно больше итераций как можно раньше и завершайте цикл как можно раньше
82. Не контролируйте циклы только ради их контролирования
83. Используйте for и redo вместо while
84. Ставьте метку (label) перед while и при вызове next, last или redo добавляйте название метки после оператора

Документирование

85. Отделяйте документацию для пользователей от документации для разработчиков
86. Используйте стандартную POD-документацию для модулей и приложений
87. Расширяйте и дорабатывайте ваши стандарты POD-документации
88. Пишите пользовательскую документацию внутри файлов с кодом
89. Храните всю пользовательскую документацию в одном месте с файлами исходников
90. По возможности помещайте POD-документацию в конец файла
91. Отделяйте техническую документацию соответственно вышеперечисленным правилам
92. Используйте блоки комментариев для важных замечаний
93. Используйте полнострочные комментарии для объяснения алгоритмов
94. Используйте комментарии # для объяснения тонкостей и странностей в коде
95. Комментируйте все, что может вызвать недоумение или ввести в заблуждение
96. Подумайте, не лучше ли это переписать, чем комментировать
97. Используйте ‘invisible’ POD-секции для длинных технических описаний
98. Проверяйте свою документацию на наличие ошибок, в том числе и синтаксических

Создание функций

99. Не изменяйте ключи сортировки внутри sort
100. Используйте reverse для инвертирования порядка элементов в массивах
101. Используйте reverse в скалярном контексте для инвертирования строк
102. Используйте unpack для извлечения полей фиксированной длины
103. Используйте split для разбиения строк по простому разделителю (паттерну)
104. Используйте Text::CSV_XS для разбиения строк по более сложным паттернам
105. Избегайте использования eval для интерполяции строк в программный код
106. Используйте Sort::Maker для создания собственных подпрограмм сортировки
107. Используйте четвертый аргумент substr для получения результата операции substr
108. Используйте левосторонние функции только по прямому назначению
109. Используйте glob вместо <..>
110. Избегайте вызова select с нецелыми аргументами (например, 0.5 – полсекунды в результате округлится до секунды)
111. Всегда отделяйте блок выполнения фигурными скобками для map и grep
112. Используйте по возможности модули, которые являются встроенными в perl по-умолчанию (Scalar::Util, List::Util, List::MoreUtils)

Процедуры

113. Вызывайте процедуры со скобками, но без предварительного &
114. Не передавайте процедурам такие же имена, как у встроенных процедур
115. Всегда в начале процедуры извлекайте параметры из @_
116. Для процедур, принимающих более трех аргументов передавайте параметры через хэш
117. Используйте defined или exist для проверки существования аргументов процедур
118. Определяйте значения по-умолчанию для аргументов сразу же после их извлечения из @_
119. Всегда возвращайте скаляр при вызове в скалярном контексте
120. Возвращайте списки при вызове процедур в списковом контексте и скаляры при вызове в скалярном контексте
121. Когда не определено ‘общего’ скалярного контекста, используйте Contextual::Return
122. Не используйте прототипы для процедур
123. Всегда возвращайте значения из процедур с использованием return
124. В исключительных ситуациях просто пишите return

Ввод/вывод

125. Не используйте сырые файловые манипуляторы
126. Используйте непрямые файловые манипуляторы
127. Если вы используете файловый манипулятор из пакета, локализуйте его
128. Используйте либо IO::File, либо open с тремя аргументами
129. Никогда не применяйте open, close или print без проверки возможности работы с файлом
130. Закрывайте файловые манипуляторы сразу же по окончании работы с ними
131. При чтении файлов используйте while(<>), а не for(<>)
132. Лучше считывать из файла строками (не блоками/байтами)
133. Делайте блочное считывание из файла с использованием do
134. Для удобства и простоты используйте Perl6::Slurp для поточного считывания из файла
135. Не используйте *STDIN если в этом нет крайней нужды
136. Всегда помещайте файловые манипуляторы в при выводе print
137. Всегда выводите сообщение для интерактивного ввода
138. Не изобретайте тестов для ввода данных
139. Используйте IO::Prompt модуль для ввода данных пользователем
140. Всегда визуализируйте прогресс при выполнении длительных операций в интерактивных приложенияъ
141. Используйте Smart::Comments модуль для автоматизации ваших индикаторов прогресса
142. Избегайте использования select при установленном autoflush