(Via Danfrth is on Tumblr.)
(Via Danfrth is on Tumblr.)
"A great read on how Windows 8 not only confused users by also developers"
Every year I say I am going to WWDC and every year it passes and I say "Next year for sure.". This year I decided it was time to put up or shut up. I did my best: I was ready at 10, logged in and started the process. I got to the checkout process after a few restarts and a couple of browsers and after I entered all my info and clicked place order, server error.
As many have reported, I got my call from Apple (although I thought it was a joke from my friends since they were sitting there when I got denied). I booked my hotel and flight and ready to go.
I am using Jeff Lamarche's First Time Guide.
I do feel bad for all the people who will not get to go. I was hoping to meet some of the cool kids while I was there yet some of them that will not be there. I plan on saying hi to as many as a can without "Being Creepy".
Working on a Mac / iOS projects, I have been trying to come up with an easy way to bump versions when it goes out the door for testing or production. Mostly I have been working it out manually, yet that is now fun after the dozenth time. I started looking around for something that would fit my workflow. I found a couple of posts that help me out.
After reading the two posts (especially the last one), it should be easy to follow what I am doing to bump the versions of the application. It feels natural with the gitflow technique. Download the code from the GitHub project here.
"This list isn't about stylistic things like which line new braces go on (new ones, duh). This list is about potential problems with the code you're writing on an objective scale. "
This is a great list. Enjoy!
" The latest versions of the Clang compiler extend the Objective-C language with related return types, which allow a limited form of covariance to be expressed. Methods with certain names (
init, etc.) are inferred to return an object of the instance type for the receiver; other methods can participate in this covariance by using the
instancetype keyword for the return type annotation. "
This is what I really want in the next version of Objective C.
I had previously published this and with all the new things I have learned, I thought it time to update and change since I am doing things different now. I admit, this seems to be a bit easier.
I have written quite a bit about using agile techniques (unit testing, continuous integration, etc) and in this post, I am going to put it all together. We will go through how to setup the project, build the application test first, how to integrate code coverage and source control flow to build features.
The application itself is not all that important. I picked something that would be easy to build and demonstrate the concepts. The application is a contact application. I based it around the post of Building a Modern Cocoa App by Martin Pilkington. I think the post does a great job of explaining an approach to building modern Cocoa Applications that I have taken when building apps for the Mac. The contact manager application is a Cocoa Application that uses Core Data as it's backing store with Unit Tests which gives us two projects, ContactManager and ContactManagerTests.
After creating the project in Xcode 4, I needed to make a few changes to the project. The first thing I wanted to do is change to use the LVVM compiler and the lldb debugger. I also set the build to always run the static analyzer. The other thing I wanted to do is get code coverage. I also added some tools to the project. Since I am going to be doing test first, I added the OCMock framework and because I wanted some output for the code coverage, I added the lcov toolset from Linux (geninfo, genhtml).
For OCMock, I added the framework to the ContactManagerTests project. The problem I ran into was that the framework would not load into the test bundle because it could not be found. This is because of the location of the file in the Frameworks directory. I had to change the Runpath Search Path to @loader_path/../Framework.
For the Coverage configuration in the ContactManager project, I did the following:
All of this setup can be done once and create a custom project if you create a lot of these types of projects.
Now that we have everything setup and ready to go, we need to figure out how to break this code into it's parts. The application stores contacts in Core Data and uses binding KVO / KVC to build out the UI. The first story I decided to take on saving a contact (since that is one of the major features of the app). I am going to describe this story (and not all of them) and you can look at the rest of the code to see how things
Save a Contact
I decided that I wanted to store first name, last name, email and phone number. Nothing amazing here. I do this with the Core Data modeler and create a Contact object class from the model I created. After this I decide to create a ContactDataController that would manage contact data. I decided to also add a CoreDataController that would manage the Core Data infrastructure (much like that from the Modern App by Martin). One thing I didn't want is a Singleton. Singletons are really hard to test and I avoid them as much as possible. For this I decided to inject the CoreDataController into the ContactDataController and make that the default initializer.
Once I had this infrastructure and tests in place I created the UI and the list and detail view controllers for the UI, I needed to figure out how to add the tests to ensure that things are working properly. Chris Hanson has had a great set of posts on doing just this. The main idea is that you will trust that Cocoa will do the right thing (KVO / KVC) but you want to verify that all the things are setup to make it work. I did just this by creating some simple methods that verify that Cocoa hooked up my Views and Controllers and that I didn't forget anything. If you look at the tests, it is pretty easy to see how this works.
That is the pattern that I followed for all the code in this application. You can review the rest of the code to see how it all fits together.
After the setup, when you run your tests, you get the code that is covered. The key here is how you want to view it. Once you have your code instrumented, you can use a tool like CoverStory to view it, yet I wanted something more automated. I found a great article that fits in with my workflow. This allows me to use lcov to generate a file that I can see before I integrate into CI (Continuous Integration) server.
Since I do not install the command line tools I did change the envcov.sh file to add the bin file to the path that includes gcov.
You will have to download the lcov tool for the project since the licence is iffy.
Source Control Flow
This one was pretty easy as well. I followed the process from here. They call this git flow and it is pretty well laid out. I used this for all my projects now. The key is that you have to use branches. You do everything off topic branches and master is pretty much your release. I find that doing this helps me focus on working on one thing at a time. If I am writing a large commit message that includes to much work... I feel I am breaking some sort of magical law :).
I use home-brew to install everything. You can install git and gitflow using this.
The code is the best place to learn. I hope you find a few nuggets in here that you can use on your projects. It has taken me a while to find my groove yet I am really happy with this now. And I am always looking to improve.
In our Hilo project we wrote TDD with lots of unit tests. The one thing we noticed is there were no good way to run tests that were asynchronous. Given that most everything in Windows 8 store apps need to be async, we wrote some test helpers to do this. Looks like the team took this and made an extension to easily get it. The only thing that is missing is the UI portion of the helpers. If you really need that (and you probably will), you can get it from the Hilo project.
"To create an anxiety relievable only by a purchase… that is the job of advertising.
Advertising increases familiarity, reminds consumers about your product, and spreads product news. We covered all that before. Today we’re looking at a fourth job advertising does: it defeats inertia.
Getting Customers to Switch
People don’t hate progress, they just prefer inertia. This stops them from buying your product even when it’s the logical choice."
(Via The Intercom Blog.)
This is a great article to think about your customer and your project.