My New Experiment: Journaling All the Things

At CocoaConf I attended a session from my fellow Big Nerd Ranch coworker, Mark Dalrymple. In this session he explored the questions we ask when looking for bugs — or more specifically their solutions.

At one point Mark showcased a text document that in glorious detail documented the assumptions, questions and answers he was going through to solve a problem. Now, this wasn’t a document Mark made for the talk, it was from a real journal entry he had. He was Rubber Ducking but documenting the discussion like a court reporter.

If you ever work with Mark you’ll quickly discover he is a relentless notetaker. This is just one more example of how it can pay off.

  • Need to step away to work on something else, here is a document to reload your context.
  • Need to invite someone else on to help solve the problem, here is your knowledge transfer.
  • Want to write up a blog post to help others in the future, here is your draft.

I left the session very inspired. As a result, for this week, technically my vacation week but I’m working on side projects, I’m starting an experiment where I try to emulate Mark’s journaling habits as best I can. I have 3 documents at the moment:

  • Daily Journal — Mostly flat list with GOALS for the day and then ACCOMPLISHMENTS of what actually got done at the end. If something in the list has notes in and of itself, it’s hot-linked to those on their own wiki page.
  • Company Journal — Documenting the efforts I’m putting into my side project and the company that encapsulates it.
  • Tech Journal — Starting with Apple, here is where I’m collection my thoughts, issues, and bugs relative to Apple technologies. I expect to make more for other stacks like web in the future.

I’m using VoodooPad for the actual files/wikis themselves. It works well letting me organize like a wiki and can handle screenshots too.

We’ll see how I hold up. I want to give it my all for at least a week and then will do a retrospective as to how it’s working out. There are challenges (like my current typing speed) but lots of potential benefits too.

Update: More from Mark’s own blog.

Do you journal like this? Any tips or other feedback? I’d love to hear it. Message me on Twitter @zorn or via email: mike@clickablebliss.com.

Isolating Mac Application Menu Behaviors

A Place for Everything, and Everything in It’s Place

My side project is a Mac app and last week I was working on a small story about sending feedback.

Send Feedback under Help Menu

As a user, I want to be able to Submit Feedback via the Help menu, So that I let the developer know what I’d like changed.

Acceptance Criteria:

  • Under the Help menu there should be option to submit feedback.
  • Upon selecting this menu item a new email will be open.
  • to: mzornek+storyteller@gmail.com
  • subject: [Storyteller Feedback] [1.0(101)] — that is the version number and build number

This was easy enough to get working but I wasn’t in love with my first implementation. If you read up on the Menu documentation for macOS you’ll find out application menus will follow the Responder Chain . A responder chain of a document-based application looks like this:

responder chain of a document-based application

Now while this is a document-based application this behavior is an application-level behavior. The best spot to put it is in the AppDelegate but I don’t like polluting that class.

My new solutions helps improve the situation in lieu of the framework’s design constraints. I still have the IBAction inside the AppDelegate but it now forwards the behavior to another object that is more isolated, with a single responsibility and is easier to test.

// AppDelegate+SubmitFeedback.swift
import Cocoa

extension AppDelegate {
    @IBAction private func submitFeedback(sender: AnyObject?) {
        submitFeedbackService.submitFeedback()
    }
}


// SubmitFeedbackService.swift
import Cocoa

protocol URLOpener {
    func openURL(url: NSURL) -> Bool
}

extension NSWorkspace: URLOpener { }

struct SubmitFeedbackService {

    private var to: String {
        return "mzornek+storyteller@gmail.com".urlEscape()
    }

    private var subject: String {
        return "[Feedback: Storyteller \(versionString)] ".urlEscape()
    }

    private var versionString: String {
        let appVersion = NSBundle.mainBundle().appVersion
        let bundleVersion = NSBundle.mainBundle().appBundleVersion
        return "\(appVersion) (\(bundleVersion))"
    }

    private let urlOpener: URLOpener

    init(workspace: URLOpener = NSWorkspace.sharedWorkspace()) {
        urlOpener = workspace
    }

    func submitFeedback() {
        let urlTemplate = "mailto:\(to)?subject=\(subject)"
        guard let emailURL = NSURL(string: urlTemplate) else {
            assertionFailure("Email should parse fine.")
            return
        }
        urlOpener.openURL(emailURL)
    }
}

