- Software quality landscape today
- Poor Quality affects release dates and users
- How testing affects culture
If you haven’t seen my slides on How to quickly eat your own dogfood in iOS, you should. It allows you to get the product in your hands faster and can help eliminate any assumptions you have about the UX by actually using it. The biggest caveat you run into is having configurations on a per target basis. For example, Google Cloud Messaging requires a
GoogleService-Info.plist file in your bundle that contains a
GCM_SENDER_ID and a
BUNDLE_ID. The values will be different for both your beta builds and production builds. You can’t have two of these files because you’d have to name them differently and the Google library loads the plist directly by name.
The solution is to modify the
GoogleService-Info.plist file after it’s been copied to the bundle. First add a step to your current
Build Phase, specifically after “
Copy Bundle Resources“. OS X has a built-in tool called PListBuddy which we’ll use to modify the
GoogleService-Info.plist once it’s been copied to the bundle. It’s ok to modify it in the bundle before it’s been digitally signed.
/usr/libexec/PlistBuddy -c "Set GCM_SENDER_ID " $BUILT_PRODUCTS_DIR/.app/GoogleService-Info.plist /usr/libexec/PlistBuddy -c "Set BUNDLE_ID " $BUILT_PRODUCTS_DIR/.app/GoogleService-Info.plist
Perform a clean, then build and you’re good to go. Alternatively, if you don’t want to hide configurations like this in an IDE, put it in a separate
.sh file and execute the script. This way you can see that there is a file in source control and it’s not hidden to other developers with an IDE setting.
You could also use this technique to modify your Info.plist values between your prod and beta builds, so you don’t have to have separate .plist files for each of them.
One of the biggest things I miss about mobile development is remote crash reporting. It was absolutely essential. It was funny at the time because it seemed like such a revolutionary concept but then I realized that I should have been doing this for both languages on the server and in the browser. Now that I’m not doing as much mobile development I started looking for a similar exception aggregation system. I was pleased to find a language agnostic system called Sentry.
If you’d like to take it a step further, you can create a wrapper that instantiates the logger and configures it for you.
You can generate multiple loggers in different classes/files.
var logger = com.restlessThinker.Logger.getLogger('newLogger'); logger.fatal('log this to sentry');
I hope this helps!
After reading it, it’s easy to see their perspective on when it’s necessary and that their implementation was very simple. We simply need to check if an object contains the specific methods defined in an interface. It uses duck typing to determine if the method exists, it doesn’t care about the parameters but just so you don’t get undefined is not a function. We obviously don’t want this everywhere but I find it works in a few scenarios. First, if we need to group classes. Second, if we must implement some design pattern that requires an interface. Third, if we have to invoke methods on a dependency injected object that we want to throw errors if a method does not exist and give other developers working on the same code feedback.
The slides are now on speaker deck.
I’ve been seeing a lot this topic lately and I thought I’d share my opinion on it. The first thing I’d like to say is that binding is easily the #1 feature request that I want brought over to iOS from Cocoa on OS X. As a long time Flex developer I’ve had the enjoyment of binding data to UI controls. For front-end development, it saves so much time and you start wondering how you’ve ever developed front-ends without it.
Even though it’s been a complete dream of mine to have reactive programming on iOS, here are the key reasons for me on why I’m waiting:
Binding is expensive. On iOS, we don’t have the luxury of speed of a desktop or laptop computer. Over time this will change but there is still a large number of devices that are iPhone 4, 4S and older generation iPads. To me this makes sense as the #1 reason that Apple hasn’t included binding in iOS. Reactive Cocoa, the popular framework for iOS is seeing a little bit of the performance issues that binding presents. I strongly believe in Larry Pages quote about speed:“Speed is product feature number one”
I’m not talking about premature optimization here but if your software performs faster your users will have a better user experience, and that is what matters the most. A lot of the early versions of libraries will have performance issues.
Reactive Cocoa is a great library for achieving binding on iOS, but what are you going to do when Apple finally includes binding natively on iOS? Will you update all of your apps? One example I have is NSJSONSerialization. There were a few libraries out there that touted ease of use and performance benefits and you had to do your own analysis on each library and decide. When it released, it was the fastest JSON serializer available on iOS and it shipped with Cocoa so you don’t have to worry about updating the library. It’s very easy for developers to ignore changes that should be made internally to an app that will be better long term.
It’s very easy to complicate application architecture with such a powerful tool. In my Flex days, there were developers using binding at an entire class level versus property level and they kept all of the models in the entire application in one class to seem “tidy” but was suffering huge performance issues over time because the binding had to react to every single property in that class whenever binding fired. This would be an absolute nightmare on a mobile device with smaller resources.
There are some benefits to using reactive cocoa or other binding frameworks on iOS, just use it wisely and program on purpose.
It takes a lot of discipline to go against the popular trend right now but with these trade-offs, I think I’ll wait a little longer. I’m confident that reactive programming on iOS will be as common as IBOutlet.