Оформление кода
Перечисленные рекомендации не проверяются компилятором, поэтому являются только советами, которые позволяет создавать пригодный и привычный для чтения код.
Стиль записи нескольких слов слитно без пробелов, при котором каждое следующее слово внутри пишется с заглавной буквы, будет далее называться camel case.
Именование
Имена пакетов определяются как измененная запись некоторого url (см. соответствующий раздел). Но обычной практикой является использование только строчных букв с разделением слов при помощи подчёркивания _ или вовсе без разделителя: com/teacode/html, com/teacode/xmlstream, libretto/jvm_jar/websocket, libretto/jvm_jar/nimbus_jose_jwt - в том числе для совместимости с файловыми системами, которые не являются чувствительными к регистру.
Имена структур и трейтов с заглавной буквы и в camel case, главное слово - это существительное (чаще в единственном, но возможно и множественном числе) либо иногда прилагательное (причастие прошедшего времени): Person, TypeInfo, LinkedList, RemovedNumbers, Pinned.
Имя поля (структуры) со строчной буквы и в camel case, главное слово - это существительное (в единственном или множественном числе) либо прилагательное (причастие прошедшего времени): name, parents, sorted, hiddenFiles
Имена методов (обозначающих действие) со строчной буквы и в camel case, главное слово - это глагол: print, removeFromList.
Но имена методов, которые используют new-выражение без указания имени трейта (определение трейта “по месту”), должны выбираться по принципу имён структур и трейтов, а не по принципу обычных методов.
В некоторых случаях глагол можно опускать в имени метода, если используется предлоги, которые позволяют интуитивно понять происходящее действие (to, from и т.п.).
Имена методов, похожих по поведению на поля, определяются аналогично именам полей.
Если метод не имеет параметров и не имеет побочных эффектов, то используется вариант без скобок (чаще всего действие похоже на вычислимое поле): title.
Если метод не имеет параметров, но имеет побочные эффекты, то используется вариант с пустыми скобами: println().
todo (устарело): В чистом виде setter/getter отсутствуют и нет рекомендаций по использованию глаголов set или get для имен методов. Имя метода получения значения допустимо оформлять как имя поля. Метод изменения допустимо оформлять с использованием имени поля, но с параметром (параметрами).
Имена переменных (в том числе as и case-переменных) и параметров со строчной буквы и в camel case, чаще всего главное слово - это существительное или буква (в очевидных случаях).
Префиксы как часть имени
Интересным направлением стиля оформления является использование префиксов (при импорт-подключении пакетов) как смысловой части имени сущности.
Например, есть сущность Node (узел), который используется в разных пакетах. При возможном частом одновременном использовании этих пакетов можно использовать более сложные имена: в одном пакете это, например, будет SourceNode, в другом пакете - TreeNode.
Но можно часть сложного имени перенести в имя пакета, одновременно используя простое имя Node. Например, Node в пакете org/example/source и тоже Node в пакете org/example/tree. Тогда при использовании префиксного имени с импортом по умолчанию будут доступны имена source/Node и tree/Node.
Имена файлов и кодировка
При оформлении библиотек и веб-приложений нет требований к именам файлов и каталогов, только необходимо использовать разрешение .ltt для исходных текстов на Libretto, сами тексты должны быть в UTF-8 кодировке (без BOM).
Но рекомендуется использовать понятную внутреннюю организацию: разделять части пакета по разным файлам, подпакеты размещать в подкаталогах. Имена файлов давать строчными буквами (на случай использования файловой системы без чувствительности к регистру символов), в качестве разделителя слов в имени использовать _ или не использовать разделитель вообще.
Пробелы, переносы строк
Используются отступы, состоящие из двух пробелов, использовать символ табуляции в явном виде не рекомендуется.
Если блок с фигурными скобами записывается в несколько строк, то открывающая скобка { ставится в конце строки, затем идёт тело блока с дополнительным отступом, а закрывающая скобка } ставится следующей строкой со соответствующим отступом:
def test(v: Unit?) = {
if (v) {
println("unit")
}
else {
println("()")
}
}
Прочие особенности синтаксиса
Не рекомендуется использовать бесскобочный способ записи вызова метода (в первую очередь при помощи :) в сложных конструкциях. Нужно учитывать приоритеты, которые могут отличаться от ожидаемых. Например, a(b: c, d) работает как a(b(c, d)) а не как a(b(c), d).
Пример:
def b(p0: String) = "b("+p0+")"
def b(p0: String, p1: String) = "b("+p0+", "+p1+")"
def a(p0: String) = "a("+p0+")"
def a(p0: String, p1: String) = "a("+p0+","+p1+")"
def main = {
println: a(b: "1", "2")
println: a((b: "1", "2"))
println: a((b: "1"), "2")
}
Выдает:
a(b(1, 2))
a(b(1, 2))
a(b(1),2)
Конструкции с case могут показаться более громоздкими, но часто они даёт лучшую читабельность кода.