Spec-Zone.ru › Nim

Руководство по стилю стандартной библиотеки

ИсточникИзменить

Введение

Хотя 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

Spec-Zone.ru

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