Clean code Good practices for readability and maintainability

Clean code Good practices for readability and maintainability Rafael Sousa Herves 1

Contents 1. Clean code 2. Naming 3. Functions 4. Comments 5. Error handling 6. Classes 2

What is clean code? 3

What is clean code? “I like my code to be elegant and efficient. ” “The logic should be straightforward to make it hard for bugs to hide. ” “Clean code does one thing well. ” Bjarne Stroustrup, inventor of C++ 4

What is clean code? “Clean code is simple and direct. ” “Reads like well-written prose. ” Grady Booch, author of Object Oriented Analysis and Design with Applications 5

What is clean code? “Clean code can be read, and enhanced by other developers. ” “It has meaningful names. ” “It provides one way for doing one thing. ” “. . . minimal dependencies, … minimal API” Dave Thomas, founder of OTI, godfather of the Eclipse strategy 6

What is clean code? “Clean code always looks like it was written by someone who cares. ” Michael Feathers, author of Working Effectively with Legacy Code 7

What is clean code? “On clean code, each routine you read turns out to be pretty much what you expected. ” Ward Cunningham, inventor of Wiki, inventor of Fit, coinventor of e. Xtreme Programming. Motive force behind Design Patterns. Smalltalk and OO thought leader. 8

Concretely public void send. Message(Object o) { //. . . } public Chat. Message(String message, Object o) { //. . . } public Message(Object o) { //. . . } 9

How to measure code quality? 10

11

Why clean code? Software development life cycle 12

Consequences of bad code • The mess grows • Productivity lowers • Application cannot be maintained → game over 13

Naming 14

Naming - Meaningful names Bad int d; // elapsed time in days Good int elapsed. Time. In. Days; int days. Since. Creation; int days. Since. Modification; int file. Age. In. Days; 15
![Naming - Intention revealing names Bad public List<int[]> get. Them() { List<int[]> list 1 Naming - Intention revealing names Bad public List<int[]> get. Them() { List<int[]> list 1](http://slidetodoc.com/presentation_image_h/8f76f5b5db4f9f8b75148d8e3b20e8ca/image-16.jpg)
Naming - Intention revealing names Bad public List<int[]> get. Them() { List<int[]> list 1 = new Array. List<int[]>(); for (int[] x : the. List) if (x[0] == 4) list 1. add(x); return list 1; } 16

17

Naming - Intention revealing names Bad Good public final static int STATUS_VALUE = 0; public final static int FLAGGED = 4; public List<int[]> get. Them() { List<int[]> list 1 = new Array. List<int[]>(); for (int[] x : the. List) if (x[0] == 4) list 1. add(x); return list 1; } public List<int[]> get. Flagged. Cells() { List<int[]> flagged. Cells = new Array. List<int[]>(); for (int[] cell : game. Board) if (cell[STATUS_VALUE] == FLAGGED) flagged. Cells. add(cell); return flagged. Cells; } 18

Naming - Pronounceable names Bad Good class Dta. Rcrd 102 { private Date genymdhms; private Date modymdhms; private final String pszqint = "102"; }; class Customer { private Date generation. Timestamp; private Date modification. Timestamp; private final String record. Id = "102"; }; 19

Naming - Avoid encodings Bad Good private String m_dsc; private String description; Phone. Number phone. String; // name not changed when type changed! Phone. Number phone; 20

Naming - Add meaningful context first. Name, last. Name, street, city, state, zipcode // better addr. First. Name, addr. Last. Name, addr. State // best Address customer. Address = new Address(); customer. Address. get. State(); 21

Functions f(x) = 22

Functions 1. Small 2. Smaller than that No bigger than the screen 80’s: 24 lines, 80 columns Today: 100 lines, 150 columns Ideally: 2, 3, 4 lines (divide and rule!) 23

Functions 3. Do one thing Functions should do one thing. They should do it well. They should do it only. 24

Functions 4. One level of abstraction High get. Html(); Medium String page. Path. Name = Path. Parser. render(page. Path); Low . append("n"); 25

Functions 5. Descriptive names Spend time Easy with IDE’s No fear of long names favors refactor 26

Functions 7. Reduce number of arguments 0: ideal 1: ok 2: ok 3: justify 4 or more: avoid 27

Functions 7. Reduce number of arguments • wrapping objects Circle make. Circle(double x, double y, double radius) Circle make. Circle(Point center, double radius) • instance variables void append. Text(String. Builder builder, String to. Append) private String. Builder builder; void append. Text(String to. Append) 28

Comments “Don’t comment bad code—rewrite it. ” —Brian W. Kernighan and P. J. Plaugher 29

Comments • Can be helpful or damaging • Inaccurate comments are worse than no comments at all • Used to compensate failure expressing with code → refactor instead • They lie • Must have them, but minimize them 30

Comments Express yourself in code Bad // Check to see if the employee is eligible for full benefits if ((employee. flags & HOURLY_FLAG) && (employee. age > 65)) Good if (employee. is. Eligible. For. Full. Benefits()) 31

Comments Noise /** * Add a CD to the collection * * @param title The title of the CD * @param author The author of the CD * @param tracks The number of tracks on the CD * @param duration. In. Minutes The duration of the CD in minutes */ public void add. CD(String title, String author, int tracks, int duration. In. Minutes) { CD cd = new CD(); cd. title = title; cd. author = author; cd. tracks = tracks; cd. duration = duration; cd. List. add(cd); } 32

Comments Scary noise /** The name. */ private String name; /** The version. */ private String version; /** The day of the month. */ private int day. Of. Month; 33

Error handling 34

Error handling - Use Exceptions, not returning codes if (delete. Page(page) == E_OK) { if (registry. delete. Reference(page. name) == E_OK) { if (config. Keys. delete. Key(page. name. make. Key()) == E_OK){ logger. log("page deleted"); } else { logger. log("config. Key not deleted"); } } else { logger. log("delete. Reference from registry failed"); } } else { logger. log("delete failed"); return E_ERROR; } try { delete. Page(page); registry. delete. Reference(page. name); config. Keys. delete. Key(page. name. make. Key()); } catch (Exception e) { logger. log(e. get. Message()); } 35

Error handling - Extract Try/Catch blocks try { delete. Page(page); registry. delete. Reference(page. name); config. Keys. delete. Key(page. name. make. Key()); } catch (Exception e) { logger. log(e. get. Message()); } public void delete(Page page) { try { delete. Page. And. All. References(page); } catch (Exception e) { logger. log(e. get. Message()); } } private void delete. Page. And. All. References(Page page) throws Exception { delete. Page(page); registry. delete. Reference(page. name); config. Keys. delete. Key(page. name. make. Key()); } 36

Error handling - Don’t return Null • Error-prone • Forces to have null-checks everywhere public void register. Item(Item item) { if (item != null) { Item. Registry registry = peristent. Store. get. Item. Registry(); if (registry != null) { Item existing = registry. get. Item(item. get. ID()); if (existing != null && existing. get. Billing. Period() != null) { if (existing. get. Billing. Period(). has. Retail. Owner()) { existing. register(item); } } } 37

Error handling - Don’t return Null Alternatives: • Return empty collections public List<Employee> get. Employees() { // if(. . there are no employees. . ) return Collections. empty. List(); } • Return Optional public Optional<Player> get. Winner() { // if(. . there is no winner. . ) return Optional. empty(); } 38

Classes 39

Classes should be small • One responsibility • Denoted by the name Don’t use words such “Super”, “Manager”, “Processor”, etc. • Brief description of the class without using words “and”, “or”, “but”, … public class Super. Dashboard extends JFrame{ public Component get. Last. Focused. Component() public void set. Last. Focused(Component last. Focused) public int get. Major. Version. Number() public int get. Minor. Version. Number() public int get. Build. Number() } public class Super. Dashboard extends JFrame { public String get. Customizer. Language. Path() public void set. System. Config. Path(String system. Config. Path) public String get. System. Config. Document() public void reset. Dashboard() public boolean get. Guru. State() public boolean get. Novice. State() public boolean get. Open. Source. State() public void show. Object(Meta. Object object) public void show. Progress(String s) public boolean is. Metadata. Dirty() public void set. Is. Metadata. Dirty(boolean is. Metadata. Dirty) public Component get. Last. Focused. Component() public void set. Last. Focused(Component last. Focused) public void set. Mouse. Select. State(boolean is. Mouse. Selected) public boolean is. Mouse. Selected() public Language. Manager get. Language. Manager() public Project get. Project() public Project get. First. Project() public Project get. Last. Project() public String get. New. Project. Name() public void set. Component. Sizes(Dimension dim) public String get. Current. Dir() public void set. Current. Dir(String new. Dir) public void update. Status(int dot. Pos, int mark. Pos) public Class[] get. Data. Base. Classes() public Metadata. Feeder get. Metadata. Feeder() public void add. Project(Project project) public boolean set. Current. Project(Project project) public boolean remove. Project(Project project) // more and more. . . } 40

Classes - Single Responsibility Principle Responsibility = Reason to change • Classes should have only one reason to change public class Super. Dashboard extends JFrame{ public Component get. Last. Focused. Component() public void set. Last. Focused(Component last. Focused) public int get. Major. Version. Number() public int get. Minor. Version. Number() public int get. Build. Number() } public class Version { public int get. Major. Version. Number() public int get. Minor. Version. Number() public int get. Build. Number() } 41

Conclusion • Make code work and make code clean are two different activities. • The more a system grows, the more difficult to maintain. • Benefits on development, benefits in the future, including you. • We are professionals, we should do it well, we should do it clean. 42

Reference book Robert C. Martin, "Clean code: A Handbook of Agile Software Craftsmanship" 43

Questions? 44
- Slides: 44