Руководство по стилю стандартной библиотеки
ИсточникИзменитьВведение
Хотя Nim поддерживает различные стили кода и форматирования, тем не менее, полезно, чтобы определенные усилия сообщества, такие как стандартная библиотека, придерживались согласованного набора руководящих принципов стиля, когда это уместно. Данное предложение по улучшению призвано перечислить ряд руководящих принципов, которым должна следовать стандартная библиотека.
Обратите внимание, что могут быть исключения из этих правил. Поскольку Nim достаточно гибкий, некоторые части этого руководства по стилю могут не иметь смысла в определённых контекстах. Кроме того, так же как руководство по стилю Python со временем меняется, это руководство по стилю тоже будет меняться.
Эти правила будут применяться только к вкладам в базу кода 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
Правила именования
-
Идентификаторы типов должны быть в 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
-
Члены перечислений должны иметь идентифицирующий префикс, например, аббревиатуру имени перечисления, если не помечено пragma
{.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 | initFoo | инициализирует тип значения Foo
|
| new | newFoo | инициализирует тип ссылки Foo через new или тип значения Foo со семантикой ссылки. |
| this or self | self | для методов-процедур, например: proc fun(self: Foo, a: int) обоснование: self в английском языке более уникально, чем this, и foo не будет DRY. |
| 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 |
Рекомендации по написанию кода
-
Оператор
returnдолжен использоваться по возможности, когда требуется его свойство управления потоком. Используйте неявную переменнуюresultпроцедуры всякий раз, когда это возможно. Это улучшает читаемость.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] -
Аналогично, любые объявления процедур и типов процедур, занимающие более одной строки, должны делать то же самое. Двойной отступ может использоваться для различения их от тела, которое следует за ними - это относится ко всем конструкциям с телом (if, while и т. д).
type EventCallback = proc( timeReceived: Time, errorCode: int, event: Event, output: var string) proc lotsOfArguments( argOne: string, argTwo: int, argThree: float, argFour: proc(), argFive: bool, argSix: int ): GenericType[int, string] {.heyLookALongPragma.} = discard -
Многострочные вызовы процедур должны продолжаться с отступом (как многострочные объявления процедур).
startProcess( nimExecutable, currentDirectory, compilerArguments environment, processOptions)
Предыдущие версии этого руководства рекомендовали вертикальное выравнивание вдоль открывающей фигурной скобки/скобки - оба стиля допустимы с предпочтением текущего стиля в новом коде.
Разное
- Используйте
a..bвместоa .. b, за исключением случаев, когдаbсодержит оператор, напримерa .. -3. Аналогично сa..<b,a..^bи другими операторами, начинающимися с... - Используйте префикс
stdдля модулей стандартной библиотеки, а именноstd/osдля одного модуля иstd/[os, sysrand, posix]для нескольких модулей. -
Предпочтительнее использовать многострочные литералы с тройными кавычками, начинающиеся с новой строки; это семантически идентично (это особенность литералов с тройными кавычками), но более наглядно, так как выравнивается со следующей строкой:
используйте это:
let a = """ foo bar """
вместо этого:
let a = """foo bar """
- API-метод-получатель для приватного поля
fooпредпочтительнее называтьfoo, а неgetFoo. Метод-получатель API предпочтительнее называтьgetFoo, а неfoo, если:- API имеет побочные эффекты
- или стоимость не
O(1)
В промежуточных случаях четких рекомендаций нет.
- Аналогично с API-методом-установщиком, заменяя
fooнаfoo=иgetFooнаsetFooв тексте выше.
© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/nep1.html