Monday, July 28, 2014

Today's Challenge: Move

I took a couple weeks off from running. Studying for an interview, a trip, my wife on a business trip (solo Dad with 2 kids), and working on my house meant I had to cut something. So I cut running.

Thankfully, the house has been a good physical activity that has included a bit of movement to keep me happy. You see, I am happy when I am physical.

For me, running, swimming, biking, and everything else I do is not just to stay in shape, it's to stay happy. Read any number of studies and think about our past. Humans were meant to move.

So this morning I got in a run and I feel awesome. The thing is, before the run, and last night I knew I would go for a run today but I did not want to. I am sure you probably don't want to either.

Here was my thinking yesterday:

  • I am too sore from house work (painting, caulking, scraping paint).
  • I have put on weight not working out the past 3 weeks.
  • My sneakers are probably too old and I will be sore.
  • I'll probably get blisters.
  • Blah Blah Blah
RUN!

I woke up at 6:15 AM this morning and felt great. Surprising since last night I went to bed about 10 after taking some Advil since I was aching all over. I was painting the house this weekend and spent a solid two days working on the house. It is coming along great but I did not expect to wake up feeling good.

So, I ignored my few aches and pains. I stuffed my fat ass into a pair of running shorts. I laced up those old sneakers. And I pounded the pavement.

As I ran I felt free. I felt alive. I felt good.

Ya, it was not my best run, my fastest, or my cleanest. But I did it.

As I thought about this I realized we are just meant to move. This movement can come in many forms. For example, if you are like me you don't wake up thinking, how can I squeeze in some time to paint the house today? But these days I think that. Is it just the fact that house is going to look good? Maybe a bit but a lot of it is climbing up and down that ladder. It is movement.

When I bought our current house I had many people tell me it was a mistake. They said, "You should have gotten a new house so you don't need to do any work on it for 5-10 years."

You know what those people were telling me? You need to find more ways to not move.

Screw that.

I think you should buy that house that needs a coat of paint. It needs some work done. Don't know how to do it? Great, learn. I sure as sunshine don't know how to do a lot of what I do. I just figure it out.

The best part of figuring it out and doing it is you get so many intangible benefits. You get exercise. You get a sense of accomplishment. And you get to know you just paid yourself first since you never paid some contractor to do a job you won't be happy with since it took longer than you expected and cost more than you wanted to pay.

So, for me. I say, find more ways to move. Find more ways to learn. Find more ways to work with your hands. Even though you think that it will suck, you'll thank yourself in the end for having done it.

Your challenge today? Move.

Friday, July 25, 2014

Snooping On Mac OS X Apps

On iOS an app is limited in scope to it's sandbox (unless you are on a jailbroken device) and so you can take a quick look at the apps filesystem within Xcode to see what it is storing. This is not so for the keychain but you can guess the keychain is in use if the app links the Security.framework.

Now, for Mac OS X, since the app may have access to more resources it can be harder to track down what resources the app you are testing is using. There are a couple ways to figure this out though. Here are the ways I use to get an idea what resources a Mac OS X app is using:

  • Activity Monitor.app
    • Launch Activity Monitor
    • Find your app
    • Double click it
    • Choose the "Open File and Ports" tab.
    • See what the app has open currently
  • Use Dtrace
    • This is the long bread method of finding out what your app is doing.
    • Even better you can trace all file opens on a specific process (meaning you get a trace of the opens int eh terminal).
    • To do this open Terminal.app
    • This command must be run as root so I will show you the command with sudo at the front which will prompt the terminal to ask for your root password to complete the command:
      • sudo opensnoop
Here is sample output from opensnoop:
sudo opensnoop
  UID    PID COMM          FD PATH                 
   89  72769 mdworker       7 /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/OpenGLES.framework/glp_sh_interposer.dylib.dSYM/Contents 
   89  72769 mdworker       7 /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/OpenGLES.framework/glp_sh_interposer.dylib.dSYM/Contents/Resources 
   89  72769 mdworker       7 /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/OpenGLES.framework/glp_sh_interposer.dylib.dSYM/Contents/Resources/DWARF 
   89  72769 mdworker       7 /Developer/Applications/Xcode.app/Contents/Library/Spotlight/uuid.mdimporter

