Category Archives: Development

Software Architecture Patterns

A software architecture pattern is a “general, reusable solution to a commonly occurring problem in software architecture within a given context.”

Wikipedia

Our industry spends a lot of time and resources to define and understand architectural patterns because building software is hard, especially when we want to maintain it over time with larger teams.

Patterns discussed here:

  • Layered architecture
  • Hexagonal architecture
  • Onion architecture
  • Package by feature
  • Clean architecture

Software architecture concepts

  • Cohesion
  • Coupling
  • Separation of concerns
  • Layers of isolation
  • Dependency inversion principle (DIP)
  • Inversion of control (IOC)

Grzegorz Ziomonski has a good overview of these architectural patterns.  His approach is to describe the principles of each, identify pros and cons, and to see how the architecture would affect a project.  His analysis is sometimes shallow, however, so it is important to refer to more authoritative literature, such as that written by the creator of a pattern.

Introduction

Why should we look at architecture?  In his article Screaming Architecture, Robert “Uncle Bob” Martin describes good architecture like this:

A good software architecture allows decisions about frameworks, databases, web servers, and other environmental issues and tools, to be deferred and delayed.  A good architecture makes it unnecessary to decide on Rails, or Sprint, or Hibernate, or Tomcat or MySql, until much later in the project.  A good architecture makes it easy to change your mind about those decisions too.  A good architecture emphasizes the use-cases and decouples them from peripheral concerns.

