visit
You can find all the previous code smells (Part I - XLV) here.
Another crashed spacecraft. Another software problem
TL;DR: Design and test the software. It is cheaper than the hardware
Spacecrafts have a long history of software faults.
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()
Code Smell 198 - Hidden Assumptions
Code Smells are my opinion.
The Analytical Engine has no pretensions whatever to originate anything. It can do whatever we know how to order it to perform… But it is likely to exert an indirect and reciprocal influence on science itself.
Ada Lovelace
Software Engineering Great Quotes
Leave cowboys to Hollywood movies.
TL;DR: Write code as a team programmer
# 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()
Code Smell 06 - Too Clever Programmer
Code Smell 02 - Constants and Magic Numbers
Code Smell 105 - Comedian Methods
The danger from computers is not that they will eventually get as smart as men, but that we will meanwhile agree to meet them halfway.
Bernard Avishai
More than one class is a mess.
TL;DR: Follow the separation of concerns principle and file organization
<?
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";
}
}
Code Smell 48 - Code Without Standards
Without requirements or design, programming is the art of adding bugs to an empty text file.
Louis Srygley
You overcomplicate your code.
TL;DR: Avoid Accidental complexity and bureaucracy
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.
Code Smells are my opinion.
A Fallacy of Software: If it works, and we don't change anything, it will keep working.
Jessica Kerr
Your code is dead and alive.
TL;DR: Look carefully for race conditions
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.
Code Smell 198 - Hidden Assumptions
Code Smell 60 - Global Classes
The last thing you wanted any programmer to do is mess with internal state
Alan Kay