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

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

by Maximiliano ContieriApril 20th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

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

People Mentioned

Mention Thumbnail
Mention Thumbnail

Company Mentioned

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

Infinite code, smells!

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. They are not required fixed per se… ( You should look into it though.)

Previous Code Smells

Let's continue...


Code Smell 81 - Result

result = ???



TL;DR: Use good names always. Result is always a very bad name.

Problems

  • Readability

Solutions

  1. Rename result.
  2. If you don't know how to name it, just name the variable with the same name as the last function call.
  3. Don't use IDEs without automatic refactors.

Sample Code

Wrong

var result;

result = lastBlockchainBlock();
//

// Many function calls

addBlockAfter(result);

Right

var lastBlockchainBlock;

lastBlockchainBlock = findlastBlockchainBlock();
//...

// Many function calls 
// we should refactor them to minimize space
// between variable definition and usage

addBlockAfter(lastBlockchainBlock);

Detection

We must forbid the word result to be a variable name.

Tags

  • Readability

Conclusion

Result is an example of generic and meaningless names.

Refactoring is cheap and safe.

Always leave the campground cleaner than you found it.

When you find a mess on the ground, clean it, doesn’t matter who did it. Your job is to always leave the ground cleaner for the next campers.

Relations

Code Smell 79 - TheResult

More info

Credits

Photo by KMA . on Unsplash


Code is like humor. When you have to explain it, it’s bad.

Cory House


Code Smell 82 - Tests Violating Encapsulation

Objects work fine and fulfill business objectives. But we need to test them. Let's break them.

TL;DR: Don't write methods with the only purpose of being used in your tests.

Problems

  • Encapsulation Violation.
  • Bad interfaces
  • Coupling

Solutions

  1. Don't break encapsulation.
  2. Test must be in full control.
  3. If you cannot control your object, you are coupled. Decouple them!

Sample Code

Wrong

<?

class Hangman {
    private $wordToGuess;

    function __construct() {
        $this->wordToGuess = getRandomWord();
        //Test is not in control of this
    }

    public function getWordToGuess(): string {
        return $this->wordToGuess;
        //Sadly we need to reveal this
    }
}

class HangmanTest extends TestCase {
    function test01WordIsGuessed() {
        $hangmanGame = new Hangman();
        $this->assertEquals('tests', $hangmanGame->wordToGuess());
        //how can we make sure the word is guessed?
    }
}

Right

<?

class Hangman {
    private $wordToGuess;

    function __construct(WordRandomizer $wordRandomizer) {
        $this->wordToGuess = $wordRandomizer->newRandomWord();
    }
}

class MockRandomizer implements WordRandomizer {
    function newRandomWord(): string {
        return 'tests';
    }
}

class HangmanTest extends TestCase {
    function test01WordIsGuessed() {
        $hangmanGame = new Hangman(new MockRandomizer());
        //We are in full control!
        $this->assertFalse($hangmanGame->wordWasGuessed());
        $hangmanGame->play('t');
        $this->assertFalse($hangmanGame->wordWasGuessed());
        $hangmanGame->play('e');
        $this->assertFalse($hangmanGame->wordWasGuessed());
        $hangmanGame->play('s');
        $this->assertTrue($hangmanGame->wordWasGuessed());
        //We just test behavior
    }
}

Detection

This is a design smell.

We can detect we need a method just for test.

Tags

  • Information Hiding

Conclusion

White-box tests are fragile. They test implementation instead of behavior.

Relations

Code Smell 52 - Fragile Tests

Code Smell 28 - Setters

More Info

Credits

This smell was inspired by @Rodrigo

Twitter



Nothing makes a system more flexible than a suite of tests.

Robert Martin


Code Smell 83 - Variables Reassignment

Variable reuse is something we see in big chunks of code.



TL;DR: Don't reuse variable names. You break readability and refactor chances and gain nothing but laziness.

