Ray Yamamoto Hilton
Freelance Mobile Architect & iOS Developer in Melbourne, Australia
~

Time and Materials vs Fixed Price

I often get asked why I prefer Time & Materials to Fixed Price, and why it’s better for the client.

The main concern people express are that T&M means that the cost is unpredictable for the client.

A fixed-price project has to try and absorb some of the risk of the project unknowns, the larger the project, the more risk and therefore the higher cost. A way to reduce the fixed cost is to do a lot of upfront plannig (e.g. completed wireframes and designs) so that development can get going with the minimum of ramp up time.

However, any project can start with the best of intentions, the most well-laid plan, the best possible chance of success – but EVERY project changes. Despite the most meticulous planning, changes may become necessary, or change is artificially prevented to keep the project on track. This leads to Change Requests (i.e. financial penalties for change) or delivering a project which is no longer what is needed.

I prefer not to have to say “no” and be able to accomodate new and better ideas to try and make the best possible product within your budget. However, it may not be possible to acheive everything given a limited budget – but we can almost certainly acheive something significant.

Time and Materials keeps the cost down to only the time that is used – the risk is shifted from me to you in exchange for a lower overall cost. Furthermore, control of the project is placed firmly in your hands and not subject to the overhead of fixed-scope contracts or change requests.

Having said that, if you are willing to let go of precise scope, you can fix the time (i.e. the price) and we will work backwards from there to determine a rough scope. Your prioritisation will determine which things are certain to happen, and which will be at risk.

Speed Limiter for iOS7

This was the very first app I worked on for the App Store, and it’s been in need of much love. It’s such a simple app that just beeps when you approach a given speed limit. I’ve added a custom control to set the speed which also better reflects the current state. I’ve also updated the UI to reflect the more modern, simplistic approach taken in iOS7.

Take a look at the before and after shots!

Before

You may need to shield your eyes and peek cautiously through your fingers.

Screenshot 1 Screenshot 2

After

Screenshot 3 Screenshot 4 Screenshot 5

Australia Post Digital Mailbox

I recently worked on the Australia Post Digital Mailbox iPhone & iPad apps. The product aims to provide a secure mechanism for consumers to receive and pay for bills with a number of providers. More information can be found here and the app is available for download in the iTunes App Store.

Internet Broadcasting with HTTP Live Streaming

Emit Media is trying to bring modern internet streaming to the community broadcasting sector in an affordable and flexible way. We have chosen HLS to be the backbone of our strategy to acheive high-scale and low-cost. I gave this presentation at Cocoaheads on the 9th May 2013.

Xcoder - DiUS iOS SIG presentation

A quick lunch-time presentation at DiUS’ iOS special interest group about Xcoder. I gave a quick overview of the background, motivations and what Xcoder can and cant do.

Reactive Extensions (Rx) - Cocoaheads presentation

Last night was the last Cocoaheads in Melbourne for the year and the format was a series of lightning talks about technology and apps. I put my hand up to do a quick run down of the concepts behind Reactive Extensions. I also touch on Reactive Cocoa (by GitHub) and how you might tackle some common async problems.

Chromatic - Cocoaheads presentation

This is a presentation I did earlier this year at Cocoaheads Melbourne about my app ‘Chromatic’. It was my first personal foray into paid apps and OpenGL, so I thought it would be an helpful to share my experiences.

Ray Hilton presents Chromatic – Melbourne Cocoaheads February 2012 from Melbourne Cocoaheads on Vimeo.

Layout Toolkit for iOS

iOS6 Introduces a the OSX constraints-based layout engine for using sets of rules to dynamically respond to frame changes. While this will make our lives a lot easier in the long run, the reality is that we will still need to support iOS5 for a while yet.

I wanted to create a simple view layout framework that could easily be ported to iOS6’s constraints-based system when the time comes. As such, the language is fairly semantic and the API is very lightweight.

