Pergunta

Eu tenho uma função que consiste principalmente de uma enorme quantidade de chamadas (50+) para outra função que insere dados em uma matriz, com a lógica aqui e ali ditando várias condições para inserir vários itens para a matriz (mais um pouco na extremidade que escreve o conteúdo da matriz para um arquivo). Eu estou querendo saber se não há uma maneira melhor de fazer esta função; Acho que eu poderia começar com conjuntos de comandos de inserção variedade logicamente dividindo-se em suas próprias funções, mas eu estou querendo saber se há qualquer mais que eu possa fazer. Existe?

Exemplo:

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

Neste caso, dataWriter é uma instância de uma classe predefinida que manipula o processo de gravação de um arquivo.

Foi útil?

Solução

A boa notícia é que você não tenha pisado diretamente no pessimization comum Lua de concatenar strings para um buffer em um loop para construir a sua saída.

Eu ia escrever o seu exemplo como este:

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

que tem a pequena vantagem de não utilizar um nome longo typo-propenso para a tabela temporária, e usa o idioma t[#t+1] para estender a parte array que deve ser mais rápido do que chamar table.insert().

Caso contrário, a fonte de quaisquer melhorias estruturais estará no "e assim por diante ad nauseum" parte do código.

  • Olhe lá para cálculos e fragmentos comuns que podem ser recolhidos em funções locais.
  • Lembre-se que você pode aninhar funções definições, funções para auxiliar pode ser limitado em escopo para o lugar que eles são usados.
  • Procure lógica demasiado inteligente, e reescrevê-los a ser sensato para quem vai ter que mantê-lo no próximo ano.
  • wiki: Padrões Lua projeto
  • wiki: Zen Of Lua
  • wiki: Dicas de otimização
  • wiki: Profiling Código Lua

Acima de tudo, cuidado com a otimização prematura. Referência que você tem agora como um ponto de comparação, e usar isso como um guia para encontrar gargalos de desempenho.

Outras dicas

Por "e assim por diante ad nauseum com um ocasional, mas da lógica real para apimentar as coisas" Presumo que significa que você tem muitos blocos como:

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

O único aspecto deste que é exclusivo para a função é a tabela que está sendo preenchido eo objeto data. Meu pessoal "melhores práticas" seria para puxar tudo isso fora em uma tabela separada como:

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

Esta tabela deve ser um global ou em um fora do escopo em que a função é definida. Agora você pode mais facilmente reconfigurar as entradas sem fazer quaisquer alterações à função que faz o trabalho real. A função em si é muito simplificada por iteração através de entradas assim:

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

Para a lógica "ocasional", cada entrada pode ter uma função opcional para dar-lhe informações interessantes no circuito. Por exemplo:.

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

Como alternativa, você pode até mesmo permitir que as entradas individuais na tabela a ser funções se você precisar de mais personalização. Cada função de entrada iria retornar uma tabela (ou não).

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

Sem nada específico para seguir em frente, eu iria tentar pesquisando cheira e ver como sua função compara. Desde os sons das coisas, provavelmente há muito para você fazer. Existem blocos de código semelhante / copiado isolado por lógica condicional diferente? Aninhados loops ou condicionais? Estes são alguns simples pontos de partida ao tentar dividir um grande função em partes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top