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

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

by Maximiliano ContieriJanuary 10th, 2023
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

Code smells are just hints of something that might be wrong. Most of these smells are not required to be fixed per se. (You should look into it, though.) You can find all the previous code smells (Part i - XXVIII)[here.] (https://hackernoon.com/the-one-and-only-software-design-principle-1x983ylp)

People Mentioned

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

Code Smells Are a Classic.

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


Let's continue...


Code Smell 141 - IEngine, AVehicle, ImplCar

Have you ever seen an IEngine in the wild?


TL;DR: Don't prefix or suffix your classes

Problems

  • Readability
  • Bijection Fault
  • Implementative Names

Solutions

  1. Remove prefixes and suffixes
  2. Name your objects after what they do

Context

Some languages have cultural conventions related to data types, Abstract classes, or Interfaces. These names load our models with cognitive translations hard to follow.


We must KISS.

Sample Code

Wrong

public interface IEngine
{
    void Start();
}

public class ACar 
{

}

public class ImplCar 
{

}

public class CarImpl
{

}

Right

public interface Engine
{
    void Start();
}

public class Vehicle 
{

}

public class Car 
{

}

Detection

  • [x]Automatic

If we have a Thesaurus, we can point to awkward names.

Exceptions

In C#, it's a common practice to put "I" in the name of an interface because, without it, you can't tell whether it is an interface or a class.


This is a language smell.

Tags

  • Naming

Conclusion

Use real names for your models.

Relations

Code Smell 130 - AddressImpl

More Info

Credits

Photo by Tim Mossholder on Unsplash


Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.


Jamie Zawinski

Software Engineering Great Quotes


Code Smell 142 - Queries in Constructors

Accessing a database in domain objects is a code smell. Doing it in a constructor is a double smell.


TL;DR: Constructors should construct (and probably initialize) objects.

Problems

Solutions

  1. Decouple essential business logic from accidental persistence.
  2. On persistence classes, run queries in functions other than constructors/destructors.

Context

On legacy code, the database is not correctly separated from business objects.


Constructors should never have side effects.


According to the single responsibility principle, they should only build valid objects

Sample Code

Wrong

public class Person {
  int childrenCount; 

  public Person(int id) {
    childrenCount = database.sqlCall("SELECT COUNT(CHILDREN) FROM PERSON WHERE ID = " . id); 
  }
}

Right

public class Person {
  int childrenCount; 

  // Create a class constructor for the Main class
  public Person(int id, int childrenCount) {
    childrenCount = childrenCount; 
    // We can assign the number in the constructor
    // Accidental Database is decoupled
    // We can test the object
  }
}

Detection

  • [x]Semi-Automatic

Our linters can find SQL patterns on constructors and warn us.

Tags

  • Coupling

Conclusion

Separation of concerns is key, and coupling is our main enemy when designing robust software.

More Info

Credits

<span>Photo by Callum Hill on Unsplash</span>


My belief is still, if you get the data structures and their invariants right, most of the code will kind of write itself.


Peter Deustch

Software Engineering Great Quotes


Code Smell 143 - Data Clumps

Some objects are always together. Why don't we split them?


TL;DR: Make cohesive primitive objects travel together

Problems

  • Bad Cohesion
  • Duplicated Code
  • Validation Complexity
  • Readability
  • Maintainability

Solutions

  1. Extract Class
  2. Find small objects

Context

This smell is friends with primitive obsession.


If two or more primitive objects are glued together, with business logic repeated and rules between them, we need to find the existing concept of the bijection.

Sample Code

Wrong

public class DinnerTable
{
    public DinnerTable(Person guest, DateTime from, DateTime to)
    {
        Guest = guest; 
        From = from;
        To = to;
    }
    private Person Guest;
    private DateTime From; 
    private DateTime To;
}

Right

public class TimeInterval
{
    public TimeInterval(DateTime from, DateTime to)
    {
        // We should validate From < To
        From = from;
        To = to;
    }
}

public DinnerTable(Person guest, DateTime from, DateTime to)
{    
    Guest = guest;
    Interval = new TimeInterval(from, to);
}

// Even Better...

public DinnerTable(Person guest, Interval reservationTime)
{    
    Guest = guest;
    Interval = reservationTime;
}

Detection

  • [x]Semi-Automatic

Detection based on cohesion patterns is available o a few linters.

Tags

  • Cohesion

Conclusion

Group behavior in the right place and hide the primitive data.

Relations

Code Smell 122 - Primitive Obsession

Code Smell 01 - Anemic Models

Code Smell 27 - Associative Arrays

More Info

Credits

Photo by Dynamic Wang on Unsplash


The heart of the software is its ability to solve domain-related problems for its user. All other features, vital though they may be, support this basic purpose.


Eric Evans

Software Engineering Great Quotes


Code Smell 144 - Fungible Objects

We have heard a lot about NFTs. Now, we master the Fungible concept.


TL;DR: Respect the MAPPER. Make fungible what is Fungible in real-world and vice-versa.

Problems

Solutions

  1. Identify fungible elements on your domains
  2. Model them as interchangeable

Context

According to Wikipedia:


Fungibility is the property of a good or a commodity whose individual units are essentially interchangeable and each of whose parts is indistinguishable from another part.


In software, we can replace fungible objects with others.


When mapping our objects with real ones, we sometimes forget about the partial model and build over the design.


Sample Code

Wrong

public class Person implements Serializable {
    private final String firstName;
    private final String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

shoppingQueueSystem.queue(new Person('John', 'Doe'));

Right

public class Person  { 
} 

shoppingQueueSystem.queue(new Person());
// The identity is irrelevant for queue simulation 

Detection

  • [x]Manual

This is a semantic smell.


We need to understand the model to check whether it is right or not.

Tags

  • Over Design

Conclusion

Make fungible what is fungible and vice-versa.


Sounds easy but requires design skills and avoiding accidental complexity.

Credits

Photo by Andrey Metelev on Unsplash


People think that computer science is the art of geniuses but the actual reality is the opposite, just many people doing things that build on each other, like a wall of mini stones.


Donald Knuth


Code Smell 145 - Short Circuit Hack

Don't use boolean evaluation as a readability shortcut.


TL;DR: Don't use Boolean comparison for side effect functions.

Problems

  • Readability
  • Side Effects

Solutions

  1. Convert short circuits into IFs

Context

Smart programmers like to write hacky and obscure code even when there is no strong evidence for this improvement.


Premature optimization always hurts readability.

Sample Code

Wrong

userIsValid() && logUserIn();

// this expression is short circuit
// Does not value second statement
// Unless the first one is true

functionDefinedOrNot && functionDefinedOrNot();

// in some languages undefined works as a false
// If functionDefinedOrNot is not defined does
// not raise an error and neither runs

Right

if (userIsValid()) {
    logUserIn();
}

if(typeof functionDefinedOrNot == 'function') {  
    functionDefinedOrNot();
}
// Checking for a type is another code smell

Detection

  • [x]Semi-Automatic

We can check if the functions are impure and change the short circuit to an IF.


Some actual linters warn us of this problem

Tags

  • Premature Optimization

Conclusion

Don't try to look smart.


We are not in the 50s anymore.


Be a team developer.

Relations

Code Smell 140 - Short Circuit Evaluation

Code Smell 06 - Too Clever Programmer

Code Smell 149 - Optional Chaining

Credits

Photo by Michael Dziedzic on Unsplash


A computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are, in short, a perfect match.


Bill Bryson


Next article: 5 more code smells.