private extension String {
    func urlEscape() -> String {
        guard let result = self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) else {
            assertionFailure("Could not escape string for URL")
            return self
        }
        return result
    }
}

// SubmitFeedbackServiceTests.swift

import XCTest
@testable import Storyteller

class SubmitFeedbackServiceTests: XCTestCase {

    func testCallingSubmitFeedbackOpensAMailtoURL() {
        let mockWorkspace = NSWorkspaceMock()
        let service = SubmitFeedbackService(workspace: mockWorkspace)
        service.submitFeedback()
        XCTAssertNotNil(mockWorkspace.lastOpenedURL)
        XCTAssertEqual(mockWorkspace.lastOpenedURL!.scheme, "mailto")
    }

}

class NSWorkspaceMock: NSObject, URLOpener {
    var lastOpenedURL: NSURL?
    func openURL(url: NSURL) -> Bool {
        lastOpenedURL = url
        return true
    }
}

Feels cleaner to me but I welcome feedback. I also suspect SubmitFeedbackService will evolve in time as there is other communication needs in the future.

PS: I hope to share more about the implementation of project in the future. I know there is a void of Mac application programming discussions going on out in the web. I will try to help out with my own journalling the best I can. Questions welcome.

CocoaConf DC 2016 Recap

Had the pleasure to attend and speak at CocoaConf DC this past weekend.

CocoaConf is a touring training conference for iPhone, iPad, and Mac developers. We bring some of the best authors, trainers, and speakers to the most passionate, engaged developers in a region—together, they make magic!

CocoaConf draws anywhere from 100-120 developers. It’s a very nice, comfortable size. Large enough to host a diverse collection of personalities and ideas, but small enough not to feel overwhelming. People actively mingle and you get to meet lots of new faces without much effort.

This was my third CocoaConf, and first as a speaker. My own talk was at the end of the first day and I spent ample time the previous weeks preparing to avoid the need to do last minute slide updates and miss sessions — and I’m glad I did so.

The sessions were really good at this CocoaConf. Sure it helps that iOS 10 is just out and there is still lots to learn, but even the talks that were version agnostic, covering patterns, architectures and bug hunting skills all got my brain spinning with ideas.

One cool benefit of my work scheduling is now I have a week of stay-home vacation and I can hopefully direct that post-conference enthusiasm towards my side projects and some extra experimentation. Specific items on my list:

  • Do more interactive prototyping of my side project and follow up with some user interviews.
  • Do some experimentation with Perfect to build a simple Swift API and host it on Linode.
  • Continue to polish up my RanchWeather app and start a blog series reviewing the code patterns.
  • Do some experimentation with Twilio authentication in preparation for a web app project.
  • Inspired by the journalling abilities of MarkD, dedicate the vacation week to a journaling experiment: Daily Journal, Project Journal, Tool Journal.

As for my talk, I think it went very well. One thing I really like as a speaker is the conference not only has a session review system but they encourage submissions of reviews with a raffle for prizes at the end so you get a lot of feedback. Most of my talk’s feedback was very positive and I appreciate the criticisms, both good and bad. Always room for improvement.

So yeah, if you are considering attending or speaking at a CocoaConf, do it. It’s very rewarding and worthy of your time. If it’s on the east coast you’re more than likely to see me there too — and if so, say hi!

Regarding Knight Rider and Delegation

One of the saddest aspects of being a Big Nerd Ranch instructor in 2016 is that students these days do not appreciate the Michael Knight is to Delegation, as RoboCop is to Subclassing discussion of yesteryear.

From Cocoa Programming for OS X: The Big Nerd Ranch Guide:

Delegation

Let’s start with a story: Once upon a time, there was a man with no name. Knight Industries decided that if this man were given guns and wheels and booster rockets, he would be the perfect crime-fighting tool. First they thought, “Let’s subclass him and override everything we need to add the guns and wheels and booster rockets.” The problem was that to subclass Michael Knight, they needed to wire his insides to the guns, wheels, and booster rockets – a time-consuming task requiring lots of specialized knowledge. So instead, Knight Industries created a helper object, the Knight Industries 2000, or “KITT,” a well-equipped car designed to assist Michael Knight in a variety of crime- fighting situations.

