A maior parte do trabalho de hoje foram continuações do trabalho de ontem, apenas implementando a lógica de negócios nas rotas da minha aplicação. Então, resolvi parar de escrever sobre isso para falar sobre três funções que criei para fazer coisas muito específicas em meu aplicativo.
Este é o diretório onde você coloca todas as suas pequenas funções que têm dificuldade em encontrar um lar, mas seu aplicativo não poderia viver sem elas.
Uma pasta utils é o local de despejo para os heróis anônimos de muitos aplicativos.
Quando você tiver que realizar uma transformação de seus dados que exigirá mais do que algumas linhas de código, que você terá que reutilizar, é uma boa ideia colocá-los em um arquivo próprio que você possa exportar para o restante do seu aplicativo.
Por que não apenas copiamos e colamos? Bem, isso violaria dois princípios de programação, DRY e separação de interesses.
Repetir-se não é apenas monótono, mas também é difícil mudar se você tiver feito isso o suficiente durante a aplicação. Imagine um algoritmo que calcula a porcentagem de chance de chuva hoje.
Não sei como as pessoas fazem isso, então não posso mostrar um exemplo. Mas, se você copiar tudo isso em todo o seu código nos diferentes lugares que precisam ter acesso a esse cálculo, você ficará muito chateado quando o Very Smart Scientific Weather Committee voltar com um algoritmo novo e mais preciso.
Pegue partes reutilizadas do seu código e encontre maneiras de empacotá-las para serem usadas em vários lugares, enquanto ainda são atualizadas em um só lugar.
Todas as funções da minha pasta utils são usadas em muitos lugares do meu aplicativo!
Como programadores, também não queremos criar funções que façam MUITAS coisas diferentes. Preferimos ter MUITAS funções que façam a mesma coisa. Por que? Bem, isso torna essas funções mais reutilizáveis!
O que isso tem a ver com uma pasta utils? Bem, as funções que estou prestes a abordar não têm lugar dentro de funções como getRoastsById porque não é isso que elas fazem! Quando precisarmos fazer outra coisa, devemos criar uma função para isso. Mas, quando não temos um lugar lógico para essa função, por ser uma “ajudante”, colocamos ela em nosso diretório de utils!
Tenho três utilitários personalizados até agora:
Espero que por seus nomes fique claro o que eles fazem, mas deixe-me compartilhar brevemente o problema que eles resolvem e como funcionam.
Problema: Em muitos dos diferentes serviços do meu aplicativo, serei solicitado a realizar uma consulta INSERT no meu banco de dados. Essas declarações exigem que você liste explicitamente 1) os nomes das colunas e 2) os valores. Eu não deveria ter que digitar isso em cada rota, então criei uma função para fazer isso por mim.
Entrada: A função leva dois parâmetros, table, uma string que corresponde ao nome de uma tabela no banco de dados e obj, um objeto Javascript que representa o modelo que o usuário deseja adicionar ao banco de dados.
Saída: Um objeto com 1) uma string INSERT formatada por propriedade com valores de espaço reservado e 2) uma matriz de valores a serem usados em uma consulta parametrizada.
const { snakeCase } = require('change-case-commonjs'); function insertStatement(table, obj) { const keys = Object.keys(obj); const values = Object.values(obj); let statement = `INSERT INTO ${table} (`; // Add snake_case keys to the statement const keyString = keys.map((key, i) => snakeCase(key)).join(', '); statement = `${keyString}) VALUES (`; // Add placeholders for the values const placeholders = keys.map((_, i) => `$${i 1}`).join(', '); statement = `${placeholders}) RETURNING *;`; // Return the query string and the values array return { text: statement, values: values }; } module.exports = insertStatement;
Problema: Semelhante à instrução INSERT, a instrução UPDATE exige que você declare explicitamente os nomes e valores das colunas em sua consulta. Esta sintaxe é diferente de uma instrução INSERT. Através da lógica condicional, eu poderia criar uma função databaseQueryGenerator, mas isso também parece violar a separação de interesses. Uma função como essa decidiria que tipo de consulta você deseja ou geraria sintaxe com base nisso?
Entrada: A função usa três parâmetros. obj, um objeto JavaScript que representa o registro atualizado. table , uma string que deve corresponder a uma tabela no banco de dados. id , um número inteiro que corresponde ao registro a ser atualizado com as novas informações.
Saída: Um objeto com 1) uma string UPDATE formatada como propriedade com valores de espaço reservado e 2) uma matriz de valores a serem usados em uma consulta parametrizada.
const { snakeCase } = require('change-case-commonjs'); function updateStatement(obj, table, id) { const keys = Object.keys(obj); const values = Object.values(obj); let statement = `UPDATE ${table} SET `; keys.forEach((key, index) => { statement = `${snakeCase(key)} = $${index 1}, `; }); // Remove the last comma and space statement = statement.slice(0, -2); // Determine the correct ID column based on the table const idColumn = table === 'users' ? 'username' : table === 'roasts' ? 'roast_id' : ''; // Finalize the statement with the WHERE clause statement = ` WHERE ${idColumn} = $${keys.length 1} RETURNING *;`; return { text: statement, values: [...values, id] }; } module.exports = updateStatement
Problema: O estilo do meu banco de dados é diferente do estilo do meu JavaScript. No entanto, não estou disposto a fazer concessões em nenhuma das áreas. Em meus arquivos JS, minha convenção de nomenclatura usa camelCase, enquanto em meu banco de dados usa Snake_case. Todos os nomes de propriedades dos objetos retornados são iguais, mas formatados de forma diferente. Para manter esse padrão de case, eu teria que acessar propriedades no meu JS usando Snake_case, mas não gosto disso.
Entrada: A função leva apenas um parâmetro, um objeto JavaScript obj que deve ter suas chaves transformadas na formatação camelCase.
Saída: O mesmo objeto, com chaves formatadas em camelCase.
const { camelCase } = require('change-case-commonjs'); function objectKeysToCamel(obj) { // Extract the keys and values const keys = Object.keys(obj); const values = Object.values(obj); let camel = {} // Change the formatting of each key, assigning it the proper value keys.forEach((key, i) => { const camelKey = camelCase(key); camel[camelKey] = values[i] }) // Return the new object return camel; } module.exports = objectKeysToCamel;
Se você quiser acompanhar as mudanças, bifurcar e executar localmente, ou até mesmo sugerir alterações de código, aqui está um link para o repositório GitHub!
https://github.com/nmiller15/roast
O aplicativo frontend está atualmente implantado no Netlify! Se você quiser experimentar alguns recursos e vê-los em ação, visualize-os em um dispositivo móvel abaixo.
https://knowyourhomeroast.netlify.app
Observação: esta implantação não tem API de back-end, portanto, contas e assados não são salvos em nenhum lugar entre as sessões.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3