Notice that you get the User ID, the Process ID, the Process (COMM), the File Descriptor, and the Path to the file that was opened.

You can play with opensnoop to limit by process name, process id, etc.  Here is the usage output:
USAGE: opensnoop [-a|-A|-ceghsvxZ] [-f pathname]
                 [-n name] [-p PID]
       opensnoop                # default output
                -a              # print most data
                -A              # dump all data, space delimited
                -c              # print cwd of process
                -e              # print errno value
                -g              # print command arguments
                -s              # print start time, us
                -v              # print start time, string
                -x              # only print failed opens
                -Z              # print zonename
                -f pathname # pathname name to snoop
                -n name # process name to snoop
                -p PID # process ID to snoop
  eg,
       opensnoop -v             # human readable timestamps
       opensnoop -e             # see error codes
       opensnoop -f /etc/motd   # snoop this file only

I like to use this by process name, start the process, run the app a bit to exercise most of the functionality, and then look at what opensnoop found. Turn on printing of the errno values and you can see if any file opens are failing.

Come to think of it, another Dtrace script I love is errinfo. This one will show you system calls that are returning an error. It is a good one to use when you know the name of a process having a problem. For example, I once worked with a app that was not logging when it launched another process but the process never started. Missed error checking aside, I used this to show that the exec was failing due to a permission error. The permissions on the sub-process were not set correctly and the other process, running as a different user could not exec the process since it did not have the correct permissions. We fixed the missing error checking and the permission error and all was well.

If you want to know what Dtrace scripts your Mac has then run "apropos Dtrace". Here is what my Mac is showing for Mavericks:
Tcl_CommandTraceInfo(3tcl), Tcl_TraceCommand(3tcl), Tcl_UntraceCommand(3tcl) - monitor renames and deletes of a command
bitesize.d(1m)           - analyse disk I/O size by process. Uses DTrace
cpuwalk.d(1m)            - Measure which CPUs a process runs on. Uses DTrace
creatbyproc.d(1m)        - snoop creat()s by process name. Uses DTrace
dappprof(1m)             - profile user and lib function usage. Uses DTrace
dapptrace(1m)            - trace user and library function usage. Uses DTrace
diskhits(1m)             - disk access by file offset. Uses DTrace
dispqlen.d(1m)           - dispatcher queue length by CPU. Uses DTrace
dtrace(1)                - generic front-end to the DTrace facility
dtruss(1m)               - process syscall details. Uses DTrace
errinfo(1m)              - print errno for syscall fails. Uses DTrace
execsnoop(1m)            - snoop new process execution. Uses DTrace
fddist(1m)               - file descriptor usage distributions. Uses DTrace
filebyproc.d(1m)         - snoop opens by process name. Uses DTrace
hotspot.d(1m)            - print disk event by location. Uses DTrace
httpdstat.d(1m)          - realtime httpd statistics. Uses DTrace
iofile.d(1m)             - I/O wait time by file and process. Uses DTrace
iofileb.d(1m)            - I/O bytes by file and process. Uses DTrace
iopattern(1m)            - print disk I/O pattern. Uses DTrace
iopending(1m)            - plot number of pending disk events. Uses DTrace
iosnoop(1m)              - snoop I/O events as they occur. Uses DTrace
iotop(1m)                - display top disk I/O events by process. Uses DTrace
kill.d(1m)               - snoop process signals as they occur. Uses DTrace
lastwords(1m)            - print syscalls before exit. Uses DTrace
loads.d(1m)              - print load averages. Uses DTrace
newproc.d(1m)            - snoop new processes. Uses DTrace
opensnoop(1m)            - snoop file opens as they occur. Uses DTrace
pathopens.d(1m)          - full pathnames opened ok count. Uses DTrace
perldtrace(1)            - Perl's support for DTrace
pidpersec.d(1m)          - print new PIDs per sec. Uses DTrace
plockstat(1)             - front-end to DTrace to print statistics about POSIX mutexes and read/write locks
priclass.d(1m)           - priority distribution by scheduling class. Uses DTrace
pridist.d(1m)            - process priority distribution. Uses DTrace
procsystime(1m)          - analyse system call times. Uses DTrace
runocc.d(1m)             - run queue occupancy by CPU. Uses DTrace
rwbypid.d(1m)            - read/write calls by PID. Uses DTrace
rwbytype.d(1m)           - read/write bytes by vnode type. Uses DTrace
rwsnoop(1m)              - snoop read/write events. Uses DTrace
sampleproc(1m)           - sample processes on the CPUs. Uses DTrace
seeksize.d(1m)           - print disk event seek report. Uses DTrace
setuids.d(1m)            - snoop setuid calls as they occur. Uses DTrace
sigdist.d(1m)            - signal distribution by process. Uses DTrace
syscallbypid.d(1m)       - syscalls by process ID. Uses DTrace
syscallbyproc.d(1m)      - syscalls by process name. Uses DTrace
syscallbysysc.d(1m)      - syscalls by syscall. Uses DTrace
topsyscall(1m)           - top syscalls by syscall name. Uses DTrace
topsysproc(1m)           - top syscalls by process name. Uses DTrace
weblatency.d(1m)         - website latency statistics. Uses DTrace

