Posted on May 22nd, 2012 No comments
I followed the advice in the 4 hour workweek blog about creating my own app. On 10May12, I had my idea. I designed it over the next two days, and on the second day also posted job specs to some freelancing sites. Today it was published! You can view it here: Green Light Timeout.
So, overall, a pretty quick turnaround. There’s a ton of stuff that I learned from this, though, so my next app should be better / cheaper / faster / etc.
The app I wanted would be a timeout app for parents to show their kids their progress through timeout. A continuing source of frustration throughout this process, I used different devices at different points in time.
When I was looking for competing apps, I looked on the iPad. I didn’t limit searches to apps only made for the iPad, but if you search on the app store using an iPad, it shows those apps first, which biased my research.
As such, I didn’t have as good an understanding of what apps were already out there, what they did well, what they didn’t, and how I could make mine better. Fortunately (if I may say so, not so humbly), my app’s simpler than the ones I found, so I got a little lucky.
I used the Blueprint app for the iPad to design the application. It’s fantastic, and I think made the spec I provided to the developer significantly more coherent and manageable. The questions the developer asked weren’t trivial or meant to clarify obvious functionality, and I give most of that credit to Blueprint.
That said, since I’ve never done any iOS development before, I didn’t realize that a lot of things that Blueprint made easy (say, gradient buttons), aren’t apparently as easy to drag & drop in XCode. So there was a little bit of a delay in development where the developer was waiting for me to provide the right assets for the app (button backgrounds, the stoplight, etc).
As far as technical specs, I think the more (useful) information you can provide, the more time you’ll end up saving. I wanted charting in my app. There’s a great, free library out there called core-plot, but if I hadn’t told the developer about it, I’m not sure he would have found it, and would have either spent time finding a library that does what I mocked up, or would have tried to write one himself, which would have been painful (both for him and for my wallet).
Hiring a developer wasn’t as fun as I thought it would be, and I’m naturally impatient, which made things worse. First off, don’t rush to hire someone. In the whole scheme of things, a few days isn’t a big deal, and wasting a decent amount of money on a shitty developer hurts more than waiting through the weekend.
I posted jobs to Freelancer and oDesk, and the oDesk responses I got were more impressive, though there were fewer of them (I think I had 3 oDesk applicants and 9 Freelancer applicants).
You’re going to get a lot of bullshit submitted to you. You’ll also get a lot of recruiters/software shops, which aren’t necessarily bad, but it takes longer to figure out if you’re working with anyone competent that way.
I asked a coding question in my job posting, and the first email I received that included an answer got me really excited. I wanted to rush back from lunch and talk to him. Then, when I actually opened the full message (Freelancer didn’t send the entire contents of the message to me), it was dead wrong. Not even “oh I could excuse it by …” wrong — totally, absolutely, unacceptably wrong.
If you’re not a developer, ask one you know for a simple “FizzBuzz” style question. Then either find a way to vet the answers yourself or ask the developer to do it – if someone can’t code something that should take 30 seconds when they have all the time in the world (remember, they’re applying to *your* job), you don’t want to pay them.
Once development started, the turnaround time was fantastic. I had apps packaged and sent to me daily.
This wasn’t how I wanted to work, however. I tried to get the developer to use GitHub, because it has a lot of handy built in project management stuff (wikis, issue tracking, file repository, *git*) and I could review code changes that way.
On the job posting, I said experience with git is a must, but I didn’t interview on that point. As such… he never learned how to use git. A lot of developers will have experience with Subversion, and GitHub provides a Subversion interface to their repositories, so instead of fighting with the next developer I hire, I’ll probably just show them the svn hookup and get what I want with little friction.
I entered issues into the GitHub issue tracker and showed the developer how to use them, and that worked really well. Using GitHub’s milestones, I was able to figure out what needed to be done before we could release, and kept things on target. If you haven’t opened bugs before or worked with an issue tracking system, Joel Spolsky has one of the best articles on bug tracking out there.
Overall, it took the guy 38 hours to code the app. It was longer than I’d hoped, but I realized towards the end that my expectations weren’t realistic.
oDesk provides some pretty cool management tools when you’re working with developers. It takes screenshots of their desktop periodically for any time they want to bill you, which is great, since I could look to make sure I wasn’t funding someone else’s development. I saw the guy used Facebook and applied to other posts, but it didn’t bother me since the majority of the pictures show development on my app.
When I was testing the app, I used the simulator almost exclusively. It takes nice screenshots, it’s fast, easy to get running, etc.
It turns out this was a huge mistake. The iOS simulator doesn’t (or at least I didn’t have it set up correctly) have power saving settings. Remember, my app is for showing kids their progress in timeout. My son is almost 5, so that’s 5 minutes, but the phone’s screen turned off after 1 minute. Now he couldn’t see the stoplight, and the app pauses if you leave the screen, so timeout stopped.
I didn’t find this bug until after I’d ended the contract on oDesk, and I didn’t want to spend another $15 to fix it, so I found the right methods to call and did it myself. So, there, I coded 2 lines in the app.
But the important lesson here is to use your app for at least a day on the device you’re planning to use it on. There’s no point submitting something super buggy to the app store; either you’ll get lucky and it’ll get rejected, or you won’t and it’ll get reamed by user ratings.
Overall, this was a blast. I really liked designing the app, working with another developer (I try not to spend too much of my off hours coding), figuring out how to make things look nice and feel usable and keep things under budget (if I’d spent over $1000 getting this built, I’m pretty sure it would have been my last – turned out it was about $600, so not bad at all).
I’m not sure it’ll make money, but it was an invaluable learning experience. I’ll do it again. Feel free to go buy it and give it a nice rating
Posted on April 23rd, 2011 1 comment
Update: David Genord pointed out a *huge* bug in my code, where jobs will never be retried; his fix has replaced the existing gist.
Our workers (DelayedJob) leak memory. Not heinously fast, but enough that monit bounces them fairly often. I tried out perftools.rb on one of our longer running jobs, reindexing contacts. I cut the job down to indexing only 25 contacts, and profiled objects instantiated. To index 25 contacts, which took about 25 seconds, the app instantiated 3.1 million objects.
Just in case the title is misinterpreted – DJ is not leaking memory. My code is.
With a little bit of memoization and a few short-circuits, I got it down to 800 thousand. That was nice, and it sped things up by an order of magnitude, but the jobs were still leaking memory
So, I decided to steal a cool concept from the next async processor I really want to work with: Resque. I changed the worker to fork and wait for every job it performs. This means that there’s an overhead added to every worker of about 200MB, but that’s nothing compared to how bad things got if all the workers started sucking up huge chunks of memory at the same time.
One caveat: I tried to look around for someone who’d already done this and just incorporated those changes, but it turns out googling “delayed job fork” doesn’t reveal much. If there’s an existing project that’s already trying to do this for delayed job, please let me know
The code changes around this are pretty simple, just changing the run method and adding a hook for handling fork reconnection stuff (it looks like DJ has some hooks built for this, but I didn’t see them in my local copy)
Before this patch, if I ran 1 worker locally, after about half an hour my machine ran out of ram (it has 8gb). If I ran 4, my computer was unusable. After the patch, I can run 4 workers locally with no perceived performance hit. Money shot:
Posted on February 23rd, 2011 1 comment
There’ve been some times where someone else would deploy and something would go wrong, and if they lost their deploy output, then it’s a lot harder to debug. Here’s a few lines that you can put in your deploy.rb to get your deploy log output written up to your server, so in case you need to find if something quietly failed at some point, you know where to look.
Posted on October 6th, 2010 No comments
There are about 4 hours in the day where the caffeine vs fatigue level is just right, and I get a lot done. Unfortunately, a lot of the stuff I work on requires a lot of computer effort too, which at first led me to creating multiple directories to work in.
After the environment variable thing I got working, everything was a lot more silo’d, which was great, but I still had to either explicitly type at the end of long running commands “;say ‘done’” or just check it spontaneously.
I don’t like having my headphones on all the time, so I wanted to hook Growl into this.
Also, I wanted to release a gem named caffeine, but someone already has a gem named caffeine, and since I’d already made it work locally, I didn’t care enough to re-package it and figure out a new name. And meth has all the wrong implications. Color me lazy.
Anyway, I ended up adding an at_exit block to my rake and spec executables, and put the following script in my path. It’s resulted in my computer telling me verbally and with sticky notes what’s going on. Who needs a secretary when you have this?
Posted on September 9th, 2010 1 comment
Something that sucks about JIRA out of the box is that the links in the description fields don’t open in new windows. For a tab-addicted guy like me, that often means I unthinkingly open a link to a Skitch and see what’s up, then close the window and immediately think, “Shit! That was the issue!”
After having another dev point out how annoying it was, I found a new project. It’s not very complicated, but it will change your life*.
In your JIRA server directory, open up atlassian-jira/includes/decorators/footer.jsp, and then add this right before the closing body tag:
And you’ll be good. I only changed the links in the description field, but you could do that for anything you wanted, really.
Posted on April 20th, 2010 No comments
Last week I talked with a guy who noted that the scheduling patch I’d blogged about for DJ was insufficient for scheduling something every day at 8AM. This is because running a job and then scheduling the job again after a success pushes the job out a little bit each time (maybe in a week or so it runs at 10AM, e.g.)
I thought about trying to make a run_at class method that would let you specify it, like “run_at ’8am’”, but that quickly fell through when I realized ’8am’ is ambiguous – 8AM every day? Every Wednesday? Every 4th week in July?
I fall inline with Brandon Keepers when I say that I don’t want to re-implement cron, because (imo) cron is one of the best scheduling tools out there already, and it comes packed onto every Unix distribution that ends with x.
Instead, I changed the run_every method to now accept a block, so you can pick the new best time to run if you’d like, or just keep using the same old (8.hours) syntax.
Think something like this:
If you like it, here’s the GitHub Repo.
Posted on October 18th, 2009 No comments
A few weeks ago, there was a fun argument over a feature at work. It was split down the middle. Feature arguments are a lot of fun, because everyone gets to pretend they know what the ambiguous “User” wants, when nobody really does.
The lines were clearly drawn, I was on the opposite side of our PM, and he had to go to a meeting. While he was gone, a (really smart) fellow dev hopped into the conversation, asking what we were arguing about. I explained the issue (surely with dripping bias), and asked him what he thought.
He sided with the PM, and explained his (different line) of reasoning. It was cogent and persuasive. As he was closing his argument, I just cut him off. “No, you’re right.”
The PM came back in, my boss in tow, started up the discussion again, and I exclaimed that I’d switched sides. I regurgitated the (really smart) fellow dev’s reasoning, and that was that.
There were a lot of important things that happened there for me. One, I just outright said that someone was right, which until then I hadn’t done very much. When I was younger it’d get to the point that I’d draw up ridiculous straw men or insane special pleading fallacies to make my point, even when I knew I was wrong, and would “win” the argument.
When you “win” with shit reasoning, everybody loses, for two reasons. One, other smart people recognize your shit reasoning, and even if they can’t argue their way out of it, they lose respect for you. Two, and this counts especially if you’re making something that other people have to use, shit reasoning leads to poorly modeled and horribly thought out products.
There’s a lot of value in being honest and working hard to identify the best ideas. One of the consequences of this is the realization that your ideas aren’t always the best and aren’t always right.
The unpredictable effect of me conceding the argument with, “you’re right?” Feeling liberated. Suddenly I wasn’t stuck to a losing side, had seen the light, and was then arguing for something that made even more sense. Also, I think by reiterating the (really smart) dev’s reasoning, I’d helped bring everyone onto the same page, but that was only by luck – if the (really smart) dev had been in the original discussion, the discourse probably wouldn’t have lasted more than 2 minutes.
There are arguments that are fun to have, where neither side can be 100% right, and there are arguments that aren’t fun to have, because one side is 100% wrong. In the second type of argument, it’s important to be on the right side, even if you’re late to the game.
Most importantly? Make sure your teammates and coworkers know you’re aware of your own fallibility.
Posted on September 30th, 2009 No comments
After (I think) removing the passwords and everything else sensitive in the code, I’ve open sourced the code behind bgtwt.com.
I’m not sure if it will get any patch submissions or not, but I figured with it being closed, it definitely wouldn’t. If you submit anything you’re proud of (you can find the code here: http://github.com/terrbear/bgtwt), and I like it, I’ll happily put it up on the site.
You’re also free to copy the code and do whatever you want with it. I’ll attach the proper license in a few days.
If you’re looking for a feature that would be awesome and want to start playing with Rails, I’d like to integrate acts_as_unvlogable into bgtwt.
Posted on September 4th, 2009 12 comments
(Apologies for the ridiculously lame title, but I laughed while writing it, so it stays.)
If you care about your user’s security, and your time, it’s time you stop asking them for passwords. Storing user passwords and handling authentication offers a bunch of problems that have already been solved, and requires a lot of work to do it right.
Think about it. If you’re storing user’s passwords in your database, you’ve automatically got sensitive information on your server. Maybe it’s just a College Football Pick ‘Em site, which stores nothing too important … until you store a user’s password. Let’s face it, most users don’t use a new password for every site, so if someone breaks into your server, you’re responsible if that information is lost.
So, you’ve got to make sure your server’s security is up to date. Then, it’s still possible there’s a break in, or you have a malicious developer. So you have to encrypt the passwords. But not just encrypt them, because that would still be susceptible to dictionary attacks. You have to salt each password.
What about brute force login attempts on your sign in page? Have you handled that?
These are just some of the problems that you have to solve the minute you decide to store someone’s password.
A better solution? OpenID. Below I’ll explain how to use my newly written (really repackaged) OpenID Rails engine, and you can be on your way to making the world an easier place to sign in.
Posted on June 9th, 2009 1 comment
Apologies for the terribly named post.
I was thinking on the way to work this morning about classes that I thought helped me write software, and classes that were meaningless. Keep in mind that I’m only evaluating these classes according to what’s helped me work, not what’s helped me in everyday conversation or social gatherings or whatever.
- Statistics – I only took 3 hours of statistics, but I think having a fundamental understanding of measuring things is incredibly useful. It helps you learn where to look for problems and pain points.
- Science – This isn’t really a class, because I don’t think any of the science classes you take in college help you learn about the scientific method. That’s not entirely a bad thing, because there’s a lot of information they need to give to you so you can understand the higher up physics courses, for example. Understanding how to isolate variables and constraints and make testable hypotheses informs everything I do nowadays.
- Automata – If you think of regular expressions as pictures, instead of arcane symbols, it helps a lot.
- Technical writing – Being able to communicate effectively over email, understanding desirable typefaces, etc., I think have been helpful.
- Data structures – You know, it’s funny. It was one of the first CS classes I took, so I thought it’d be dumb, but I got to work out a lot of how queues and stacks and trees worked before having to rely on them heavily.
- Systems programming & Operating systems – When you start running your own applications (because of funding or because it’s too complicated to convey to someone else), knowing about schedulers and memory leaks and threads and processes and shells is incredibly useful.
- Assembly or C – Most of my early classes were in C++ (I know, not C at all), but at least I got some of the syntax, and then I did several classes that involved asm. I think those were awesome, just because you understand what needs to be done to move information around a computer, and how (and when) it gets expensive.
Not so helpful:
- Algorithms – I think this is probably more a result of the teacher than of the class itself. I think having a basic understanding of bigO is important, but it’s not important for an entire semester. I think understanding code and statistics provides a better foundation for optimizing and choosing algorithms, and our teacher didn’t offer any of that.
- Chemistry – I still don’t understand why I needed to take this class.
- Circuits – Has had no bearing, whatsoever, on how I do my job. I’ve tried my hardest to block out how inductors and capacitors work.
This is an incomplete list, but if you happen to come across it, maybe it’ll make you smarter.