Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Writing Reusable Code

Writing Reusable Code

Presented at 360iDev 2014.

The true test in whether a code base is “modular” is whether specific components can have a lifecycle that extends beyond the life of a given project. Ideally, as you get a couple projects under your belt, you shouldn’t find yourself writing functionality that you’ve written before.

Modular code not only makes maintenance of a project easier, it also provides opportunities to adapt functionality for future projects. As your code library grows, you’ll be able to build projects faster. This will allow you to invest your project’s budget in advancing your or your company’s capabilities, instead of spending time solving problems that have already been solved.

In this session, we’ll review the principles of writing reusable and modular code. We’ll also review how to apply these principles in drawing the line between generic behavior (what’s reusable) and specific implementation (what’s specific for this app).

Daniel Pfeiffer

August 27, 2014
Tweet

More Decks by Daniel Pfeiffer

Other Decks in Programming

Transcript

  1. Writing Reusable Code Daniel Pfeiffer Lead Developer / Float Mobile

    Learning ! @mediabounds dpfeiffer@floatlearning.com
  2. 360|iDev 2014 / Writing Reusable Code “Reusable” code is… •

    Not (necessarily) code that is distributed through static libraries or CocoaPods • Code with a lifecycle beyond a given project • Able to completely fulfill its responsibility in your app • Maintainable without being rewritten
  3. 360|iDev 2014 / Writing Reusable Code When you’re mindful of

    code’s reusability… • You’re not solving the same problems 
 time and time again • You’re saving time—both in development and testing • You’re freeing up budget to allocate towards advancing your or your company's capabilities
  4. 360|iDev 2014 / Writing Reusable Code Not every line of

    code is worthy 
 of more of your time.
  5. 360|iDev 2014 / Writing Reusable Code Loose-Coupling • Each component

    should know as little as possible— if anything at all—about surrounding components • Reduces dependencies • Prevents changes from having 
 unanticipated consequences • Code becomes more readily reused and maintained
  6. 360|iDev 2014 / Writing Reusable Code Evidence of Tightly-Coupled Code

    • When changes in one component force 
 updates in many other components • When fixing one bug introduces three more ©1992 Bill Watterson
  7. 360|iDev 2014 / Writing Reusable Code Loose-Coupling with Protocols •

    They’re not just for delegates! • Protocols define expected behavior of an object • Protocols are for the developer and for the compiler • Promotes agnosticism between classes - Implementation changes over time—
 that’s the whole point of maintenance - Easier to add functionality when 
 it impacts fewer members
  8. 360|iDev 2014 / Writing Reusable Code Example: Selecting Files from

    a Cloud Service Dropbox File Provider Google Drive File Provider File Selector
  9. 360|iDev 2014 / Writing Reusable Code Example: Selecting Files from

    a Cloud Service Dropbox File Provider Google Drive File Provider File Selector Box File Provider
  10. 360|iDev 2014 / Writing Reusable Code Example: Adding a “File

    Providing” Protocol Dropbox File Provider Google Drive File Provider File Selector Box File Provider File Providing Protocol
  11. 360|iDev 2014 / Writing Reusable Code protocol FileProviding { var

    name: String { get } var isAuthenticated: Bool { get } var authenticatedUserName: String { get } func logout() ! func loginWithCompletionHandler(
 completionHandler:(FFRUser, NSError?) -> Void) ! func retrieveFilesAtPath(path: String, 
 completionHandler:([FFRFile], NSError?) -> Void) ! func fileAtIndexPath(indexPath: NSIndexPath) -> FFRFile } Example: Adding a “File Providing” Protocol In order for a class to claim “I am capable of providing files,” what must it be able to do?
  12. 360|iDev 2014 / Writing Reusable Code Use Generics • For

    when the type of data doesn’t matter—
 only the outcome • Promotes agnosticism by adding functionality to 
 any type, provided it meets a set of requirements
  13. 360|iDev 2014 / Writing Reusable Code func swapValues<T>(inout a: T,

    inout b: T) { let originalA: T = a a = b b = originalA } Use Generics var a: Int = 10, b: Int = 12 println(a) // a = 10 swapValues(&a, &b) println(a) // a = 12 var a_str: String = "360iDev", b_str: String = "Hello" println(a_str + ", " + b_str) // "360iDev, Hello" swapValues(&a_str, &b_str) println(a_str + ", " + b_str) // "Hello, 360iDev"
  14. 360|iDev 2014 / Writing Reusable Code Problems with Pre-emptive Subclassing

    • Produces over-engineered solutions by "solving" problems that never existed • Adds unneeded layers of complexity • Paralysis by analysis
  15. 360|iDev 2014 / Writing Reusable Code Don’t equate a tall

    inheritance tree with 
 good architecture. Good architecture is characterized by code that clearly and completely fulfills the need.
  16. 360|iDev 2014 / Writing Reusable Code Superclassing • Focus on

    solving the problem at hand • Create reusable code through refactoring • Don’t waste time creating unneeded architecture
  17. 360|iDev 2014 / Writing Reusable Code Behavior Specific Example: Core

    Data Table View Controller Create an NSFetched ResultsController Select an Entity Sort/Group Entity Fulfill UITableView 
 data source Create a UITableViewCell Format cell Handle user selection
  18. 360|iDev 2014 / Writing Reusable Code Behavior Specific Example: Core

    Data Table View Controller Create an NSFetched ResultsController Select an Entity Sort/Group Entity Fulfill UITableView 
 data source Create a UITableViewCell Format cell Handle user selection
  19. 360|iDev 2014 / Writing Reusable Code Behavior Specific Example: Core

    Data Table View Controller Create an NSFetched ResultsController Select an Entity Sort/Group Entity Fulfill UITableView 
 data source Create a UITableViewCell Format cell Handle user selection Respond to Core 
 Data updates
  20. 360|iDev 2014 / Writing Reusable Code Behavior Specific Example: Core

    Data Table View Controller Create an NSFetched ResultsController Select an Entity Sort/Group Entity Fulfill UITableView 
 data source Create a UITableViewCell Format cell Handle user selection Respond to Core 
 Data updates CoreDataViewController FilesViewController / LocationsViewController
  21. 360|iDev 2014 / Writing Reusable Code Where Inheritance Doesn't Help

    • When you don't know (or don't trust) 
 the parent implementation • When you can't reuse functionality because you can't subclass the class containing the functionality • When the parent contains functionality 
 irrelevant to it's children • When children are simply enabling/disabling functionality of the parent
  22. 360|iDev 2014 / Writing Reusable Code Single Responsibility Principle •

    Every context should have a single responsibility • That responsibility should be entirely fulfilled 
 by the context • You must determine the definition of a 
 “single responsibility” • A “responsibility” can become more specific 
 or less specific as a project matures
  23. 360|iDev 2014 / Writing Reusable Code Benefits of a Single

    Responsibility • Contexts become easier to maintain when they have a well-defined responsibility • Ensuring discrete responsibility prevents unintended consequences during maintenance or updates
  24. 360|iDev 2014 / Writing Reusable Code Example: Composition and View

    Controllers View Controller Icon 
 Formatter Analytics Location 
 Manager Results Fetcher
  25. 360|iDev 2014 / Writing Reusable Code Composition with Categories •

    Allow you to add functionality to an existing class— even when you don’t have the source code • All instances—including subclasses—have access 
 to this functionality • Encourages composition by providing a logical home for common/utility functionality - Functionality that alters a Core Foundation object (e.g. shuffling an array) should be in a category - Add functionality to a base class (e.g. UIViewController) so it’s available for all instances
  26. 360|iDev 2014 / Writing Reusable Code Composition with Protocols (Data

    Sources / Delegates) • Encourages composition by providing an interface for different classes to communicate • Inheritance is not a means to customize content • Separate content from behavior • Delegate responsibilities that are “out-of-scope”
  27. 360|iDev 2014 / Writing Reusable Code Composition with MVVM (Model-View-View

    Model) • Encourages composition by moving presentation logic closer to the model • Presentation logic becomes the composited pieces • Consistent representation of data regardless of the context in which it’s 
 being rendered Model View Model View Controller View Update Notify Update Action
  28. 360|iDev 2014 / Writing Reusable Code Documentation • How can

    I reuse your code if I don’t know 
 what it does? • How can I reuse your code if I’m not confident my customizations 
 will not have 
 unintended effects?
  29. 360|iDev 2014 / Writing Reusable Code Documentation is not Just

    for Others • Helps you better understand your code by formalizing responsibilities of various contexts • Forces you to ask prodding questions that may uncover hidden edge cases • Helps you remember what you were thinking when you wrote it the first time
  30. 360|iDev 2014 / Writing Reusable Code Documentation can take on

    many forms • Clearly named members • Accompanying documentation (e.g. wiki) • In-line documentation • Tests
  31. 360|iDev 2014 / Writing Reusable Code Let's Review ✓ Focus

    on solving actual problems ✓ Find and remove unneeded dependencies ✓ Work backwards—refactor into reusable code ✓ Don’t use inheritance to customize content ✓ Achieve full functionality by compositing several classes, each with discrete responsibility ✓ Define responsibilities and behaviors in your app; organize code accordingly ✓ Document your code