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

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

by Maximiliano ContieriSeptember 11th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Your code smells because there are likely many instances where it could be edited or improved.

People Mentioned

Mention Thumbnail
featured image - How to Find the Stinky Parts of Your Code [Part XLIII]
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 - XLII) here.


Let's continue...


Code Smell 211 - Tab over Spaces


Tabs or spaces, are equivalent?


TL;DR: Don't use Tabs. It is not a "personal style decision"

Problems

Mixed Standards


Solutions

1. Use spaces. Always.

2. Use automatic tools to prevent tabs in the code.

Context

Developers might see using tabs or spaces for indentation as a matter of personal preference or team convention.


it is generally recommended towith the chosen method of indentation within a project.

There are a few advantages of using spaces over tabs.


Spaces will always look the same, no matter the text editor, font spacing, or IDE used.

Tabs can vary in width, which can lead to inconsistent indentation when code is viewed on different platforms or in different editors.


Spaces are more consistent in terms of alignment and readability, particularly when it comes to code that involves a mix of spaces and tabs.


Spaces are more predictable and easier to read, which can help to reduce errors in code.


Some screen readers and other assistive technologies may have difficulty reading code that uses tabs for indentation, particularly when tabs are used inconsistently or when tab width is not uniform.

Sample Code

Wrong


def calculate_average(numbers):

total = 0 

count = 0 

    for number in numbers: 

total += number 

        count += 1 

    average = total / count 

return average 

numbers = [1, 2, 3, 4, 5]

print("The average is:", calculate_average(numbers))


Right


def calculate_average(numbers):

total = 0 

count = 0 

for number in numbers: 

    total += number 

    count += 1 

average = total / count 

