- Seiri, or organization : Knowing where things are—using approaches such as suitable naming—is crucial. You think naming identifiers isn’t important? well it’s IMPORTANT.
- Seiton, or tidiness : A place for everything, and everything in its place. A piece of code should be where you expect to find it—and, if not, you should re-factor to get it there.
- Seiso, or cleaning : Keep the workplace free of hanging wires, grease, scraps, and waste. what is the use of commented-out code lines that capture history or wishes for the future? Get rid of them.
- Seiketsu, or standardization: The group agrees about how to keep the workplace clean. they put standards ? Where do those standards come from? we will find that later on
- Shutsuke, or discipline (self-discipline) : This means having the discipline to follow the practices and to frequently reflect on one’s work and be willing to change.
I like my code to be elegant and efficient. The logic should be straightforward to make it hard for bugs to hide, the dependencies minimal to ease maintenance, error handling complete according to an articulated strategy, and per- formance close to optimal so as not to tempt people to make the code messy with unprinci- pled optimizations. Clean code does one thing well.
what if you were a doctor and had a patient who demanded that you stop all the silly hand-washing in preparation for surgery because it was taking too much time?2 Clearly the patient is the boss; and yet the doctor should absolutely refuse to comply. Why? Because the doctor knows more than the patient about the risks of dis- ease and infection. It would be unprofessional (never mind criminal) for the doctor to comply with the patient.
So too it is unprofessional for programmers to bend to the will of managers who don’t understand the risks of making messes.
use names that actually reveals your intention of using that variable
Say that we’re working in a mine sweeper game. We find that the board is a list of cells called theList
. Let’s rename that to gameBoard
.
Each cell on the board is represented by a simple array. We further find that the zeroth subscript is the location of a status value and that a status value of 4 means “flagged.” Just by giving these concepts names we can improve the code considerably:With these simple name changes, it’s not difficult to understand what’s going on. This is the power of choosing good names.
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard)
if (cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
Do not refer to a grouping of accounts as an accountList
unless it’s actually a List. The word list
means something specific to programmers. If the container holding the accounts is not actually a List
, it may lead to false conclusions. So accountGroup
or
bunchOfAccounts
or just plain accounts
would be better.NOTE : even if the container is a List
, it’s probably better not to encode the container type into the name.
It is not sufficient to add number series or noise words, even though the compiler is satisfied. If names must be different, then they should also mean something different.
Consider, for example, the truly hideous practice of creating a variable named klass
just because the name class
was used for something else OR user, user_1 , user_2
A significant part of our brains is dedicated to the concept of words. And words are, by definition, pronounceable. It would be a shame not to take advantage of that huge portion of our brains.
use names that are easy to search for in your code
avoid encoding types in your variable names something like : PhoneNumber phoneString; // name not changed when type changed!
Or name interfaces like IShapeFactory
in that case ShapeFactory
should be better
Readers shouldn't have to mentally translate your names into other names they already know.
- Avoid words like
Manager
,Processor
,Data
, orInfo
in the name of a class. - Methods should have verb or verb phrase names like
postPayment
,deletePage
, orsave
. - When constructors are overloaded, use static factory methods with names that describe the arguments.
Complex fulcrumPoint = Complex.FromRealNumber(23.0);
is better than
Complex fulcrumPoint = new Complex(23.0);
If names are too clever, they will be memorable only to people who share the author’s sense of humor.
- Avoid using function named
BigBang
to meanDeleteItems
Avoid having fetch
, retrieve
, and get
as equivalent methods of different classes as it’s confusing.
Likewise, it’s confusing to have a controller
and a manager
classes , what will be the difference ?
Avoid using the same word for two purposes. Using the same term for two different ideas is essentially a pun.
For example :
if we r using insert
function to insert records into our database and we have another class that has a function that puts value into a collection then using insert
as a function name will be a pun and in that case add
or append
will be better function name.
Remember that the people who read your code will be programmers. So go ahead and use computer science (CS) terms, algorithm names, pattern names, math terms, and so forth.
The name AccountVisitor
means a great deal to a programmer who is familiar with the VISITOR
pattern. What programmer would not know what a JobQueue
was? There are lots of very technical things that programmers have to do. Choosing technical names for those things is usually the most appropriate course.
The code that has more to do with problem domain concepts should have names drawn from the problem domain.
insertUser -> Problem Domain
pubbleSortUsers -> Soluation Domain
Imagine that you have variables named firstName
, lastName
, street
, houseNumber
, city
, state
, and zipcode
. Taken together it’s pretty clear that they form an address.
create a class named Address
. Then, even the compiler knows that the variables belong to a bigger concept.
In an imaginary application called “Gas Station Deluxe,” it is a bad idea to prefix every class or function with GSD
The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.
This implies that the blocks within if statements, else statements, while statements, and so on should be one line long. Probably that line should be a function call. Not only does this keep the enclosing function small, but it also adds documentary value because the function called within the block can have a nicely descriptive name.
FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT ONLY.
if a function is divided into sections such as declarations
, initializations
, and sieve
. This is an obvious symptom of doing more than one thing. Functions that do one thing cannot be reasonably divided into sections.
Mixing levels of abstraction within a function is always confusing. Readers may not be able to tell whether a particular expression is an essential concept or a detail. for example:
getHtml()
-> High level abstractionString pagePathName = PathParser.render(pagePath);
-> intermediate level abstraction.append("\n")
-> low level abstraction
We want the code to read like a top-down narrative. We want every function to be fol- lowed by those at the next level of abstraction so that we can read the program, descending one level of abstraction at a time as we read down the list of functions.
switch
statements always do N things. Unfortunately we can’t always avoid switch
statements, but we can make sure that each switch statement is buried in a low-level
class and is never repeated. We do this, of course, with polymorphism
.
- The smaller and more focused a function is, the easier it is to choose a descriptive name.
- Don’t be afraid to make a name long. A long descriptive name is better than a short enigmatic name.
- A long descriptive name is better than a long descriptive comment.
The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification—and then shouldn’t be used anyway.
Flag arguments|True,False|
are ugly. Passing a boolean into a function is a truly terrible practice. It immediately complicates the signature of the method, loudly proclaiming that this function does more than one thing. It does one thing if the flag is true and another if the flag is false!
A function with two arguments is harder to understand than a monadic function. For exammple, writeField(name)
is easier to understand than writeField(output-Stream, name)
.
There are times, of course, where two arguments are appropriate. For example, Point p = new Point(0,0);
is perfectly reasonabl.
Functions that take three arguments are significantly harder to understand than dyads. The issues of ordering, pausing, and ignoring are more than doubled. I suggest you think very carefully before creating a triad.
For example, consider the common overload of assertEquals
that takes three arguments: assertEquals(message, expected, actual)
. How many times have you read the message
and thought it was the expected
?
When a function seems to need more than two or three arguments, it is likely that some of those arguments ought to be wrapped into a class of their own. Consider, for example, the difference between the two following declarations:
Circle makeCircle(double x, double y, double radius);
Circle makeCircle(Point center, double radius);
Function that takes argument lists can be monads, dyads or even triads:
void monad(String... args);
void dyad(String name, String... args);
void triad(String name, int count, String... args)
Choosing good names for a function can go a long way toward explaining the intent of the function and the order and intent of the arguments. In the case of a monad, the function and argument should form a very nice verb/noun pair.
writeField(name)
is better than write(name)
Your function promises to do one thing, but it also does other hidden things. Sometimes it will make unexpected changes to the variables of its own class or even more.
Consider, for example, This function uses a standard algorithm to match a userName
to a password
. It returns true
if they match and false
if anything goes wrong. But it also has a side effect. Can you spot it?
public class UserValidator {
private Cryptographer cryptographer;
public boolean checkPassword(String userName, String password) {
User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
}
return false;
}
}
The side effect is the call to Session.initialize()
, of course. The checkPassword
function, by its name, says that it checks the password. If it is called out of order, session data may be inadvertently lost. Temporal couplings are con-fusing, especially when hidden as a side effect.
If you must have a temporal coupling, you should make it clear in the name of the function. In this case we might rename the function checkPasswordAndInitializeSession
, though that certainly violates “Do one thing.”
output arguments should be avoided. If your function must change the state of something, have it change the state of its owning object.
when you see this functions appendFooter(report);
you will be asking Does this function append report
as the footer to something? Or does it append some footer to report
? Is s an input or an output?
better approch is to add the append report.appendFooter();
as a functiuon to a report object to make it clear.
Functions should either do something or answer something, but not both as it will be confusing.
for example public boolean set(String attribute, String value);
This function sets the value of a named attribute and returns true
if it is successful and false
if no such attribute exists.
This leads to odd statements like this: if (set("username", "unclebob"))
so a better version will be :
if (attributeExists("username")) {
setAttribute("username", "unclebob");
....
}
public void delete(Page page) {
try {
deletePageAndAllReferences(page);
}catch (Exception e) {
logError(e);
}
}
private void deletePageAndAllReferences(Page page) throws Exception {
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
private void logError(Exception e) {
logger.log(e.getMessage());
}
In the above, the delete
function is all about error processing. It is easy to understand and then ignore. The deletePageAndAllReferences
function is all about the processes of fully deleting a page. Error handling can be ignored. This provides a nice separation that makes the code easier to understand and modify.
Functions should do one thing. Error handing is one thing. Thus, a function that handles errors should do nothing else.
Use Exceptions instead of Error codes.
Duplication may be the root of all evil in software. Many principles and practices have been created for the purpose of controlling or eliminating it.
every function, and every block within a function, should have one entry and one exit. Following these rules means that there should only be one return
statement in a function, no break
or continue
statements in a loop, and never, ever, any goto
statements.
So if you keep your functions small
, then the occasional multiple return
, break
, or continue statement does no harm and can sometimes even be more expressive than the single-entry, single-exit rule. On the other hand, goto only makes sense in large functions, so it should be avoided.