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

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

by Maximiliano ContieriApril 7th, 2023
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

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 SmellsYou can find all the previous code smells (Part i - XXXIII) here.
featured image - How to Find the Stinky Parts of Your Code [Part XXXIV]
Maximiliano Contieri HackerNoon profile picture

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 - XXXIII) here.


Let's continue...


Code Smell 166 - Low-Level Errors on User Interface

Fatal error: Uncaught Error: Class 'logs_queries_web' not found in /var/www/html/query-line.php:78


Stack trace: #0 {main} thrown in /var/www/html/query-line.php on line 718


TL;DR: Catch your errors. Even the ones you don't expect.

Problems

  • Security


  • Error Handling


  • Error Logging


  • Bad UX Experience

Solutions

  1. Use a top-level handler.


  2. Avoid languages favoring return codes.


  3. Expect database and low-level errors.

Context

Even in 2022, we can see "serious" websites showing casual users a stack or debugging message.

Sample Code

Wrong


<?



Fatal error: Uncaught Error: Class 'MyClass' 

  not found in /nstest/src/Container.php:9

Right


<?



// A user-defined exception handler function

function myException($exception) {

    logError($exception->description())

    // We don't show Exception to final users      

}



// Set user-defined exception handler function

set_exception_handler("myException");

Detection

  • [x]Automatic

We can use mutation testing to simulate problems and see if they are handled correctly.

Tags

  • Security

Conclusion

We need to keep maturing.


Our solutions shouldn't be sloppy.



We need to improve our reputation as serious software engineers.

Relations

Code Smell 72 - Return Codes

More Info

Fail Fast

Disclaimer

Code Smells are just my opinion.

Credits

Photo by jesse orrico on Unsplash


80 percent of my problems are simple logic errors. 80 percent of the remaining problems are pointer errors. The remaining problems are hard.

Mark Donner

Software Engineering Great Quotes


Code Smell 167 - Hashing Comparison

Hashing guarantees two objects are different. Not that they are the same.


TL;DR: If you check for the hash, you should also check for equality

Problems

Solutions

  1. Check for hash (fast), and then check for Equality (slow)

Context

On Oct 7th, 2022, one of the larger blockchains had to be halted.


This news was shocking since most blockchains are decentralized by definition.


You can read a full article here:

How a Hacker Stole $566M USD Exploiting a Code Smell

Sample Code

Wrong


public class Person {
 

public String name;

// Public attributes are another smell  
 

 @Override

 public boolean equals(Person anotherPerson) {

   return name.equals(anotherPerson.name); 

 } 	

@Override

 public int hashCode() {

   return (int)(Math.random()*256); 

 }

 // This is just an example of non-correlation  

 // When using HashMaps we can make a mistake 

 // and guess the object is not present in the collection 

}

Right


public class Person {
 

public String name;

// Public attributes are another smell  
 

 @Override

 public boolean equals(Person anotherPerson) {

   return name.equals(anotherPerson.name); 

 }
 	

@Override

 public int hashCode() {

   return name.hashCode(); 

 }

 // This is just an example of non-correlation  
 
}

Detection

  • [x]Semi-Automatic

Many linters have rules for hash and equality redefinition.


With mutation testing, we can seed different objects with the same hash and check our tests.

  • Identity
  • Security

Conclusion

Every performance improvement has its drawbacks.


Caches and replications are notable examples.


We can (must) use them carefully.

Relations

Code Smell 49 - Caches

Code Smell 150 - Equal Comparison

More Info

Equality and Hash

Hashcode in Java

Hashcode vs Equal

Disclaimer

Code Smells are just my opinion.


This will surprise some of your readers, but my primary interest is not with computer security. I am primarily interested in writing software that works as intended.

Wietse Venema

Software Engineering Great Quotes


Code Smell 168 - Undocumented Decisions

We need to make some changes. We need to be clear on why

TL;DR: Be declarative on your design or implementation decisions.

Problems

  • Code Comments
  • Lack of testability

Solutions

  1. Be Explicit about the reasons.
  2. Convert the comment to a method.

Context

Sometimes we find arbitrary rules not so easily testable.


If we cannot write a failing test, we need to have a function with an excellent and declarative name instead of a comment.

Sample Code

Wrong


// We need to run this process with more memory

set_memory("512k)          

run_process();           

Right


increase_memory_to_avoid_false_positives();

run_process();      

Detection

  • [x]Semi-Automatic

This is a semantic smell.


We can detect comments and warn us.

Tags

  • Comments

Conclusion

Code is prose. And design decisions should be narrative.

Relations

Code Smell 05 - Comment Abusers

Code Smell 75 - Comments Inside a Method

Disclaimer

Code Smells are just my opinion.

Credits

Photo by Goh Rhy Yan on Unsplash


Programs, like people, get old. We can’t prevent aging, but we can understand its causes, limit its effects and reverse some of the damage.

Mario Fusco

Software Engineering Great Quotes


Code Smell 169 - Glued Methods

Don't make two or more things at once.

TL;DR: Try to be as atomic as possible in your methods

Problems

  • Coupled Code
  • Harder to test
  • Harder to read

Solutions

  1. Break the method

Refactorings

https://maximilianocontieri.com/refactoring-002-extract-method

Context

If you name a method with 'And', you are probably missing an extract-and-break method opportunity.

Sample Code

Wrong


calculatePrimeFactorsRemoveDuplicatesAndPrintThem()

// Three responsibilities

Right


calculatePrimeFactors();

removeDuplicates();

printNumbers();



// Three different methods

// We can test them and reuse them

Detection

  • [x]Semi-Automatic

Some linters can warn us about methods including the term 'and'.

Tags

  • Coupling

Conclusion

When making methods, it is very important to play some rubber duck story and tell ourselves if we are making things right.

Relations

%[https://maximilianocontieri.com/code-smell-85-and-functions]

Disclaimer

Code Smells are just my opinion.

Credits

Photo by Scott Sanker on Unsplash


Learning the art of programming, like most other disciplines, consists of first learning the rules and then learning when to break them.

Joshua Bloch


Code Smell 170 - Refactor With Functional Changes

Developing is great. refactoring is amazing. Don't make it at the same time

TL;DR: Don't change functionally and refactor at the same time.

Problems

  • Hard to review solutions
  • Merge Conflicts

Solutions

  1. Never change functionality while refactoring

Context

Sometimes we detect a refactoring is needed for further development.


We are experts at learning.


We should put our solution on hold. Work on the refactoring, and continue with our solution.

Sample Code

Wrong


getFactorial(n) {

  return n * getFactorial(n);

}



// Rename and Change



factorial(n) {

  return n * factorial(n-1);

}



// This is a very small example

// Things go works while dealing with huge code

Right


getFactorial(n) {

  return n * getFactorial(n);

}



// Change



getFactorial(n) {

  return n * getFactorial(n-1);

}



// Run the tests



factorial(n) {

  return n * factorial(n-1);

}



// Rename

Detection

This is a refactoring smell.

  • [x]Manual

Tags

  • Refactoring

Conclusion

We should use a physical token.


Either we are in the refactoring stage or the developing stage.

Disclaimer

Code Smells are just my opinion.

Credits

Photo by Dannie Jing on Unsplash


When I’m studying code, refactoring leads me to higher levels of understanding that I would otherwise miss. Those who dismiss comprehension refactoring as useless fiddling with the code don’t realize they never see the opportunities hidden behind the confusion.

Martin Fowler


5 more code smells are coming soon…