return average 
numbers = [1, 2, 3, 4, 5]
print("The average is:", calculate_average(num


Detection

[X] Automatic

We can enforce a policy to avoid tabs.


Tags

  • Standards

Conclusion

Bad indentation can make the code difficult to read and understand and can cause errors if the indentation is not consistent throughout the code.


Using spaces for indentation is generally recommended for consistency, readability, and accessibility.

Relations

Code Smell 164 - Mixed Indentations

Code Smell 48 - Code Without Standards

Credits

Photo by Faisal Waheed on Unsplash


It is hard to write even the smallest piece of code correctly.


Joshua Bloch


Code Smell 212 - Elvis Operator

Elvis Presley Mannequin


Your code is not safer using this operator

TL;DR: Don't propagate nulls.

Problems

  • NULL propagation
  • Harder to read code
  • Hacky code

Solutions

  1. Remove the nulls.
  2. If you can't remove it, deal explicitly with them.

Context

The Elvis operator is also known as the null-coalescing operator or the null-safe operator.


It is a shorthand operator used in some programming languages to simplify null-checking.


The Elvis operator takes the form of ?. and is used to access a property or method of an object only if that object is not null.


If the object is null, the operator returns null without attempting to access the property or method, thus avoiding a potential null reference exception.


The nickname "Elvis operator" originated from the visual resemblance of the operator to the famous singer Elvis Presley's hairstyle.


The symbol "?:", with its round shape on top and a curl underneath, vaguely resembles the pompadour hairstyle that Elvis Presley was known for.

Sample Code

Wrong

val shipTo = address?: "No address specified"

Right

val shipTo = if (address != null) address else "No address specified"

// This keeps the billion-dollar mistake error 

Detection

  • [x]Automatic

We can detect this operator usage and replace them with more strict checks.

Tags

  • Null

Conclusion

The code can be difficult to follow and may require additional comments or explanations to make it clear what is happening.


The operator hides potential errors or bugs in the code.


For example, if an object is null and the Elvis operator is used to return a default value, this may mask the fact that there is a problem with the code that is causing the object to be null in the first place.


In several languages, such as Common Lisp, Clojure, Lua, Object Pascal, Perl, Python, Ruby, and JavaScript, the OR operator (typically || or or) has the same behavior as the above: returning its first operand if it would evaluate to true in a boolean environment, and otherwise evaluating and returning its second operand.


When the left-hand side is true, the right-hand side is not even evaluated; it is "short-circuited." This is different from the behavior in other languages such as C/C++, where the result of || will always be a boolean.

Relations

Code Smell 149 - Optional Chaining

Code Smell 06 - Too Clever Programmer

Code Smell 12 - Null

Code Smell 140 - Short Circuit Evaluation

More Info

Wikipedia

Null: The Billion Dollar Mistake

Credits

Photo by Susan Mohr on Unsplash


You can't communicate complexity, only an awareness of it.


Alan Perlis


Code Smell 213 - Hoisting

Spinning top


You can prevent undefined

TL;DR: Declare your variables and look after the scope

Problems

  • Readability
  • Least Surprise Principle violation
  • Variable Shadowing

Solutions

  1. Be explicit on declarations
  2. Use 'const' declaration when possible.
  3. Declare variables at the beginning of the scope.
  4. Use strict mode

Context

Hoisting allows variable declarations to be moved to the top of their containing scope during the compilation phase.


Variables declared with var and function declarations are "hoisted" to the top of their respective scopes automatically in several languages.

Sample Code

Wrong

console.log(willBeDefinedLater); 
// Output: undefined (but no error)

var willBeDefinedLater = "Beatriz";
console.log(willBeDefinedLater); 
// Output: "Beatriz"

Right

const dante = "abandon hope all ye who enter here"; 
// Declaring a constant 'dante'
// with value "abandon hope all ye who enter here"

console.log(dante); 
// Output: "abandon hope all ye who enter here"

dante = "Divine Comedy"; // Error: Assignment to constant variable

Detection

  • [x]Semi-Automatic

We can perform mutation testing to check if changing the scope of the variables brings unexpected results.

Tags

  • Mutability

Conclusion

Hoisting is yet another magic tool some compilers provide to favor lazy programmers.

But if it fights back in debugging time.

Relations

Code Smell 116 - Variables Declared With 'var'

Code Smell 42 - Warnings/Strict Mode Off

More Info

Wikipedia

Strict Mode

Credits

Photo by Ash from Modern Afflatus on Unsplash


The best error message is the one that never shows up.


Thomas Fuchs


Code Smell 214 - Duplicate Parameter Names

A Woman Looking at Herself in the Mirror


Two arguments of the same type. Two equal names

TL;DR: Turn on Strict Checks

Problems

  • Unexpected errors
  • Ambiguity
  • The Least Surprise Principle violation
  • Portability

Solutions

  1. Enable strict mode
  2. Use role-naming arguments

Context

Most compilers forbid duplicate parameters since they are a common mistake in a large parameters list

Sample Code

Wrong

function addNumbers(a, b, a) {
  console.log(a + b);
}

addNumbers(2, 3, 4);

// Outputs 7 (2 + 3 + 2)

Right

"use strict";

function addNumbers(a, b, a) { }
//                          ^
// SyntaxError: Duplicate parameter name not allowed in this context

Detection

  • [x]Automatic

By enabling strict mode, the compiler will warn us

Tags

  • Naming

Conclusion

Enable the stricter modes you can find on your compilers.

Try to fail fast and catch errors as early as possible and leave the hard and dumb work to the tools.

Relations

Code Smell 188 - Redundant Parameter Names

Code Smell 65 - Variables Named after Types

More Info

Sonar Source

Mozilla Org

Fail Fast

Credits

Photo by Caroline Veronez on Unsplash


One of the things I've been trying to do is look for simpler or rules underpinning good or bad design. I think one of the most valuable rules is avoiding duplication. "Once and only once" is the Extreme Programming phrase.


Martin Fowler


Code Smell 215 - Deserializing Object Vulnerability

A Person typing on a laptop keyboard

Metaprogramming is always a problem

TL;DR: Don't allow remote code execution

Problems

  • Security

Solutions

  1. Validate and sanitize input
  2. Avoid executing code. Input only data
  3. Apply sandboxing or isolation

Context

Deserializing objects from an untrusted source is indeed a security-sensitive operation.


Suppose you have a web application that accepts serialized objects as input from user-submitted data, such as in an API endpoint or a file upload feature.


The application deserializes these objects to reconstruct them into usable objects within the system.


If an attacker submits maliciously crafted serialized data to exploit vulnerabilities in the deserialization process.


They might manipulate the serialized data to execute arbitrary code, escalate privileges, or perform unauthorized actions within the application or the underlying system.


This type of attack is commonly known as "deserialization attacks" or "serialization vulnerabilities."

Sample Code

Wrong

import pickle  # Python's serialization module

def process_serialized_data(serialized_data):
    try:
        obj = pickle.loads(serialized_data)  
        # Deserialize the object
        # Process the deserialized object
        # ...

# User-submitted serialized data
user_data = (
    b"\x80\x04\x95\x13\x00\x00\x00\x00\x00\x00\x00\x8c\x08os\n"
    b"system\n\x8c\x06uptime\n\x86\x94."
)
# This code executes os.system("uptime") 

process_serialized_data(user_data)

Right

import json

def process_serialized_data(serialized_data):
    try:
        obj = json.loads(serialized_data)  
        # Deserialize the JSON object
        # Does not execute code
        # ...

user_data = '{"key": "value"}'

process_serialized_data(user_data)

Detection

  • [x]Semi-Automatic

Several linters warn about deserialization points.

Tags

  • Security

Conclusion

Metaprogramming opens doors to abusers.

Relations

Code Smell 189 - Not Sanitized Input

More Info

Laziness I - Metaprogramming

Sonar Source

Credits

Photo by Towfiqu barbhuiya on Unsplash


Whenever possible, steal code.


Tom Duff



Next week, 5 more smells