The tools are implemented as a category on UIView. Class-methods are used to build layout views that can contain many subviews (e.g. Vertical, Horizontal and Pinned layouts, while instance-methods are used to wrap the current view and return the new view (e.g. Padding, Clipping, etc).

Code

You can find the code on github in the WSFoundation project.

Prettify your Layout Code

I wanted to avoid the procedural look that loadView() tends to take on:

1
2
3
4
5
6
7
8
9
10
11
UIView *myView = [[UIView alloc] initWithFrame:CGRectZero];
myView.backgroundColor = [UIColor blueColor];
myView.layer.borderWidth = 1;
myView.layer.borderColor = [UIColor greenColor].CGColor;

UIView *innerView = [[UIVIew alloc] initWithFrame:CGRectZero];
innerView.backgroundColor = [UIColor redColor];

[myView addSubview:innerView];

self.view = myView;

Rather, take advantage of blocks so that there is a visual mapping of code-nesting to the view hierarchy:

1
2
3
4
5
6
7
8
9
self.view = [UIView view:^(UIView *myView) {
  myView.backgroundColor = [UIColor blueColor];
  myView.layer.borderWidth = 1;
  myView.layer.borderColor = [UIColor greenColor].CGColor;

  [myView addSubview:[UIView view:^(UIView *innerView) {
      innerView.backgroundColor = [UIColor redColor];
  }]];
}];

I find that the second example is much easier to visually parse and understand. Furthermore, in many cases, you can avoid having to implement a custom layoutSubviews or viewWillLayoutSubviews method by rethinking your views to fit into one of the cases below.

The main entry point for this code is the UIView+WSLayout category. You can instantiate and extend the internal view classes, but the category should suffice for the following cases:

Layout Views

Vertical And Horizontal Layout

1
2
3
4
5
self.view = [UIView verticalLayoutView:^(UIView *verticalLayoutView) {
  [verticalLayoutView addSubview:titleLabel];
  [verticalLayoutView addFixedSpace:10];         // Utility method to add a fixed space
  [verticalLayoutView addSubview:bodyLabel];
}];

Stacks all subviews in the given direction from top-bottom (vertical) or left-right (horizontal). The layout engine will honour the view’s sizeThatFits: to calculate it’s optimum size and will stretch out subviews that declare their autoresizing masks as being flexible height/width. These views can be nested, such that a vertical view could contain a horizontal view for a button bar, etc. This is really useful for building content views.

Pinned Layout

1
2
3
4
5
6
7
8
9
self.view = [UIView pinnedToBoundsLayoutView:^(UIView *pinnedView){
  [pinnedView addSubview:backgroundImageView];
  [pinnedView addSubview:gradientOverlay];
  [pinnedView addSubview:[UIView horizontalLayoutView:^(UIView *horizontalView) {
      [horizontalView addSubview:leftButton];
      [horizontalView addFlexibleSpace];          // Utility method to add a stretchable space
      [horizontalView addSunview:rightButton];
  }]];
}];

All subviews inherit the bounds of the container. The container will consult all subviews for sizeThatFits: and return a CGSize that honours the largest height & width. This is useful for creating a view that has a few transparent views stacked in the z-axis, such as a background image, gradient overlay and then some text & buttons.

Wrapped Views

Generic Container

1
[view withContainer]

Returns a view that forwards sizeThatFits: and layoutSubviews to the receiver. It also sets the receiver’s frame to be the container views bounds. This is useful for situations where you have conflicting properties to apply to a view, such as using maskToBounds for cornerRadius as well as a drop shadow or transforming a view without changing the layout code). For example:

1
2
3
4
5
6
7
8
9
10
11
12
[[[view apply:^(UIView *view) {
  view.layer.cornerRadius = 3
  view.layer.borderWidth = 1;
  view.layer.borderColor = [UIColor greenColor].CGColor;
  view.layer.maskToBounds = YES;
}] withContainer] apply:^(UIView *view) {   
  view.layer.maskToBounds = NO;
  
  // Place frame outside of the bounds
  shadowView.frame = CGRectMake(0,view.frame.size.height, view.frame.size.width, 4);
  [view addSubview:shadowView];
}];

This will set the view to have a border with a corner radius. No subview can be drawn outside of the view’s bounds with maskToBounds turned on, so we use withContainer to return a wrapping view that can have additional views added to it. The

Fixed Size

1
[view withFixedSize:CGSizeMake(320,44)];

This will return a view with a fixed size of 320,44 and stretch the original view’s bounds to fit. This is useful when the original class (say a UIButton, which is not easily subclassable) does not implement sizeThatFits: as desired and you wish to wrap it in a view that will always return a given size. You can define behaviour without subclassing as follows:

1
2
3
4
[view withCalculatedSize:^CGSize(UIView *viewToSize, CGSize sizeToFit) {
  CGSize innerSize = [viewToSize sizeThatFits:sizeToFit];
  return CGSizeMake(innerSize.width*2, innerSize.height*2);       // Double the size of the inner view
}];

Padding & EdgeInsets

1
[view withEdgeInsets:UIEdgeInsetsMake(5,15,30,5)];

Returns a view that will pad the current view using the UIEdgeInsets provided. There is also a convenience method to inset the view on all sides by the same amount:

1
[view withPadding:20];

The above is synonymous to calling withEdgeInsets with 20 pixels on each side.

Centreing

