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.)
Let's continue...
Const declares something to be constant. Can it mutate?
TL;DR: Don't rely on languages cheating about directives.
const array = [1, 2];
array.push(3)
//array => [1, 2, 3]
//Wasn't it constant ?
//constant != immutable ?
const array = [1, 2];
const newArray = [...array,3 ]
//array => [1, 2] Didn't mutate
//newArray = [1, 2, 3]
Since this is a "language feature", we can explicitly forbid it.
We should always favour immutability on our designs and take extra care with side effects.
Correctness is clearly the prime quality. If a system does not do what it is supposed to do, then everything else about it matters little.
Bertrand Meyer
Be consistent with the parameters you use. Code is prose.
TL;DR: Don't confuse you readers. Keep the order.
function giveFirstDoseOfVaccine(person, vaccine) {
//
}
function giveSecondDoseOfVaccine(vaccine, person) {
//
}
giveFirstDoseOfVaccine(jane, pfizer);
giveSecondDoseOfVaccine(jane, pfizer); //Unnoticed mistake
function giveFirstDoseOfVaccine(person, vaccine) {
//
}
function giveSecondDoseOfVaccine(person, vaccine) {
//
}
giveFirstDoseOfVaccine(jane, pfizer);
giveSecondDoseOfVaccine(jane, pfizer); //Jane is immunized
This is a very simple smell.
Readability is very important to avoid mistakes.
Code Smell 10 - Too Many Arguments
Photo by Lance Grandahl on Unsplash
Computers are good at following instructions, but not at reading your mind.
Donald Knuth
Yet another premature optimization pattern
TL;DR: Do not use lazy initialization. Use an object provider instead.
class Employee
def emails
@emails ||= []
end
def voice_mails
@voice_mails ||= []
end
end
class Employee
attr_reader :emails, :voice_mails
def initialize
@emails = []
@voice_mails = []
end
end
#We can also inject a design pattern to externally deal
#with voice_mails so we can mock it in our tests
Lazy initialization is a common pattern when used checking for a non-initialized variable.
It should be straightforward to detect them.
Singletons are another antipattern often combined with lazy initialization.
We must avoid premature optimizations. If we have real performance problems we should use a Proxy, Facade or more independent solution.
Photo by Sam Solomon on Unsplash
We have to stop optimizing for programmers and start optimizing for users.
Jeff Atwood
One class calculating formulas for another class.
TL;DR: Leave the formulas to the objects gathering the information.
function area(rectangle) {
return rectange.width * rectangle.height;
//Notice we are sending consecutive messages to
//the same object and doing calculations
}
class Rectangle {
constructor(width, height, color) {
this.height = height;
this.width = width;
}
area() {
return this.width * this.height;
}
}
Since many cascading messages are sending to the same object, we can detect a pattern.
This is a very basic smell. If we are manipulating another object characteristics, we should let it do it the maths for us.
Photo by Michal Matlon on Unsplash
Computer science is not about machines, in the same way that astronomy is not about telescopes. There is an essential unity of mathematics and computer science.
Michael R. Fellows
When creating events, we should decouple the trigger from the action.
TL;DR: Name your functions acording to what happened.
const Item = ({name, handlePageChange)} =>
<li onClick={handlePageChange}>
{name}
</li>
//handlePageChange is coupled to what you decide to do
//instead of what really happened
//
//We cannot reuse this kind of callbacks
const Item = ({name, onItemSelected)} =>
<li onClick={onItemSelected}>
{name}
</li>
//onItemSelected will be called just when a item was selected. KISS
//Parent can decide what to do (or do nothing)
//We defer the decision
This is a semantic smell. We can detect it on peer code reviews.
Names are very important. We should delay implementation coupled names until the very last moment.
Photo by Ashim D’Silva on Unsplash
Thanks to Maciej for this tip
Beyond basic mathematical aptitude, the difference between good programmers and great programmers is verbal ability.
Marissa Mayer
And that’s all for now…
The next article will explain 5 more code smells!