visit
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.)
You can find all the previous code smells (Part I - XLIV) here.
Let's continue...
You abuse cases in switches and make subtle mistakes
TL;DR: Cases are GOTOs, but you might be missing them
Forgetting a break clause will continue with the following case.
This is similar to a very that implied an urgent release.
switch (number) {
case 1:
printf("Number is 1.\n");
break;
case 2:
printf("Number is 2.\n");
// Missing break
case 3:
// Case 2 will continue here
printf("Number is 3.\n");
break;
default:
printf("Number is not 1, 2, or 3.\n");
}
// If the number is 2 this will output numbers 2 and 3
switch (number) {
case 1:
printf("Number is 1.\n");
break;
case 2:
printf("Number is 2.\n");
break; // Added 'break' to prevent fall-through
case 3:
printf("Number is 3.\n");
break;
default:
printf("Number is not 1, 2, or 3.\n");
}
// This is correct even though switches AND defaults
// Are other code smells
Code Smell 110 - Switches With Defaults
Code Smell 36 - Switch/case/elseif/else/if statements
How to Get Rid of Annoying IFs Forever
Disclaimer: Code Smells are my opinion.
I am not terribly dogmatical about the goto statement. I have the uncomfortable feeling that others are making a religion out of it, as if the conceptual problems of programming could be solved by a single trick, by a simple form of coding discipline!
Don't abuse this fancy operator
TL;DR: Use comma operator just for loops
const gravitationalConstant = 6.67430e-11;
const massBlackHole1 = 1.5e31; // Mass of the first black hole in kg
const massBlackHole2 = 2.2e32; // Mass of the second black hole in kg
const distanceBlackHoles = 5.7e20; // Distance between black holes in meters
var force = (distanceSquared = distanceBlackHoles * distanceBlackHoles,
(gravitationalConstant * massBlackHole1 * massBlackHole2) /
distanceSquared);
// Two operations in a single statement with comma operator
function calculateGravitationalForce(mass1, mass2, distance) {
const gravitationalConstant = 6.67430e-11;
return (gravitationalConstant * mass1 * mass2) / (distance * distance);
}
const massBlackHole1 = 1.5e31; // Mass of the first black hole in kg
const massBlackHole2 = 2.2e32; // Mass of the second black hole in kg
const distanceBlackHoles = 5.7e20; // Distance between black holes in meters
const force = calculateGravitationalForce(
massBlackHole1,
massBlackHole2,
distanceBlackHoles
);
// Notice force is calculated with a separate function
This valid operator was designed to shorten for loops but is now sometimes abused.
Relations Code Smell 53 - Explicit Iteration
My computer's so fast it finishes an infinite loop in 5 minutes.
- Chisel Wright
Software evolves, and so does culture.
TL;DR: Avoid old terms like whitelists, blacklists, master, etc.
val whitelist = listOf("Barbie", "Ken")
val blacklist = listOf("Midge")
val gitCommand = "git pull origin master"
val process = Runtime.getRuntime().exec(gitCommand)
val allowlist = listOf("Barbie", "Ken")
val denylist = listOf("Midge")
val gitCommand = "git pull origin main"
val process = Runtime.getRuntime().exec(gitCommand)
Code Smell 105 - Comedian Methods
An ultimate joint challenge for the biological and the computational sciences is the understanding of the mechanisms of the human brain, and its relationship with the human mind.
- Tony Hoare
You use nice words to excuse bad code
TL;DR: Don't excuse bad code. Write a clean one!
# This is a function that adds two numbers
def s(a, b):
# Now you are going to add a and b
res = a + b
# And return the result
return res
def sum(adder, anotherAdder):
return adder + anotherAdder
def calculate_sum(number1, number2):
# Calculate the sum of two numbers
result = number1 + number2
return result
# In this improved version:
#
# The function name calculate_sum is more descriptive than sum,
# making it clear that this function calculates the sum of two numbers.
# (Wrong) it is more imperative and mistakes the 'what' with the 'how'
#
# The parameter names number1 and number2 are more meaningful
# than adder and anotherAdder, helping to indicate the purpose of each parameter.
# (wrong) They indicate type instead of role
#
# The comment # Calculate the sum of two numbers provides a clear
# and concise explanation of what the function does,
# making it easier for someone reading the code to understand its purpose.
# (wrong) in fact, it is an example of deodorant and useless comment
Code Smell 151 - Commented Code
Code Smell 183 - Obsolete Comments
Code Smell 146 - Getter Comments
Code Smell 05 - Comment Abusers
The reason we mention comments here is that comments often are used as a deodorant. It's surprising how often you look at thickly commented code and notice that the comments are there because the code is bad.
- Martin Fowler
Pass by copy, pass by reference. which is better?
TL;DR: Beware of passing arguments by reference
Some languages like Go use pass-by-value semantics. When you pass arguments to a function, copies are made. However, when you pass a pointer to an object, you can modify the original object within the function. This is another code smell. On the contrary, functional languages forbid this mechanism completely.
using System;
namespace Example
{
class Betelgeuse
{
static void Main(string[] args)
{
double starSize = 100.0;
Console.WriteLine("star size: {0}", starSize);
// star size: 100
double supernovaSize = SimulateFinalSize(ref starSize);
// Notice 'ref' modifier
Console.WriteLine("supernova size: {0}", supernovaSize);
// supernova size: 10000
Console.WriteLine("original star size after: {0}", starSize);
// original star size after: 10000
// WRONG: It should not be affected
}
public static double SimulateFinalSize(ref double size)
{
// Notice 'ref' modifier
// Oversimplification
// You should use Sedov-Taylor solution
size = size * 100;
return size;
}
}
}
using System;
namespace Example
{
class Betelgeuse
{
static void Main(string[] args)
{
const double starSize = 100.0;
// The const modifier warns the compiler
Console.WriteLine("star size: {0}", starSize);
// star size: 100
double supernovaSize = SimulateFinalSize(starSize);
// Notice 'ref' is omitted
Console.WriteLine("supernova size: {0}", supernovaSize);
// supernova size: 10000
Console.WriteLine("original star size after: {0}", starSize);
// original star size after: 100
// It remains at the original value
}
public static double SimulateFinalSize(double size)
{
// Notice 'ref' is omitted
// Oversimplification
// You should use Sedov-Taylor solution
size = size * 100;
return size;
}
}
}
Code Smell 116 - Variables Declared With 'var'
Code Smell 176 - Changes in Essence
Make it correct, make it clear, make it concise, make it fast. In that order.
Wes Dyer