{"meta":{"title":"Refatorando camadas de acesso a dados","intro":"Copilot Chat pode sugerir maneiras de desacoplar o código de acesso a dados de sua lógica de negócios, facilitando a manutenção e a escala de um aplicativo.","product":"GitHub Copilot","breadcrumbs":[{"href":"/pt/copilot","title":"GitHub Copilot"},{"href":"/pt/copilot/tutorials","title":"Tutoriais"},{"href":"/pt/copilot/tutorials/copilot-cookbook","title":"Livro de receitas do GitHub Copilot"},{"href":"/pt/copilot/tutorials/copilot-cookbook/refactor-code","title":"Refatorar o código"},{"href":"/pt/copilot/tutorials/copilot-cookbook/refactor-code/refactor-data-access-layers","title":"Refatorar camadas de acesso a dados"}],"documentType":"article"},"body":"# Refatorando camadas de acesso a dados\n\nCopilot Chat pode sugerir maneiras de desacoplar o código de acesso a dados de sua lógica de negócios, facilitando a manutenção e a escala de um aplicativo.\n\nConsultas SQL codificadas e código fortemente acoplado para acesso a dados podem dificultar a escalabilidade ou a troca de bancos de dados, e geralmente resultar em lógica repetida.\n\nCopilot Chat pode recomendar a implementação de um padrão de repositório ou uma camada de acesso a dados que abstraa as interações de banco de dados, tornando o código mais modular e reduzindo a redundância. Ele também pode ajudar a refatorar consultas SQL em versões otimizadas, aprimorando o desempenho e a capacidade de manutenção.\n\n> \\[!NOTE] As respostas descritas neste artigo são exemplos.\n> Copilot Chat as respostas são não determinísticas, portanto, você pode obter respostas diferentes das mostradas aqui.\n\n## Cenário de exemplo\n\nEste código Python se conecta a um banco de dados SQLite, recupera um registro de usuário e retorna os dados do usuário. No entanto, ele não abstrai a lógica de conexão ao banco de dados e usa uma consulta embutida em código vulnerável à injeção de SQL.\n\n```python id=database-connection\nimport sqlite3\n\ndef get_user_by_id(user_id):\n    conn = sqlite3.connect('database.db')\n    cursor = conn.cursor()\n    cursor.execute(f\"SELECT display_name FROM users WHERE id = {user_id}\")\n    user = cursor.fetchone()\n    conn.close()\n    return user\n```\n\n## Exemplo de prompt 1\n\nVocê pode começar fazendo Copilot uma pergunta geral sobre como melhorar o código.\n\n```copilot copy prompt ref=database-connection\nHow can I improve this code to make it safe and easier to update and expand? List possible improvements but don't show revised code.\n```\n\n## Exemplo de resposta 1\n\nCopilot faz várias sugestões para melhorar o código:\n\n* Abstraia os detalhes da conexão do banco de dados.\n* Use consultas parametrizadas para evitar a injeção de SQL.\n* Use um gerenciador de contexto para garantir que a conexão de banco de dados seja encerrada corretamente se ocorrer um erro.\n* Adicione tratamento de erros.\n\n## Exemplo de prompt 2\n\nVocê pode usar a resposta ao seu primeiro prompt para escrever um prompt mais específico.\n\n```copilot copy prompt ref=database-connection\nRewrite this code to make it more scalable and easier to maintain. Use a context manager. Avoid hardcoded SQL queries and tightly coupled data access code. Instead, use a repository pattern to abstract database interactions and make the code more modular and reusable. Where possible optimize the code to improve performance. Include error trapping, and make sure the code is not vulnerable to SQL injection.\n```\n\n## Exemplo de resposta 2\n\nCopilot sugere dividir o código em arquivos separados, cada um com uma finalidade específica. Ele também fornece um código de exemplo para retornar os detalhes de um usuário.\n\nAs alterações sugeridas implementam um padrão de repositório e usam consultas parametrizadas para evitar a injeção de SQL.\n\n```python\n# database.py\nimport sqlite3\n\nclass Database:\n    def __init__(self, db_path):\n        self.db_path = db_path\n\n    def __enter__(self):\n        self.conn = sqlite3.connect(self.db_path)\n        self.cursor = self.conn.cursor()\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        if exc_type or exc_val or exc_tb:\n            self.conn.rollback()\n        else:\n            self.conn.commit()\n        self.conn.close()\n\n# user_repository.py\nclass UserRepository:\n    def __init__(self, db):\n        self.db = db\n\n    def get_user_by_id(self, user_id):\n        try:\n            self.db.cursor.execute(\"SELECT display_name FROM users WHERE id = ?\", (user_id,))\n            user = self.db.cursor.fetchone()\n            return user\n        except sqlite3.Error as e:\n            print(f\"An error occurred: {e}\")\n            return None\n\n# main.py\nfrom database import Database\nfrom user_repository import UserRepository\n\ndef get_user_by_id(user_id):\n    with Database('database.db') as db:\n        user_repo = UserRepository(db)\n        return user_repo.get_user_by_id(user_id)\n\n# Example usage\nif __name__ == \"__main__\":\n    user = get_user_by_id(1)\n    if user:\n        print(user)\n    else:\n        print(\"User not found or an error occurred.\")\n```\n\nO código revisado aprimora o original de várias maneiras:\n\n* O código agora implementa uma camada básica de acesso a dados.\n* A classe `Database` manipula a conexão com o banco de dados SQLite, implementando o protocolo do gerenciador de contexto com os métodos `__enter__` e `__exit__`. Isso garante que a conexão ao banco de dados seja gerenciada corretamente, incluindo a confirmação de transações e o encerramento da conexão.\n* A classe `UserRepository` encapsula a lógica para acessar dados do usuário.\n* Os valores das consultas são parametrizados para evitar a injeção de SQL.\n* Erros são detectados, com detalhes impressos no console.\n\n## Leitura adicional\n\n* [Engenharia de prompts para o GitHub Copilot Chat](/pt/copilot/concepts/prompting/prompt-engineering)\n* [Práticas recomendadas para usar GitHub Copilot](/pt/copilot/get-started/best-practices)"}