While approaching the perimeter of an arms dealer’s compound, Michael Knight would say, “KITT, I need to get to the other side of that wall.” KITT would then blast a big hole in the wall with a small rocket. After destroying the wall, KITT would return control to Michael, who would charge through the rubble and capture the arms dealer. Note how creating a helper object is different from the RoboCop approach. RoboCop was a man subclassed and extended. The RoboCop project involved dozens of surgeons who extended the man into a fighting machine. This is the approach taken by many object-oriented frameworks.

In the Cocoa framework, many objects are extended in the Knight Industries way – by supplying them with helper objects. In this section, you are going to provide the speech synthesizer with a type of helper object called a delegate.

What do you think the new metaphor should be?

Join Us at CocoaConf DC, Sept 9-10th

I’ve been to multiple CocoaConfs as an attendee and it’s with great pride I’m happy to say I’ll be a speaker at one soon.

CocoaConf Boston

CocoaConf is a traveling conference focused on Apple technologies that has been around since 2011. It’s big enough to have multiple tracks of content but small enough that you’ll have time to socialize with most of the other speakers and attendees throughout the event.

The 2016 “tour” is coming to a close. I’ll be speaking at the Washington DC CocoaConf (Sept 9-10) but if you are on the west coast you might want to consider San Jose, CocoaConf (Nov 4-5th).

When registering use code “COCOAHEADS” for 10% off!

I can’t wait to see everyone. If you will joining us, please come by and say hi. I’ll have some Big Nerd Ranch swag for ya.

My New PC Gaming Computer

Final Parts List: http://pcpartpicker.com/list/4Wjcf8

I’m a fairly serious/casual gamer (as in serious love of many games, casual in that I can only play so many hours a week because of other life responsibilities). I play a lot of 3DS (Pokemon, Zelda) and I also own a Wii U, a PS4 and lots of other older/retro consoles.

I’ve been considering a gaming PC for a while. My main drive has been to support a mix of playing World of Warcraft and Final Fantasy 14. I’ve been playing both on my 2011-era iMac (Bootcamp-ing into Windows for FF14) but the graphics performance of the old machine was starting to become a real limiting factor. Additionally was the interest in playing some PC-only (or PC preferred) games, like Overwatch and Stardew Valley.

A few months ago I started assembling a parts list and talking to some other friends. Part of me just wanted to buy a pre-built system but for better or worse my geeky friends assured me the assembly wouldn’t be that bad and it would let me save some money or buy some better components.

My initial target was to spend about $1500 and go for a upper mid-tier machine. I wasn’t interested in VR right now and just wanted something to play games. After getting acquainted with the video cards and performance I choose the GTX 970. I had a full parts list waiting to go but I didn’t pull the trigger. This was around April and I was still traveling a bit. I was also working towards paying off my student loans and decided I’d do that first.

GTX 1080

When I came back to my parts list at the end of May there was the announcement of the new GTX 1080 and 1070. These new cards were destroying the performance charts and I started to get a little greedy. I kept up with the release, and noticing the 1080 was selling out joined an alert website to let me know where and when it became available. I eventually grabbed a Founder’s Edition directly from Nvidia. I will concede the upcoming non-Founder’s Edition cards are probably better cooled and cheaper but I was anxious to play and didn’t want to wait until end of June / July to get my hands on this thing. I splurged.

I came back and cleaned up my final parts list. I ordered the rest of the machine from NewEgg with a few pieces from Amazon. (Even if a bit more I’d prefer to buy from NewEgg and Amazon who are very easy to work with regarding returns and such.)

One item I was not planning to buy but did, was a new monitor. I was really hoping to get dual use out of my Apple Thunderbolt monitor (which I use with my iMac to extend my display) but as I did research it would seem hooking that up to a display port was not going to work out. I ended up buying a Dell Gaming S2716DG 27-inch monitor to make it work, and it does. I just am not enjoying using it with my iMac as much as my other Apple monitor since the colors aren’t matching like they used to.

Assembly

Workbench

After ordering the parts a week before, I sat at home Friday night and got started with the assembly. I took my time. I read the motherboard and other manuals as I slowly connected it all together.

