Seu código cheira mal porque provavelmente há muitos casos em que ele poderia ser editado ou melhorado.
A maioria desses cheiros são apenas indícios de algo que pode estar errado. Portanto, eles não precisam ser consertados por si só... (no entanto, você deve investigar isso).
Você pode encontrar todos os cheiros de código anteriores (Parte I - XLV) aqui .
Vamos continuar...
Outra nave espacial acidentada. Outro problema de software
DR: Projete e teste o software. É mais barato que o hardware
Luna-25 caiu na superfície da lua em 19 de agosto de 2023.
4 dias antes do Chandrayaan-3 da Índia pousar suavemente no pólo sul da Lua.
Uma análise forense revelou que as instruções compartilhavam um ônibus e não foram priorizadas corretamente.
As naves espaciais têm um longo histórico de falhas de software.
class TaskManager: def __init__(self): self.tasks = [] def add_task(self, task, priority): self.tasks.append((task, priority)) def execute_tasks(self): # No sorting for task, _ in self.tasks: task.execute() class Task: def __init__(self, name): self.name = name def execute(self): print(f"Executing task: {self.name}") task_manager = TaskManager() highPriorityTask = Task("Slow down") mediumPriorityTask = Task("Take Photos") reviveKlaatu = Task("Klaatu barada nikto") # unsorted task_manager.add_task(mediumPriorityTask, 2) task_manager.add_task(highPriorityTask, 1) task_manager.add_task(reviveKlaatu, 3) task_manager.execute_tasks()
class TaskManager: def __init__(self): self.tasks = [] def add_task(self, task, priority): self.tasks.append((task, priority)) def execute_tasks(self): # Sort tasks by priority (high to low) self.tasks.sort(key=lambda x: x[1], reverse=True) for task, _ in self.tasks: task.execute() class Task: def __init__(self, name): self.name = name def execute(self): print(f"Executing task: {self.name}") task_manager = TaskManager() highPriorityTask = Task("Slow down") mediumPriorityTask = Task("Take Photos") reviveKlaatu = Task("Klaatu barada nikto") # unsorted task_manager.add_task(mediumPriorityTask, 2) task_manager.add_task(highPriorityTask, 1) task_manager.add_task(reviveKlaatu, 3) task_manager.execute_tasks()
Este é um cheiro de design
Crie componentes de software e simule condições reais e não reais
Code Smell 198 - Suposições ocultas
Code Smells são minha opinião .
A Máquina Analítica não tem qualquer pretensão de originar nada. Pode fazer tudo o que sabemos como ordená-lo... Mas é provável que exerça uma influência indireta e recíproca na própria ciência.
Ada Lovelace
Ótimas citações de engenharia de software
Deixe os cowboys para os filmes de Hollywood.
TL;DR: Escreva código como um programador de equipe
Escreva código profissional.
Use nomes declarativos não enigmáticos.
Os codificadores Cowboy não seguem as melhores práticas.
Eles não seguem as sugestões da equipe.
A codificação Cowboy é geralmente considerada uma abordagem pouco profissional e arriscada para o desenvolvimento de software porque pode levar a um código difícil de manter e sujeito a erros.
Os programadores Cowboy são boas pessoas; no entanto, eles não podem trabalhar em grupo .
# Very simple example # Compute the sum of two numbers without any structure or best practices. num1 = input("Enter the first number: ") num2 = input("Enter the second number: ") # WARNNING!!!! Don't remove the line below !!!!! # (Unpleasant comment) res = num1 + num2 # (No data type checking or error handling) print("The sum is: " + result) # (No validation or formatting) # (No good names, no functions, no error handling, no testing, # no version control, and no structure.)
def add_numbers(): try: firstAddend = float(input("Enter the first number: ")) secondAddend = float(input("Enter the second number: ")) total = firstAddend + secondAddend return total except ValueError: print("Invalid input. Please enter valid numbers.") return None def main(): total = add_numbers() if total is not None: print("The sum is: {:.2f}".format(sum)) if __name__ == "__main__": main()
Você pode definir regras ambientais para evitar essas práticas de codificação e reforçar a formação de equipes.
Desenvolvimento de software é trabalho em equipe.
Code Smell 06 - Programador muito inteligente
Code Smell 02 - Constantes e Números Mágicos
Code Smell 105 - Métodos Comediantes
https://www.linkedin.com/pulse/software-development-cowboy-coding-hakan-atbaş/
Foto de Taylor Brandon no Unsplash
O perigo dos computadores não é que acabem por se tornar tão inteligentes como os homens, mas que, entretanto, concordemos em enfrentá-los a meio caminho.
Bernard Avishai
Mais de uma aula é uma bagunça.
DR: Siga o princípio da separação de preocupações e organização de arquivos
Declare uma única classe por arquivo
Usar escopo de nome
Em linguagens que declaram classes usando um sistema de arquivos, ter uma classe por arquivo geralmente é considerada uma prática recomendada.
Essa abordagem ajuda a melhorar a organização e a capacidade de manutenção do código e reduz possíveis problemas.
Você pode organizar namespaces em diretórios separados dentro da estrutura do seu projeto.
Dessa forma, você pode manter uma base de código lógica e eficiente, evitando problemas de declaração de múltiplas classes em um único arquivo.
<? namespace MyNamespace; class Class1 { public function sayHello() { echo "Hello from Class1!\n"; } } class Class2 { public function sayHello() { echo "Hello from Class2!\n"; } }
<? namespace MyNamespace; class Class1 { public function sayHello() { echo "Hello from Class1!\n"; } }
<? namespace MyNamespace; class Class2 { public function sayHello() { echo "Hello from Class2!\n"; } }
Muitos padrões impõem esta regra
Mantenha seu código organizado e siga os padrões conhecidos.
Code Smell 48 - Código sem padrões
Foto de Marjan Blan no Unsplash
Sem requisitos ou design, programar é a arte de adicionar bugs a um arquivo de texto vazio.
Louis Srygley
Você complica demais seu código.
TL; DR: Evite complexidade e burocracia acidentais
Um cheiro de código de "burocracia" pode estar relacionado a complexidade desnecessária, burocracia ou configuração excessiva que torna a base de código mais difícil de entender ou manter.
class VotingSystem: def __init__(self, config): self.config = config def validate_voter(self, voter_id): if self.config['voter_verification_enabled']: # Code to verify the voter's identity goes here def cast_vote(self, voter_id, candidate): if self.config['voting_enabled']: # Code to record the vote goes here def generate_vote_report(self): if self.config['generate_report']: # Code to generate a voting report goes here def audit_voting_system(self): if self.config['audit_enabled']: # Code to perform an audit of the voting system goes here # ... other voting-related methods ... # Usage config = { 'voter_verification_enabled': True, 'voting_enabled': False, 'generate_report': False, 'audit_enabled': True } voting_system = VotingSystem(config) # Voter validation, voting, report generation, # and auditing are handled based on the configuration.
class VoterVerification: def verify_voter(self, voter_id): # Code to verify the voter's identity goes here class VotingMachine: def cast_vote(self, voter_id, candidate): # Code to record the vote goes here class VoteReporter: def generate_report(self): # Code to generate a voting report goes here class VotingAuditor: def audit_voting_system(self): # Code to perform an audit of the voting system goes here # Usage voter_verification = VoterVerification() voting_machine = VotingMachine() vote_reporter = VoteReporter() voting_auditor = VotingAuditor() # Voter verification, vote casting, report generation, # and auditing are handled separately.
Algumas ferramentas podem adivinhar que você está sobrecarregando seus objetos com responsabilidades desnecessárias.
O cheiro de código burocrático é evidente, pois os desenvolvedores precisam navegar pela configuração complexa para determinar quais recursos estão ativos.
Isso não apenas adiciona complexidade desnecessária, mas também aumenta a probabilidade de configurações incorretas que podem afetar a integridade do seu sistema.
Código Cheiro 54 - Barcos Ancorados
Code Smells são minha opinião .
Uma falácia do software: se funcionar e não mudarmos nada, ele continuará funcionando.
Jéssica Kerr
Seu código está vivo e morto.
TL; DR: Observe atentamente as condições da corrida
Evite condições de corrida
Evite variáveis globais
Use a sincronização adequada
O código de Schrödinger é um código que pode estar em dois estados diferentes ao mesmo tempo, mas o estado do código não é determinado até que seja executado.
Isso pode acontecer quando o código contém uma condição de corrida ou quando o código depende do estado de uma variável global que pode ser alterada por outros threads ou processos.
import threading cats_alive = 0 def thread_1(): cats_alive += 1 def thread_2(): cats_alive -= 1 if cats_alive > 0: feedThem() # The value of cats_alive is indeterminate, # so the code can be in either of the two states: # # 1. cats_alive > 0 and feedThem() is called. # 2. cats_alive <= 0 and feedThem() is not called.
import threading lock = threading.Lock() cats_alive = 0 def thread_1(): with lock: cats_alive += 1 def thread_2(): with lock: cats_alive -= 1 if cats_alive > 0: feedThem() # With the lock, the two threads cannot access # the `cats_alive` variable at the same time. # This means that the value of `cats_alive` is always determined, # and the program will not exhibit Schrödinger code behavior.
Faça revisões de código em código simultâneo
Para evitar o código de Schrödinger, evite condições de corrida e evite depender do estado de variáveis globais que podem ser alteradas por outros threads ou processos.
Se você precisar usar uma variável global em seu código, certifique-se de que ela esteja sincronizada corretamente.
Code Smell 198 - Suposições ocultas
Código Cheiro 60 - Aulas Globais
Foto de Yerlin Matu no Unsplash
A última coisa que você gostaria que qualquer programador fizesse é mexer com o estado interno
Alan Kay
Na próxima semana, mais 5 cheiros.