Su código huele mal porque probablemente hay muchos casos en los que podría editarse o mejorarse.
La mayoría de estos olores son sólo indicios de que algo podría estar mal. Por lo tanto, no es necesario arreglarlos per se... (Aunque deberías investigarlo).
Puedes encontrar todos los olores del código anterior (Parte I - XLV) aquí .
Continuemos...
Otra nave espacial estrellada. Otro problema de software
TL;DR: Diseñar y probar el software. Es más barato que el hardware.
Luna-25 se estrelló en la superficie lunar el 19 de agosto de 2023.
4 días antes de que el Chandrayaan-3 de la India aterrizara suavemente en el polo sur de la Luna.
Un análisis forense reveló que las instrucciones compartían autobús y no estaban priorizadas correctamente.
Las naves espaciales tienen un largo historial de fallas 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 es un olor a diseño.
Cree componentes de software y simule condiciones reales y no reales.
Code Smell 198 - Suposiciones ocultas
Code Smells es mi opinión .
La Máquina Analítica no tiene pretensión alguna de originar nada. Puede hacer cualquier cosa que sepamos ordenarle que realice... Pero es probable que ejerza una influencia indirecta y recíproca sobre la ciencia misma.
Ada Lovelace
Grandes citas de ingeniería de software
Dejen a los vaqueros con las películas de Hollywood.
TL;DR: escribir código como programador de equipo
Escribe código profesional.
Utilice nombres declarativos no crípticos.
Los codificadores vaqueros no siguen las mejores prácticas.
No siguen las sugerencias del equipo.
La codificación cowboy generalmente se considera un enfoque poco profesional y arriesgado para el desarrollo de software porque puede generar un código difícil de mantener y propenso a errores.
Los programadores vaqueros son buenas personas; sin embargo, no pueden trabajar en 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()
Puede establecer reglas ambientales para evitar estas prácticas de codificación y hacer cumplir la formación de equipos.
El desarrollo de software es trabajo en equipo.
Code Smell 06 - Programador demasiado inteligente
Code Smell 02 - Constantes y números mágicos
Code Smell 105 - Métodos de comediante
https://www.linkedin.com/pulse/software-development-cowboy-coding-hakan-atbaş/
Foto de Taylor Brandon en Unsplash
El peligro de las computadoras no es que con el tiempo lleguen a ser tan inteligentes como los hombres, sino que, mientras tanto, aceptaremos llegar a un punto medio.
Bernard Avishai
Más de una clase es un desastre.
TL;DR: Siga el principio de separación de intereses y la organización de archivos
Declarar una sola clase por archivo
Usar alcance de nombre
En los lenguajes que declaran clases utilizando un sistema de archivos, tener una clase por archivo generalmente se considera una mejor práctica.
Este enfoque ayuda a mejorar la organización y el mantenimiento del código y reduce los problemas potenciales.
Puede organizar espacios de nombres en directorios separados dentro de la estructura de su proyecto.
De esta manera, puede mantener una base de código lógica y eficiente y, al mismo tiempo, evitar los problemas de declarar varias clases en un solo archivo.
<? 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"; } }
Muchas normas hacen cumplir esta regla.
Mantenga su código organizado y siga los estándares conocidos.
Código Olor 48 - Código Sin Estándares
Foto de Marjan Blan en Unsplash
Sin requisitos ni diseño, la programación es el arte de agregar errores a un archivo de texto vacío.
Luis Srygley
Complicas demasiado tu código.
TL;DR: Evite la complejidad y la burocracia accidentales
Un olor a código "burocrático" podría estar relacionado con una complejidad innecesaria, burocracia o una configuración excesiva que hace que el código base sea más difícil de entender o mantener.
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.
Algunas herramientas pueden adivinar que estás inflando tus objetos con responsabilidades innecesarias.
El olor a código burocrático es evidente ya que los desarrolladores necesitan navegar por la compleja configuración para determinar qué funciones están activas.
Esto no sólo añade complejidad innecesaria sino que también aumenta la probabilidad de que se produzcan errores de configuración que podrían afectar la integridad de su sistema.
Código Olor 54 - Barcos anclados
Code Smells es mi opinión .
Foto de la ampliación en Unsplash
Una falacia del software: si funciona y no cambiamos nada, seguirá funcionando.
Jessica Kerr
Tu código está vivo y muerto.
TL;DR: Mire atentamente las condiciones de carrera
Evite las condiciones de carrera
Evite las variables globales
Utilice una sincronización adecuada
El código Schrödinger es código que puede estar en dos estados diferentes al mismo tiempo, pero el estado del código no se determina hasta que se ejecuta.
Esto puede suceder cuando el código contiene una condición de carrera o cuando el código depende del estado de una variable global que otros subprocesos o procesos pueden cambiar.
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.
Realizar revisiones de código en código concurrente
Para evitar el código Schrödinger, evite las condiciones de carrera y evite depender del estado de las variables globales que pueden ser cambiadas por otros subprocesos o procesos.
Si necesita utilizar una variable global en su código, asegúrese de que esté sincronizada correctamente.
Code Smell 198 - Suposiciones ocultas
Code Smell 60 - Clases globales
Foto de Yerlin Matu en Unsplash
Lo último que quisiera que hiciera un programador es meterse con el estado interno
Alan Kay
La semana que viene, 5 olores más.