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).
El código anterior huele
Puedes encontrar todos los olores del código anterior (Parte I - XLV) aquí .
Continuemos...
Código Olor 226 - Prioridades mixtas
Otra nave espacial estrellada. Otro problema de software
TL;DR: Diseñar y probar el software. Es más barato que el hardware.
Problemas
- Falla de biyección
- Defectos inesperados
Soluciones
- Crea simulaciones precisas
- Crear software tolerante a fallos
Contexto
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.
Código de muestra
Equivocado
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()
Bien
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()
Detección
- [x] Manual
Este es un olor a diseño.
Etiquetas
- Fiabilidad
Conclusión
Cree componentes de software y simule condiciones reales y no reales.
Relaciones
Code Smell 198 - Suposiciones ocultas
Más información
Descargo de responsabilidad
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
Código Olor 227 - Codificación de vaqueros
Dejen a los vaqueros con las películas de Hollywood.
TL;DR: escribir código como programador de equipo
Problemas
- Legibilidad
- Código no confiable
- Problemas de gestión de personas
- Falta de cordinacion
Soluciones
Escribe código profesional.
Utilice nombres declarativos no crípticos.
Contexto
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 .
Código de muestra
Equivocado
# 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.)
Bien
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()
Detección
- [x] Manual
Puede establecer reglas ambientales para evitar estas prácticas de codificación y hacer cumplir la formación de equipos.
Excepciones
- Proyectos personales muy pequeños.
Etiquetas
- Declarativo
Conclusión
El desarrollo de software es trabajo en equipo.
Relaciones
Code Smell 06 - Programador demasiado inteligente
Code Smell 02 - Constantes y números mágicos
Code Smell 105 - Métodos de comediante
Más información
https://www.linkedin.com/pulse/software-development-cowboy-coding-hakan-atbaş/
Créditos
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
Code Smell 228: varias clases por archivo
Más de una clase es un desastre.
TL;DR: Siga el principio de separación de intereses y la organización de archivos
Problemas
- Organización del código
- Acoplamiento
- Problemas de carga automática
- Depuración
- Control de versiones y conflictos de fusión
Soluciones
Declarar una sola clase por archivo
Usar alcance de nombre
Contexto
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.
Código de muestra
Equivocado
<? namespace MyNamespace; class Class1 { public function sayHello() { echo "Hello from Class1!\n"; } } class Class2 { public function sayHello() { echo "Hello from Class2!\n"; } }
Bien
<? namespace MyNamespace; class Class1 { public function sayHello() { echo "Hello from Class1!\n"; } }
<? namespace MyNamespace; class Class2 { public function sayHello() { echo "Hello from Class2!\n"; } }
Detección
- [x] Automático
Muchas normas hacen cumplir esta regla.
Etiquetas
- Acoplamiento
Conclusión
Mantenga su código organizado y siga los estándares conocidos.
Relaciones
Código Olor 48 - Código Sin Estándares
Más información
Créditos
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
Código Olor 229 - Burocracia
Complicas demasiado tu código.
TL;DR: Evite la complejidad y la burocracia accidentales
Problemas
- Complejidad accidental
- Legibilidad
- Falla de biyección
Soluciones
- Asigne responsabilidades a objetos del mundo real utilizando MAPPER .
Contexto
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.
Código de muestra
Equivocado
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.
Bien
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.
Detección
- [x] Semiautomático
Algunas herramientas pueden adivinar que estás inflando tus objetos con responsabilidades innecesarias.
Etiquetas
- hinchazones
Conclusión
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.
Relaciones
Código Olor 54 - Barcos anclados
Descargo de responsabilidad
Code Smells es mi opinión .
Créditos
Foto de la ampliación en Unsplash
Una falacia del software: si funciona y no cambiamos nada, seguirá funcionando.
Jessica Kerr
Código Olor 230 - Código Schrödinger
Tu código está vivo y muerto.
TL;DR: Mire atentamente las condiciones de carrera
Problemas
- Principio de violación de mínima sorpresa
- Condiciones de carrera
Soluciones
Evite las condiciones de carrera
Evite las variables globales
Utilice una sincronización adecuada
Contexto
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.
Código de muestra
Equivocado
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.
Bien
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.
Detección
- [x] Manual
Realizar revisiones de código en código concurrente
Etiquetas
- concurrencia
- Globales
Conclusión
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.
Relaciones
Code Smell 198 - Suposiciones ocultas
Code Smell 60 - Clases globales
Créditos
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.