Problems

  • Readability
  • Refactor chances
  • Missed Optimization
  • Mutability
  • Garbage Collection Missed Opportunities

Solutions

  1. Define, use and dispose variables.
  2. Keep your Definition, Usage and Destroy variables short.

Sample Code

Wrong

class Item:
  def __init__(self, name):
    self.name = name
  def taxesCharged(self):
    return 1;
class Money:
  pass 

lastPurchase = Item('Soda');
# Do something with the purchase

taxAmount = lastPurchase.taxesCharged();
# Lots of stuff related to the purchase
# I drink the soda

# I cannot extract method from below without passing
# useless lastPurchase as parameter

# a few hours later..
lastPurchase = Item('Whisky');
# I bough another drink

taxAmount += lastPurchase.taxesCharged();

Right

class Item:
  def __init__(self, name):
    self.name = name
  def taxesCharged(self):
    return 1;
class Money:
  pass 
  
def buySupper():
  supperPurchase = Item('Soda');
  # Do something with the purchase
 
  # Lots of stuff related to the purchase
  # I drink the soda
  return supperPurchase;

def buyDrinks():
  # I could extract method! 

  # a few hours later..
  drinksPurchase = Item('Whisky');
  # I bough another drink
  
  return drinksPurchase;

taxAmount = buySupper().taxesCharged() + buyDrinks().taxesCharged();

Detection

Many linters can warn us from reusing variables

Tags

  • Readability

Conclusion

Reusing variables is a non-contextual copy and paste hint.

Relations

Code Smell 03 - Functions Are Too Long

More Info

Credits

Photo by Robby McCullough on Unsplash

Twitter


Either way you look at it (DRY or laziness), the idea is the same: make your program flexible. When change comes (and it always does), you'll have a much easier time changing with it.

Chris Pine



Code Smell 84 - Max < Min (Javascript)

Some functions do not behave as expected. Sadly, most programmers accept them.




TL;DR: Don't trust max() and min() functions. Just ignore them.

Problems

  • Principle of least astonishment
  • Bijection Violation.
  • Unexpected Results

Solutions

  1. Use mature languages.
  2. Avoid max() and min() functions.
  3. Model Infinites carefully.

Sample Code

Wrong

console.log(Math.max() > Math.min());

//returns false

console.log(Math.max());

//returns -Infinite

Right

console.log(Math.max() > Math.min());
console.log(Math.max());

//returns Exception. Not enough arguments passed.
//Max requires at least one argument

Detection

These functions belong to the standard Math library. Therefore, they are not easy to avoid.

We can block them on our linters.

Tags

  • Javascript

Conclusion

We need to be very careful using functions that violate real-world concepts using language tricks.

Relations

Code Smell 69 - Big Bang (JavaScript Ridiculous Castings)

More Info

Credits

Photo by Cris Baron on Unsplash

Inspired by @@Oliver Jumpertz

Twitter


Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.

Rick Cook


Code Smell 85 - And Functions



Do not perform more than requested.

TL;DR: Unless you need atomicity, do not perform more than one task.

Problems

  • Coupling
  • Single Responsibility Principle violation
  • Readability
  • Low Cohesion
  • Testability

Solutions

  1. Break the function

Sample Code

Wrong

def fetch_and_display_personnel():
  data = # ...
  
  for person in data:
    print(person)

Right

def fetch_personnel():
  return # ...

def display_personnel(data):
  for person in data:
    print(person)

Detection

Functions including "and" are candidates. However, we need to check them carefully since there might be false positives.

Tags

  • Readability
  • Naming

Conclusion

We should avoid doing more than needed, and our functions should be both minimal and atomic.

More Info

Credits

Photo by Paul on Unsplash

This smell was inspired by

Twitter


If it takes more than a sentence to explain what you are doing, it’s almost always a sign that what you are doing is too complicated.

Sam Altman


And that’s all for now…

The next article will explain 5 more code smells!