Last year I released a book based on all my speaking engagements around Auto Layout called Achieving Zen With Auto Layout. The book was very well received when it was announced and it made me realize I enjoyed writing about technical topics again (with the absence of a publisher, everything is wonderful!).
I’m pleased to announce that I’ve spent the last few months updating the book for a second edition. This new edition of the book contains a ton of new content and converted nearly every piece of code from Objective-C to Swift.
New topics covered include:
Working with size classes
Active and inactive constraints
Using layout guides effectively
Layout anchors
Debugging constraints using Swift (which is harder than it should be!)
Much, much more.
If you’re new to iOS and Auto Layout or just want to learn about what’s new with layout in iOS 9 and El Capitan, this is the book for you.
I’ve been working with Swift primarily over the last month. Recently I started working on a new custom interface piece that was having some rendering issues with its layout constraints. I went into LLDB and quickly realized that using private methods such as _autolayoutTrace and recursiveDescription to print out a hierarchy of my views and see ambiguity wasn’t possible out of the box.
The reason for this is that when you’re in a Swift frame, LLDB is expecting you to call a Swift method it knows about. Since _autolayoutTrace and the like are private API, they don’t have any visibility to Swift. Safety!
There are a few different ways to get around this. The first is straight in LLDB. You can use the expr command to tell LLDB that you are passing it a snippet of Objective-C code like so:
What we’re doing here is printing out our entire view hierarchy to the debugger. Frequently typing that long of a statement is obviously a bit tedious, so I tend to put it in my .lldbinit file.
<code class="bash">command alias alt expr -l objc++ -O --[[UIWindow keyWindow] _autolayoutTrace]
Now you can just type alt and get the same output from the debugger.
You’ll notice that I am throwing this out for the entire contents of the keyWindow. I haven’t been able to find a way to pinpoint it down a single property such as self.view, so if you have any feedback on that, please share!
If you’re mixing Objective-C and Swift, you likely already have a bridging header. You can bridge add a category on UIView that exposes the recursiveDescription and _autolayoutTrace methods to Swift.
<code class="objectivec">#ifdef DEBUG
@interface UIView (LayoutDebugging)
#pragma clang push
#pragma clang diagnostic ignored “-Wincomplete-implementation”
- (id)recursiveDescription;
- (id)_autolayoutTrace;
#pragma clang pop
@end
#endif
And the implementation file.
#import “UIView+LayoutDebugging.h”
#ifdef DEBUG
@implementation UIView (LayoutDebugging)
// Nothing to see here!
@end
#endif
Let’s walk through this. You’ll notice that I have the entire thing wrapped in an #ifdef DEBUG statement because I am working with private APIs that I presume the App Store usage checker would flag and reject your app against. With the #ifdef, I am saying that it should only be included on development builds. Apple will have no idea what abuses we are committing since it will never make it to the release builds!
The other atrocity I am committing in this file is the use of #pragma clang diagnostic to tell the compiler to ignore any ‘uninmplemented method’ warnings that will pop-up from not being able to find an implementation for the two methods we defined in our category. Since they exist as private API, we don’t need to reimplement them.
Now if you break in a Swift frame with LLDB and try to call self.view._autolayoutTrace() you’ll get an output you expected.
Happy debugging!
If you’ve found this post useful, and want to learn more about how to best take advantage of Auto Layout in your OS X and iOS apps, be sure to purchase my new book Achieving Zen With Auto Layout
My biggest mistake with Glassboard was having blinders to the fact that the design decisions Sepia Labs made when building Glassboard would likely clash with mine. That doesn’t have anything to do with visual design. Instead, I’m referring to the platform architecture decisions they made as a funded startup, or spin-off, or whatever they were.
The folks at Sepia had a parent company in Newsgator that was funding everything on Glassboard from the server costs, their salaries, and all the perks that go with that. More importantly, they were funding these things with the typical startup mentality in mind: get as many users as humanly possible and then worry about monetization later.
Glassboard under Second Gear had a completely different mindset: try to convert our most passionate existing users to paid users, and then grow from that. I sadly failed at doing that. There are a variety of different reasons for that failure, but one of them is how much time I spent undoing some architectural decisions from their previous owner.
That’s not a knock against Sepia or NewsGator. They built a great product. They just built it with a far different set of constraints than I had as the new owner funding this out of pocket.
E-Mail
One of the biggest was e-mail. Glassboard was sending over 150,000 emails a day when I took over. The SendGrid bill was $2400 in November of 2013, which is kind of crazy. I was able to cut that bill in half by negotiating a better rate to account for how much email we send, but it was still four figures a month.
Sepia didn’t need to worry about justifying that cost because it was another feature in the checkbox to try and acquire users. Don’t want to use an app and get push notifications? We’ll send you an email every single time someone comments on your board posts!
E-mail to Second Gear’s Glassboard is, however, a sunken cost because none of those costs were ever passed on to my customers. My thinking at the time was that I could convert enough users to premium accounts to fund the transactional email for everyone. In reality, that proved to not be the case.
I spent far too long in that mindset. When I finally wised up and made transactional email a premium user feature, my costs dropped down to under $100 a month. It also pissed off more users than it converted, but that was to be expected. The lesson I learned is that people wanted those emails, but they didn’t want to pay for them. It was a nice-to-have thing, but not a must have. I wish I had learned that lesson $15,000 ago.
Computing Costs
The biggest project I undertook during my time with Glassboard was converting the entire backend to use computing resources more efficiently. There were three different cloud services that powered Glassboard:
Notifications Role: this handled dispatching push notifications, emails, and archive processing. It ran on 2 medium-sized cloud service instances.
Attachment Processor Role: this would take the videos users uploaded, compress them, and make them more mobile friendly. This ran on a single Large cloud service instance. Why I didn’t kill video on day 1 is beyond me. What a poor job on my part.
Glassboard Platform: This was the kitchen sink project. It ran the API, the web app, web hook processors, and pretty much everything else. It was 4 medium sized instances when I took it over (I may have the number wrong, but it was quite a few).
I was able to get a few quick wins by enabling auto-scaling so that the instances would rise and fall based on usage patterns. It’s silly to pay for a ton of servers at 3AM on a Sunday when there’s not nearly enough users to justify the costs.
The biggest issue is that the only way to scale Glassboard in that incarnation was to throw more hardware at it. I spent an ungodly amount of time converting the entire backend platform to use C#’s async-await pattern. I am fairly confident I touched every single file in the project. One does not merely convert one portion of their code to be asynchronous. It’s a rabbit hole that you keep going down until you reach the bottom.
It was a lot of work, but once it was deployed I cut my server costs across the board in half.
Of course, by the time I got to that point, it was too late. I cut costs on a product that wasn’t commercially viable. Oops!
Lessons Learned
Building products with a bootstrapped mentality is completely different than a startup mentality. When bootstrapped, every decision you make affects the bottom line, and that is a bottom line you care about from day one. Trying to convert a platform that wasn’t designed with that in mind proved to be too great of a challenge for me as the sole proprietor of Glassboard. Rather than focusing on improving the core Glassboard product, I spent most of my time trying to cut costs where possible to curb our losses.
Would it have been more feasible if I had some help? Most likely, but I still don’t think that would have saved the platform.
If I had a do-over, I think my first decision would have been to shut down the Glassboard service as it was in November of 2013 and relaunch it without any of the legacy user accounts or data. If you wanted to continue using the service under Second Gear, subscribe now. That would have lowered costs up front and allowed me a lot more runway and likely time to delay a lot of cost-cutting projects that took up most of my 2014. Of course, there’s obvious tradeoffs in this decision too.
The worst day I had in my time with Glassboard came last month. It was becoming obvious that even with the latest round of changes to the business model and pricing schemes, things weren’t turning around as well as I had hoped. I had no beliefs that new pricing would be a magic bullet to solve all of the platform’s problems, but I did think it’d be more successful converting users than it was.
In reality what happened is that rather than paying a small monthly or annual fee to continue using Glassboard as they were, more people opted to find another free alternative to move their group or business whether it be Slack, Google+ (lol really), or any of the 85,000 other alternatives on the market.
Couple this with me having a pretty big crisis with a botched migration to a new push platform, and things weren’t going really well for me. This was the point I started to think about where to take Glassboard next. Rather than keep all those discussions internal to my brain, I emailed a variety of different people ranging from friends, colleagues, users, and other business owners. This is the email I sent them:
Have come to the realization that running Glassboard in its current state is not tenable financially, mentally, or physically.
A lot of different problems with it as a product and not sure how to solve that. Mostly it feels like a niche product without a well defined audience.
Any ideas on how to figure that stuff out or where to go with it? Trying to get a bunch of different opinions, because I’m honestly not sure what to do.
Most everyone responded back, and not much of the feedback was good in the “your platform is great! Keep going!” sense. Most people were scratching their heads just as much as I was about where to take this thing next.
The best response I got fairly direct: who is the audience for your Glassboard and what problem do you solve for them?
I didn’t have a good answer for either of those questions. Shit.
Finding An Audience
If the answer to “who is your product’s audience” is “anyone with an iPhone or Android device” you are likely screwed. One of the biggest things I have learned from the entire Glassboard experience is that ‘spray and pray’ audience targeting is something that isn’t likely to work. Glassboard’s marketing message has always been fairly generic from both its time as a Sepia Labs product and under my helm. The last marketing message was “Talk to your people”, with people being a pretty generic term meaning it could work for personal or corporate communications.
There are very few collaboration products on the market that work well for both of those markets.
I spent a good amount of time over the last few weeks looking at analytics data to try to understand who was currently paying for the service and trying to analyze each of the markets that was being served by Glassboard currently. I analyzed them by three different metrics:
Audience size: How many potential customers are there like this group?
Likelihood they will pay: Do they have money AND are they willing to
part with it to solve the problem?
Access to market: How easy is it for you to market to these people and
get them to pay you for it?
My potential markets based on analytics and user interviews were families, small businesses (think Q Branch), medium-sized businesses (think OmniGroup), conferences, consumer ad hoc groups (a book club), and professional ad hoc groups (a beta test board or a cocoaheads meetup).
Analysis said I should focus my efforts towards the professional ad hoc groups and medium sized businesses because they had a large audience, were likely to pay if Glassboard could solve an actual problem for them, and there weren’t too many gatekeepers preventing me access to marketing at them.
Solving A Painful Problem
The key to selling a product to a user (whether it be a consumer, business, or enterprise) is to offer a solution to a problem they are having. If you can make that problem less painful, people are willing to pay for it. For instance, an app like OmniOutliner is successful because it’s far easier to create complex outlines in it across platforms than it is using just plain text files. TextExpander makes good money because they help power users save keystrokes by automating repeatable strings of text.
Glassboard? Well, I realized that Glassboard wasn’t really targeted at any specific group and it didn’t really solve any real sort of problem.
Here are a few different ways I tried to explain the problems Glassboard solved:
It allows anyone with an iPhone or Android to communicate securely and privately.
It allows users to have threaded conversations rather than IRC-style chat lines.
It allows conference attendees to communicate with each other from their mobile devices.
None of these are real painful problems. You can likely name a variety of different apps that can solve #1 and #3. Threaded communications is nice, but it’s also proven to be far too niche and not really something people are willing to pay for.
I realized that Glassboard in its current form is for all intents just yet another chat platform for iOS and Android. Yeah it had an audience, but not an audience that was willing to pay for it to stay around. It didn’t solve an actual problem better than any of the free alternatives out there, so people left rather than keeping the lights on.
What Did We Learn?
What lesson can you take from my failures? Take a look at your current product and ask yourself what problem it is solving that makes it stand out from the competition. Also, ask who has that problem and if you are reaching them as well as you could.
If you are in a situation like me where you don’t have a good answer for either of those questions, you need to sit down and start answering some hard questions about where you take things next.
In my case, the risks of shifting Glassboard towards where I thought it should go next were too high for me to take on. Every business and product is different. Hopefully you learn from my mistakes and can make an excellent (and successful) product.
Last week I announced that Glassboard will be going out of business as of November 1, because I was unable to turn it into a profitable business. There are a lot of different things I want to cover eventually about the past year I’ve spent working on this thing. For one, it’s therapeutic to me to get it out of my head. Second, my hope is that people can learn something from my successes (yes, there were some) and failures (those too).
I knew going in that Glassboard was a moonshot. I was in essence taking over a platform that was run by six people with stable salaries from a parent company and doing it by myself, while trying to shift what turned out to be the titanic away from the iceberg.
Running any business, large or small, is mostly about managing risk. You want to invest in the things that will grow profits. Startup culture skews this in our industry, because venture capitalists are willing to assume near-term losses in favor of potential long-term riches, but for our purposes, let’s assume we are building a business like our parents made. The goal is to spend less than you are bringing in.
I am a terrible Blackjack player, but I know enough to be able to play on a few hundred bucks and have some fun. If you’re under 12, you want to take another card, because you’re really not going to hurt yourself. If you’re over 12, you’ve got to start figuring out what cards have been dealt already from the deck and determine if its worth the risk of possibly busting or not getting a high enough count to beat the dealer.
Despite being terrible at Blackjack, I play it fairly conservatively and don’t stray from those two rules too often. I try to run my businesses in the same way. Second Gear and Glassboard have always been small shops that are run with the intent of supporting me and if it grows beyond that, great.
I knew the risk of taking on Glassboard up front would be how much money it was losing each month in sunken hosting costs (not including development and design time). I projected a few different scenarios for good, great, and ‘make it rain’ levels of growth to get the business out of the red and towards profitability.
Despite cutting the monthly losses by 80% from the time I took over to today, I never fully got to that break even point and began to realize that getting there and beyond was going to require a lot more hard decisions and evaluation.
So, how do you know when you’re done and it’s time to fold? When you start thinking about shutting things down, you’re done. There may be a Hail Mary out there that could possibly save the sinking ship, but my guess is that it will only prolong the inevitable.
For me, I knew for sure last Thursday that I was done. I realized it was going to be another $60,000 or so to turn Glassboard into the product that I thought it could be eventually. There was no way I could do that emotionally, mentally, or financially. The risk was too big. I announced the next day I was cutting my losses and shutting the service down.
Glassboard was a gamble that didn’t really pay off financially (no, mom. I am not losing the house), but it was still rewarding in a lot of other ways. Hopefully those will become apparent over the next few weeks as I dump all this out of my head.