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

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

by Maximiliano ContieriJuly 2nd, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Javascript has a lot of magic tricks that make some developers proud and a sense of belonging to juniors. Be very careful with Javascript Arrays. Avoid creating Arrays with one argument. Be as declarative as possible with your code. Be aware of your code smells and try to avoid them.

People Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - How to Find the Stinky Parts of Your Code [Part XL]
Maximiliano Contieri HackerNoon profile picture


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 - XXXIXhere.


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

  1. Be as declarative as possible
  2. 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:

Twitter


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

  1. 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 130 - AddressImpl

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

  1. Be declarative and explicit
  2. 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

Mars Climate Orbiter Disaster

Coupling - The one and only software design problem

Measure Solution

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

  1. 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 115 - Return True

Code Smell 118 - Return False

Code Smell 101 - Comparison Against Booleans

More Info

How to Get Rid of Annoying IFs Forever

SonarSource

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

  1. 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

Code Smell 54 - Anchor Boats

Code Smell 67 - Middle Man

More Info

Wikipedia

Disclaimer

Code Smells are my opinion.

Credits

Photo by Lan Gao on Unsplash


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…