Part forty is here!!!
It 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 - XXXIX) here.
Let's continue...
Code Smell 196 - Javascript Array Constructors
Array creation is homogenous and predictable, or is it a hack?
TL;DR: Be very careful with Javascript Arrays.
Problems
- The Least surprise principle violation
Solutions
- Be as declarative as possible
- Avoid creating Arrays with one argument.
Context
Javascript has a lot of magic tricks.
Knowing them makes some developers proud and a sense of belonging to juniors.
A language should be intuitive, homogeneous, predictable, simple, and pure.
Sample Code
Wrong
const arrayWithFixedLength = new Array(3);
console.log(arrayWithFixedLength); // [ <5 empty items> ]
console.log(arrayWithFixedLength[0]); // Undefined
console.log(arrayWithFixedLength[1]); // Undefined
console.log(arrayWithFixedLength[3]); // Undefined
console.log(arrayWithFixedLength[4]); // Undefined
console.log(arrayWithFixedLength.length); // 3
Right
const arrayWithTwoElements = new Array(3, 1);
console.log(arrayWithTwoElements); // [ 3, 1 ]
console.log(arrayWithTwoElements[0]); // 3
console.log(arrayWithTwoElements[1]); // 1
console.log(arrayWithTwoElements[2]); // Undefined
console.log(arrayWithTwoElements[5]); // Undefined
console.log(arrayWithTwoElements.length); // 2
const arrayWithTwoElementsLiteral = [3,1];
console.log(arrayWithTwoElementsLiteral); // [ 3, 1 ]
console.log(arrayWithTwoElementsLiteral[0]); // 3
console.log(arrayWithTwoElementsLiteral[1]); // 1
console.log(arrayWithTwoElementsLiteral[2]); // Undefined
console.log(arrayWithTwoElementsLiteral[5]); // Undefined
console.log(arrayWithTwoElementsLiteral.length); // 2
Detection
- [x]Automatic
We can check for the notation with one argument and flag it as a warning.
Tags
- Smart
Conclusion
Many "modern" languages are full of hacks to make life easier for programmers but are a source of potential undiscovered bugs.
Relations
Code Smell 06 - Too Clever Programmer
Code Smell 69 - Big Bang (JavaScript Ridiculous Castings)
Code Smell 93 - Send me Anything
Disclaimer
Code Smells are just my opinion.
Credits
Photo by Ryan Quintal on Unsplash
Originally on this tweet:
When someone says, "I want a programming language in which I need only say what I want done," give him a lollipop.
Alan J. Perlis
Software Engineering Great Quotes
Code Smell 197 - Gratuitous Context
TL;DR: Don't prefix or suffix your names with irrelevant information
Problems
- Lack of Polymorphism
- Bad Naming
- Bijection violation with names
Solutions
- Remove this context from your names
Context
In software development, gratuitous context refers to the unnecessary inclusion of additional information or data in code or user interfaces that do not contribute to the functionality or usability of the software.
It can make the software more difficult to use, understand and maintain.
It also increases the risk of errors or defects.
Sample Code
Wrong
struct WEBBExoplanet {
name: String,
mass: f64,
radius: f64,
distance: f64,
orbital_period: f64,
}
struct WEBBGalaxy {
name: String,
classification: String,
distance: f64,
age: f64,
}
Right
struct Exoplanet {
name: String,
mass: f64,
radius: f64,
distance: f64,
orbital_period: f64,
}
struct Galaxy {
name: String,
classification: String,
distance: f64,
age: f64,
}
Detection
- [x]Semi-Automatic
We can find command patterns and rename all objects.
Tags
- Naming
Conclusion
Class Preffixing was a widespread practice decades ago to claim ownership.
Carefully consider the context and content of the software, and avoid including unnecessary or extraneous information wherever possible.
Now we know clean names are more important.
Relations
Code Smell 141 - IEngine , AVehicle, ImplCar
Code Smell 174 - Class Name in Attributes
More Info
What exactly is a name - Part II Rehab
Disclaimer
Code Smells are my opinion.
Credits
Photo by Mitchell Griest on Unsplash
The most dangerous kind of waste is the waste we do not recognize.
Shigeo Shingo
Code Smell 198 - Hidden Assumptions
Software is about contracts and ambiguous contracts are a nightmare
TL;DR: Keep your code explicit
Problems
Solutions
- Be declarative and explicit
- Don't oversimplify
Context
Hidden assumptions are underlying beliefs or expectations not explicitly stated in the code.
They are still present and can impact the behavior of the software.
Various reasons can give rise to assumptions such as incomplete requirements, incorrect presumptions about the user or environment, limitations of the programming language or tools, and bad accidental decisions.
Sample Code
Wrong
tenCentimeters = 10
tenInches = 10
tenCentimeters + tenInches
# 20
# this error is based on the hidden assumption of a unit (any)
# and caused the Mars Climate Orbiter failure
Right
class Unit:
def __init__(self, name, symbol):
self.name = name
self.symbol = symbol
class Measure:
def __init__(self, scalar, unit):
self.scalar = scalar
self.unit = unit
def __str__(self):
return f"{self.scalar} {self.unit.symbol}"
centimetersUnit = Unit("centimeters", "cm")
inchesUnit = Unit("inches", "in")
tencCentimeters = Measure(10, centimeters)
tenInches = Measure(10, inches)
tenCentimeters + tenInches
# error until we introduce a conversion factor
# in this case the conversion is constant
# inches = centimeters / 2.54
Detection
- [x]Manual
This is a design smell
Tags
- Coupling
Conclusion
Hidden assumptions can be difficult to identify and can lead to bugs, security vulnerabilities, and usability issues.
To mitigate these risks, software developers should be aware of their assumptions and biases.
Developers also need to engage with users to understand their needs and expectations.
They must test their software in various scenarios to uncover hidden assumptions and edge cases.
Relations
Code Smell 02 - Constants and Magic Numbers
More Info
Coupling - The one and only software design problem
Disclaimer
Code Smells are my opinion.
Credits
Photo by Christian Pfeifer on Unsplash
A human organization is just as much an information system as any computer system. It is almost certainly more complex, but the same fundamental ideas apply. Things that are fundamentally difficult, like concurrency and coupling, are difficult in the real world of people, too.
Dave Farley
Code Smell 199 - Gratuitous Booleans
A code that either returns or no returns at all
TL;DR: Check carefully your boolean expressions
Problems
- Readability
- Possible Defects
Solutions
- Refactor and remove obsolete code
Context
When a function is designed to return an invariant value, it may be poor design, but it shouldn’t adversely affect the outcome of your program. However, when it happens on all paths through the logic, it is likely a mistake.
This rule raises an issue when a function contains several return statements that all return the same value.
Sample Code
Wrong
# Gratuitous boolean expressions
if a > 0 and True:
print("a is positive")
else:
print("a is not positive")
Right
if a > 0:
print("a is positive")
else:
print("a is not positive")
Detection
- [x]Automatic
Many linters can detect this problem by parsing execution trees.
Tags
- Complexity
Conclusion
Boolean expressions should be straightforward to read and understand.
Relations
Code Smell 101 - Comparison Against Booleans
More Info
How to Get Rid of Annoying IFs Forever
Disclaimer
Code Smells are just my opinion.
Credits
Photo by Jungwoo Hong on Unsplash
The central enemy of reliability is complexity.
Daniel Geer
Code Smell 200 - Poltergeist
An object that appears and disappears mysteriously
TL;DR: Add the necessary indirection layers, but no more.
Problems
- Accidental complexity
- Readability
- YAGNI violation
Solutions
- Remove the intermediate object
Context
A poltergeist (or gypsy wagon) is a short-lived object used to perform initialization or to invoke methods in another, more permanent class.
An object is responsible for many small tasks, resulting in excessive coupling and a lack of cohesion in the code.
Sample Code
Wrong
public class Driver
{
private Car car;
public Driver(Car car)
{
this.car = car;
}
public void DriveCar()
{
car.driveCar();
}
}
Car porsche = new Car();
Driver homer = new Driver(porsche);
homer.DriveCar();
Right
Car porsche = new Car();
porsche.driveCar();
// We don't need the driver
Detection
- [x]Manual
This is a design smell.
Tags
- Complexity
Conclusion
Don't add accidental complexity to the essential complexity we already have.
Remove middleman objects if they are not needed.
Relations
More Info
Disclaimer
Code Smells are my opinion.
Credits
The art of programming is the art of organizing complexity, of mastering multitude and avoiding its bastard chaos as effectively as possible.
E. W. Dijkstra
5 more code smells are coming soon…