paint-brush
How to Find the Stinky Parts of Your Code [Part XLVI] by@mcsee
635 reads
635 reads

How to Find the Stinky Parts of Your Code [Part XLVI]

by Maximiliano ContieriNovember 27th, 2023
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

Cowboy coders don't follow best practices. They don't follow team suggestions. Cowboy coding is generally considered an unprofessional and risky approach to software development because it can lead to code that is hard to maintain and prone to errors.

People Mentioned

Mention Thumbnail
featured image - How to Find the Stinky Parts of Your Code [Part XLVI]
Maximiliano Contieri HackerNoon profile picture
Your code smells because there are likely many instances where it could be edited or improved.


Most of these smells are just hints of something that might be wrong. Therefore, they are not required to be fixed per se… (You should look into it, though.)

Previous Code Smells

You can find all the previous code smells (Part I - XLV) here.


Let's continue...

Code Smell 226 - Mixed Priorities

Another crashed spacecraft. Another software problem


TL;DR: Design and test the software. It is cheaper than the hardware

Problems

Solutions

  1. Create accurate simulations
  2. Make software

Context

crashed on the moon's surface on August 19, 2023.


4 days before India’s soft landed on Moon's south pole.


A revealed that the instructions shared a bus and were not prioritized correctly.


Spacecrafts have a long history of software faults.

Sample Code

Wrong

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()

Right

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()

Detection

  • [x]Manual
This is a design smell

Tags

  • Reliability

Conclusion

Create software components and simulate real and not real conditions

Relations

Code Smell 198 - Hidden Assumptions

More Info

Disclaimer

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


Code Smell 227 - Cowboy Coding

Leave cowboys to Hollywood movies.


TL;DR: Write code as a team programmer

Problems

  • Readability
  • Unreliable code
  • People Management Issues
  • Lack of

Solutions

  1. Write professional code.


  2. Use declarative non-cryptic names.

Context

Cowboy coders don't follow best practices.


They don't follow team suggestions.


Cowboy coding is generally considered an unprofessional and risky approach to software development because it can lead to code that is hard to maintain and prone to errors.


Cowboy Programmers are good people; however, .

Sample Code

Wrong

# 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.)

Right

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()

Detection

  • [x]Manual


You can set environmental rules to prevent these coding practices and enforce team building.

Exceptions

  • Very small personal projects

Tags

  • Declarative

Conclusion

Software development is teamwork.

Relations

Code Smell 06 - Too Clever Programmer

Code Smell 02 - Constants and Magic Numbers

Code Smell 105 - Comedian Methods

More Info

Credits

Photo by on
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


Code Smell 228 - Multiple Classes per File

More than one class is a mess.


TL;DR: Follow the separation of concerns principle and file organization

Problems

  • Code Organization
  • Coupling
  • Autoloading problems
  • Debugging
  • Version control and merge conflicts

Solutions

  1. Declare a single class per file


  2. Use name scoping

Context

In languages that declare classes using a file system, having one class per file is generally considered a best practice.


This approach helps improve code organization and maintainability and reduces potential issues.


You can organize namespaces into separate directories within your project structure.


This way, you can maintain a logical and efficient codebase while avoiding the issues of declaring multiple classes in a single file.

Sample Code

Wrong

<?

namespace MyNamespace;

class Class1 {
    public function sayHello() {
        echo "Hello from Class1!\n";
    }
}

class Class2 {
    public function sayHello() {
        echo "Hello from Class2!\n";
    }
}

Right

<?

namespace MyNamespace;

class Class1 {
    public function sayHello() {
        echo "Hello from Class1!\n";
    }
}
<?

namespace MyNamespace;

class Class2 {
    public function sayHello() {
        echo "Hello from Class2!\n";
    }
}

Detection

  • [x]Automatic
Many standards enforce this rule

Tags

  • Coupling

Conclusion

Keep your code organized, and follow known standards.

Relations

Code Smell 48 - Code Without Standards

More Info

Credits

Photo by on
Without requirements or design, programming is the art of adding bugs to an empty text file.


Louis Srygley


Code Smell 229 - Red Tape

You overcomplicate your code.


TL;DR: Avoid Accidental complexity and bureaucracy

Problems

  • Accidental Complexity
  • Readability
  • Bijection Fault

Solutions

  1. Assign the responsibilities to real-world objects using the MAPPER.

Context

A "red tape" code smell could relate to unnecessary complexity, bureaucracy, or excessive configuration that makes the codebase harder to understand or maintain.

Sample Code

Wrong

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.

Right

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.

Detection

  • [x]Semi-Automatic
Some tools can guess you are bloating your objects with unnecessary responsibilities.

Tags

  • Bloaters

Conclusion

The red tape code smell is evident as developers need to navigate the complex configuration to determine which features are active.


This not only adds unnecessary complexity but also increases the likelihood of misconfigurations that could impact the integrity of your system.

Relations

Code Smell 54 - Anchor Boats

Disclaimer

Code Smells are my opinion.

Credits

Photo by on
A Fallacy of Software: If it works, and we don't change anything, it will keep working.

Jessica Kerr


Code Smell 230 - Schrödinger Code

Your code is dead and alive.


TL;DR: Look carefully for race conditions

Problems

  • Principle of Least Surprise Violation

Solutions

  1. Avoid race conditions


  2. Avoid global variables


  3. Use proper

Context

Schrödinger code is code that can be in two different states at the same time, but the state of the code is not determined until it is executed.


This can happen when the code contains a race condition, or when the code depends on the state of a global variable that can be changed by other threads or processes.

Sample Code

Wrong

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.

Right

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.

Detection

  • [x]Manual
Make code reviews on concurrent code

Tags

  • Concurrency
  • Globals

Conclusion

To avoid Schrödinger code, avoid race conditions and avoid depending on the state of global variables that can be changed by other threads or processes.


If you need to use a global variable in your code, ensure it is correctly synchronized.

Relations

Code Smell 198 - Hidden Assumptions

Code Smell 32 - Singletons

Code Smell 60 - Global Classes

Credits

Photo by on
The last thing you wanted any programmer to do is mess with internal state

Alan Kay


Next week, 5 more smells.
바카라사이트 바카라사이트 온라인바카라