How to Find the Stinky Parts of Your Code [Part XVIII]
source link: https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xviii
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
I’m senior software engineer specialized in declarative designs and S.O.L.I.D. and Agile lover.
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 86 - Mutable Const Arrays
Const declares something to be constant. Can it mutate?
TL;DR: Don't rely on languages cheating about directives.
Problems
Unexpected side effects
Accidental complexity
Solutions
Use better languages
Use spread operator
Sample Code
Wrong
const array = [1, 2];
array.push(3)
//array => [1, 2, 3]
//Wasn't it constant ?
//constant != immutable ?
Right
const array = [1, 2];
const newArray = [...array,3 ]
//array => [1, 2] Didn't mutate
//newArray = [1, 2, 3]
Detection
Since this is a "language feature", we can explicitly forbid it.
Mutability
JavaScript
Conclusion
We should always favour immutability on our designs and take extra care with side effects.
More Info
Credits
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
Code Smell 87 - Inconsistent Parameters Sorting
Be consistent with the parameters you use. Code is prose.
TL;DR: Don't confuse you readers. Keep the order.
Problems
Readability
Consistency
Solutions
Refactor and change parameters order.
Use named parameters
Sample Code
Wrong
function giveFirstDoseOfVaccine(person, vaccine) {
//
}
function giveSecondDoseOfVaccine(vaccine, person) {
//
}
giveFirstDoseOfVaccine(jane, pfizer);
giveSecondDoseOfVaccine(jane, pfizer); //Unnoticed mistake
Right
function giveFirstDoseOfVaccine(person, vaccine) {
//
}
function giveSecondDoseOfVaccine(person, vaccine) {
//
}
giveFirstDoseOfVaccine(jane, pfizer);
giveSecondDoseOfVaccine(jane, pfizer); //Jane is immunized
Detection
Some very smart linters may be able to compare arguments and hint for possible mistakes.
Readability
Conclusion
This is a very simple smell.
Readability is very important to avoid mistakes.
Relations
Code Smell 10 - Too Many Arguments
Credits
Photo by Lance Grandahl on Unsplash
Computers are good at following instructions, but not at reading your mind.
Donald Knuth
Code Smell 88 - Lazy Initialization
Yet another premature optimization pattern
TL;DR: Do not use lazy initialization. Use an object provider instead.
Problems
Surprising Side Effects
Premature Optimization
Fail Fast Violation
Implementative Coupling
The Least Surprise Principle Violation
Mutability
Transactional and Multi-threaded applications problems
Solutions
Inject Responsibilities with First Class Objects
Sample Code
Wrong
class Employee
def emails
@emails ||= []
end
def voice_mails
@voice_mails ||= []
end
end
Right
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
Detection
Lazy initialization is a common pattern when used checking for a non-initialized variable.
It should be straightforward to detect them.
Premature Optimization
Conclusion
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.
Relations
More Info
Credits
Photo by Sam Solomon on Unsplash
We have to stop optimizing for programmers and start optimizing for users.
Jeff Atwood
Code Smell 89 - Math Feature Envy
One class calculating formulas for another class.
TL;DR: Leave the formulas to the objects gathering the information.
Problems
Declaratively
Low reuse
Real-world concept missing
Encapsulation
Solutions
Move the math formula to the class
Search for real-world abstractions
Sample Code
Wrong
function area(rectangle) {
return rectange.width * rectangle.height;
//Notice we are sending consecutive messages to
//the same object and doing calculations
}
Right
class Rectangle {
constructor(width, height, color) {
this.height = height;
this.width = width;
}
area() {
return this.width * this.height;
}
}
Detection
Since many cascading messages are sending to the same object, we can detect a pattern.
Encapsulation
Coupling
Conclusion
This is a very basic smell. If we are manipulating another object characteristics, we should let it do it the maths for us.
Relations
More Info
Credits
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
Code Smell 90 - Implementative Callback Events
When creating events, we should decouple the trigger from the action.
TL;DR: Name your functions acording to what happened.
Problems
Observer Pattern violation
Coupling
Solutions
Name the events after "what happened", not "what you should do".
Sample Code
Wrong
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
Right
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
Detection
This is a semantic smell. We can detect it on peer code reviews.
Coupling
Naming
Conclusion
Names are very important. We should delay implementation coupled names until the very last moment.
More Info
Credits
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!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK