Building for perfection
-
Upload
jorge-ortiz -
Category
Software
-
view
434 -
download
0
Transcript of Building for perfection
Building for PerfectionJorge D. Ortiz FuentesMADRID · NOV 27-28 · 2015
Building for Perfection
Jorge D. Ortiz Fuentes @jdortiz
#Swift4AA
A Canonical Examples
production
#Swift4AA
#Swift4AA
Agenda
What is an advanced architecture?
Paradigms
Principles
Design Patterns
Conclusions
Advanced Architecture
#Swift4AA
Advanced Architecture
High level structures
• Effectiveness
• Efficiency
• Robustness
• Beauty and elegance
#Swift4AA
Architectural BenefitsReduce complexity
Maximize re-use
Reduce repetition
Basis for easier growth
Better testability
Readability and easier collaboration
– Salvador Dalí
“Have no fear of perfection, you’ll never reach it”
Not just one
But there are wrong ones
Most likely yours
😜
Wrong one
Paradigms
#Swift4AA
Programming Paradigms
Obj
ect
Orien
ted
Imperative PrgmDeclarative Prgm
Control Flow
Data Flow
#Swift4AA
Is Swift a Functional Language?
Purity or pragmatism?
Swift allows to express solutions declaratively
Many standard functions to help and even more from some libraries
Principles
#Swift4AA
Principles
Single responsibility
Open/Closed
Liskov
Interface Segregation
Dependency Inversion
Design Patterns
#Swift4AA
Syntactic Fructose
guard
defer
repeat
…
Guard
func presentCell(cell: SpeakerCellProtocol, indexPath: NSIndexPath) { let index = indexPath.row guard index < speakers.count else { return } let speaker = speakers[index] cell.displayName(speaker.name) cell.displayTitle(speaker.title) cell.displayDateSubmitted(relativeDateStringFromDate(speaker.dateSubmitted)) }
#Swift4AA
Swift abstractions: protocols
Swift doesn’t have abstract classes
Usage of the protocol extensions
Don’t “translate” design patterns to Swift
protocol Exportable { func export(text: String) }
extension Exportable { func export() {} }
class MarkdownDocument: Document, Exportable { }
Trait
class HTMLExporter { func export(text: String) -> String { // Generate } }
class MarkdownDocument: Document { let exporter = HTMLExporter() }
Poor Templateclass Exporter { func exportToHTML() -> String { let header = generateHeader() let body = generateContent() let footer = generateFooter() return header + body + footer }
final func generateHeader() -> String { //Implementation return "<html>" }
func generateContent() -> String { fatalError() return “" } func generateFooter() -> String { //Implementation return “</html>" } }
Swifty Templateprotocol Exporter { func exportToHTML() -> String func generateHeader() -> String func generateContent() -> String func generateFooter() -> String }
extension Exporter { final func exportToHTML() -> String { let header = generateHeader() let body = generateContent() let footer = generateFooter() return header + body + footer } final func generateHeader() -> String { //Implementation return "<html>" } func generateFooter() -> String { //Implementation return "</html>" } }
#Swift4AA
Protocol Extensions
Adds to class API vs subsystem (composition)
Reuse
DRY
#Swift4AA
Error Handling
Elegant implementation
Extended to current Cocoa for free
Errors subclass ErrorType
var control = Houston(fuel: 1.0, astronaut: nil, spaceshipOK: true)
do { try control.launchSpaceship() } catch Houston.LaunchError.NoFuel { // Add Fuel print("Adding fuel") } catch Houston.LaunchError.NoAstronaut { print("Next in line") } catch Houston.LaunchError.BrokenShip(let problem) { print(problem) } catch let unknowError { // }
Ready for Lifeclass Houston { let fuel: Double let astronaut: String let spaceshipOK: Bool init (fuel: Double, astronaut: String?, spaceshipOK: Bool) { self.fuel = fuel self.astronaut = astronaut ?? "" self.spaceshipOK = spaceshipOK } enum LaunchError: ErrorType { case NoFuel, NoAstronaut, BrokenShip(String) } func launchSpaceship() throws { guard fuel >= 1.0 else { throw LaunchError.NoFuel } guard astronaut != "" else { throw LaunchError.NoAstronaut } guard spaceshipOK else { throw LaunchError.BrokenShip("Engine") } print("Launching spaceship") } }
#Swift4AA
Generics
Aimed at DRY
Much better that id (Obj-C) or AnyObject/Any
And use where for further restrictions
Generic Awesome Power
func countGreater<T where T:Comparable>(array: [T], value: T) -> Int { var count = 0 for elem in array where elem > value { count++ } return count }
#Swift4AA
If you scratch my back…
It is also true that some patterns make using Swift easier
Prefer non-optionals: Null Object (and combine it with errors)
class Text { func displayContents() { print("Hola") } }
class NullText: Text { override func displayContents() { } }
func fetchText() -> Text { return NullText() }
let text = fetchText() text.displayContents()
Null Object
class Text { func displayContents() { print("Hola") } }
func fetchText() -> Text? { return nil }
if let text = fetchText() { text.displayContents() }
#Swift4AA
Still PendingIntrospection
• Very limited
• Useful for: Dependency Injection, KVC/KVO
Dynamic Dispatching
Community Supported features:
• Promises
• Reactive Extensions
Conclusions
#Swift4AA
Conclusions
Swift is a very expressive language
• Intent
It is mature enough to be used with advanced architectures
Some additional features would be more than welcome
Thank you!
@jdortiz #Swift4AA
MADRID · NOV 27-28 · 2015