Предложение по улучшению Nim #1 - Руководство по стилю стандартной библиотеки
Введение
Хотя Nim поддерживает множество стилей кода и форматирования, тем не менее, полезно, чтобы определенные усилия сообщества, такие как стандартная библиотека, следовали согласованному набору руководящих принципов стиля, когда это уместно. Это предложение по улучшению призвано перечислить ряд руководящих принципов, которым должна следовать стандартная библиотека.
Обратите внимание, что к этим правилам могут быть исключения. Поскольку Nim очень гибкий, некоторые части этого руководства по стилю могут не иметь смысла в определенных контекстах. Кроме того, как и руководство по стилю Python http://legacy.python.org/dev/peps/pep-0008/ со временем меняется, то же самое произойдет и с этим руководством.
Эти правила будут применяться только к вкладам в базу кода Nim и официальным проектам, таким как компилятор Nim, стандартная библиотека и различные официальные инструменты, такие как C2Nim.
Правила отступов и пробелов
- Строки не должны быть длиннее 80 символов. Ограничение количества информации в каждой строке делает код более читабельным - читателю нужно обрабатывать меньшие блоки информации.
- Для отступа блоков следует использовать два пробела; табуляция не допускается (компилятор это проверяет). Использование пробелов обеспечивает более согласованный вид кода в разных редакторах. В отличие от пробелов, ширина табуляции варьируется в разных редакторах, и не все редакторы позволяют изменять эту ширину.
- Хотя использование пробелов для стилистических целей, помимо одобренных этим руководством, разрешено, к таким практикам следует подходить с осторожностью. Не все редакторы поддерживают автоматическое выравнивание разделов кода, и перевыравнивание длинных разделов кода вручную может быстро стать утомительным.
# This is bad, as the next time someone comes # to edit this code block, they # must re-align all the assignments again: type WordBool* = int16 CalType* = int ... # 5 lines later CalId* = int LongLong* = int64 LongLongPtr* = ptr LongLong
Правила именования
Примечание: Хотя правила, изложенные ниже, являются текущими правилами именования, эти правила не всегда действовали. Ранее правила именования идентификаторов следовали традиции Паскаля с префиксами, которые указывали базовый тип идентификатора - PFoo для указателей и ссылок, TFoo для типов значений, EFoo для исключений и т. д. Хотя это с тех пор изменилось, во многих местах стандартной библиотеки все еще используется эта конвенция. Такой стиль сохраняется исключительно по причинам обратной совместимости и будет изменен в будущем.
- Идентификаторы типов должны быть в PascalCase. Все остальные идентификаторы должны быть в camelCase, за исключением констант, которые могут использовать PascalCase, но не обязаны.
# Constants can start with either a lower case or upper case letter. const aConstant = 42 const FooBar = 4.2 var aVariable = "Meep" # Variables must start with a lowercase letter. # Types must start with an uppercase letter. type FooBar = object
Для констант, полученных из обертки C/C++, разрешены ALL_UPPERCASE, но это некрасиво. (Зачем кричать CONSTANT? Константы не вредят, переменные вредят!)
- При именовании типов, которые существуют в вариантах значение, указатель и ссылка, используйте обычное имя для варианта, который будет использоваться чаще всего, и добавьте суффикс «Obj», «Ref» или «Ptr» для других вариантов. Если нет единственного варианта, который будет использоваться чаще всего, добавьте суффиксы только к вариантам указателей. То же самое относится к оберткам C/C++.
type Handle = object # Will be used most often fd: int64 HandleRef = ref Handle # Will be used less often
- Типы исключений и ошибок должны иметь суффикс «Error» или «Defect».
type ValueError = object of CatchableError AssertionDefect = object of Defect Foo = object of Exception # bad style, try to inherit CatchableError or Defect
- Члены перечислений должны иметь идентификационный префикс, например, сокращение имени перечисления, если не помечено с помощью псевдонима
{.pure.}.type PathComponent = enum pcDir pcLinkToDir pcFile pcLinkToFile
- Значения перечислений, не являющиеся чистыми, должны использовать camelCase, тогда как чистые значения перечислений должны использовать PascalCase.
type PathComponent {.pure.} = enum Dir LinkToDir File LinkToFile
- В эпоху HTTP, HTML, FTP, TCP, IP, UTF, WWW глупо притворяться, что это какие-то особые слова, требующие всех заглавных букв. Вместо этого относитесь к ним как к тому, что они есть: реальные слова. Таким образом, это
parseUrlвместоparseURL,checkHttpHeaderвместоcheckHTTPHeaderи т. д. - Операции, такие как
mitemsилиmpairs(или устаревшаяmget), которые позволяют получить изменяемый вид на некоторую структуру данных, должны начинаться сm. - Когда доступны как встроенное изменение, так и «возвращает преобразованную копию», последнее является причастием прошедшего времени первого:
- reverse и reversed в алгоритме
- sort и sorted
- rotate и rotated
- Когда версия «возвращает преобразованную копию» уже существует, как
strutils.replace, версия встроенного изменения должна получить суффикс-In(replaceInв этом примере).
- Используйте
subjectVerb, а неverbSubject, например:fileExists, а неexistsFile.
API стандартной библиотеки разработан для лёгкого использования и согласованности. Простота использования измеряется количеством вызовов для достижения конкретного действия высокого уровня. Конечная цель состоит в том, чтобы программист мог угадать имя.
Библиотека использует простую систему именования, которая использует распространенные сокращения для сохранения кратких, но содержательных имён.
| Английское слово | Использовать | Примечания |
|---|---|---|
| initialize | initT |
init используется для создания типа значения T
|
| new | newP |
new используется для создания типа ссылки P
|
| find | find | должен возвращать позицию, где что-то было найдено; для логического результата используйте contains
|
| contains | contains | часто сокращение от find() >= 0
|
| append | add | используйте add вместо append
|
| compare | cmp | должен возвращать целое число с < 0 == 0 или > 0 семантикой; для логического результата используйте sameXYZ
|
| put | put, []=
|
рассмотрите перегрузку []= для put |
| get | get, []
|
рассмотрите перегрузку [] для get; рассмотрите возможность не использовать get в качестве префикса: len вместо getLen
|
| length | len | также используется для количества элементов |
| size | size, len | size должно относиться к размеру в байтах |
| capacity | cap | |
| memory | mem | подразумевает операцию низкого уровня |
| items | items | стандартный итератор по коллекции |
| pairs | pairs | итератор по парам (ключ, значение) |
| delete | delete, del | del предположительно быстрее, чем delete, потому что не сохраняет порядок; delete сохраняет порядок |
| remove | delete, del | несогласованно в настоящее время |
| include | incl | |
| exclude | excl | |
| command | cmd | |
| execute | exec | |
| environment | env | |
| variable | var | |
| value | value, val | val предпочтительнее, несогласованно в настоящее время |
| executable | exe | |
| directory | dir | |
| path | path | path — это строка "/usr/bin" (например), dir — содержимое "/usr/bin"; несогласованно в настоящее время |
| extension | ext | |
| separator | sep | |
| column | col, column | col предпочтительнее, несогласованно в настоящее время |
| application | app | |
| configuration | cfg | |
| message | msg | |
| argument | arg | |
| object | obj | |
| parameter | param | |
| operator | opr | |
| procedure | proc | |
| function | func | |
| coordinate | coord | |
| rectangle | rect | |
| point | point | |
| symbol | sym | |
| literal | lit | |
| string | str | |
| identifier | ident | |
| indentation | indent |
Рекомендации по кодированию
- Оператор «возврат» в идеале используется, когда требуются его свойства управления потоком. Используйте неявную переменную результата процедуры всякий раз, когда это возможно. Это улучшает читаемость.
proc repeat(text: string, x: int): string = result = "" for i in 0 .. x: result.add($i)
- Используйте proc, когда это возможно, используя более мощные средства макросов, шаблонов, итераторов и конвертеров только по необходимости.
- Используйте оператор
let(а не операторvar), при объявлении переменных, которые не изменяются в пределах своей области видимости. Использование оператораletгарантирует неизменяемость переменных и даёт тем, кто читает код, лучшее понимание назначения кода.
Рекомендации для многострочных выражений и операторов
- Кортежи, которые занимают более одной строки, должны отступать параметры, выравнивая их с параметрами над ними.
type LongTupleA = tuple[wordyTupleMemberOne: int, wordyTupleMemberTwo: string, wordyTupleMemberThree: float]
- Аналогично, все объявления процедур и типов процедур, которые занимают более одной строки, должны делать то же самое.
type EventCallback = proc (timeReceived: Time, errorCode: int, event: Event, output: var string) proc lotsOfArguments(argOne: string, argTwo: int, argThree: float, argFour: proc(), argFive: bool): int {.heyLookALongPragma.} =
- Многострочные вызовы процедур должны продолжаться в той же колонке, что и открывающая скобка (как и многострочные объявления процедур).
startProcess(nimExecutable, currentDirectory, compilerArguments environment, processOptions)
© 2006–2021 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/nep1.html