1
[view withCentreing];

Returns a view that positions the current view in the centre of the bounds.

Scrolling

1
[view withScrolling];

Wraps the given view in a scroll view container that will call sizeThatFits on the subview. If the content size is less than the bounds of the scroll view, it will attempt to stretch it to be the same height. If this is a layout view, then it will stretch the flexible regions to make the most of the space.

apply:

1
2
3
[view apply:^(UIView *view) {
  view.backgroundColor = [UIColor redColor];
}];

There is also an apply: method added to the view, which simply yields the current view. This allows additional in-line configuration of a view without having to assign the view to a local variable.

Limitations and Gotchas

  • A horizontal/vertical layout container will stretch the view in the non-alignment direction
  • If marked with a flexible autoresizingMask in the alignment direction, it will be ignored when calculating minimum size, but stretched proportionally if the frame is larger.
  • The layout containers make heavy use of sizeThatFits:, if a view does not implement this as ‘calculate and return the size that best fits its subviews’, then odd behaviour can start to creep in.

Hood v2

We recently updated Hood to v2. This release marks massive speed improvements, simpler UI and more focused utility. This was a pretty significant re-write on both the server and client-side that has been a couple of months in the making.

On the server-side, we’ve really improved the speed of the system by being smarter about caching and more aggressive in how we fetch content. We’ve also refined the API so that the client does less smarts, allowing the server to tweak things like ordering, pagination size, refresh times, etc. We also fetch data from more sources while returning less duplicates.

On the client-side, we had an almost entire UI re-write. We removed unused features (like photos/people browsing) and, based on user-feedback, focused more on locations. We now allow you to continue browsing a location after you leave there as well as returning to other recently visited locations. We removed a lot of client-side storage logic that really slowed down the experience (a painful example of how premature optimisation can lead to caching working against your intention).

I’ll be posting an article in the next couple of weeks about the layout code used to achieve much of the Hood UI.

The app has just been released and is available on the iTunes App Store

Screenshot 1 Screenshot 1 Screenshot 1 Screenshot 1

So, you want to build an iPhone App?

You’ve had an idea and you’d like to build an iPhone App but where do you start?

I have tried to list some of the challenges that may affect your plans for world domination. This is not meant to be a negative article but perhaps it reflects on the sorts of common scenarios that I, and other developers, tend to see every day. I hope that this will not dissuade you, but perhaps it will allow you to more rigorously critique your own ideas and attitudes.

Needless to say, these are my opinions based on what I have experienced, but I hope it can help prospective entrepreneurs avoid some of the most common hurdles.

This is by no means an exhaustive list and I may add to it over time.

Our Relationship

A good working relationship is key to delivering quality products.

Ideally, we would be co-located as that can help us become more sympathetic to each other’s motivations. The most enjoyable (productive?) working relationship is a highly dynamic one where we set noble goals and are willing to adapt and change in order to do the best possible job.

Don’t plan too much

“I have it all worked out and I just need someone to develop it”

This phrase will raise a red-flag with most developers as it makes the assumption that development is just a linear, assembly-line process. It also suggest that too much time may have been spent on planning. Traditional thinking may lead people to think that planning what you’re going to do before approaching developers/designers is a good thing. However, this can lead to significant emotional investment and therefore resistance to change. This will limit our ability to innovate.

Ideally, I would like to start talking as early as possible to make sure you are making decisions with as much information as possible.

Having said that, if you do have a very specific idea of what you want and you feel you have already got it set out in sufficient detail, you could consider off-shore development. This will probably work out cheaper in the short term if you have everything prepared up front, as it is working out what your product is that is the hard part.

Originality & Competition

It is almost certain that your idea isn’t original, and that is not a bad thing.

If there is competition, it goes without saying to do some research about who they are and why you think they have succeeded (or not).

If there doesn’t appear to be anyone in the market yet, it is probably safe to assume that is because people have tried and failed to do so. Assuming that your idea is unique and original will lead you down a path of naive optimism. It’s a worthwhile exercise to take the mindset that your idea is NOT original and try and work through the problems others have had.

Accept failure

It will happen, perhaps over and over again.

The success stories are from people who don’t give up and learn from their experiences. Failure is a necessary part of becoming successful and a perfectly normal part of business. In fact, we strive to fail early if we have to fail at all, as we minimise costs and have enough remaining stamina to try and try again (and again).

I will go on-and-on about getting to market as soon as possible.

Be open to critique

Your ideas will be open to a lot of criticism by the market, and customers can be brutally honest. As we work through the ideas and try and bed down the nature of the product, we will have to be brutally honest with ourselves and push back on every idea, every screen, every button to make sure it stands up to our rigorous standards and high-level goals.

