Using separation by behaviour to reduce view controller responsibilities, code size and repetition.
Unfortunately the presentation has embedded video as well as three breaks for demos in Xcode, so the full effect isn't transmitted very well.
Code reuse© Apokrupto 2015
View Slide
Code reuseCode complexity© Apokrupto 2015
Cyclomatic Complexity• Number of independent paths through a• function• class• module© Apokrupto 2015
Cyclomatic Complexity• Good < 10-12• Review < 20• Refactor >20• Unmaintainable ~30-40• Fatally unmaintainable > 50© Apokrupto 2015
Cyclomatic Complexity© Apokrupto 2015
Code reuseUsing separation by behaviour to reduce view controllerresponsibilities, code size and repetition© Apokrupto 2015
Principles• DRY - Don’t repeat yourself• Worth repeating© Apokrupto 2015
Principles• Single responsibility• Separation of concerns• Promotes reuse• What do ‘rate my app’ & ‘call our helpdesk’features have to do with each other?• And what do they have to do with the model?© Apokrupto 2015
MVC• The ‘Massive View Controller’ problem• Unrelated functionality implemented in the sameclass• What if we have a “Call the helpdesk” button onmultiple screens?• DRY• Base class?© Apokrupto 2015
MVC• The ‘Massive View Controller’ problem• Unrelated functionality implemented in the sameclass• What if we have a “Call the helpdesk” button onmultiple screens?• DRY• Base class?© Apokrupto 2015Behaviours
© Apokrupto 2015
What do we get?• Animating the button’s arrival• Animating the background• Dismissing the button• Rating the app• Calling the helpdesk© Apokrupto 2015
What do we get?• MySlidingInAndOutBackgroundAnimatingAppRateAndHelpDeskViewController.h• 700 lines of code• Change requests• if-else/switch hell© Apokrupto 2015
What do we get?• MySlidingInAndOutBackgroundAnimatingAppRateAndHelpDeskViewController.h• 700 lines of (unrelated) code• Change requests• if-else/switch hell© Apokrupto 2015
Separating the behaviours• Animating the button’s arrival• Animating the background• Dismissing the button• Rating the app• Calling the helpdesk© Apokrupto 2015
Separating the behaviours• Take them all out of the View Controller• Use composition to put them back• Make them configurable• Without explicitly adding them to the VC© Apokrupto 2015
Demo• Setting behaviours© Apokrupto 2015
Behaviour Ownership• The behaviour may be destroyed at any moment,because there are no strong references to it• We fix this by making it an associated object ofthe view controller• giving us the necessary ownership• and making the composition© Apokrupto 2015
Behaviour Ownership© Apokrupto 2015
Demo• Re-use• Individual tweaks© Apokrupto 2015
Facts & figures• Recent project• 115 separate behaviours• App level, library specific, generic• App level - highest coupling• Generic - lowest & most reusable© Apokrupto 2015
AdvancedWhat’s wrong with this picture?© Apokrupto 2015
Advanced© Apokrupto 2015
Advanced• Your behaviours can be the delegates and datasources for your view controllers• Implement scroll, table & other view’sdelegates and data sources in behaviours© Apokrupto 2015
Demo• Behaviours with data sources© Apokrupto 2015
Advanced• Add delegates & data sources to yourbehaviours• localisation• can be another behaviour• or use the view controller© Apokrupto 2015
To sum up• Separating individual responsibilities results insmaller, more maintainable and reusable code• Greater flexibility with unit testing• Refactoring is a simple delete• Skinny is good© Apokrupto 2015
But you can get too skinny© Apokrupto 2015
Big finish© Apokrupto 2015
Core Data as a behaviour• Generally NSFetchedResultsController is used witha table view to populate a view controller• Much of this is generic• A Core Data behaviour can act as theUITableViewDelegate and UITableViewDataSource• But the behaviour does not know how to populatecells, or what to do if they are selected© Apokrupto 2015
Core Data as a behaviour© Apokrupto 2015
Core Data as a behaviour• Generic Core Data behaviour with table view outlet• Behaviour is UITableViewDataSource and UITableViewDelegate• Behaviour will proxy the results from a CD fetch request to thetable view• Behaviour has a Core Data Data Source and Core Data Delegate• Data Source handles the specifics of populating a table viewcell• Delegate handles the specifics of selecting a cell© Apokrupto 2015
Core Data Data Source© Apokrupto 2015
Big finish demo© Apokrupto 2015
Big finish stats• Adding a golf course• Core Data table population• Customising the table• Background animation• Sliding animation813© Apokrupto 2015
Big finish stats• Adding a golf course• Core Data table population• Customising the table• Background animation• Sliding animation767 LOC© Apokrupto 2015
Big finish stats• Adding a golf course• Core Data table population• Customising the table• Background animation• Sliding animation767 LOC94© Apokrupto 2015
Big finish stats• Very low complexity• Highest complexity method: 6• Average complexity: 1.6• Average NLOC: 6© Apokrupto 2015
It doesn’t end there• It doesn’t have to be a table view• Collection views• Page views• Hand crafted views representing anycollection© Apokrupto 2015
Lessons Learned• Write generic code• Write low complexity code• Write code that is designed to be extended• Keep that code available somewhere• git, cocoapod, library, github, carthage© Apokrupto 2015
Thank you© Apokrupto 2015mail: [email protected] twitter: @apokrupto