Skip to content

Instantly share code, notes, and snippets.

@rogernogueira
Last active August 1, 2023 21:41
Show Gist options
  • Save rogernogueira/8161e05db4c86460185cdd57e3ea9eba to your computer and use it in GitHub Desktop.
Save rogernogueira/8161e05db4c86460185cdd57e3ea9eba to your computer and use it in GitHub Desktop.
RMA - Clean Code
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"toc_visible": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [
"#[**RMA - Educacional**](https://https://rmaeducacional.kpages.online/curso-serpro2023)\n",
"#Clean CODE\n",
"\n",
"\n",
"\n",
"---\n",
"\n"
],
"metadata": {
"id": "-1EEdvMvjPgt"
}
},
{
"cell_type": "markdown",
"source": [
"# Melhores Práticas de Codificação em Python\n",
"\n",
"## Siga a PEP 8\n",
"\n",
"PEP 8 é um documento que descreve as convenções de estilo para o código Python. Seguir a PEP 8 pode tornar o seu código mais legível e familiar para outros desenvolvedores Python.\n",
"\n",
"Alguns pontos importantes da PEP 8 incluem:\n",
"\n",
"- Use 4 espaços por nível de recuo.\n",
"- Limite todas as linhas a um máximo de 79 caracteres.\n",
"- Use linhas em branco para separar funções e classes.\n",
"- Comente o seu código.\n",
"- Use nomes descritivos para funções, variáveis e classes.\n",
"\n",
"Este é um exemplo de código Python bem formatado de acordo com a PEP 8\n"
],
"metadata": {
"id": "3o6EBEdYWa1C"
}
},
{
"cell_type": "code",
"source": [
"def funcao_exemplo(parametro1, parametro2):\n",
" \"\"\"\n",
" Esta é uma função de exemplo que segue a PEP 8.\n",
" \"\"\"\n",
" if parametro1 > parametro2:\n",
" resultado = parametro1 - parametro2\n",
" else:\n",
" resultado = parametro2 - parametro1\n",
"\n",
" return resultado"
],
"metadata": {
"id": "4OKbAFxDWn0P"
},
"execution_count": 24,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"##Refatoração de Código\n",
"Refatorar o código significa melhorar a estrutura do código sem alterar seu comportamento. A refatoração pode tornar o código mais limpo, mais fácil de entender e mais fácil de manter.\n",
"\n",
"Lembre-se, é sempre melhor prevenir a duplicação de código. Se você se encontrar copiando e colando blocos de código, provavelmente há uma maneira melhor de fazer isso!"
],
"metadata": {
"id": "LOObw-A_W0EN"
}
},
{
"cell_type": "markdown",
"source": [
"##Uso de Compreensões de Lista\n",
"As compreensões de lista são uma característica poderosa do Python que permite que você crie listas de uma maneira muito concisa."
],
"metadata": {
"id": "p17wcbO3XIWd"
}
},
{
"cell_type": "code",
"source": [
"quadrados = [x**2 for x in range(10)]"
],
"metadata": {
"id": "astR4cWEXep5"
},
"execution_count": 25,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"---"
],
"metadata": {
"id": "FqZ3g5vSmT-p"
}
},
{
"cell_type": "markdown",
"source": [
"# Documentação de Código em Python\n",
"\n",
"## A Importância da Documentação\n",
"\n",
"Documentar o seu código é uma prática essencial que facilita a compreensão do que o seu código faz e como ele funciona. Uma boa documentação é especialmente útil para os outros (ou para você no futuro) que estão lendo e tentando entender o seu código.\n",
"\n",
"## Comentários no Código\n",
"\n",
"Comentários são usados para explicar partes do código que podem ser difíceis de entender.\n",
"\n"
],
"metadata": {
"id": "BTV5B1dWXt71"
}
},
{
"cell_type": "code",
"source": [
"# Exemplo de um comentário\n",
"\n",
"x=0\n",
"# Esta linha de código adiciona 1 à variável x\n",
"x += 1"
],
"metadata": {
"id": "HSFA0AuEXzoa"
},
"execution_count": 27,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"##Docstring\n",
"Docstrings são usados para documentar módulos, classes, funções e métodos. Eles são colocados logo após a definição de uma função ou classe e são escritos entre três aspas duplas."
],
"metadata": {
"id": "x_lG2RVHXzZp"
}
},
{
"cell_type": "code",
"source": [
"def soma(a, b):\n",
" \"\"\"\n",
" Esta função recebe dois argumentos, a e b, e retorna a soma dos dois.\n",
" \"\"\"\n",
" return a + b"
],
"metadata": {
"id": "uXtyb1ewX929"
},
"execution_count": 28,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Você pode acessar a docstring de uma função usando a propriedade __doc__ da função."
],
"metadata": {
"id": "k6CpOda3WnBu"
}
},
{
"cell_type": "code",
"source": [
"print(soma.__doc__)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "KCPI9s1wYF66",
"outputId": "feaaa185-ce1c-4cfe-b28e-93d38e888bf1"
},
"execution_count": 29,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"\n",
" Esta função recebe dois argumentos, a e b, e retorna a soma dos dois.\n",
" \n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"---"
],
"metadata": {
"id": "vU1K0HYLmZhQ"
}
},
{
"cell_type": "markdown",
"source": [
"# Análise Estática de Código em Python\n",
"\n",
"## O Que é Análise Estática de Código?\n",
"\n",
"A análise estática de código é uma forma de analisar e avaliar o seu código sem executá-lo. É uma prática muito útil para detectar erros, bugs, estilo de codificação incoerente e outros problemas potenciais no seu código.\n",
"\n",
"## Linters de Python\n",
"\n",
"Um linter é uma ferramenta que realiza a análise estática do código. No Python, um dos linters mais populares é o Pylint.\n",
"\n",
"Para instalar o Pylint, você pode usar o seguinte comando no terminal:\n",
"```\n",
"pip install pylint\n",
"```"
],
"metadata": {
"id": "CodrJASfYJoB"
}
},
{
"cell_type": "markdown",
"source": [
"Depois de instalar o Pylint, você pode usá-lo para verificar um arquivo Python com o seguinte comando:\n",
"```\n",
"pylint meu_arquivo.py\n",
"```\n",
"O Pylint irá então analisar o seu código e fornecer um relatório de quaisquer problemas que encontrar."
],
"metadata": {
"id": "wwHYYQnJYgFL"
}
},
{
"cell_type": "markdown",
"source": [
"##Uso do Pylint no Notebook Jupyter\n",
"Você também pode usar o Pylint diretamente em um notebook Jupyter. Primeiro, você precisa instalar o ipywidgets e o pylint com o pip:"
],
"metadata": {
"id": "8S-u4gmRZQlQ"
}
},
{
"cell_type": "code",
"source": [
"!pip install ipywidgets pylint"
],
"metadata": {
"id": "-BgsvkNuYfcX"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Depois, você pode usar o seguinte código para executar o Pylint no seu notebook:"
],
"metadata": {
"id": "Em1e1PjaZiyL"
}
},
{
"cell_type": "code",
"source": [
"!pylint minha_funcao.py"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "bFb7WwVDZqIy",
"outputId": "7514f807-c968-4021-fbce-a8ca66ef0701"
},
"execution_count": 30,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"************* Module minha_funcao.py\n",
"minha_funcao.py:1:0: F0001: No module named minha_funcao.py (fatal)\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"---"
],
"metadata": {
"id": "b9ME0bVHmjh8"
}
},
{
"cell_type": "markdown",
"source": [
"# Funções e Métodos em Python\n",
"\n",
"## Funções Pequenas\n",
"\n",
"Idealmente, uma função deve realizar uma única tarefa. Funções que executam uma única tarefa são mais fáceis de escrever, testar e ler.\n",
"\n",
"Vejamos um exemplo:\n"
],
"metadata": {
"id": "99bsXENYQij3"
}
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"id": "x3YpVN5pQXJf",
"outputId": "756ee691-7951-43dc-ae23-58f6ba60154c"
},
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"'Olá, RMA!'"
],
"application/vnd.google.colaboratory.intrinsic+json": {
"type": "string"
}
},
"metadata": {},
"execution_count": 32
}
],
"source": [
"def saudacao(nome):\n",
" return f'Olá, {nome}!'\n",
"saudacao(\"RMA\")"
]
},
{
"cell_type": "markdown",
"source": [
"##Uso Correto de Argumentos\n",
"O número de argumentos que uma função aceita pode afetar a legibilidade do código.\n",
"\n"
],
"metadata": {
"id": "mD-lakOGRA8E"
}
},
{
"cell_type": "code",
"source": [
"def cria_usuario(nome, sobrenome, email):\n",
" return {\n",
" 'nome': nome,\n",
" 'sobrenome': sobrenome,\n",
" 'email': email,\n",
" }\n",
"\n",
"usuario = cria_usuario('João', 'Silva', 'joao.silva@email.com')\n",
"print(usuario)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "pxHTUdvYRKLG",
"outputId": "f67b7891-dace-4783-d2f2-e565432066b5"
},
"execution_count": 33,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"{'nome': 'João', 'sobrenome': 'Silva', 'email': 'joao.silva@email.com'}\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"##Evitando Efeitos Colaterais\n",
"Efeitos colaterais ocorrem quando uma função modifica um estado que está fora de seu escopo."
],
"metadata": {
"id": "PIBMdLzXRT03"
}
},
{
"cell_type": "code",
"source": [
"contador = 0\n",
"\n",
"def incrementa_contador():\n",
" global contador\n",
" contador += 1\n",
" return contador\n",
"\n",
"print(incrementa_contador())\n",
"\n"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "rkXGToTVRU-J",
"outputId": "41014b6b-2400-4a8c-b99c-0c8a4a5db0ed"
},
"execution_count": 34,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"1\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"Acima, temos um exemplo de uma função com efeitos colaterais - ela modifica a variável global contador. A maneira Pythonic de fazer isso seria retornar um novo valor em vez de modificar o estado existente."
],
"metadata": {
"id": "XZIZssQwRo0C"
}
},
{
"cell_type": "code",
"source": [
"def incrementa_contador(contador):\n",
" return contador + 1\n",
"\n",
"contador = incrementa_contador(contador)\n",
"print(contador)"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "HPMJw6EWRpyx",
"outputId": "0422ae3c-feb9-4160-87ab-4cb69f50c4da"
},
"execution_count": 35,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"2\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"Essa versão da função é mais previsível e menos propensa a erros, porque ela não tem efeitos colaterais."
],
"metadata": {
"id": "lIkBar98Rxoh"
}
},
{
"cell_type": "markdown",
"source": [
"---"
],
"metadata": {
"id": "dENQSBkhmoIb"
}
},
{
"cell_type": "markdown",
"source": [
"# Classes e Objetos em Python\n",
"\n",
"## Princípios S.O.L.I.D\n",
"\n",
"Os princípios S.O.L.I.D são um conjunto de orientações de design orientado a objetos que podem tornar o código mais compreensível, flexível e sustentável.\n",
"\n",
"- **S**ingle Responsibility Principle (SRP): Uma classe deve ter apenas um motivo para mudar. Deve ter apenas uma tarefa ou responsabilidade.\n",
"\n",
"- **O**pen/Closed Principle (OCP): As entidades de software (classes, módulos, funções, etc.) devem estar abertas para extensão, mas fechadas para modificação.\n",
"\n",
"- **L**iskov Substitution Principle (LSP): As subclasses devem ser substituíveis por suas classes base.\n",
"\n",
"- **I**nterface Segregation Principle (ISP): Os clientes não devem ser forçados a - **depender de interfaces que não usam.\n",
"\n",
"- **D**ependency Inversion Principle (DIP): Dependa de abstrações, não de concreções."
],
"metadata": {
"id": "Pl-_O1iWR4I_"
}
},
{
"cell_type": "code",
"source": [
"class Usuario:\n",
" def __init__(self, nome, email):\n",
" self.nome = nome\n",
" self.email = email\n",
"class NotificadorUsuario:\n",
" def enviar_email(self, usuario, mensagem):\n",
" print(f\"Enviando email para {usuario.email} com a mensagem {mensagem}\")"
],
"metadata": {
"id": "uCnWklUxR48c"
},
"execution_count": 36,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Herança e Composição\n",
"Herança e composição são dois conceitos fundamentais na programação orientada a objetos. A herança é um mecanismo que permite que uma classe herde características e comportamentos de outra classe. A composição é um mecanismo que permite que uma classe inclua outras classes como partes dela."
],
"metadata": {
"id": "KCsYbwX7T5bJ"
}
},
{
"cell_type": "code",
"source": [
"class Veiculo:\n",
" def __init__(self, nome):\n",
" self.nome = nome\n",
"\n",
"class Carro(Veiculo):\n",
" def buzinar(self):\n",
" print(f'{self.nome} está buzinando!')\n",
"\n",
"carro = Carro('Fusca')\n",
"carro.buzinar()"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "kNNLzgGLS-PU",
"outputId": "48343991-18dc-4c1c-e5f0-f7b5866963de"
},
"execution_count": 9,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Fusca está buzinando!\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"---"
],
"metadata": {
"id": "m-qSCNeVmvTv"
}
},
{
"cell_type": "markdown",
"source": [
"# Tratamento de Erros e Exceções em Python\n",
"\n",
"## Uso de Try/Except\n",
"\n",
"O Python usa blocos try/except para lidar com erros e exceções. Quando um erro é encontrado em um bloco try, o Python interrompe a execução desse bloco e passa para o primeiro bloco except correspondente.\n",
"\n"
],
"metadata": {
"id": "XgUtShOWUQCZ"
}
},
{
"cell_type": "code",
"source": [
"\n",
"\n",
"try:\n",
" resultado = 10 / 0\n",
"except ZeroDivisionError:\n",
" print(\"Erro: divisão por zero!\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "6GclG_yPUbxH",
"outputId": "397f282a-528c-4f25-9c52-aaeb56c2cbb0"
},
"execution_count": 10,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Erro: divisão por zero!\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"\n",
"## Use a Cláusula Finally\n",
"\n",
"A cláusula finally é um bloco opcional que pode ser adicionado no final de um bloco try/except. O bloco finally será sempre executado, independentemente de uma exceção ter sido levantada no bloco try.\n",
"\n",
"\n"
],
"metadata": {
"id": "vjgicfgkUkN2"
}
},
{
"cell_type": "code",
"source": [
"try:\n",
" resultado = 10 / 0\n",
"except ZeroDivisionError:\n",
" print(\"Erro: divisão por zero!\")\n",
"finally:\n",
" print(\"Esta mensagem será sempre impressa\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "pdBWvv04UjT5",
"outputId": "4b427469-dc98-40f6-8c6c-e62ad3fbf7a0"
},
"execution_count": 11,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Erro: divisão por zero!\n",
"Esta mensagem será sempre impressa\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"##Levantando Exceções\n",
"O Python permite que você lance suas próprias exceções usando a palavra-chave raise."
],
"metadata": {
"id": "xwm0VVlUU3KR"
}
},
{
"cell_type": "markdown",
"source": [],
"metadata": {
"id": "s3CfuFjPS_Dg"
}
},
{
"cell_type": "code",
"source": [
"def divide(a, b):\n",
" if b == 0:\n",
" raise ValueError(\"O divisor não pode ser zero\")\n",
" return a / b\n",
"\n",
"try:\n",
" divide(10, 0)\n",
"except ValueError as e:\n",
" print(e)"
],
"metadata": {
"id": "ixIGqAJ4VA5a"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"---"
],
"metadata": {
"id": "bT3Peh8umzZD"
}
},
{
"cell_type": "markdown",
"source": [
"Copy code\n",
"# Testando em Python\n",
"\n",
"## A importância dos testes\n",
"\n",
"Os testes são uma parte fundamental do desenvolvimento de software. Eles ajudam a garantir que o código esteja funcionando conforme o esperado e facilitam a detecção de bugs ou problemas.\n",
"\n",
"## Módulo Unittest\n",
"\n",
"O Python vem com um módulo embutido chamado unittest para escrever testes para o seu código.\n"
],
"metadata": {
"id": "2btt4_sDVKf3"
}
},
{
"cell_type": "code",
"source": [
"import unittest\n",
"\n",
"def soma(a, b):\n",
" return a + b\n",
"\n",
"class TestSoma(unittest.TestCase):\n",
" def test_soma_positivos(self):\n",
" self.assertEqual(soma(5, 10), 15)\n",
"\n",
" def test_soma_negativos(self):\n",
" self.assertEqual(soma(-5, -10), -15)\n",
"\n",
"if __name__ == \"__main__\":\n",
" unittest.main()"
],
"metadata": {
"id": "6D0lBtdcVNoH"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"##Usando Assertions\n",
"Asserções são declarações que verificam se uma determinada condição é verdadeira. Se a condição for falsa, o programa lança uma exceção."
],
"metadata": {
"id": "tnKceLrgWNMp"
}
},
{
"cell_type": "code",
"source": [
"def soma(a, b):\n",
" assert isinstance(a, (int, float)), \"O argumento 'a' deve ser um número\"\n",
" assert isinstance(b, (int, float)), \"O argumento 'b' deve ser um número\"\n",
" return a + b"
],
"metadata": {
"id": "MrC4pKbhV46U"
},
"execution_count": 19,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"Neste curso, exploramos os fundamentos do Clean Code em Python, abordando desde as melhores práticas para escrita de código limpo, como convenções de nomenclatura e documentação, até técnicas mais avançadas, como análise estática de código e testes unitários. Ao aplicar esses princípios, você não apenas melhorará a qualidade do seu código, mas também tornará o processo de desenvolvimento mais eficiente e menos propenso a erros. Lembre-se, escrever código limpo é uma habilidade essencial para qualquer desenvolvedor e prática constante é a chave para dominar essa arte.\n"
],
"metadata": {
"id": "VRtx7lXMoXJM"
}
},
{
"cell_type": "code",
"source": [],
"metadata": {
"id": "UmLzsLNboaGo"
},
"execution_count": null,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment