Reduce “surface area” of your code.
Allows changes later without affecting other code.
No magic values.
Generalize your code with variables.
You should almost never use a numeric literal other than 0 or 1 except to assign it to a variable.
Use static final
variables to make “symbolic constants”.
Define each magic numbers only once.
There should be an inverse relation between scope of variables and verbosity of name.
Loop variables are often one letter (e.g. i
, and j
).
And sometimes parameters of very short methods whose arguments are pretty abstract. (E.g. s
for a String
parameter that can be any String
.)
But otherwise use at least one-word, meaningful names.
It’s especially important that method and constructor parameters be meaningful because the first thing you look at when trying to understand a method is its signature.
List<String> lines = new ArrayList<String>();
lines = Files.readAllLines(getFilePath());
The ArrayList
created in the first line is immediately replaced with the List
returned by readAllLines
, becoming gargbage immediately.
List<String> lines = Files.readAllLines(getFilePath());
public String firstHalf(String s) {
String half = s.substring(0, s.length() / 2);
return half;
}
No need for a variable here.
public String firstHalf(String s) {
return s.substring(0, s.length() / 2);
}
Many of you really need to get on board with this.
Methods should be about five lines of code.
It’s fine to write a method that is only used in one place.
A method call to a method with a meaningful name carries much more information about intent than the codeof the method, which has to be decoded.
When you name a variable or method with a meaningful name you now have two statements about what it is: the name and it’s actual definition.
That enables you (or anyone else reading the code) to check that they match.
Is this code right?
int foo = (a - b) / 2;
How about this code?
int average = (a - b) / 2;
This is the main power move of object oriented programming.
So use it.
switch (object.kind()) {
case SQUARE -> drawSquare(object);
case TRIANGLE -> drawTriangle(object);
case CIRCLE -> drawCircle(object);
}
vs.
object.draw();
if (maybeFoo.getClass() == new Foo().getClass()) ...
if (maybeFoo.getClass() == Foo.class) ...
if (maybeFoo instanceof Foo) ...
vs
if (maybeFoo.isFoo()) ...
or even:
maybeFoo.doFooishThing();
Do not access the inner workings of other objects.
A.K.A. only one dot.
foo.entries.find(something)
foo.entries().find(something)
foo.findEntry(something)
It is okay to have multiple dots when each method is returning a value, not exposing the inner structure of an object.
Arrays.stream(ss)
.map(s -> s.substring(0, 1))
.filter(this::isVowel)
.count();
That’s fine.