Clean Code
Clean Code
Agenda
• Dirty Code
• Anti Patterns Treads
• Design Principles
• Design Patterns
• Clean Code
Dirty Code
• Dirty Code or rather Code smell is term used by Developers to define quality of code.
• Code smell is not a bug, but signs of design weakness, that slows down the development speed and eventually lead to bugs
• The general feel of some source code that it sucks or smells badly, because every attempt to make some changes result in lots of extra work
• More infohttps://en.wikipedia.org/wiki/Code_smell
Dirty Code Problems
• Its really difficult to understand what is written and why it is written.
Dirty Code Problems
• Really difficult to introduce a change
• Can never be sure if you will break previous code.
• The Screaming monkey problem
• Copy Paste problem
• Problem Accumulation
• Hopelessness
Screaming monkey problem
Story
• A ladder leading up to a bunch of bananas was placed in a cage of monkeys. When the monkeys climbed up, the cage was sprinkled with cold water. Nobody climbed up.
• A new monkey was let into the cage, and discovered the bananas. When he tried climbing up, he was beaten by the others.
• Another monkey was let into the cage and was beaten up by all, including the new monkey
Conclusions
• Don’t just repeat what other are telling you unless you understand why and agree. Perhaps the root cause doesn’t exist any longer.
Problem Accumulation
Story• Area was pristine clean for many days , one fine day a lazy guy threw
garbage at the place just one bag , next one week place was filled with garbage , reason other people saw garbage and instead of picking it up they threw their own.
Conclusions• Fix problems immediately• Continuous sanitization• Prevent the impression of hopelessness
• Hopelessness leads to less ambitious work, which leads to more bugs, which leads to irresponsibility, which creates more hopelessness
Anti Pattern Threads
• Well proven receipt for disaster, both coding and management
• How to recognize the problem
• How to recover
• Where to go (design pattern)
• How to move away from it (refactoring)
Anti Pattern Example : Blob
• One class monopolizes the processing and other classes primarily encapsulate data
• Procedural design hidden by object-oriented notations
• Typically too complex for reuse and testing
• Refactored solution: Distribute responsibilities to surrounding classes
Anti Pattern Example : Lava Flow
• Dead/unused code fragments that seems to be important, but no one can really explain what they do or why they exist
• Is generally the result of earlier prototyping, where developers tried out several ways to solve a problem and casting sound practices to the wind and sacrificing documentation
• Refactored solution: step-wise removal of code fragment under the control of unit testing
More examples
• There are lots of examples of anti pattern these can be found in wiki
• https://en.wikipedia.org/wiki/Anti-pattern
• A good resource for Anti pattern
https://sourcemaking.com/antipatterns
Moving on to Positive
Design Principle
“There are two ways of constructing a software design:
One way is to
make it so simple that there are obviously no deficiencies,
and the other way is to
make it so complicated that there are no obvious deficiencies.“
-C.A.R. Hoare
SOLID software design
• An acronym grouping five important software design principles
• More info• https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
Principle of single responsibility
• A component should be focused on one part of the system functionality• A component typically is a class, but can refer to other syntactic entities as
well
• That responsibility should be entirely encapsulated by the component• Responsibility defines as a reason to change
• More info• https://en.wikipedia.org/wiki/Single_responsibility_principle
Open-closed principle
• Classes should be open for extension but closed for modification
• Ideally, a new feature is added by extension instead of modifying code
Principle of separation of concerns
• The organization of a system into elements of non-repeating sets of cohesive responsibilities
• Each part fulfills a meaningful and intuitive role while maximizing its ability to adapt to change
• More info• https://en.wikipedia.org/wiki/Separation_of_concerns
Principle of least astonishment
• When reading code, you mutter for yourself that this was pretty much what you expected
• The principle aims to exploit users' pre-existing knowledge to minimize the learning curve
• More info• https://en.wikipedia.org/wiki/Principle_of_least_astonishment
DRY – Don’t Repeat Yourself
• Eliminate all information duplicates• This is the opposite of copy & paste programming, which in many cases is a
major source of bugs
• A modification of a single element should not affect unrelated elements and logically related elements should change in a predictable and uniformed way
Design Pattern
What is a design pattern?
• Reuse of well-proven OO design solutions• Patterns are discovered, not invented• Focus on reuse and problem solving
• The GOF book (1994) (https://en.wikipedia.org/wiki/Design_Patterns) was the main starting point• Design Patterns: Elements of Reusable Object-Oriented Software• Documented in a formal way Establish a terminology
• However, patterns are not:• Brand new ideas nor solutions• Solutions to every problem• An excuse for not thinking
Examples of design patterns
Creational Structural Behavioral
Abstract factory Adapter Chain of responsibility
Builder Bridge Command
Factory method Composite Interpreter
Prototype Decorator Iterator
Singleton Facade Mediator
Flyweight Memento
Proxy Observer
State
Strategy
Template method
Visitor
Clean Code
• Gradually making the existing code better and better
• Reducing the complexity and therefore increasing the quality
• High quality code has a high degree of maintainability
• High maintainability leads to• Lower cost of maintenance and
• Shorter time to market with new features
How to clean code?• Important to have or create an extensive unit test suite, to ensure no
system features are broken
• Apply refactoring's and run all the tests
• Stick to common software design principles• Don’t repeat yourself
• Fix broken windows
• Remove code smell
• Aim for design patterns and eliminate anti-patterns
Clean CodeComments & Formatting
The world’s most famous code comment
What is a comment?
• Doc comments• Good for overview navigation
• Code comments• Should be avoided
• Prefer meaningful names instead
• Legacy comments• Keep them short and link to the rest
Get rid of noise comments
General advise for code and comments
• Treat code comments as a last resort, when you’ve failed to refactor the code into small classes and methods with enlightening and meaningful names
• Remove dead code
Clean CodeMeaningful Names
Naming matters
Do not use various name encodings
• Ancient Hungarian Notation• phoneString, postCodeInt, balanceFloat, strName
• Strange prefixes• private int m_count = 42;
• class CCustomer {…}
• Non-pronounceable names• int gtTFkVa() {...}
Choose names that reveal business logic
• Use meaningful names• Should tell the reader it’s purpose
• Make names searchable• i.e. don’t prefix with system acronym
• Only use single letter names for loops• However, avoid mixing 1 and l, 0 and O
• Use wide letters such as k, n and m
• Be consistent• i.e. don’t change meaning of a partial name
Clean CodeFunctions
Functions should be small
• Not too many lines
• Should primarily do one thing
• Do not mix abstraction levels
• Should be possible to describe what it does within one sentence
Return early
• Avoid if-else structures, if one of the branches returns immediately
Avoid too many parameters
• Prefer functions with zero or one parameters
• Sometimes two parameters
• Seldom three parameters
• Never more than that
• Still having many parameters? -> Wrap them into an object
Avoid side-effects
• Do not write a function that is both a predicate and a setter• Separate into two functions
• Ensure the updating part is reflected in the method name
• Isolate a system updating operation into a dedicated function
Clean CodeClasses
Classes should be small
• Not too many methods• Methods should be small, therefore will the number of lines be acceptable
• Single responsibility• It should do one thing and do it well
• One reason for change
• Cohesive• Most variables should be used in most methods
• Easy to describe• A short sentence should be sufficient to describe what the class does
Cohesive class
• In a strongly cohesive class, all methods are referring all instance variables
• Subsets of strong cohesion, are candidates for extract class refactoring
Loosely coupled classes
• Lack of coupling means easier to understand and isolated from ripple effects during modifications
• Let classes depend on abstractions instead of concrete details• Represent class dependencies as dependency on interfaces
• Makes it easy to swap out one class for another class during testing or feature addition
Class organization
• Public constants
• Private variables
• Constructors
• Public/protected/private business methods
Clean CodeData Structures
Data Structures vs. Objects
• Data structures expose their data and have no meaningful functions
• Objects hide their data behind abstractions and expose functions that operate on that data
Procedural code vs. Object-Oriented code
• Procedural code (using data structures) makes it• Easy to add new functions without changing the existing data structures
• Hard to add new data structures because all functions must change
• OO code makes it• Easy to add new classes without changing existing functions
• Hard to add new functions because all the classes must change
• Hybrids• Do not create classes that are little of both
• Makes it hard to add new functions and new data structures
The Law of Demeter (principle of least knowledge)• A method m of class C should only call methods of these:
• class C
• An object held in a member variable of C
• An object passed as an argument to m
• An object created by method m
• Do not invoke methods on objects returned by any of the invoked functions• Don’t talk to strangers, talk to friends
• More info• https://en.wikipedia.org/wiki/Law_of_Demeter
Clean CodeError Handling
Never return an ERROR code
• If something goes wrong, throw an exception
• Do not return a special value, the caller has to check
Do not return null
• Do not return null from a method, use other tactics
• Check first• boolean hasXyz() / Xyz getXyz()
• Empty collection• List<Xyz> getXyzList() {... return new ArrayList<>() ...}
• Throw• Xyz getXyz() {... throw new NoSuchXyz(…) ...}
Do not accept null arguments
• Simpler program logic if you don’t have to deal with null all the time
• Treat an incoming null value as a fatal error, e.g. bug
Throw exceptions
• Create application exceptions as subclasses to System.Exception
• Catch an exception when it make sense to do something about it
Separate normal flow from error handling
• A function should have max one try-catch-finally
• If possible; extract the try block statements into a function
Clean CodeRefactoring
What is refactoring?
• Stepwise procedures to improve code, intended to be performed by tools
• The refactoring bible• Refactoring: Improving the Design of Existing Code
Refactoring techniques
• Extract method• Extracts a code segment into a method, passing used variables as arguments
• Extract variable/constant• Extracts parts of an expression into a variable or constant
• Extract class• Extract a group of data elements into a separate class• Typically has to be performed manually
• Extract base class/interface• Extract one or more methods into a base class
• Rename class/method• Change the name of variable, method or class• The tool ensures that all usages gets updated as well
Clean CodeUnit Testing
Test F.I.R.S.T.
• Fast• A test suite must run fast, else you will run it more seldom
• Independent• Test cases must not depend on each other (output of one is input of another)
• Repeatable• It should be possible to rerun the test suite any number of times, in any environment
• Self-validating• Test output should be limited to passed or failed• You should never have to check log files to find out if a test was successful
• Timely• Tests should be written before or during the time you write production code• Never write test after you have completed the production code
Check only one aspect
• Write a test function testing only a single aspect
• Refactor a long test function into smaller functions, each checking a single aspect
• Refactor common code parts into helper functions
• Extract groups of common helper functions into an abstract support class
Clean tests
• Your test code ensure your production code is healthy
• Hence, ensure your test code is healthy as well
• Never comment out failing test• Either there is bug that need to be fixed,
• Or a feature that has been removed
Given When Then
Organize a test function into three code groups
• Given• Define values used for the test case
• When• The target expression
• Then• Assertions of the result
Ways to achieve clean code
• General Coding Principles
• Refactoring
• Testing