Вопрос

У меня есть функция, которая состоит в основном из огромного количества вызовов (более 50) другой функции, которая вставляет данные в массив, причем логика здесь и там диктует различные условия для вставки различных элементов в массив (плюс немного в конце, которая записывает содержимое массива в файл).Мне интересно, нет ли лучшего способа сделать эту функцию;Полагаю, я мог бы начать с логического разделения наборов команд вставки массива на их собственные функции, но мне интересно, могу ли я сделать еще что-нибудь.Есть ли?

Пример:

function buildTable(fileName, data)
    local dataToWrite = {}
    table.insert(datTWrite, {
        Type = "type1",
        Key = "someKey",
        Value = data.SomethingInteresting
    })
    --and so on ad nauseum with an occasional but of actual logic to spice things up
    dataWriter:open(fileName .. ".bla")
    dataWriter:batchWrite(dataToWrite)
    dataWriter:close()
end

В этом случае DataWriter является экземпляром предопределенного класса, который обрабатывает процесс записи в файл.

Это было полезно?

Решение

Хорошей новостью является то, что вы не перешли непосредственно к обычной Lua-пессимизации объединения строк в буфер в цикле для построения вашего вывода.

Я бы написал ваш образец следующим образом:

function buildTable(fileName, data)
    local t = {}
    t[#t+1] = {
        Type = "type1",
        Key = "someKey",
        Value = data.SomethingInteresting
    }
    --and so on ad nauseum with an occasional but of actual logic to spice things up
    dataWriter:open(fileName .. ".bla")
    dataWriter:batchWrite(t)
    dataWriter:close()
end

который имеет небольшое преимущество в том, что не использует длинное имя временной таблицы, подверженное опечаткам, и использует t[#t+1] идиома для расширения части массива, которая должна быть быстрее, чем вызов table.insert().

В противном случае источник любых структурных улучшений будет находиться в части кода "и так далее до тошноты".

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

Прежде всего, остерегайтесь преждевременной оптимизации.Возьмите за основу то, что у вас есть сейчас, и используйте это как руководство для поиска узких мест в производительности.

Другие советы

Под "и так далее до тошноты со случайной, но реальной логикой, чтобы оживить ситуацию" я предполагаю, что вы имеете в виду, что у вас есть много блоков, таких как:

table.insert(datTWrite, {
    Type = "type1",
    Key = "someKey",
    Value = data.SomethingInteresting
})

Единственным аспектом этого, который является уникальным для функции, является заполняемая таблица и data объект.Моей личной "лучшей практикой" было бы перенести все это в отдельную таблицу, например:

local entries = {
    {
        Type = "type1",
        Key = "someKey",
        ValueField = "SomethingInteresting",
    },
    {
        Type = "type2",
        Key = "someOtherKey",
        ValueField = "SomethingElse",
    },
    -- etc.
}

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

for i, entry in ipairs(entries) do
    table.insert(datTWrite, {
        Type = entry.Type,
        Key = entry.Key,
        Value = data[entry.ValueField]
    })
end

Для "случайной" логики каждая запись может иметь необязательную функцию, предоставляющую вам интересную информацию в цикле.Например.:

for i, entry in ipairs(entries) do
    if not entry.CheckSomething or entry.CheckSomething() then
        table.insert(datTWrite, {
            Type = entry.Type,
            Key = entry.Key,
            Value = data[entry.ValueField]
        })
    end
end

В качестве альтернативы, вы могли бы даже разрешить отдельным записям в таблице БЫТЬ функциями, если вам нужна дополнительная настраиваемость.Каждая функция ввода возвращала бы таблицу (или нет).

for i, entry in ipairs(entries) do
    if type(entry) == "function" then
        local newEntry = entry()
        if newEntry then
            table.insert(datTWrite, newEntry)
        end
    else
        table.insert(datTWrite, {
            Type = entry.Type,
            Key = entry.Key,
            Value = data[entry.ValueField]
        })
    end
end

Не имея ничего конкретного для продолжения, я бы попробовал исследовать код пахнет и посмотрите, как сравнивается ваша функция.Судя по всему, вам, вероятно, есть чем заняться.Существуют ли блоки похожего / скопированного кода, изолированные другой условной логикой?Вложенные циклы или условные выражения?Это несколько простых отправных точек при попытке разбить большую функцию на части.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top