Have fun with Dtrace, it can open up your debugging and give you a view into processes you don't own.

Wednesday, July 23, 2014

Breaking Mac Apps

One of the reasons I took my current gig as a Software Development Engineer Test (SDET) was so I could learn more about my craft of software development. Too often as the developer under stress to get something out the door it can be tempting to do the minimum testing possible to get the feature out the door. That temptation is tempered by the fact that you know if you ship crap then you will have more headaches than spending the extra time now to get it right.

So, I wanted to concentrate on breaking a product too see what I learn by finding it's rough spots. This has been fun at times in the sense that I am actually learning ways to more effectively test my own software. I plan to use this knowledge to write better software myself.

I am currently testing a product on both Mac OS X and iOS. As a dev I have some things I learned from writing Mac apps that I have been able to put to use in my job as a tester.

One of those is to always test the First Run case. What is this? The First Run test involves running the app as if you were a new user installing and running the app for the first time.

How to do this on Mac?

  • Does the app use the Keychain to store anything? Find out and make sure to clear it before you run the test.
  • Does the app use the User Defaults to store anything? Probably, so go learn the command line tool defaults. Here is a short primer:
    • Open Terminal.app
    • Run this: defaults
      • Now you have the standard usage (screenshot shown above).
    • If you app's defaults are stored in the domain "com.mycompany.myapp" then type this to view what the app is storing: 
      • defaults read com.mycompany.myapp
    • Now before a First Run test run this to clear the stored setting: 
      • defaults delete com.mycompany.myapp
  • Does your app use any other storage? SQLLite for example? CoreData store?
    • Find out, find out where the files are stored and then delete them before you run a First Run test.
Run the test and see what blows up.

Too often we forget to retest this scenario as we work on features and the simple First Run case can get broken.

Test it often to weed out problems before new users find them.  I always run this on candidate builds for a new release to end users. I am also always surprised when this breaks since we seldom think the simple changes we are making in our app will break the First Run.

Monday, July 21, 2014

Sometimes You Just Have To Get Your Hands Dirty

Hockey Tweet in Landscape iPhone 4s (Landscape
was not in the original)
I have dropped off the radar for a bit as I have been busy with some projects. I took a week off from everything but code as I worked on porting my old 2009 Hockey Tweet app to Swift. I have written about that and will some more as I have major updates.

I was also studying for some interviews I had. One was an all day affair with a 7 hour interview that included a 2 hour pair coding session. We are still talking and no news yet to report on the job.

Outside of that I have been ramping up house work. For several reasons, I might have to sell my house (job), the house needs a new paint job, the deck needs a new paint job (or I will be replacing sooner rather than later), and of course I have all the prep work to do (caulking, 15 tubes Sunday) to even begin to paint.  Sunday I got a solid 8 hours in of caulking and then painting.

