Информация Качественное оформление кода с использованием языка программирования Lua

Информация для этой статьи была взята из открытых источников, в том числе использовался англоязычный гайд по правильному оформлению кода от одного из контрибьюторов LuaRocks Hisham Muhammad. Данная статья имеет рекомендательный характер и будет полезна к прочтению теми разработчиками, которые предпочитают разрабатывать скрипты с открытым исходным кодом, а также тем разработчикам, которые работают в команде с другими разработчиками. Качественная разработка начинается с порядка в коде.



Качественное оформление кода в проектах с использованием языка программирования Lua



Изначально Lua не имеет практически никаких требований и стандартов написания кода, так что действительно можно сказать, что любой рабочий код будет считаться правильным. Но это не совсем правильный подход к работе и каких-никаких стандартов нужно придерживаться как минимум для того, чтобы понимать свой код даже через какое-то время после его фактического написания. Как уже было сказано, это исключительно ваше дело, но если вы собираетесь выкладывать код на всеобщее обозрение - позаботьтесь, чтобы он был читаемый и его можно было понять: правильно расставленной табуляции будет недостаточно - важно и то, как вы строите свой скрипт - как в коде располагаются элементы.

Чтобы не придумывать новые стандарты, мы будем опираться на те, что используются разработчиками достаточно популярных модулей, опубликованных на LuaRocks. Думаю, что это будет правильно, ведь за всеми этими модулями огромное количество рабочего времени, и существование и популярность этих библиотек говорит о том, что они очень успешны.

Главное правило написания правильного кода - его краткость. Строки кода не должны быть километровыми, старайтесь держаться в неких рамках и в случае необходимости переносить части кода на новые строки. Согласитесь, разобраться в длинном условном выражении будет проще, если оно будет поделено на несколько строк вручную, нежели если редактор кода поделит его автоматически, либо вовсе оставит таким длинным, что придётся пользоваться функцией горизонтального пролистывания.

[!] Видите, что кода много - переносите!


Lua:
-- Неправильно!
if red and green and blue and gray and black and white and apple and banana and rock and game and script and you and me then
    print("Кажется, условие слишком длинное и нечитаемое!")
end

-- Правильно!
if red and green and blue and gray and black and white and
apple and banana and rock and game and script and you and me then
    print("Кажется, это больше похоже на правильный вариант!")
end

Lua поддерживает как одинарные кавычки, так и двойные - их можно использовать во всех случаях, но в больших проектах с типом кавычек начинается полная неразбериха и с этим нужно что-то делать. Второе правило: в любых ситуациях используйте только двойные кавычки - это обусловлено тем, что в большинстве языков программирования двойные кавычки как раз таки используются для обозначения строк, а одинарные для обозначения символов. Одинарные же кавычки можно использовать в тех ситуациях, когда необходимо использовать двойные кавычки внутри строки, либо при необходимости выделить один единственный символ. Возможно, сначала будет непривычно, но со временем этой пройдет.

[!] Двойные кавычки - текст, одинарные - символы и экранирование!

Lua:
local string = "Здравствуйте, это автор этой статьи!"
local quotes = 'Здравствуйте, а вы читали книгу "Гарри Поттер"?'

Названия функций могут быть разные: кто-то делит слова нижним подчёркиванием, кто-то делает первую букву слова заглавной, кто-то начинает функцию с маленькой буквы, а кто-то начинает с большой - в конечном итоге код начинает походить на ассорти из разных видов названий и это вызывает некоторые трудности взаимодействия с кодом. Гайд LuaRocks рекомендует использовать стиль разделения слов в функции при помощи нижнего подчёркивания. Более того, функции, проверяющие что-либо и возвращающие значение TRUE, либо FALSE рекомендуется называть с префиксом «is» в начале, например, is_available или is_colored. К большим функциям стоит писать пояснение при помощи комментариев: писать необходимо о том, что делает функция, какие аргументы она принимает и что она может вернуть в результате выполнения.

[!] Называть функции стоит через нижнее подчёркивание, также стоит оставлять пояснения!


Lua:
function set_color(object, color) -- table, integer
function is_colored(object) -- table; return boolean
function get_data(object) -- table; return table

Что касается таблиц в Lua, то здесь всё просто: если это возможно, используйте, что называется «plain keys», для обращения к таблицам и для записи в них данных. Если необходимо подставить значение из переменной, либо индекс, в таком случае передать его можно через квадратные скобки. Лучше взглянуть на пример взаимодействия:

Lua:
local new_table = {
    new_key = "test",
    one_two = 15,
    four_three = {"good"}
}