Motherboard

Motherboard Mounted

Some things gave me trouble. It took a few attempts to get the motherboard mounted in the case. In general there was always a scary feeling of putting too much pressure on a part to get it to fit in. The case came with a ton of different screws and I had to take a lot of time to make sure I was using the right pair for the job.

All Done

Windows

I worked on Friday from 8pm till about midnight and then Saturday morning 9am until lunch to finish the assembly. Much longer than a seasoned PC gamer I’m sure — but keep in mind this was my first build since college and even then I had a lot of help from my roommate. Once assembled I was lucky in that it powered on into the BIOS right away.

Windows

Despite some known gaming headaches, I decided you use Windows 10. It installed fairly quickly. During initial setup I did opt-out of a lot of personalization features that do not interest me. My next challenge, getting the network card working.

My gaming PC is not near my cable modem so I need wireless connectivity and surprisingly this is not on the motherboard — I needed a seperate PCI card. The card I bought seemed to use PCI for the housing but also plugged into the USB on the motherboard. After spending some time downloading the latest drivers and playing the format game with some USB sticks I eventally installed the software but the card would not start up. It took some searching but I eventually found out I had to disable XHCI Handoff to enable the third USB connection on my motherboard which is what I was using to connect the wireless card. With all of that figured out, I had network access on my computer and began downloading some system updates and then some games.

The Games

I’m sure I’ll buy some more in time (and would greatly love your recommendations, email me) but for now the primary PC games for me are:

  • Final Fantasy 14
  • Overwatch
  • Civilization V
  • World of Warcraft (idle until Legion)
  • Stardew Valley (New, not played yet)
  • Rocket League (New, not played yet)
  • Undertale (New, not played yet)
  • Hearthstone (I play this on my iMac and iPad as well but there are some nice Windows-only analytics add ons I might try.)

Final Thoughts

I have mixed feeling about the time I spent doing the build. It does feel empowering to refresh my memory of how to do it all — but that said it’s not something I get a ton of enjoyment out of so let’s hope this box keeps ticking without too much maintenance in the years ahead. And while I do carry a little guilt about going for the super high end video card I also look forward to for the next few years being able to turn on ULTRA options without losing frames.

The World Needs a Better Core Data

Lots of WWDC predictions out there this week. Here’s a dream of mine. Sadly one that I’ve given up on, at least from Apple.

A Better Core Data.

  • Tracking state is 1970s thinking. We should be tracking changes over time and rendering the current state of the object graph.
  • Migrations, the number one feature. As you add new entities to a store, you do so through a migration. Change a column name, you do it through a migration. The current Core Data migration story is embarrassingly complex and very fragile. We need to have trust in our migrations.
  • A single, focused, persistent store format. Allowing people to choose between XML, Binary, SQLite, InMemory and Custom adds more pain than it solves. Keep things simple. One on-disk format.

Clash of the Coders: Day 0

One of the many interesting benefits I get working for Big Nerd Ranch is the opportunity to participate in many fun and unique events. One of the bigger ones is called Clash of the Coders.

Clash of the Coders is an annual coding competition, whereby Big Nerd Ranch effectively “shuts down” for a a few days to allow developers to flex their coding muscles in to build something (anything) that is both wizardly and useful.

This years edition of “Clash” starts at 6pm tonight, Wednesday March 30th. While people are encouraged to brainstorm ideas and form teams ahead of time, no code shall be written until the event starts.

During the event we are treated to full time catering, shoulder and neck massages as well as other free-form geek activities. (I hear Christian will have his new Oculus Rift around for testing.)

While remote nerds can choose to stay remote and participate, anyone who wants to come into the office can. Last year I was at home and didn’t really get into it. This year I’m working out of the office so I’m anxious to see how it all works out.

As for my project and team, I’m still working on it. I have an idea and if need be will work on it solo but am also hosting a meeting after lunch for ‘Clash Singles’ to see if we can form some last minute teams.

At the end of Clash (Saturday, 6pm) we have a nice BBQ dinner (spouses and kids welcome) and we run a science fair of sorts, where people demo their work and answer questions. People are judged on project complexity, presentation and other factors. Bonus points are awarded if your team was interdisciplinary (mixing people of different departments) and if you were able to integrate any of the emerging technologies on our watch list. Top prize allows you to choose from list of high end geeky toys (think drones and musical instruments) with second/third prizes getting some nice Amazon gift cards.

