visit
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.)
You can find all the previous code smells (Part i - XXVii) here.
Being generic and foreseeing the future is good (again).
TL;DR: Don't over-generalize
class Boss(object):
def __init__(self, name):
self.name = name
class GoodBoss(Boss):
def __init__(self, name):
super().__init__(name)
# This is actually a very classification example
# Bosses should be immutable but can change their mood
# with constructive feedback
class Boss(object):
def __init__(self, name):
self.name = name
# Bosses are concrete and can change mood
A more elegant solution would be to declare an interface since it is less coupled.
Code Smell 11 - Subclassification for Code Reuse
Code Smell 43 - Concrete Classes Subclassified
Code Smell 92 - Isolated Subclasses Names
Code Smell 135 - Interfaces With just One Realization
Writing a class without its contract would be similar to producing an engineering component (electrical circuit, VLSI (Very Large Scale Integration) chip, bridge, engine...) without a spec. No professional engineer would even consider the idea.
Bertrand Meyer
Software Engineering Great Quotes
Yet another bad code reuse symptom
TL;DR: Favor composition over inheritance
classdef Animalia
end
classdef Chordata < Animalia
end
classdef Mammalia < Chordata
end
classdef Perissodactyla < Mammalia
end
classdef Equidae < Perissodactyla
end
classdef Equus < Equidae
//Equus behaviour
end
classdef EFerus < Equus
//EFerus behaviour
end
classdef EFCaballus < EFerus
//EFCaballus behaviour
end
classdef Horse
methods
// Horse behavior
end
end
Many linters report Depth of inheritance tree (DIT).
Code Smell 11 - Subclassification for Code Reuse
Code Smell 43 - Concrete Classes Subclassified
Code Smell 37 - Protected Attributes
Code Smell 125 - 'IS-A' Relationship
Coupling: The one and only problem
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
Bertrand Meyer
Software Engineering Great Quotes
There's an industry trend to avoid writing code as much as possible. But this is not for free
TL;DR: Write your code unless you need an existing complex solution
$ npm install --save is-odd
// //www.npmjs.com/package/is-odd
// This package has about 500k weekly downloads
// //github.com/i-voted-for-trump/is-odd/blob/master/index.js
module.exports = function isOdd(value) {
const n = Math.abs(value);
return (n % 2) === 1;
};
function isOdd(value) {
const n = Math.abs(value);
return (n % 2) === 1;
};
// Just solve it inline
Code Smell 94 - Too Many imports
Complexity kills. It sucks the life out of developers, it makes products difficult to plan, build and test, it introduces security challenges, and it causes end-user and administrator frustration.
Ray Ozzie
Software Engineering Great Quotes
Validations should be on the interface, or not?
TL;DR: Always create correct objects in your back-ends. UIs are accidental.
<script type="text/javascript">
function checkForm(form)
{
if(form.username.value == "") {
alert("Error: Username cannot be blank!");
form.username.focus();
return false;
}
re = /^\w+$/;
if(!re.test(form.username.value)) {
alert("Error: Username must contain only letters, numbers and underscores!");
form.username.focus();
return false;
}
if(form.pwd1.value != "" && form.pwd1.value == form.pwd2.value) {
if(form.pwd1.value.length < 8) {
alert("Error: Password must contain at least eight characters!");
form.pwd1.focus();
return false;
}
if(form.pwd1.value == form.username.value) {
alert("Error: Password must be different from Username!");
form.pwd1.focus();
return false;
}
re = /[0-9]/;
if(!re.test(form.pwd1.value)) {
alert("Error: password must contain at least one number (0-9)!");
form.pwd1.focus();
return false;
}
re = /[a-z]/;
if(!re.test(form.pwd1.value)) {
alert("Error: password must contain at least one lowercase letter (a-z)!");
form.pwd1.focus();
return false;
}
re = /[A-Z]/;
if(!re.test(form.pwd1.value)) {
alert("Error: password must contain at least one uppercase letter (A-Z)!");
form.pwd1.focus();
return false;
}
} else {
alert("Error: Please check that you've entered and confirmed your password!");
form.pwd1.focus();
return false;
}
alert("You entered a valid password: " + form.pwd1.value);
return true;
}
</script>
<form ... onsubmit="return checkForm(this);">
<p>Username: <input type="text" name="username"></p>
<p>Password: <input type="password" name="pwd1"></p>
<p>Confirm Password: <input type="password" name="pwd2"></p>
<p><input type="submit"></p>
</form>
<script type="text/javascript">
// send a post to a backend
// backend has domain rules
// backend has test coverage and richmodels
// it is more difficult to inject code in a backend
// Validations will evolve on our backend
// Business rules and validations are shared with every consumer
// UI / REST / Tests / Microservices ... etc. etc.
// No duplicated code
function checkForm(form)
{
const url = "//<hostname/login";
const data = {
};
const other_params = {
headers : { "content-type" : "application/json; charset=UTF-8" },
body : data,
method : "POST",
mode : "cors"
};
fetch(url, other_params)
.then(function(response) {
if (response.ok) {
return response.json();
} else {
throw new Error("Could not reach the API: " + response.statusText);
}
}).then(function(data) {
document.getElementById("message").innerHTML = data.encoded;
}).catch(function(error) {
document.getElementById("message").innerHTML = error.message;
});
return true;
}
</script>
Code Smell 97 - Error Messages Without Empathy
Code Smell 90 - Implementative Callback Events
I think another good principle is separating presentation or user interface (UI) from the real essence of what your app is about. By following that principle I have gotten lucky with changes time and time again. So I think that's a good principle to follow.
Martin Fowler
Software Engineering Great Quotes
We learn short circuits in our first programming courses. We need to remember why.
TL;DR: Be lazy when evaluating boolean conditions
<?
if (isOpen(file) & size(contents(file)) > 0)
// Full evaluation
// Will fail since we cannot retrieve contents
// from not open file
<?
if (isOpen(file) && size(contents(file)) > 0)
// Short circuit evaluation
// If file is not open it will not get the contents
Code Smell 101 - Comparison Against Booleans
Code Smell 69 - Big Bang (JavaScript Ridiculous Castings)
Writing a class without its contract would be similar to producing an engineering component (electrical circuit, VLSI (Very Large Scale Integration) chip, bridge, engine...) without a spec. No professional engineer would even consider the idea.
Bertrand Meyer
Software Engineering Great Quotes