5. • No universal definition
!
• Difference between clean code, working code and good code
• Clean code: readable, maintainable, extensible
• Working code: does what it is supposed to do
• Good code: combination of clean and working code
What is clean code?
Working
code
Clean
code
Good
code
6. Why is readability important?
• The process of changing code:
1.Find component
2.Find affected lines
3.Write
4.Test
!
• Reading —> 80/20
!
• Readability:
• Save your time
• Improve maintenance
• Increase extensibility
9. Code formatting
• Brain is good on recognising patterns
• Vertical space
• Horizontal space
• Expressions
• Casing
!
• Text search along project
!
• Follow language styles
!
• Be consistent
16. Code comments
• Code is not self-explanatory
• Code has side effects
//Careful! setting delegate reloads table content
self.tableView.delegate = self;
!
• Domain specific (complex math, business rules,…)
• Public APIs in libs
/**
Loads Purchase history and returns MOReceipts
@param block Block executed when the history is loaded. Contains parsed MOReceipts
@param errorBlock Block executed when an error occurs
*/
- (void)updateReceiptsOnSuccess:(MOResponseArrayBlock)block error:
(MOErrorBlock)errorBlock;
!
• In general, avoid comments
18. Control sentences
• Format
• Conditionals:
• Simple expressions —> variables
if (price - price * discountPercentage + discountAmount < minimumPrice) {
println("Difficult clause")
}
!
let amountToPay = price - price * discountPercentage + discountAmount
if (amountToPay < minimumPrice) {}
!
• Do not use more than 3 or 4 expressions
• Prefer positive clauses
var notForbidden = false
if !notForbidden {}
!
!
• Do not use assignments or side effects
if ((x = y * 2) != 0) {}
if (self = [super init]) {}
if (condition && [self destroyObject]) {}
19. Control sentences
• Avoid Spaghetti code (nested depth < 3)
if (condition1) {
if (condition2) {
for(i = 0; i < 10; i++) {
if (condition4) {
if (condition5) {
}
return;
}
}
}
}
!
!
• Collapse when possible
if (condition1) {
if (condition2) {
}
}
!
if (condition1 && condition2) {
}
!
• Do not use goto, break, continue
20. Control sentences
• “if”statements
• Avoid empty cases
• Avoid obvious“else if”clauses
if flag {
}
else if !flag {
println("Difficult to read")
}
• “for”loops
• Do not abuse
for (;condition;) { /*...*/ }
• Do not modify the conditional variable inside
for (i = 0; i < 10; i++) {
i *= 2;
}
!
• Ternary operators
• Only use for assignments
condition? [self method1] : [self method2];
name = user.name? : @"Anonymous";
!
• Must be extremely simple
22. Functions and methods
• Clear naming
summation(4)
!
• 1 Level of abstraction
let dates = downloadAndParse(“http://myrurl.com”)
!
• Single Responsibility Principle (SRP)
“Every context should have a single responsibility, and that responsibility should be entirely encapsulated by the context”
- Wikipedia
!
• No side effects
!
• Explicit error handling
- (BOOL)writeToURL:(NSURL *)aURL
options:(NSDataWritingOptions)mask
error:(NSError **)errorPtr;
23. Functions and methods
• Parameters
• Prefer over instance variables (or globals/statics)
• Avoid output
• Reduce amount (<4)
[NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeWidth multiplier:0.5
constant:0.0]
!
• 1 point of exit
!
• Remove empty methods or only calling super
!
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
25. Classes
• SRP. Check yourself:
• Name should describe responsibility
• Describe functionality without “and”,“or”,“but”,“if”
• Do you have flags?
!
• Open-Close principle
“Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification” - Wikipedia
!
• Hide all implementation details
• Simplify public headers/methods/properties
!
• Explicit dependencies
!
• Sort you methods and properties (public/private)
26. Classes
• Avoid statics
!
• Use polymorphism
if (a.isKindOfClass(MyClass)) {
!
!
• Take advantage of categories
MyProjectUtils.convertToUrlEncoding("hello")
StringUtils.convertToUrlEncoding(“hello")
“hello".convertToUrlEncoding()
!
"hello".drawInRect(rect:rect, withAttributes: attributes)
!
• Sort your toolbox!
28. Modules
• SoC
“Design principle for separating a computer program into distinct sections, such that each section addresses a separate
concern. A concern is a set of information that affects the code of a computer program”. Wikipedia
!
• Explicit
• API
• Callbacks (protocols, blocks,…)
• Threads
!
• Split by functionality vs type
!
• Hide internals
!
• Structure your data
- (NSDictionary *)findNearestPersonToLocation:(NSArray *)coordinates;
- (Person *)findNearestPersonToLocation:(CLLocationCoordinate2D)coordinate;
29. Modules
• Dependencies
• Law of Demeter
“LoD can be succinctly summarized in one of the following ways:
• Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
• Each unit should only talk to its friends; don't talk to strangers.
• Only talk to your immediate friends.”. Wikipedia
!
aVar.getB().getC()
!
!
• Avoid cycles
!
• Prefer Interfaces vs concrete classes
!
• Isolate lifecycle
!
• Make proper use of Software patterns
A B C
31. Software patterns
• Robust, flexible and well known solutions
!
• Reduce cognitive load
“Among psychologists it is widely acknowledged that, compared to "cold" learning, people learn more effectively when
they can build on what they already understand”. Wikipedia.
!
• Some of most interesting:
• MVC / MVVM
• Inheritance / Composition
• Inversion Of Control / Dependency Injection
• Delegate/Observer
• Factory
• Chain Of Responsibility
• ….
32. MVC
• Model
• Contains information in Plain objects
• Connects to endpoints, DB,.…
• View
• Draws the screen
• Receives/passes events to/from controllers
• Controller
• Connects the View and the Model layers
!
• Most common pitfalls in iOS
• Massive controllers (DataSources, components,…)
• Controllers doing Model/View work
• View & Controller coupling
!
• Alternative: MVVM (Model-View-ViewModel)
33. Inheritance vs Composition
• Inheritance is good for“is-a”relations
• Use composition as default
Inheritance Composition
Difficult to keep SRP Easy to keep SRP
Details from base class to subclasses Close components
Massive base classes Small components
Behaviour on compilation time Behaviour on runtime
34. Inversion of Control / Dependency Injection
• Increase reusability of modules
• Lifecycle controlled on system level
• IoC
• Invert relation code-3rd party
• Generic API definitions
• Dependencies are provided
• DI
• Dependencies are injected (constructors, setters)
!
class TextEditor {
var checker = SpellCheckerES() //TextEditor coupled with ES checker
}
!
class TextEditor {
var checker: SpellChecker
init(checker: SpellChecker) {
self.checker = checker //Implementation of checker decided by DI controller
}
}