I started the painting so that I can begin alternating between caulking and painting. Since they use the hand and arm muscles differently, once I get tired with one I can switch to the other for a while. I also have over half of the house caulked now and wanted to get the front of the house completed. I figure I can do the front first and then continue the back of the house into the fall. Since you won't see if, you won't notice it is half/not done.

So, it's been a week of getting dirty. Dirty with new code as I learn to program in Swift. Dirty with house work.

Now some may ask, why not pay someone to paint your house? Heck, I wish. But at a $25,000 average quote to paint the house including prep work (some would not include prep since the amount of caulking was so daunting); I am sucking it up and being a man (frugal).

This just means I might have less posts for a while since how many blog posts can you do about painting you house? Who knows, but I am sure we will find out ;-)

Monday, July 14, 2014

Swift Websites of Note: July 14, 2014

While porting HockeyTweet 2009 from Ojective-C to HockeyTweet 2014 in Swift I have been doing lots of Swift reading. Here are some of the sites I have come across of interest in the past week.

Airspeed Velocity's name is a play on the Monty Python joke about the airspeed velocity of a swallow. The site is an in-depth look into areas of the Swift language. Very good deep dives here if you want to go below the surface of Swift to read about how to get your hands real dirty with the languages nooks and crannies so far.

Of course I have to mention the official Swift Blog from Apple. It is nice to see Apple opening up and finding more ways to reach developers. I think this is needed if they want to get widespread buy-in with the new language and it is certainly appreciated. I look forward to good information coming from this blog.

Not a new site by any means and widely known throughout the iOS/Mac world is Brent Simmons. Brent has decided to jump on board with Swift so he can provide feedback to Apple as he learns the language. Check out his blog, inessential, for current posts on Swift as he shares what he has learned with it.

Those are 3 of the blogs I have been reading this week as I work with Swift.

Sunday, July 13, 2014

Modernizing a 2009 iOS App with 2014 Swift

I wanted to learn a bit more about how Swift works and the best way to learn a new language is to start to code in it. The videos and book are great but I need to get the code under my fingertips to start to understand it better.

So, to get some experience with Swift I decided to port my first iOS app, HockeyTweet, from 2009 to a modern HockeyTweet built with Swift in 2014.

First what was HockeyTweet? It was a Twitter app optimized for Tweeting about Hockey games in a time before custom keyboards, auto correction, or enhanced predictive text inputs. So the scroll views were there to help you spell player names, put in arena names, post your favourite comments on the play, etc. It sold like...well, the opposite of hotcakes.

What it did do though, was help me to teach myself iOS programming which meant a leap into front end UI design, a new language (Objective-C), and new development tools. Now after 5 years of programming with Xcode daily, I am a little more experienced. How will that impact learning a new language and porting the app? Let's see.

Here are my notes as I worked on the app over the last 5 days:
  • Started on Xcode 6 Beta 2.
  • Moving to Beta 3 my storyboard elements all greyed out in the storyboard and were not viewable in the preview pane. Had to delete and recreate.
  • Learning the Swift syntax has been the normal new language growing pains. At least the code completion, warnings, and errors help to understand.
  • My app would crash in the Simulator when I tried to test it. Learned there are some missing init for a ViewController classes in Swift, you need these classes implemented for each ViewController you create:
    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        // Perform custom init here
        super.init(nibName: nil, bundle: nil)
    }
    
    init(coder aDecoder: NSCoder!) {
   // Perform custom init here
        super.init(coder: aDecoder)
    }

  • Getting my head to wrap around ? and ! for variable unwrapping. ? Is optional and ! Is used to unwrap a value if it is not nil.
  • I forgot how easy it is to get a container view from the parent view; access it via the embed segue.
  • Conversion from Cocoa to Swift sucks in the places that Swift methods for Cocoa methods are not provided. Like the missing loading from file methods for containers like NSArray and NSDictionary.
  • I lost storyboard elements again with some getting greyed out. Had to add a textview and label 2 times now due to this.

