This document discusses principles and best practices for writing clean code. It defines clean code as code that works, is easy to read, understand and extend. It emphasizes writing code for other developers who will maintain it. Some key points include writing small, focused methods with meaningful names; avoiding duplicated code; using exceptions appropriately; formatting code consistently; and writing thorough automated tests. The overall goal is to communicate intent in the code as clearly as possible through these practices.
2. Software Develop
Software Maintenance
% of time spent reading code vs writing it
Intellectually Complex
Documentation?
If it’s not broken, don’t fix it
More difficult at each iteration
3. Clean Code Definition
Works
Easy to read
Easy to understand
Easy to extend
Efficient (straight to the point)
Clean (someone cared)
7. Write for others
Always code as if the guy who ends up maintaining
your code will be a violent psychopath who knows
where you live!
8. Boy Scout Rule
Always leave the campground cleaner than you found
it.
9. Care about
Even if it’s only to correct formatting
Avoid the “Broken Window Theory”
Broken Window Theory: https://blog.codinghorror.com/the-broken-window-theory
10. Don’t Reinvent the Whell
Before writing, ask if someone already did or if there is
any lib that do what is needed
Less is more!
13. Detecting Bad Code
Not used code
Duplicated code
Methods with lots of parameters
Long methods (20 lines or more)
Conditional Complexity
Speculative Generality
Comments (what instead of why)
For a thorough list, access: http://www.codinghorror.com/blog/2006/05/code-smells.html
15. General Concepts
Help the next one, because the next one can be you
Don’t create abstractions thinking about the future
Don't be afraid of changing things, in the worst case it was
already broken
Don't optimize prematurely
Prefer composition over inheritance
Avoid static methods/singletons
Delete code is more fun than create it
16. Use Meaningful Names
Use names that reveal intent
Give preference to client language
(Ubiquitous Language)
Don’t economize chars
Don’t be funny
Avoid prefixes (strMyVariable)
If it's not clear, rename it
Don't use characteristics of the variable
Date yyyyMMdd = ...
Color blue = Color.RED; //BAD CODE
17. Use Meaningful Names
public List<Cell> getCells() {
List<Cell> lst = new ArrayList<Cell>();
for (Cell c : data)
if (c.getStatus() == 4)
lst.add(c);
return lst;
}
18. Use Meaningful Names
public List<Cell> getMarkedCells() {
List<Cell> markedCells = new ArrayList<>();
for (Cell cell : gameBoard)
if (cell.isMarked()) {
markedCells.add(cell);
}
return markedCells;
}
19. Clean Methods
Should be small
Really, small than that
Should do only one thing (SRP)
Better if organized top to bottom
Avoid global variables, use parameters
Doesn’t has side effects
One input, one output
Doesn’t has duplicated code (DRY)
Lots of parameters? Change for a class
20. Clean Methods
public void printUserName(int userCode) {
Usuario user = getUser (userCode);
if (exists(user)) {
printOnConsole(user.getName());
}
}
private User getUser(int userCode) {
return dao.getUser(userCode);
}
private boolean exists(User user) {
return user != null;
}
private void printOnConsole(String message) {
system.out.println(message);
}
21. Clean Methods
public void printUserName(int userCode) {
Usuario user = getUser (userCode);
if (exists(user)) {
printOnConsole(user.getName());
}
}
private User getUser(int userCode) {
return dao.getUser(userCode);
}
private boolean exists(User user) {
return user != null;
}
private void printOnConsole(String message) {
system.out.println(message);
}
22. Clean Methods
public void printUserName(int userCode) {
Usuario user = getUser (userCode);
if (exists(user)) {
printOnConsole(user.getName());
}
}
private User getUser(int userCode) {
return dao.getUser(userCode);
}
private boolean exists(User user) {
return user != null;
}
private void printOnConsole(String message) {
system.out.println(message);
}
23. Clean Methods
public void printUserName(int userCode) {
Usuario user = getUser (userCode);
if (exists(user)) {
printOnConsole(user.getName());
}
}
private User getUser(int userCode) {
return dao.getUser(userCode);
}
private boolean exists(User user) {
return user != null;
}
private void printOnConsole(String message) {
system.out.println(message);
}
24. Clean Comments
Explain why, not what
Avoid redundancy
//Get a list of users
List users = getUsers();
//Get the users again so we can check what changed
List users = getUsers();
25. Clean Comments
If you need comments, probably you should create a
method instead
List clientIds = ...
//Get clientes from database
for (Client cli : clientIds) {
...
}
List clientIds = ...
getClientsFromDatabase(clientIds);
26. Clean Comments
// Verify if employee has all benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
if (employee.hasAllBenefits())
27. Clean Comments
while ((line = in.readLine()) != null) {
...
} //end while
// InputStream results = formatter.getResultStream();
// Reader reader = new StreamReader(results);
//TODO Validate received code
28. Clean Formatting
The goal isto make communication better
Follow the formatting pattern of the team/project
Declare variables as close as possible where they are
used
Always use curly braces
if (loggedIn) {
loginsCount++;
}
29. Clean Formatting
Use vertical grouping to separate code
List clients = ...
premiumClients = selectPremiumClients(clients);
saveFlagBillSent(premiumClients);
saveProcessLog(premiumClients, successMsg);
sendBillTo(premiumClients);
sendEmailBillAvailable(premiumClients);
30. Clean Exception Handling
You can log the exception or throw it, never both
Use log4j (or others), System.out is bad
Give preference to RuntimeException
32. Clean Exception Handling
Whenever possible, DON’T return null
List<Employee> employees = getEmployees();
for(Employee e : employees) {
totalPay += e.getPay();
}
}
public List<Employee> getEmployees() {
if( .. there are no employees .. ) {
return Collections.emptyList();
}
}
33. Clean Tests
Give the tests the same love as production code
Give preference to unit tests
Assert one concept per test
Assert one concept per test (important)
Always run all (unit) tests
Don’t use test class constructor, use @Before and
@BeforeClass
Avoid manual setup/verifications
The simpler the better