I’ll post more as Clash gets going. If you have any questions let me know.

How We Record Talks at Philly CocoaHeads

I came across this post from Rico Jones on how he records the Portland Ruby Brigade’s monthly meetings and thought I’d do something similar for how we record the Philly CocoaHead presentations.

Capture Setup

Why Only Main Talks

This first thing I’ll note is we do not record the entire meeting. Early on this was to due to the experimental nature of our recording setup but more recently, at a leadership meeting, we made the call to continue to only record our “main talks”. We do this for a few reasons:

  • Not recording the “show and tell” talks lets those be a little bit more free-form, with less pressure on the presenters (which is a big reason why they are in the agenda).
  • Many of the show and tells are in-progress app demos, and so there is benefit to keeping them non-public.
  • We expect a higher level of preparedness for the main talks, and to ask for people to put that much time into a talk, it would seem wrong not to capture it.
  • If the whole meeting were being captured / broadcast it would encourage people not to come.

The Setup

Starting from the presenter’s laptop we provide an HDMI cable. If they want to present or demo from an iOS device we have an HDMI to Lightning adaptor.

The HDMI cable then feeds into our capture device, an Elgato Game Capture HD. This device is targeted at the streaming game market but is just as viable to capture normal HDMI signals. The device itself is an HDMI passthrough with no frame drops or anything. The device is even powered through the USB cable so no need for a power cord. The video / audio is then compress into mp4 (on device using hardware encoding). The compressed signal is sent to a Macintosh running some custom Elgato software. I use an older Macbook Air to act as our dedicated capture computer. While there are many other features for dedicated streamers, we simply press record.

We then take the other end of the HDMI cable and route it to our projection system. Now the Apple Store that hosts us has a very impressive setup but sadly it’s not as easy as it should be. They have an HDMI connection, and while it works for the Apple TV it doesn’t register when we plug it into a Mac. To get around this we used to use an HDMI to DVI adaptor and the alternate DVI input. It worked fine but doing it this way lost the audio. Recently we’ve fixed this by buying a converter box that splits the HDMI into both DVI and an audio jack. Again, the Apple Store does have a in-house roof speaker system but for us sadly it’s been down. In the interim we’ve been getting by with a Beats Pill Speaker the Apple Store is nice enough to provide.

While not part of the capture, I will give a friendly nod to Fin, an iOS performance timer we run on an iPad mini to help the speakers know how much time they have left. Works great.

I’ll also recommend the presenter remote I use. It’s a Kensington, with a nice simple to use USB dongle that slips into the remote when not in use. It has a laser pointer too but I can’t say I use it much. Battery life has been very good for this device.

So that captures the video and audio from the presenter’s laptop or device but what about the speaker’s voice? For that we use a lapel clip on mic and Digital Audio Recorder. The recorder can work without the mic if you are looking to capture a room discussion but for 1 person, adding the mic is a real quality difference.

After the meeting we combine the video and audio captures using ScreenFlow. Editing is fairly simple for most cases, usually as simple matching up the action and adjusting some audio. The finished product is exported and then uploaded to Vimeo Pro, which acts as our library of sorts. (We pay for Vimeo Pro to keep ads out and to make sure we have API access.) People can watch the talks through Vimeo itself or our new Apple TV app, “PhillyCocoaHeadsTV” (search for “CocoaHeads” on the TV).

Future Improvements

Overall I’m pretty happy with the current setup but I do have some ideas:

  • It would be nice if we could get the Apple HDMI connection to work, that would simply our wires a bit.
  • At work we use a Catchbox to help capture Q and A. It would be nice to work out something similar for us.
  • While it might save a bit of editing time to convert to a wireless mic, it’s pretty low on my list. Would have to improve some other aspect to make it more worth while.
  • There is a lot of equipment to carry in, setup and carry out. It’s very reliant on me personally at the moment. I’ll probably be missing a meeting or two this year so I hope to train someone else to run this while I’m gone.

Hope you enjoyed my rundown. If you help capture stuff like this and have any tips or tricks, let me know. Thanks.