I will push back and critique many aspects of the product to make sure we put effort into areas that matter and avoid spending too much time/money on dead-ends.

Be pragmatic, be flexible

You may have to let go of some of your preconceived notions in order to allow innovation around your core ideas occur. This can be very challenging.

During prototyping and development we may realise that we are solving the wrong problem, and we will need to revisit our basic assumptions and change tact.

Once you are in the market, you can react directly to the real-world rather than second-guessing ourselves and trying to infer what the mythical customer wants. Your ideas and the market are all subject to change and you must be prepared to embrace the chaos and react to the changing demands. This doesn’t mean you implement every whim of the customers, rather you try and get good at recognising opportunities that can help you more strongly define your product.

You will probably want to have a quick look at the Agile and Lean approaches to software development. Agile details a simple set of high-level goals – a guiding philosophy – to keep focused on whats important in a team. I wont try and reproduce the wealth of good material out there around these subjects, but a good starting point

I will almost guarantee that the idea you have now will not be quite the same after a week or two of working together.

Execution > Idea

Ideas are common, good execution is rare.

By execution we mean the way your product is presented to the user, how it performs and how much utility it has. These are very hard things to get just right and its worth workshopping through these at an early stage to re-enforce the good ideas and throw out the not-so-good ones.

Do Less

There is still a prevailing attitude in the software world to deliver products that do everything under the sun. These are often very expensive products that most people only use a small proportion of. A disruptive product could enter a market like this and target that small proportion at a fraction of the incumbents price.

Long feature lists are a bad idea; they will burn up your budget and offer diminishing returns. Try placing your features in order of importance and pick the least number of features that can make a viable product. We can then work on more features for a subsequent release with the benefit of market feedback.

Just In Time

Why do today what can be done tomorrow?

Deliver what you need to deliver and follow up with additional functionality before people need it. A good anecdote is how 37 Signals delivered Basecamp without a billing system – they billed in monthly cycles so had 30-days in which to work out a solution, so there was no need to delay their main product launch.

Money & Time

It’s expensive to build and app (Typically >$40k) but thats not the end of it.

You also need a design and marketing budget to make sure your app has the best possible chance of surviving and gaining traction. Subsequently, you will want to update the app to respond to market demand and you will probably have on-going marketing and hosting costs. These bills stack up and they will generally overshadow what you initially spend on development, so its important to work out a budget you are willing to commit and we can work backwards from there.

I normally suggest that the project should take 3 months or less and 2-4 people on the team. Adjust your project scope to fit, not the other way around. This will help you choose whats most important and allow us to deliver a polished product on time without compromising quality.

Tip of the Iceberg

Usually, apps don’t exist in isolation. There can be several back-end services that provide storage, communications, administration, etc. These services can sometimes be quite large and complex in their own right. If your app needs to communicate with other users, integrate with social networks or use third-party APIs, it will probably need server-side development.

Web apps are a viable alternative

Native apps are attractive because they offer deeper integration with the platform and slicker performance, but they are not always the right option. If you are prototyping an idea or you need cross-device/platform early on then I would suggest you consider starting with a web-based product and build out native versions when you really need it.

Can I pay you in equity?

Probably not.

I cannot speak for all developers, but I would be surprised if any would accept equity over cash at an early idea stage. Putting aside for one moment that the idea is only a small proportion of what makes a good product, this is really a question of the developer investing in your business.

Many developers will choose to invest their risk in their own projects. If they are going to choose to invest their time in your project, then it will cease to be your project to run as-you-wish and a share in control will need to be negotiated. Joel Spolsky wrote a good answer on how to divvy up ownership in a new startup.

For me, the most appealing investment opportunity is one where the members of the team have complimentary skills and a demonstrated ability to innovate, react and most importantly, deliver.

Everyone is different, and your milage may vary.

Crowded App Store

Just because you are in the App Store doesn’t mean you will get a torrent of downloads.

In fact, it is quite usual for not much to happen. There are tactics you can employ to get the attention of Apple and get featured in one of their categories, but maintaining the traffic after these features expires can be tough.

Mentoring & Seed Funding

If you feel you need to get some mentoring to get your business going, you could consider approaching a startup accelerator like AngelCube, StartMate or PushStart. Their schemes vary, but basically they provide you with seed funding (~20k) for a percentage (~10%) of your company and aim to get your product pitch honed within a 3 months and put you in front of as many investors as possible to secure your next round of funding. The interview process itself is pretty gruelling, but if you survive you will be brimming with confidence.

Further Reading

I would recommend reading (or at least flicking through):