print(new_table.new_key)
print(new_table.four_three[1])

local something = "one_two"
print(new_table[something])

Табуляция - очень важная вещь, которая обеспечивает читаемость текста. Обычно редакторы кода предлагают размер табуляции либо в два пробела, либо в четыре. Слишком большие размеры табуляции делают код нечитабельным, поэтому предпочтительнее использовать что-то среднее. Варианты в два или три пробела - золотая середина.

Что касается комментариев в коде, то после двух дефисов стоит ставить один пробел и только после него начинать писать комментарий. Если вы используете многострочные комментарии, стоит добавлять один табуляционный отступ и начинать комментарий на новой строке, т.е. не на той, где вы открыли комментарий, пример представлен ниже.


Lua:
-- Это однострочный комментарий, написанный ПРАВИЛЬНО!

--Это однострочный комментарий, он НЕПРАВИЛЬНЫЙ!
--   Это однострочный комментарий, он тоже НЕПРАВИЛЬНЫЙ!

--[[
    Это многострочный комментарий, написанный ПРАВИЛЬНО.
    Использована табуляция, комментарий на новой строке
]]

--[[ Это НЕПРАВИЛЬНОЕ использование комментария ]]
--[[ Так писать комментарии тоже не стоит
Это НЕПРАВИЛЬНЫЙ способ написания комментариев! ]]

Также не стоит пихать несколько функций в одну строку, язык программирования, конечно, не против такого, но это может ввести в заблуждение. Для каждой функции и объявленной переменной есть своя строка - не волнуйтесь, место не закончится. В этом есть свои плюсы, например, вы сможете хвастаться количеством строк в вашем коде.

Lua:
-- Так делать НЕ НУЖНО!
local hello = "world"; print(hello)

-- А вот так можно
local hello = "world"
print(hello)

Lua позволяет передавать функциям строки без использования круглых скобочек, но это тоже неправильное оформление. Не забывайте ставить скобки, ведь так ваш код становится более читабельным для других пользователей. Также старайтесь передавать только те аргументы, которые действительно используются в функции.

Lua:
require "socket" -- так делать НЕ СТОИТ!
require("socket") -- а вот так выглядит неплохо

Табуляция в объявляемых переменных для выравнивания операторов для Lua не подходит, не стоит этим заниматься!

Lua:
-- Это плохой вариант!
local apple              = true
local fruit_long_var     = false

-- Это хороший вариант!
local apple = true
local fruit_long_var = false

Используйте тернарные операторы, если это возможно, чтобы исключать лишние условные выражения. Это очень удобно и практично!

Lua:
-- Хороший вариант!
local content = false
print(content and "Available" or "Not available")

-- Плохой вариант!
local content = false
if content then
    print("Available")
else
    print("Not available")
end

Старайтесь не повторяться в коде: вы всегда можете создать универсальную функцию, которая будет выполнять определенное действие, и в дальнейшем использовать именно эту функцию для достижения своих целей. Совсем необязательно заниматься копированием и вставкой - вы генерируете огромное количество мусора в коде. Если же вы используете что-то лишь один раз наоборот старайтесь не создавать лишнюю функцию, которую вы используете лишь единожды - проще поместить всё в тело родителя.

Lua:
-- Неправильный вариант!
local file = io.open("source.txt", "r")
local data = file:read("*all")
file:close()
file = io.open("file.txt", "r")
local data2 = file:read("*all")
file:close()

-- Правильный вариант!
local function read_file(filepath)
    local file = io.open(filepath, "r")
    local data = file:read("*all")
    file:close()
    return data
end
local data = read_file("source.txt")
local data2 = read_file("file.txt")



В статье расписаны все основные моменты. Если вам кажется, что стоило бы что-нибудь добавить, вы можете написать об этом.
Надеюсь, что информация, представленная в этой статье, была вам полезна и вы подметили что-нибудь важное для себя!
 

LelHack

Известный
452
125
Ещё можно добавить подобную тему для pawn например, а так познавательно
 
  • Нравится
Реакции: qdIbp

ImPasha

Software Developer & System Administrator
Автор темы
Друг
1,789
2,141
Ещё можно добавить подобную тему для pawn например, а так познавательно
Соглашусь, про PAWN бы не помешало!
Стиль написания кода на Pawn не сильно отличается от стандартов, которые приняты в языках, подобных Си. Разница лишь в том, как объявляются некоторые функции и переменные, но принципиально ничего нового. Достаточно открыть любой из уже существующих гайдов и он скорее всего подойдет для Pawn.
 
  • Нравится
