Ваш код неприятен, потому что, вероятно, существует множество случаев, когда его можно было бы отредактировать или улучшить.
Большинство этих запахов — всего лишь намеки на что-то неладное. Следовательно, их не обязательно исправлять как таковые… (Хотя вам стоит над этим разобраться.)
Все предыдущие коды запахов (Часть I — XLV) вы можете найти здесь .
Давай продолжим...
Еще один разбившийся космический корабль. Еще одна программная проблема
TL;DR: Разработайте и протестируйте программное обеспечение. Это дешевле, чем аппаратное обеспечение
Луна-25 упала на поверхность Луны 19 августа 2023 года.
За 4 дня до того, как индийский корабль «Чандраян-3» совершил мягкую посадку на южном полюсе Луны.
Судебно-медицинский анализ показал, что инструкции использовали общую шину и не были правильно расставлены по приоритетам.
Космические корабли имеют долгую историю сбоев в программном обеспечении.
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()
Это дизайнерский запах
Создавайте программные компоненты и моделируйте реальные и нереальные условия.
Код запаха 198 — Скрытые предположения
Код Запахи — это мое мнение .
Аналитическая машина не претендует на создание чего-либо. Он может делать все, что мы знаем, как ему приказать… Но он, скорее всего, окажет косвенное и взаимное влияние на саму науку.
Ада Лавлейс
Великие цитаты о программной инженерии
Оставьте ковбоев голливудским фильмам.
TL;DR: Пишите код как командный программист
Пишите профессиональный код.
Используйте декларативные незашифрованные имена.
Программисты-ковбои не следуют лучшим практикам.
Они не следуют предложениям команды.
Ковбойское программирование обычно считается непрофессиональным и рискованным подходом к разработке программного обеспечения, поскольку оно может привести к созданию кода, который будет сложно поддерживать и который подвержен ошибкам.
Программисты-ковбои — хорошие люди; однако они не могут работать в группе .
# 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 — Слишком умный программист
Code Smell 02 — Константы и магические числа
Код запаха 105 — комические методы
https://www.linkedin.com/pulse/software-development-cowboy-coding-hakan-atbaş/
Фото Тейлора Брэндона на Unsplash
Опасность компьютеров заключается не в том, что они со временем станут такими же умными, как люди, а в том, что мы тем временем согласимся пойти им навстречу.
Бернар Авишай
Более одного класса — это беспорядок.
TL;DR: Следуйте принципу разделения ответственности и организации файлов.
Объявите один класс для каждого файла
Используйте область видимости имени
В языках, в которых классы объявляются с использованием файловой системы, обычно рекомендуется иметь по одному классу на файл.
Такой подход помогает улучшить организацию и удобство сопровождения кода, а также уменьшает потенциальные проблемы.
Вы можете организовать пространства имен в отдельные каталоги в структуре вашего проекта.
Таким образом, вы сможете поддерживать логичную и эффективную кодовую базу, избегая при этом проблем с объявлением нескольких классов в одном файле.
<? 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 – Кодекс без стандартов
Фото Марьяна Блана на Unsplash
Программирование без требований и дизайна — это искусство добавления ошибок в пустой текстовый файл.
Луи Срыгли
Вы слишком усложняете свой код.
TL;DR: Избегайте случайных сложностей и бюрократии
Запах кода «бюрократической волокитой» может быть связан с ненужной сложностью, бюрократией или чрезмерной конфигурацией, которая затрудняет понимание или поддержку кодовой базы.
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.
Некоторые инструменты могут догадаться, что вы перегружаете свои объекты ненужными обязанностями.
Запах бюрократического кода очевиден, поскольку разработчикам приходится ориентироваться в сложной конфигурации, чтобы определить, какие функции активны.
Это не только добавляет ненужную сложность, но и увеличивает вероятность неправильных конфигураций, которые могут повлиять на целостность вашей системы.
Код Запахи — это мое мнение .
Фотография с увеличенным изображением на Unsplash
Заблуждение программного обеспечения: если оно работает и мы ничего не меняем, оно продолжит работать.
Джессика Керр
Ваш код мертв и жив.
TL;DR: внимательно следите за условиями гонки.
Избегайте условий гонки
Избегайте глобальных переменных
Используйте правильную синхронизацию
Код Шредингера — это код, который может находиться в двух разных состояниях одновременно, но состояние кода не определяется до тех пор, пока он не будет выполнен.
Это может произойти, если код содержит состояние гонки или когда код зависит от состояния глобальной переменной, которая может быть изменена другими потоками или процессами.
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.
Делайте обзоры кода для параллельного кода
Чтобы избежать кода Шредингера, избегайте условий гонки и избегайте зависимости от состояния глобальных переменных, которые могут быть изменены другими потоками или процессами.
Если вам нужно использовать глобальную переменную в своем коде, убедитесь, что она правильно синхронизирована.
Код запаха 198 — Скрытые предположения
Код Smell 60 — глобальные классы
Фото Йерлина Мату на Unsplash
Последнее, чего вы хотели бы от программиста, — это портить внутреннее состояние.
Алан Кей
На следующей неделе еще 5 запахов.