`Robert “Uncle Bob” Martin, Screaming Architecture

Each of the architecture patterns described here provide some or all of the benefits described by Uncle Bob, but they all come with their own costs as well.  We’ll try to analyze these factors as we compare the patterns.

Layered Architecture

A layered architecture organizes the project structure into horizontal layers, each layer performing a specific role within the application.  While this pattern does not specify the number or types of layers that must exist, most layered architectures consist of four standard layers:

  1. Presentation layer
  2. Business layer
  3. Persistence layer
  4. Database layer

There are two important rules for this pattern:

  1. No logic related to one layer’s concern should be placed in another layer.
  2. All dependencies go in one direction.

The first rule states that no logic related to one layer’s concern should be placed in another layer.

One of the powerful features of the layered architecture pattern is the separation of concerns among components.  Components within a specific layer deal only with logic that pertains to that layer.  For example, components in the presentation layer deal only with presentation logic, whereas components residing in the business layer deal only with business logic.  This type of component classification makes it easy to build effective roles and responsibility models into your architecture, and also makes it easy to develop, test, govern, and maintain applications using this architecture pattern due to well-defined component interfaces and limited component scope.

Mark Richards, Software Architecture Patterns

The second rule states that all dependencies go in one direction.  In its simplest form, an implementation of the layered architecture pattern would dictate that components in one layer can only depend on components in the layer directly below it, known as a closed layer.  This concept is known as layers of isolation.  This concept means that changes made in one layer of the architecture generally don’t impact or affect components in other layers.  This reduces coupling between layers.  It also means that each layer is independent of the other layers, thereby having little or no knowledge of the inner workings of other layers in the architecture.

There are times when it makes sense for certain layers to be open, such as when adding shared service components (e.g. data and string utilities or auditing and logging facilities).

Analysis

BenefitNotes
SimplicityThe concept is very easy to learn and visible in the project by inspection.
Consistent across different projectsThe layers and overall code organization is pretty much the same in every layered project.
Guaranteed separation of concernsDevelopers can focus on the details of the layer they are working on.
Browsability from a technical perspectiveWhen changing something in some/all objects of a given kind, they’re very easy to find and they’re kept all together.
DrawbackNotes
No built-in scalabilityWhen the project grows too large, this pattern doesn’t aid in refactoring.
Hidden use casesYou can’t say what a project is doing by simply looking at the code organization.  You need to read class names and sometimes even the implementation.
Low cohesionClasses that contribute to common scenarios and business concepts are far from each other because the project is organized around separating technical concerns.
No dependency inversionThe pattern does not describe how dependencies should be implemented, so if components are implemented without consulting other patterns, direct dependencies are defined instead of abstractions.
Not use-case focusedThis pattern organizes components based on type of function and does not provide any help to discover use cases when taking a high-level look at the code.

Resources

Hexagonal Architecture

The Hexagonal Architecture – also known as the Ports and Adapters Architecture – was created by Alistair Cockburn with the primary aim of decoupling the applications core logic from the services it uses.  This allows different services to be “plugged in” and it allows the application to be run without these services.

This pattern prescribes that every piece of functionality the application offers is available through an API or function call, and that the application accesses external entities (e.g. databases, networking, UI) via a well-defined interface.  The application communicates over these “ports”, and an adapter is implemented for each port.

This can be build down to the following principles:

  1. The inside part knows nothing about the outside part.
  2. Any adapter that fits a given port can be used.
  3. No use case or domain logic is implemented in the outside part.
BenefitNotes
Easy to learnIt’s just ports and adapters.
Application and domain purityThe most important code in the application is not cluttered by technical details.
FlexibilityAdapters can be swapped out easily.
TestabilityTest replacements for the outside dependencies can be provided without using extra mocking tools.
DrawbackNotes
HeavinessA lot of extra classes are required, especially when only one UI and one database need to be supported.
IndirectionsTo follow the flow of control you must look at the implementation of a port and be aware of the state of the application.
Confusing to apply with frameworksIt’s now always clear what should be considered the outside.
No code organization guidelinesHow code is organized is not informed by this pattern.
Not use-case focusedThis pattern organizes components based on type of function and does not provide any help to discover use cases when taking a high-level look at the code.

Resources

Onion Architecture

The Onion Architecture was created by Jeffrey Palermo to provide the following benefits:

  • Supports long-lived applications
  • Supports applications with complex behavior
  • Emphasizes the use of interfaces for behavior
  • Forces the externalization of infrastructure

This pattern can be viewed as an evolution and combination of the Layered Architecture and the Hexagonal Architecture.

The primary differences between this pattern and the Layered Architecture are:

  • Infrastructure is pulled to the outer ring (aka top layer).
  • Dependency layers are open.
  • The Dependency Inversion Principle is prescribed for defining communication between layers.

It shares the following premise with the Hexagonal Architecture:

  • Externalize infrastructure and write adapter code so that the infrastructure does not become tightly coupled.

Key tenets of the Onion Architecture:

  • The application is built around an independent object model.
  • Inner layers define interfaces.  Outer layers implement interfaces.
  • Direction of coupling is toward the center.
  • All application core code can be compiled and run separate from infrastructure.

Dependency Inversion Principle

As mentioned above, the Dependency Inversion Principle is core to this pattern.  This principle refers to a specific form of decoupling software modules that reverses the conventional dependency relationship.

  • High-level modules should not depend on low-level modules.  Both should depend on abstractions.
  • Abstractions should not depend on details.  Details should depend on abstractions.

This design principle inverts the way some people may think about object-oriented programming, dictating that both high- and low-level objects must depend on the same abstraction.

Inversion of Control (IoC)

Another core to this pattern is Inversion of Control (IoC).  Typical implementations of this principle use one of the following patterns:

  • Factory pattern
  • Service locator pattern
  • Dependency injection
  • Strategy design pattern

Analysis

BenefitNotes
Plays well with DDD (domain-driven design)
Directed couplingThe most important code in the application depends on nothing, everything depends on it.
FlexibilityFrom an inner-layer perspective, you can swap out anything in any of the outer layers and things should work just fine.
TestabilitySince the application core does not depend on anything else, it can be easily and quickly tested.
DrawbackNotes
Learning curveFor some reason, people tend to mess up splitting responsibilities between layers, especially harming the domain model.
IndirectionInterfaces everywhere!
Potentially heavyLooking at Palermo’s project, the application core has no dependencies on frameworks due to the abstractions.
Multi-layer dependenciesDoes not protect outer layers from changes in inner layers.
Not use-case focusedThis pattern organizes components based on type of function and does not provide any help to discover use cases when taking a high-level look at the code.

Resources

Package by Feature

In a typical Layered Architecture, code is often organized based on the layers, with all the components in one layer provided in the same package.  This is often called Package by Layer.

The problem with this approach is that cohesion (the strength of relationships between pieces of functionality) inside each package is usually low and the coupling (the degree of interdependency) between packages is very high.  This seems like exactly the opposite of what we want to achieve.

The Package by Feature Architecture pattern attempts to address these concerns by building layers within each feature.

The essence of this pattern can be described like this:

Maintaining high cohesion and low coupling at the package model level and being able to recognize what an application does by looking at its package/module structure.

From Grzegorz Ziomonski:

In a typical Layered Architecture, the cohesion inside a package is low and the coupling between packages is high.  We rarely change technologies or conventions regarding a particular layer, comparing to how often we add a single feature, hence low cohesion.  And, in most cases, each class in a layer (package) depends on at least one class in another layer (package), making the coupling between them high.

In Package by Feature style, we ideally change classes only in a single package – the one related to the feature we’re working on – so cohesion is high, and there are only a few dependencies between features, so coupling is low.

Analysis

BenefitNotes
More informative package structureThe system’s main features or behaviors can be deduced from the code structure.
High cohesion and low couplingComponents that are packaged together are related to each other, and dependencies on other packages are limited.
Better encapsulationYou can make effective use of access modifiers to hide the information that ought to stay hidden.
Better growth potential (in the code volume sense)Unless you develop too big or too small features, you shouldn’t encounter the problem of too big or too many packages.
Use cases may be visible“If features are identified properly, they will tend to represent use cases supported by the application.
DrawbackNotes
Unspecified feature sizeThere is no clear guidance or proof that one understanding of feature is better than another.
Learning curveThe concept is simple, but since you need to find your own way to slice a system into features, mastering it can be really hard.
Messiness potentialIn a tangled domain, in which everything is connected to everything, the slicing into features might become artificial and the low coupling promise might not be fulfilled.

Resources

Clean Architecture

The Clean Architecture, created by Robert “Uncle Bob” Martin, is an attempt at integrating the benefits of all of the other architecture patterns.  These include:

  • Independent of Frameworks
  • Testable
  • Independent of UI
  • Independent of Database
  • Independent of any external agency

This architecture, like the onion architecture, is represented by concentric circles and makes heavy use of a dependency rule:

The Dependency Rule

The Dependency Rule for this pattern states that source code dependencies can only point inwards.  Nothing in an inner circle can know anything at all about something in an outer circle, similar to the Layered Architecture and unlike the Onion Architecture.  So when we pass data across a boundary, it is always in the form that is most convenient for the inner circle.

The layers in this pattern are organized in such a way as to move things that may change further from the center.

  • Entitiesencapsulate enterprise-wide business rules.  An entity can be an object with methods or it can be a set of data structures and functions.  They encapsulate the most general and high-level rules and are least likely to change when something external changes (e.g. page navigation or security).  No operational change to any particular application should affect the entity layer.
  • Use Casesapplication-specific business rules, encapsulating and implementing all of the use cases of the system.  These use cases orchestrate the flow of data to and from the entities.  Changes in this layer should not affect entities, and changes in externalities (databases, UI, common frameworks) should not affect this layer.  Changes to the operation of the application will affect the software in this layer.
  • Interface AdaptersLike the Hexagonal Architecture, these adapters convert data from the format most convenient for the use cases and entities to the format most convenient for some external agency, such as the database or the UI.  This layer will contain the architecture of the GUI (e.g. MVC etc.), including presenters, views, and controllers.  This layer will also contain any other adapters necessary to convert data from some external form to an internal form used by the use cases and entities.
  • Frameworks and Driversframeworks and tools such as database, the web/UI framework, etc.  Not much code is written in this layer other than glue code.  (One thing I have still to determine is how this glue code is different from interface adapters in the green layer.)

Analysis

BenefitNotes
Use cases are clearly visible
FlexibleSwitching between frameworks, databases, or application servers is explicitly enabled.
TestableThe heavy use of interfaces allows tests to be written for any part of the application.
No idiomatic framework usageThe application components would not be familiar to a developer who is familiar with focusing on frameworks.
Learning curveIt’s harder to grasp than the other styles due to lack of references to frameworks.
IndirectThere will be a lot more interfaces than one might expect.
HeavyYou might end up with a lot more classes than in projects that follow other architecture patterns.

Resources

Object Oriented Programming vs. Functional Programming

Reference: Object Oriented Programming vs. Functional Programming by Bill Gathen

Object oriented programming as a programming paradigm has been around for a long time – since the late 1950s and early 1960s, with the term being introduced in the 1970s with the Smalltalk language. It is defined as:

Object-oriented programming (OOP) is a programming paradigm based on the concept of “objects”, which are data structures that contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods.

Wikipedia

Functional programming as a programming paradigm has its roots in lambda calculus, with Lisp being an early functional-flavored language in the late 1950s, although it hasn’t received popular use until the last decade or so and can be seen in many languages not dedicated to this paradigm with frameworks such as React and Reactive Extensions (Rx). It is defined as:

Functional programming is a programming paradigm – a style of building the structure and elements of computer programs – that treats computation as the evaluation of the mathematical functions and avoid changing-state and mutable data.

Wikipedia

Both paradigms have the shared goal of creating understandable, flexible programs that are free of bugs, but they have two different approaches for how to best create those programs.

In an article posted in 2014 on this subject, Uncle Bob boils these two paradigms down to this:

  • FP imposes discipline upon assignment. Immutability provides safety, particularly in multiprocessing and multiprocessor environments.
  • OOP imposes discipline on function pointers. Polymorphism allows stable high-value business rules to be kept from depending upon volatile low-value modules such as user interfaces and databases.

OOP and FP each have their appropriate use cases. Neither is a panacea.

Richard Warburton’s eBook Object-Oriented vs. Functional Programming: Bridging the Divide Between Opposing Paradigms attempts to compare the two paradigms, primarily using the SOLID principles as a means of comparison. Based on my review of his eBook, I walked away with the following points:

  • FP avoids or can easily satisfy all the SOLID principles.
  • FP and OOP can coexist in the same codebase.

From When FP? AND when OOP? on ragenwald.com:

The biggest difference between the two “schools of thought” concerns the relationship between data and operations on the data.

The central tenet of OOP is that data and the operations upon it are tightly coupled: An object owns its data and it owns the implementation of the operations on the data. It hides those from other objects via its interface, a collection of methods or messages it responds to. Thus, the central model for abstraction is the data itself, hidden as it is behind a small API in the form of its interface.

The central activity in OOP is composing new objects and extending existing objects by adding new methods to them.

The central tenet of FP is that data is only loosely coupled to functions. You can write different operations on the same data structure, and the central model for abstraction is the function, not the data structure. Functions hide their implementation, and the language’s abstractions speak to functions and the way they are combined or expressed, such as generic functions or combinators.

The central activity in FP is writing new functions.

I like the final statement made by this article:

Good software is written in both styles, because good software has more than one need to satisfy.

WWDC 2016

I had the opportunity to go to my 3rd WWDC (Apple’s World Wide Developers Conference).  WWDC is a great place to learn about the new things Apple is introducing in upcoming versions of their products as well as to talk with Apple engineers and others who are developing for their platforms.

All of the content from the sessions delivered at WWDC is available online.

High-Level Summary

  • New features in iOS 10
    • SiriKit
    • New user notification framework with more ways to display and manage notifications
    • New extension points in iMessage
    • Improvements in UIKit animations and transitions
    • Improvements in collection views and table views
  • New features in watchOS 3
    • Button modified to bring up a dock of active apps.  Glances removed in favor of docked view of app.
    • Background app refresh
    • Changes to navigation by using the digital crown to navigate between elements at the same level.
    • Access to the digital crown.
  • Swift 3
    • The API design guidelines were applied to the language and Cocoa/CocoaTouch frameworks.
  • Networking
    • HTTP/2 Server Push is now supported
    • Network statistics

Evaluation

The changes in the notification system and in watchOS can really improve the user experience for presenting notifications.

The changes to Swift continue to improve the safety provided by the language to reduce the occurrence of bugs.

Good info on improving the performance of table and collection views.

HTTP/2 Server Push can significantly improve the responsiveness of mobile apps.

Apple made some really nice changes in watchOS (notifications, background refresh, navigation) that should make the watch a lot easier to use.

Sessions

isKindOfClass and XCTest

I learned something very useful today.  My group uses Apple’s XCTest as a framework for test automation.  Because of the way XCTest gets associated with the app, there are certain rules you need to follow that aren’t completely obvious in order to use certain very common features of CocoaTouch.

How XCTest Can Test Your App

When you create a test target to test your app, a separate executable image is built that doesn’t include the components of your app.  When you run a test, your app is run and then the test image is injected into the app process.  The result is that type information comparisons (e.g. isKindOfClass:) only work if the class objects are in the same image.

Fixing Type Comparisons

In order to compare types reliably, you must not include the same source files in both the app target and the test target.  If your project is small, this is a relatively simple task.  However, as your project gets larger and you start using CocoaPods or include libraries in other ways, you need to get a little more creative.

In our case, we use CocoaPods pretty extensively, and we build some of our code in libraries (and therefore separate pods) and some in the application.  The result is that I needed to create multiple pod targets to ensure that no source file was included in both targets.

Other XCTest Tidbits

I ran into this problem because I was building some tests with mocks and other tests without them, and the mocks were located in a separate pod.  In order to get my app to use the mocks, I created an app target that included the mocks directly.  Why, you might ask?  For the following reasons:

  1. My app view controller need access to the data that is being mocked before my tests are run.
  2. Setting a singleton value in a +load method doesn’t work because the +load method in the test target isn’t called
  3. Swizzling in the test target doesn’t work.

References

Git fix guide

I consider myself a fairly advanced user of Git.  I’ve been using it for most of the past 5 years and really enjoy the workflow improvements, and in the circles I run I am typically consulted when folks have a question about Git.  Of course, I couldn’t be nearly as effective without the help of others on the web.

For example, today I was looking for a way to remove a file from a commit that I hadn’t yet pushed, and my search led me to Seth Robertson’s page On undoing, fixing, or removing commits in git.  This page walks you through solutions by asking a series of questions about the current state of your repository and your changes.  Great guide!

Oh, and to remove a file from a commit, you can issue this command:

1
git reset HEAD^

which will undo the last commit, restoring your index to the previous commit, and leave the working directory with the changes uncommitted.

Double-Checked Locking and Objective-C

A common problem in software is to do something exactly once – e.g. create a singleton.  A corollary of that action is to do something exactly once in the life of an instance.  I have found myself using the corollary much more frequently as I move away from using singletons, which I’ve done to improve testability.

With singletons, a common solution is to use locking or, to avoid the performance penalty of locking, double-checked locking.  Of course, double-checked locking has issues with most modern languages caused by CPU and compiler instruction reordering.  Objective-C has provided an elegant solution to those problems, but the solution comes up a little bit short.

Creating a Singleton – Single-Threaded

In a single -threaded application, creating a singleton can be done without additional protection, like this:

01
02
03
04
05
06
07
08
09
10
+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        s_sharedInstance = [MyClass new];
    }
 
    return s_sharedInstance;
}

Creating a Singleton – Multi-Threaded

In a multi-threaded application, it’s not so simple as you will want to protect yourself against multiple callers of this method.  A simple solution simply adds a lock:

01
02
03
04
05
06
07
08
09
10
11
12
13
+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    @synchronized(self)
    {
        if (s_sharedInstance == nil)
        {
            s_sharedInstance = [MyClass new];
        }
    }
 
    return s_sharedInstance;
}

The problem with this solution is that you pay the price of locking even though you only need it the first time the method is called.

Double-Checked Locking

A common solution to avoid the penalty of locking is to use double-checked locking.  With double-checked locking you check the value of the static instance both outside and inside the lock, like this:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        @synchronized(self)
        {
            if (s_sharedInstance == nil)
            {
                s_sharedInstance = [MyClass new];
            }
        }
    }
 
    return s_sharedInstance;
}

At first blush, it would seem that this would solve the problem of assigning the static variable AND avoiding the penalty of the lock.  The problem is that the CPU and/or the compiler could reorder the memory access instructions.  A solution suggested by Mike Ash inserts memory barriers before accessing the variable and uses the volatile keyword.  The memory barrier, available in libkern/OSAtomic.h, solves the CPU problem and the volatile keyword solves the compiler problem.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
+ (MyClass *) sharedInstance
{
    static MyClass * volatile s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        @synchronized(self)
        {
            if (s_sharedInstance == nil)
            {
                OSMemoryBarrier();
                s_sharedInstance = [MyClass new];
            }
        }
    }
 
    OSMemoryBarrier();
    return s_sharedInstance;
}

The problem with this solution is that it is still quite expensive in the most common case.  Apple has provided another solution:  dispatch_once.

dispatch_once

dispatch_once is provided with Grand Central Dispatch to execute statements exactly once, like this:

01
02
03
04
05
06
07
08
09
10
11
+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
 
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        s_sharedInstance = [MyClass new];
    });
 
    return s_sharedInstance
}

This is a terrific solution for use with singletons, but what if you want to use it with an instance?  It actually happens to work, but Apple has a warning against using it in this way in the documentation for dispatch_once:

The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage (including Objective-C instance variables) is undefined.

Hmm, that’s unfortunate.  Here’s hoping Apple will change their implementation.  In the meantime, it would appear that the only solutions for the non-static and non-global case are:

  1. Use a synchronized block for every call.
  2. Use memory barriers.

References

Rolling a Ruby gem back to a previous version

I ran into a problem with the Ruby gem for a tool I use recently when I installed the latest version and then found it was broken.  I wanted to roll back to the previous version, which turns out to be extremely simple.  Here is the command I used and the responses I received:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
> sudo gem uninstall cocoapods
Password:
 
Select gem to uninstall:
1. cocoapods-0.23.0
2. cocoapods-0.24.0
3. cocoapods-0.25.0
4. cocoapods-0.26.2
5. cocoapods-0.27.1
6. cocoapods-0.28.0
7. cocoapods-0.29.0
8. cocoapods-0.30.0
9. All versions
>

I selected 8 in the list, and when I checked the version of the gem after running this command, it had indeed been rolled back.  Simple.  Sweet.  Just what I needed.

CocoaConf 2013 in San Jose

Last weekend I attended CocoaConf in San Jose.  CocoaConf is a technical conference for developers working iOS or Mac OS X.  Workshops and sessions are taught by form Apple developers and important developers in the industry, many of whom have written books.  It was a great conference, both for the content and for the opportunity to mingle with other like-minded individuals.

Resources

My Highlights

  • Beautiful and Shiny – The iOS Graphics System (all-day workshop) – The info is all available, but the workshop was a great forcing function to learn about it and try things out.
  • Unit Testing Your iOS App With Kiwi – Very interesting way to write unit tests. Built on top of the unit testing framework (OCUnit) that comes with an Xcode installation.
  • Cocoa Gesture Recognizers – Awesome flexibility.
  • Stronger, Better, Faster With Instruments And Debugging – Great introduction to using Instruments. One thing I didn’t know is that there are different instruments when you’re connected to the device and when you use the simulator.
  • Exploring MVC-N – My favorite session of the conference. The concept isn’t all that earth shattering – have a single component that is responsible for communicating over the network – but it’s one that we haven’t implemented to date that could simplify our network code.
    • The speaker is really down on 3rd party libraries because you’ve then delegated the knowledge of that area to a library you don’t know much about. Since networking is a core component of most apps, it should be something that is written in-house.
  • Cocoa Design Patterns – Presentation of using the Chain of Responsibility pattern to avoid singletons is very interesting.
  • NSPredicates for Fun and Profit – Very cool way to search through text and collections. Can make that logic very simple (or very complicated if you’re not careful).
  • Advanced Behavior and Performance Testing with UI Automation – Really interesting testing can be done with UIAutomation, but it’s all done in JavaScript and within Instruments.
    • Great list of tools provided in this talk.
  • Making Successful Apps – Good stuff for program and product management, although applicable for anyone designing and building apps.

My Detailed Notes

Beautiful and Shiny – The iOS Graphics System (all-day workshop)

Bill Dudney

  • The Layer of a UIView uses memory for every pixel
  • The frame property is now (iOS 6) a computed value.  Setting the frame sets the center and the bounds.size.
  • We shouldn’t be changing the frame on a view anymore as that messes up auto layout.
    • Note: We don’t currently use auto layout anywhere.
  • If you use the simple masks and shadows APIs, it uses offscreen rendering and is expensive.
    • Example: Rounded corners with clipsToBounds
    • Instead, use clipping masks.
    • Before you ship, always test with Debug -> Color Offscreen-Rendered in the Simulator to see what the app is doing.
  • You should avoid drawing unless you can build it in Photoshop, because drawing is expensive.
  • “Introduction to Geometric Modeling” video by professor at UC Davis who describes how Bezier curves work.
  • Don’t implement gesture handling using touchesBegan and touchesEnded.  Instead, use a gesture recognizer.

Mastering The Project File

Michele Titolo

  • Slides
  • Apparently project.pbxproj files can be converted to JSON, although I couldn’t get it to work.
    • plutil -convert json project.pbxproj

Unit Testing Your iOS App With Kiwi

Pete Hodgson

  • Slides
  • Kiwi is built on top of SenText (OCUnit) using blocks and syntax that looks vaguely like English.
  • Kiwi can handle stubbing and mocking, although he didn’t include any details in his talk.
  • It is recommended that we use CocoaPods to pull in 3rd party software.
  • “Test what you can isolate.”

Keynote:  The People We Work For

Matt Drance

  • Customers
    • Think about how what you are doing (designing, implementing a feature, fixing a bug) will make their lives better.
  • Peers
    • Communication is important in helping the team be productive.  This could be as simple as sending an email to let people know where you left off if you are going on vacation, moving to a different project or group, or leaving.   “Reduce tension in the room.”
  • You
    • Make sure you take care of yourself.
  • Tools

Cocoa Gesture Recognizers

Jonathan Penn

Stronger, Better, Faster With Instruments And Debugging

Kyle Richter

  • Slides
  • This was a fairly basic overview of the debugger and Instruments, but very useful.
  • Breakpoints:
    • Conditional breakpoints appear to be pretty performant.
  • Debugger command line:
    • The list command will list the source code around the current breakpoint.
    • The bt command will list the backtrace for the current break.
  • “Make sure you test against slower devices, such as the 3GS or the 4.”
  • There are different instruments for running on a device and running on the simulator.
  • Leaks that are the same size but aren’t grouped together may be the same leak but for some reason Instruments didn’t group them together.  This is similar to behavior we see in BugSense when grouping crashes together.
  • Other tools:
    • Network Link Conditioner.
    • Blended Layers in the Simulator
      • Using a clear background color requires iOS to composite the view with the background which is expensive.  Avoid clear background unless you can’t determine the background color.
    • Misaligned Images in the Simulator
      • Misaligned images will be slightly blurry.  Normally caused by math errors when laying out views.
    • Slow Animations in the Simulator

Exploring MVC-N

Marcus Zarra

  • Slides
  • If you’re using other people’s code (e.g. a 3rd party framework) you’re probably doing the wrong thing.  Why?  Because you consider this a solved problem but you didn’t write the code and therefore likely don’t understand what that 10,000 lines of code are doing.
  • The concept of MVC-N is that networking is separated out from the view controllers.
  • The NetworkController talks to the network and stores the result in the persistent store – Marcus uses Core Data.
    • Properties:
      • NSOperationQueue
      • NSMnagedObjectContext
    • Method
      • Different method for each type of request
    • How to create
      • Dependency injection
      • Singleton
      • AppDelegate property
  • Have one NSOperation subclass for each network call.
    • He doesn’t recommend using blocks because blocks are not easily cancelable.
    • Another problem with blocks is because of code bloat – a lot of code in one place.
  • For unit testing, he recommends setting up a simple server on the local network that always returns the same result.
  • If you can let network operation fail without notifying the user, do it.
  • Summary
    • Own your network code.
    • Don’t put network code in view controllers.
    • Keep all network code together.
    • All UI should feed from Core Data.
    • Disconnect data collection and data display.
  • http://github.com/zarrastudios
  • Questions:
    • I asked him about using Core Data for data we don’t need to persist (e.g. most of our data) and he recommended it using an in-memory store.
    • NSManagedObjectContext can be used to represent data received from the network, which represents the data as key-value pairs.

Cocoa Design Patterns

Saul Mora

  • You don’t want to release crapps.  You want to release apps.
  • Patterns
    • Chain of Responsibility pattern, aka Responder Chain
      • Call sendAction:to:from:forEvent: to make a request of an object in the hierarchy.
        • Example: Dismissing the keyboard can be done by calling this method on the application object and specifying self for the “from” property.
      • Derive the app delegate from UIResponder.
    • Command pattern
      • We do this with our operations by creating a separate object for each network operation.
    • Template pattern
  • Anti-Patterns
    • Factory, Abstract Factory
    • Singletons
      • Consider a Singleton Manager – Service Locator pattern.

NSPredicates for Fun and Profit

Josh Smith

  • Slides
  • You can use it for scanning strings, arrays, and Core Data.
  • Predicates are basically search expressions which can be strings (BEGINSWITH, ENDSWITH, CONTAINS, etc.) or a block.

Advanced Behavior and Performance Testing with UI Automation

Jonathan Penn

  • Slides and sample code
  • UIAutomation is all in JavaScript in Instruments.
  • It is completely sandboxed so you can’t use NodeJS or other frameworks.
  • You can see screenshots within Instruments as your script runs.
  • You can use the accessibilityIdentifier to display various states in Instruments as you change the state.
  • He recommends including “use strict” at the top of the script.
  • Define tests in a function in the script.  Doing this puts all messages displayed by the script on a single line that can be expanded.  This also sets a log type (e.g. Pass or Fail) and shows a different color on the timeline.
    • He showed raw JavaScript, which was very messy.
    • Then he showed functionalizing the JavaScript so that the tests looked like single statements.  Much cleaner.
  • He showed swiping up and then down repeatedly in a loop to find a memory leak.  Very cool!
  • Tools:
    • Reflector – AirPlay iOS device screen to your Mac
    • UI Screen Shooter – Take screen shots of your app for the app store
    • tuneup.js – Collection of JavaScript utilities that build upon and improve UIAutomation
    • mechanic.js – Lets you take the power of UIAutomation with the simplicity of modern JavaScript CSS selector engines to make your UIAutomation scripts terse and beautiful
    • Bwoken – iOS UIAutomation  test runner runs UIAutomation tests from the command line in the simulator or on the device
    • cisimple – Continuous integration in the cloud
    • Book: Test iOS Apps with UI Automation
    • UIAutoMonkey
    • KIF (Keep It Functional) – iOS integration testing framework

Making Successful Apps

Michael Simmons

  • Co-owner of Flexibits who created Fantastical which was at one point the top app in the App Store.  He also owns the company that does HockeyApp.
  • Why are you *really* doing this?
  • What are your goals?
    • > You cannot be on autopilot.  You have to question everything.  Otherwise, how do you know that what you are doing is right?
    • > (If the UI is good (easy to use, simple, etc.) it will be successful.)
    • Why are you doing this?
    • What do you want?
    • Dream but be realistic!
      • Don’t be afraid to ship your 1.0 with limited features, but communicate with your users what your plans are to provide those features.
  • What is your plan?
    • Too ambitious?  Not enough?  Real artists ship.
  • Who is your audience?
    • Consumers?  Professionals?  Both?
      • How can it be for both?  It can start out simple and then build up as the user uses it.
    • Creating an appropriate app is vital.
  • What is your passion?
    • What excites you?
    • What makes you happy?
    • What underwhelms you?
  • Details you should be thinking about
    • Be the best.
    • Are you doing something unique and original?
    • Marketing is not an evil word.  If you build it, they might come.  Marketing doesn’t have to be sleazy.  It is required to build awareness.
      • Marketing is also about the design of the app and of the icon.
      • They use the Icon Factory for their icons.
  • App Launch
    • Sneak peek/teaser (public beta?).  Create mystique.
    • Last minute details dialed in.
      • For sales, they use Fast Spring for selling from their website as well as selling through the App Store.  This also allows them to offer a free trial.
      • You can create promo codes to make your app available to press or others before you release.
    • Marketing/PR
      • Embargoes are tricky.  He doesn’t use them anymore because when you release through the App Store you don’t have any control on when it is actually available.
    • Launch!
      • You should do your own support because it is the lifeline to your customers.
      • Negative emails are fantastic because your users are passionate about your app.
      • Don’t rely on your users to design your app.
      • 99 cents is not the right price for app.  Is a a marketing tool.  If your app is that good it will sell.
  • So, how do you make great apps?
    • Define your goals.
    • Create a plan.  Or two.
    • Find your passion.
    • Admit your weaknesses.
  • Piwik (http://piwik.org/) – Web analytics.
  • Frequency of updates
    • You want to get an update out at least every 3 months.
    • Don’t update for the sake of updates.
  • 3rd party support (e.g. Get Satisfaction)
    • He doesn’t like them as it gets between you and your users.
    • He hates forums.
    • He prefers email support.
    • He has a policy of responding within 24 hours.  Users love it.
  • Release notes
    • If just “Bug Fixes” include the release notes for the previous version as well.
  • Keywords
    • Don’t use competitor names as keywords.
    • The obvious ones are the important ones.

Sorting Objective C Import Directives

I know I’m a bit obsessive compulsive, but I’m rather fastidious about how I organize #import statements in alphabetical order at the top of my Objective C files.  If I’m creating and maintaining the file myself, it’s not so bad, but when I work on an existing file it’s a lot more work.  Wouldn’t it be cool if I could just run the sort command on the imports?

Automator to the rescue!  By creating a service in Automator, you can create a service that is accessible from Xcode – or any other app for that matter.

Check out this article by Christian Engvall that describes the steps required to make it happen.  Pretty cool!

ARC weak references on iOS 4

I’m finally exploring ARC (Automatic Reference Counting) for development on iOS 4 and above.  Mike Ash provides a terrific introduction to ARC along with some pitfalls.

One of the pitfalls of using ARC is that weak references (aka zeroing weak references) are not supported on iOS 4 or on Snow Leopard.  You could use Mike’s MKZeroingWeakRef class with all weak references, but now there is a better option:  PLWeakCompatibility.  This package allows you to use all the goodness of ARC weak references with the native syntax.  Brilliant!

You can even get PLWeakCompatibility on GitHub so you can keep up to date on its progress.

References: