Slide 1

Slide 1 text

Elevate Your Intent Matt Green

Slide 2

Slide 2 text

About Me • Github: https://github.com/mattgreen • Twitter: @mattgreenrocks • Email: [email protected]

Slide 3

Slide 3 text

“Programs must be written for people to read, and only incidentally for machines to execute.” - Harold Abelson, Structure and Interpretation of Computer Programs

Slide 4

Slide 4 text

Why Intent? • Code is a sequence of instructions • But it can’t tell us what it’s doing, or why • How can we convey our intent?

Slide 5

Slide 5 text

What Are We Doing? • We are problem solvers first and foremost • Can we change how we think about problem solving? • Code is only as good as our understanding • These are skills to build our careers on

Slide 6

Slide 6 text

Requirements • Story: User Logs In • User enters username and password • Credentials sent to web service • If credentials are valid, store username + unique token in Keychain • Otherwise, display an error message

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Responsibilities • This code has four main responsibilities: • UI handling • HTTP request sending • HTTP response parsing • Keychain storage • One problem: this is a simple requirement!

Slide 10

Slide 10 text

Muddled intent • Multiple responsibilities • Several levels of abstraction • Involved test setup • Two conditionals away from pain! • Employ design to increase intent

Slide 11

Slide 11 text

Decoupling the API • Extract the web service to a new API class • API class will only be responsible for: • Sending requests • Parsing responses • Good class and method names further increase intent

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

What Did We Gain? • Named a domain concept: the web service • Encapsulated the responsibility of: • Communicating with the API • Interpreting the response • Isolated the dependency (BubbleWrap)

Slide 15

Slide 15 text

Testing the API • Use integration tests • Only test against API.login responsibilities • Need to mock web service response • Small, focused classes = simpler test suites

Slide 16

Slide 16 text

Decoupling Keychain • Extract Keychain access out to a new class • Responsible for persisting username and token • Thus, we name it UserRegistration, rather than something involving Keychain

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

Benefits • Introduced a domain concept • Abstracted: • ACSimpleKeychain details (service, id) • Error-checking style • Dependency itself (ACSimpleKeychain)

Slide 20

Slide 20 text

Testing UserRegistration • Similar to API: • Call UserRegistration.store • Check against ACSimpleKeychain directly • Narrow interfaces ease testing

Slide 21

Slide 21 text

Generalizing... • API and UserRegistration are boundaries: they allow us to interact with the world • Boundaries typically fall into a few categories, such as persistence, networking, and hardware sensors • However, they are dependencies...

Slide 22

Slide 22 text

Dependencies • Dependencies may: • Have, or introduce bugs • Change their API across versions • Have a clunky, error-prone API • In short: they increase risk! • So, we isolate them

Slide 23

Slide 23 text

Why isolate? • Dependency-induced complexity obscures actual domain complexity • To prevent this, we use layers: • Domain: “what does my app do?” • Technical: “how does it accomplish it?” • Layers are required for complex systems

Slide 24

Slide 24 text

Dependencies And Evil “Evil things exist. You're going to have mutable state; you're going to use libraries that don't fail loudly; libraries are sometimes going to force global mutable state on you…I want that stuff on one side so that I can always keep my eye on it...because occasionally those evil forces inhabit a body and make it wear hockey masks and swing sharp objects at me and, damn it, I'm a programmer; I can't be fighting off global- mutable-state-possessed homicidal monsters.” - Gary Bernhardt

Slide 25

Slide 25 text

Managing Boundaries • Name it after a domain concept • Write a simple API tailored to your app • Check for errors, and fail loudly • Rely on integration tests to verify/upgrade dependency

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

Pushing Onward • The controller still knows: • That we call the API • To store the credentials if the login succeeded • How do we test that logic? • What do we do this logic is complex?

Slide 28

Slide 28 text

The edge of MVC • Extract interaction to a service object, such as LoginUser that is UI agnostic • Encapsulate interaction between API and UserRegistration, simplifying our view controller • However, the API is async. How to cope?

Slide 29

Slide 29 text

Desired Code...

Slide 30

Slide 30 text

Enter Elevate • Elevate is a global task queue designed for service objects • Robust: powered by NSOperationQueue • Start/stop operations from view controller • Simplifies async I/O in service objects

Slide 31

Slide 31 text

Elevate Usage • Elevate calls execute on any object passed to the view controller’s async method • The async method returns an NSOperation to cancel the operation • Only one operation may run at a time

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Elevate Simplifies IO • iOS web service requests are async • Elevate’s HTTP client: • Feels like a blocking HTTP client • Allows cancellation via NSOperation • Increased readability = increased intent

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

Conclusion • Maximizing intent requires practice • ‘Average’ code can be improved by simply extracting concerns out • Boundaries are necessary, but incur risk • Elevate helps you create a service layer

Slide 36

Slide 36 text

Further Study • Clean Architecture: http://blog.8thlight.com/uncle-bob/ 2012/08/13/the-clean-architecture.html • Destroy All Software: https://www.destroyallsoftware.com/ • Growing Object Oriented Software Guided By Tests, by Steve Freeman & Nat Pryce

Slide 37

Slide 37 text

Questions?