Реакции: qdIbp, etereon и SShooteRR

Rei

Известный
Друг
1,611
1,668
напиши про DRY, почему-то все пейсатели луа мультичитов этим пренебрегают
 
  • Нравится
Реакции: ImPasha

Dmitriy Makarov

25.05.2021
Проверенный
2,500
1,131
Если вам кажется, что стоило бы что-нибудь добавить, вы можете написать об этом
Не знаю, как для других, но для меня лично подобное объявление переменных удобнее, чем писать их в столбик, если их дофига. Особенно, это часто бывает, когда работаешь с ImGui. Запутаться сложно.
Lua:
-- Не удобно
local first_window = imgui.ImBool(false)
local secondary_window = imgui.ImBool(false)
local GMCheckBox = imgui.ImBool(false)
local AimCheckBox = imgui.ImBool(false)
local SmoothAim = imgui.ImInt(0)
local FOVAim = imgui.ImInt(0)

-- Удобно
local config = {
    Windows = {
        first_window = imgui.ImBool(false),
        secondary_window = imgui.ImBool(false)
    },
    CheckBoxes = {
        GMCheckBox = imgui.ImBool(false),
        AimCheckBox = imgui.ImBool(false)
    },
    Sliders = {
        SmoothAim = imgui.ImInt(0),
        FOVAim = imgui.ImInt(0)
    }
}
Имхо.)
 
  • Нравится
Реакции: OosKar

ImPasha

Software Developer & System Administrator
Автор темы
Друг
1,789
2,141
Не знаю, как для других, но для меня лично подобное объявление переменных удобнее, чем писать их в столбик, если их дофига. Особенно, это часто бывает, когда работаешь с ImGui. Запутаться сложно.
Lua:
-- Не удобно
local first_window = imgui.ImBool(false)
local secondary_window = imgui.ImBool(false)
local GMCheckBox = imgui.ImBool(false)
local AimCheckBox = imgui.ImBool(false)
local SmoothAim = imgui.ImInt(0)
local FOVAim = imgui.ImInt(0)

-- Удобно
local config = {
    Windows = {
        first_window = imgui.ImBool(false),
        secondary_window = imgui.ImBool(false)
    },
    CheckBoxes = {
        GMCheckBox = imgui.ImBool(false),
        AimCheckBox = imgui.ImBool(false)
    },
    Sliders = {
        SmoothAim = imgui.ImInt(0),
        FOVAim = imgui.ImInt(0)
    }
}
Имхо.)
Никто не говорит, что использовать таблицы - плохо. А вот способ оформления названий самих переменных стоило бы использовать другой. Самым подходящим является Snake Case, например, var_name, либо в крайнем случае Camel Case, например, varName. Переменные, название которых начинается с заглавной буквы, подходят для имитации объектно-ориентированного программирования, например, для названий классов. Я как раз писал в статье о том, что стили оформления названий не нужно смешивать, как это сделано у тебя в некоторых местах - это неправильно.
 

#Kai-

Известный
705
292
Бредятина, сплошная...
Так надо, так не надо, а почему - хуй знает, наверное потому что так надо.... ЧТО простите?

Lua:
-- Это плохой вариант!
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false

-- Это хороший вариант!
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false

Какой вариант в таком случае лучше? Лично я табулирую.
По мне так 1-й вариант который "Неправильный" читаемый в 1000000 раз лучше, нежели второй. Во втором случае apple теряется и её вообще не видно.

А ведь главная задача этой темы вроде как научить делать максимально читаемый код, но вырывать из контекста с тупыми примерами - глупо. Когда в большой работе где гораздо больше кода некоторые "правила" - теряют свою актуальность.

Дожили, учат даже комментарии в коде правильно делать, да они существуют исключительно с 1 целью - обозначить что делает этот участок кода, какая нахуй разница как он написан, с пробелом после "--" или без, когда комментарии пишут в 99.99% случаев обычными словами, а не кодом. Соглашусь что юзать многострочный вариант через "--" берд!
 
Последнее редактирование:

ImPasha

Software Developer & System Administrator
Автор темы
Друг
1,789
2,141
Бредятина, сплошная...
Так надо, так не надо, а почему - хуй знает, наверное потому что так надо.... ЧТО простите?

Lua:
-- Это плохой вариант!
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false
local apple              = true
local fruit_long_var     = false

-- Это хороший вариант!
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
local apple = true
local fruit_long_var = false
Какой вариант в таком случае лучше? Лично я табулирую.

