Spec-Zone.ru › Nim 1

Предложение по улучшению 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API