3. Clean CodeClean Code The Why Question ??? Raya Software
4. Clean code Introduction to Raya Guide There will be a code
Code Quality Measurement Bad Code The Boy Scout Rule Our Attitude
We are Authors Clean CodeRaya Software
5. Introduction to Raya Guide The need How to read Clean
CodeRaya Software
6. There will be a code Generated code, only? If so let the
customer generate the program for him self New languages &
technologies may get closer to requirements, but: We will never get
rid of code Clean CodeRaya Software
8. Bad Code Rush + Later = Mess (of Bad Code) Rush: it is a
market nature; we cant get rid of Later: enhancing it will enhance
the formula Challenge is: A working mess is better than nothing
Cant fully disagree, but look at team productivity if we insist on
saying so: Clean CodeRaya Software
9. Bad Code With Later team productivity will be: So keep in
mind LeBlancs law: Later Equals Never Clean CodeRaya Software
10. The Boy Scout Rule We may face Bad Code in: Projects
written by others Projects we wrote in a rush So there always be a
Bad Code The Solution is The Boy Scout Rule: Leave the campground
cleaner than you found it Which means: check in cleaner code than
you checked it out Imagine working in a project where code simply
got better Clean CodeRaya Software
11. Our Attitude Clean Code is a matter of attitude more than
being a matter of knowledge Managers passion? Delivery time
Customers passion? Requirement & Cost Our passion? ... [Mess =
Miss ] Delivery time [Mess = Miss ] Requirement [Mess = Miss ] Team
Productivity Clean CodeRaya Software Clean Code
12. We are Authors @author field of a Javadoc is pointing at us
The author is writing for .. Reader No way to write code without
read the ratio of time spent reading vs. writing is well over 10:1
Making it easy to read makes it easier to write Professionals
choose Paperback Model not the Academic Model Clean CodeRaya
Software
13. Meaningful NamesMeaningful Names The Who Question ??? Raya
Software
14. Meaningful Names Introduction Rule #1: Use
Intention-Revealing Names Rule #2: Avoid Disinformation Rule #3:
Make Meaningful Distinction Rule #4: Use Pronounceable Names Rule
#5: Use Searchable Names Rule #6: Avoid Encodings Rule #7: Avoid
Mental Mapping Rule #8: Dont be Cute Rule #9: Pick One Word per
Concept Rule #12: Dont Add Extra-free Context Conclusion Meaningful
NamesRaya Software
15. Introduction Names are everywhere We name our: Variables
Methods Arguments Classes Packages Source files Directories Jar
files WAR & EAR files Meaningful NamesRaya Software
16. Rule #1 Use Intention-Revealing Names Meaningful NamesRaya
Software int d; // elapsed time in days Very Bad int
elapsedTimeInDays; int daysSinceCreation; int
daysSinceModification; int fileAgeInDays; Good Motive: If a name
requires a comment, then the name does not reveal its intent.
17. Rule #2 Avoid Disinformation Meaningful NamesRaya Software
Variable name Motive accountList Dont use this name unless it is
already a List object XYZControllerForEfficientHandlingOfStrings
XYZControllerForEfficientStorageOfStrings how long will it take to
see the difference between them Karakter will never be found when
the programmer searches for character int a = l; if ( O == l ) a =
O1; else l = 01; uppercase O or just Zero ? lower case L or just
one ? - liar if you answer it without changing the code font
18. Rule #3 Make Meaningful Distinction Meaningful NamesRaya
Software public static void copyChars(char a1[] , char a2[]) { for
(int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } } Bad public
static void copyChars(char[] source , char[] destination) { for
(int i = 0; i < source.length; i++) { destination[i] =
source[i]; } } Good Motive: Number-series names are not only
disinformative but they are noninformative at all
19. Rule #4 Use Pronounceable Names Try to read the following
variable genymdhms Now we sounds like Idiots So seriously the
reason for this rule is not to being an idiot Meaningful NamesRaya
Software
20. Rule #5 Use Searchable Names Single-letter names can ONLY
be used as local variables inside short methods. The length of a
name should correspond to the size of its scope Meaningful
NamesRaya Software 7 e Very Bad DAYS_PER_WEEK week Good Motive:
Single-letter names and numeric constants are not easy to locate
across a body of text. There can be no worse reason for using the
name c than because a and b were already taken.
21. Rule #6 Avoid Encodings Member Variables Prefixing each
member variable with m_ Meaningful NamesRaya Software
22. Rule #6 Avoid Encodings Interfaces & Implementation
Meaningful NamesRaya Software Interface IShapeFactory {...} Class
ShapeFactory implements IShapeFactory {...} Very Bad Interface
ShapeFactory {...} Class ShapeFactoryImp implements ShapeFactory
{...} Good Motive: If I must encode either the interface or the
implementation, I choose the implementation. I dont want my users
knowing that Im handing them an interface. I just want them to know
that its a ShapeFactory.
23. Rule #7 Avoid Mental Mapping Like using r instead of url So
dont be Smart, but Be Professional When to Use Solution Domain
Names When it is more close to patterns of computer science
concepts When to Use Problem Domain Names When it is more close to
business Meaningful NamesRaya Software
24. Rule #8 Dont Be Cute Like using HolyHandGrenade() instead
of DeleteItems() Names based on cultural base or sense of humor
will only be remembered by people who know it Meaningful NamesRaya
Software
25. Rule #9 Pick One Word per Concept Like using fetch(),
retrieve(), and get() in the same layer How on earth should the
caller know which method to call ? !!! Meaningful NamesRaya
Software
26. Rule #12 Dont Add Extra-free Context In a Gas Station
Deluxe application, it is a bad idea to prefix every class with GSD
Meaningful NamesRaya Software
27. Conclusion Dont be afraid of renaming things People will be
grateful if you do so Let Refactoring Tools Help you Believe me, it
will pay off in the short run and continue to pay in the long run
Meaningful NamesRaya Software
28. Who is this? Clean CodeRaya Software
29. MethodsMethods The How Question ??? Raya Software
30. Methods Introduction Rule #1: Small Rule #2: Do One Thing
Rule #3: One Level of Abstraction per Method Rule #4: Avoid Switch
Statements Rule #5: Use Descriptive Names Rule #6: Minimize Method
Arguments Rule #7: Have No Side Effects Rule #9: Separate Command
from Query Some Structured Programming Concepts Dont Repeat
Yourself (DRY) MethodsRaya Software
31. Introduction Please, read this method and see how much
sense you can get of it in 3 minutes Now see the coming refactored
version of it MethodsRaya Software
32. Introduction Surprise, isnt it?, So how we can do it ?
MethodsRaya Software HtmlUtil.java (Refactored) public static
String renderPageWithSetupsAndTeardowns( PageData pageData, boolean
isSuite ) throws Exception { boolean isTestPage =
pageData.hasAttribute("Test"); if (isTestPage) { WikiPage testPage
= pageData.getWikiPage(); StringBuffer newPageContent = new
StringBuffer(); includeSetupPages(testPage, newPageContent,
isSuite); newPageContent.append(pageData.getContent());
includeTeardownPages(testPage, newPageContent, isSuite);
pageData.setContent(newPageContent.toString()); } return
pageData.getHtml(); }
33. Rule #1: Small First: methods should be small Second: they
should be smaller than that Im not kidding They should be a
Screen-Full Or should hardly ever be 20 lines long After applying
this on the refactored version, look on the re-refactored one:
MethodsRaya Software
34. Rule #1: Small Again, s-u-r-p-r-i-s-e MethodsRaya Software
HtmlUtil.java (re-Refactored) public static String
renderPageWithSetupsAndTeardowns( PageData pageData, boolean
isSuite) throws Exception { if (isTestPage(pageData))
includeSetupAndTeardownPages(pageData, isSuite); return
pageData.getHtml(); }
35. Rule #2: Do One Thing FUNCTIONS SHOULD DO ONE THING. THEY
SHOULD DO IT WELL. THEY SHOULD DO IT ONLY. Look at the refactored
version, its doing 3 things: Determining whether the page is a test
page. If so, including setups and teardowns. Rendering the page in
HTML. Which just violates our rule MethodsRaya Software
36. Rule #3: One Level of Abstraction per Method mixing levels
of abstraction within a method is always confusing Readers may not
be able to tell whether a particular expression is an essential
concept or a detail !!! MethodsRaya Software
37. Rule #4: Avoid Switch Statements First of all it violates
the Do One Thing rule As a work around: Bury the switch statement
in the basement of an ABSTRACT FACTORY (GOF pattern) Sometimes we
cant get rid of it, but we should try MethodsRaya Software
38. Rule #5: Use Descriptive Names As covered in the last
section Dont be afraid to make a name long. Dont be afraid to spend
time choosing a name. MethodsRaya Software
39. Rule #6: Minimize Method Arguments From the Guide
MethodsRaya Software
40. Rule #7: Have No Side Effects Try to spot any side effect
in the following MethodsRaya Software UserValidator.java 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; } }
41. Rule #7: Have No Side Effects Its name implies checking the
password But it also initializing the session !!!!!!!! Which may
cause data lose if someone call it without knowing this Solution:
if we cant divide it, then just tell the caller that you are doing
so and rename it: checkPasswordAndInitializeSession() MethodsRaya
Software
42. Rule #9: Separate Command from Query Methods should either
do something or answer something MethodsRaya Software if
(set("username", "unclebob"))... Bad if
(attributeExists("username")) { setAttribute("username",
"unclebob"); ... } Good Motive: Is it asking whether the username
attribute was previously set to unclebob? Or is it asking whether
the username attribute was successfully set to unclebob? Solution:
You can rename it setAndCheckIfExists, but that doesnt much help
the readability of the if statement. But the real solution is to
separate the command from the query so that the ambiguity cannot
occur.
43. Some Structured Programming Concepts Edsger Dijkstra said
that every function, and every block within a function, should have
one entry and one exit. Only one return statement in a method. No
break or continue statements in a loop. And never, ever, any goto
statements. MethodsRaya Software
44. Dont Repeat Yourself (DRY) Duplication may be the root of
all evil in software In our method the following was repeated 4
times through it: SetUp SuiteSetUp TearDown SuiteTearDown Now look
at the final version MethodsRaya Software
45. Error HandlingError Handling The Teeeet Question ??? Raya
Software
46. Error Handling Introduction Rule #1: Prefer exceptions to
Returning Error Codes Rule #11: Extract Try/Catch Blocks Rule #3:
Use Unchecked Exceptions Rule #4: Dont Eat the Exception Rule #5:
Resist Temptation to write a Single Catchall Rule #6: Always use
Catchall after handling known ones Rule #8: Dont Return NULL Rule
#9: Dont Pass Null Error HandlingRaya Software
47. Introduction It might seem odd to have a section about
Error Handling when talking about readability Some Programs are
dominated by Error Handling Error handling is important, but if it
covers the logic, then its wrong. Error HandlingRaya Software
48. Rule #1: Prefer exceptions to Returning Error Codes Error
HandlingRaya Software if (deletePage(page) == E_OK) { if
(registry.deleteReference(page.name) == E_OK) { if
(configKeys.deleteKey(page.name.makeKey()) == E_OK){
logger.log("page deleted"); } else { logger.log("configKey not
deleted"); } } else { logger.log("deleteReference from registry
failed"); } } else { logger.log("delete failed"); return E_ERROR; }
Bad try { deletePage(page); registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey()); } catch (Exception e) {
logger.log(e.getMessage()); } Good Motive: Error Codes awful nested
IFs But using Exceptions now, we can read the normal flow
49. Rule #11:Extract Try/Catch Blocks Error HandlingRaya
Software try { deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey()); } catch (Exception e) {
logger.log(e.getMessage()); } Not so good public void delete(Page
page) { try { deletePageAndAllReferences(page); } catch (Exception
e) { logError(e); } } private void deletePageAndAllReferences(Page
page) throws Exception {.} private void logError(Exception e) {.}
Good Motive: The delete is all about error processing
deletePageAndAllReferences is all about the processes of deleting a
page, which provides a nice separation that makes the code easier
to understand and modify.
50. Rule #3: Use Unchecked Exceptions The debate is over !!!!!!
Why not using Checked Exceptions Increasing error handling in many
parts of our system Breaking or better said destroying
Encapsulation When to use Checked Exceptions: If the caller knows
& wants how to handle it When dealing with Critical Systems or
libraries Error HandlingRaya Software
51. Rule #4: Dont Eat the Exception Error HandlingRaya Software
try { callBadMethod(); } catch (Exception ex) { } bad try {
callBadMethod(); } catch (Exception ex) { ex.printStackTrace(); }
Good Motive: At least use the printStackTrace method or you will
never know anything about it. Moreover to do is logging it.
52. Rule #5: Resist Temptation to write a Single Catchall
Exception handlers that trap many errors at once will probably
reduce the reliability of your program More probably the an
exception will be caught and the handler will not know about it.
Error HandlingRaya Software
53. Rule #6: Always use Catchall after handling known ones You
cant be sure that the exceptions you handled is the only ones So
append them by the default catchall to protect your system. Error
HandlingRaya Software
54. Rule #8: Dont Return NULL Look how NULL makes code awful:
Solution: Returning a special case object. Wrapping our method with
another that throws exception. The only method that returns NULL is
the one you didnt implement Error HandlingRaya Software
UserValidator.java public void registerItem(Item item) { if (item
!= null) { ItemRegistry registry =
peristentStore.getItemRegistry(); if (registry != null) { Item
existing = registry.getItem(item.getID()); if
(existing.getBillingPeriod().hasRetailOwner()) {
existing.register(item); } } } }
55. Rule #9: Dont Pass NULL If returning null from methods is
bad, then passing null into methods is far worse Passing NULL
should be handled inside the method or NullPointerException will be
thrown Unless the used API is passing NULL, you should avoid it
whenever possible Error HandlingRaya Software