Дожили, учат даже комментарии в коде правильно делать, да они существуют исключительно с 1 целью, обозначить что делает этот участок кода, какая нахуй разница как он написан, с пробелом после "--" или без. Соглашусь что юзать многострочный вариант через "--" берд!
Если ты пишешь код для себя и не собираешься его публиковать - ты можешь писать его так, как хочешь. Если ты будешь публиковать код или ты работаешь с другими людьми необходимо придерживаться определенных стилей и стандартов, чтобы другим людям было приятно работать с твоим кодом. Да и самому будет проще вспомнить через время что и за что отвечает в коде. Если постоянно писать по разному - далеко не уедешь. В этой статье приведены примеры того, как построен код в популярных проектах на LuaRocks, которыми пользуется огромное количество людей и которые разрабатываются огромным количеством людей, именно поэтому в статье рассказывается именно о таких стандартах, а ни о каких других. А насчёт табуляции, даже в официальной документации Lua говорится, что табуляция в случае с объявлением переменных не используется, как это делают в Си.
 

#Kai-

Известный
705
292
Если ты пишешь код для себя и не собираешься его публиковать - ты можешь писать его так, как хочешь. Если ты будешь публиковать код или ты работаешь с другими людьми необходимо придерживаться определенных стилей и стандартов, чтобы другим людям было приятно работать с твоим кодом. Да и самому будет проще вспомнить через время что и за что отвечает в коде. Если постоянно писать по разному - далеко не уедешь. В этой статье приведены примеры того, как построен код в популярных проектах на LuaRocks, которыми пользуется огромное количество людей и которые разрабатываются огромным количеством людей, именно поэтому в статье рассказывается именно о таких стандартах, а ни о каких других. А насчёт табуляции, даже в официальной документации Lua говорится, что табуляция в случае с объявлением переменных не используется, как это делают в Си.
Невозможно постоянно писать по разному, так или иначе каждый для себя придёт ко своему оформлению и будет использовать исключительно его.
На счет табуляции ничего не понял, не используется кем? Я говорю что я использую и пример мой по-моему здравый.
 

ImPasha

Software Developer & System Administrator
Автор темы
Друг
1,789
2,141
Невозможно постоянно писать по разному, так или иначе каждый для себя придёт ко своему оформлению и будет использовать исключительно его.
На счет табуляции ничего не понял, не используется кем? Я говорю что я использую и пример мой по-моему здравый.
Ты можешь посмотреть на пост парой постов выше и увидеть, что у человека нет единого оформления переменных - для людей, которые будут потом изучать этот код, это станет проблемой, хотя человек вроде не первый день пишет на этом языке программирования, как-то сам по себе стиль не образовался. Про табуляцию - информация из официальной документации на сайте Lua: используется только для оформления конструкций в коде, никак не для выравнивания операторов при объявлении переменных. Да, в Си, например, так делают, в Lua такое не приветствуется, и это не мной придумано.
 

#Kai-

Известный
705
292
Ты можешь посмотреть на пост парой постов выше и увидеть, что у человека нет единого оформления переменных - для людей, которые будут потом изучать этот код, это станет проблемой, хотя человек вроде не первый день пишет на этом языке программирования, как-то сам по себе стиль не образовался. Про табуляцию - информация из официальной документации на сайте Lua: используется только для оформления конструкций в коде, никак не для выравнивания операторов при объявлении переменных. Да, в Си, например, так делают, в Lua такое не приветствуется, и это не мной придумано.
Незнаю, человека выше никто в команду не возьмет, сужу исключительно по темам его тут.
Этот человек либо недавно в программировании как таковом, либо просто спиздил чужой код.

P.S Согласен на счет табуляции, так она не для чего другого и не может быть использована.

Так и не понял все равно, я дал пример где с табуляцией читается гораздо проще и легче - значит так правильно? Смысл этой табуляции исключительно в читаемости кода, зачем вообще выравнивать операторы - как не для читаемости??? Тут согласен что бред.

По поводу "спиздил чужой код".

Никто никого не обвиняет, лично сужу по себе. Мне иногда проще CTRL + C/ CTRL+V захерачить, нежели сидеть и тратить драгоценное время ради какого-то там блять скриптика.
 
Последнее редактирование:

Double Tap Inside

Известный
Проверенный
1,916
1,255
Я еще любительотделять ветки
perenosom stroki
Lua:
if true then
    true = false
    nil = true

elseif nil then
    false = tostring(nil)
    print(print)

else
    local forever = tonumber("inf")
    deleteSamp(forever)
end