What are my thoughts on Swift?

  1. It's young and missing some stuff we take for granted in Cocoa. That is not a problem though, I expect heavily used functions from Cocoa that are missing to come over time. In the meantime we will have to wrap some Objective-C types to Swift native types.
  2. It takes a while to mind shift into the new Optionals and variable unwrapping but in general I like the idea and what it is fixing. I think this will be a good thing and cause less bugs if people do not try to circumvent it.
  3. Wow, what a lot less code I have to write now to implement the same app. I like it.
  4. Storyboards have come a long way from what you cold achieve with NIBs in 2009. I knew this already form other apps but seeing it in a rewrite was cool.
  5. UI Layout is a bit of a pain and feels like more work doing the constraint sizes but in the long run I can see this being less work and less code to write to handle the custom view sizes. Not needing custom code paths for iPad, iPhone 5+, iPhone 4s will be a blessing. A project or two and we will look back at older projects and cringe I am guessing.
  6. I am still subconsciously typing ; in places. I search and replace (occasionally) to delete them and it is entertaining to see that I added them again without thinking.

So, after 4 days of coding a total of about 12 hours I have completed the following:

  • Compose UI Ported
    • Missing Info View
    • Missing Custom Fan Favourites Edit View
  • UI layout
    • Best for iPhone 4s (original)
    • Need to handle larger sizes as a test of constraints. I will save this for later.
  • Model
    • Partially ported so far.
    • Loading initial data is taking some time since I need to work out the conversion from NSObjects to Swift objects when loading plist files with NSDictionary(contentsOfFile: String).
    • Network calls not hooked up.
    • Currently using initial load and sample data from testing of original HockeyTweet in 2009 so the players on the teams will be messed up.
    • Dropped schedule for now.
What do I plan to add next:
  • UITextView Hookup
    • Need to be able to take user input and have scrollviews insert data into tweet.
  • CharsRemaining Label
    • Hook up when UITextView for tweet composition is complete.
  • Share
    • I get to drop all the old Twitter code and go with the new Twitter API from Apple. I want tog et this hooked up and working.
  • Networking
    • Pull updated arenas, schedules, and team rosters from my web service.
    • This might be a chance to try out a new backend. Since I am not building this app for AppStore submission I will test this local only unless I land on a backend technology that I can run for free in the cloud.
Philipe Casgrain, my friend from CocoaHeads in Ottawa, put me onto the Summer of Swift. A contest to learn by coding. The idea is to code an app in Swift and do weekly updates to the project over the summer. I am going to enter that and continue to update the app over the summer. Adding back in original features and some new stuff to experiment with Swift.

The code is available to view on Github at HockeyTweetSwift if you want to take a look, grab some ideas, or make the next great Hockey Tweeting App! Ok, that last one is a joke.


Tuesday, July 8, 2014

Ongoing Interview Prep

When you go into an interview you want the job right? I know I do.

Today, if you want the job then you need more than a resume. I am sorry to say, but if your value is all based on your previous job experience then you are missing a whole area from which to shine.

One of those areas is to build something, anything outside of work. There are multiple stories on the web about building stuff outside of your job for many reasons (here is a current popular one Spotify Design Lead on Why Side Projects Should be Stupid). For me, I love a challenge and working outside of my comfort zone to help me grow.

Here are reasons to build something outside of work:

  1. Learn: You can learn a new language, platform, API, or if you want to do something outside of programming, you can learn to plan and build something. I have played with Arduino to learn a bit about hardware, woodworking to fix and build stuff for my house, and music to learn just how difficult, yet easy, music is to create.
  2. Show: If you program something outside of work then you can post it on github and then you have an example of your work to show to a prospective employer. This is a win-win for you since you can show how you write code, how you design your software, how you test, etc.
  3. Tell: With a project outside of work you can talk about it. Many of the projects I have worked on are NDA which can make it hard to talk about what I did. It gets awkward when you can not talk about what you did for the last year. A self made project outside of work gives you something to talk about, challenges faced, and lets you show an interviewer how you think and deal with problems.
This is one thing I call ongoing interview prep. Not only are these projects fun but they give me a chance to discuss different topics to at an interview.

My current project is to port my 2009 iOS HockeyTweet app to 2014 iOS using Swift. This is letting me learn Swift and see how the changes in iOS over the last 5 years have changed how to write a virtually identical app. So far, a lot less code to do the same thing.

I'll be posting more on this once I complete the project.