Recently we took on a client project which entailed building an Android app. The client delivered to us a set of sixteen 30x30 pixel PNG icons for use in the app. The icons displayed well on low-density screen devices, such as the Samsung Moment, but they were not large enough to accurately retain detail on higher density screen based devices, e.g. HTC G1 and the Nexus One. The solution was to redraw the icons in vector format and size them for the various screen densities.
Android uses a number of resource directory qualifiers for controlling which density-specific icon will be displayed for each device. In this case I focused on creating icons for low-density (ldpi), medium-density (mdpi), and high-density (hdpi) screens. Effectively, this means three specific sizes of each icon are needed—36x36 pixel, 48x48 pixel, and 72x72 pixel icons. It is worth noting that the new icon document resolution should remain at 72 pixels/inch for all icons, including high-density screen icons (don’t be fooled by the android density numbers).
The process began by importing all sixteen icons onto a single document in Adobe Fireworks. I used Fireworks’ vector tools to retrace each icon. Rather than using the merging tools on the vector paths, I used Rogie King’s Alpha converted vector groups technique to preserve a high amount of editing for the icons. The new vector paths can be seen in the icons below.

After vectorizing all sixteen of the original icons, I then set out to resize them. The Android developer docs contain useful guidelines for creating menu icons with consistent visual weight across all devices.
To maintain pixel perfect appearance, tweaks will often need to be made when vectors are resized up or down. The alpha converted vector groups helped facilitate the tweaking process. The icons below are sized for their respective screen densities.
After all the icons are resized and exported as transparent PNG images, they must be placed in their respective folder in the resources directory—drawable-ldpi, drawable-mdpi, drawable-hdpi. The filenames must remain the same for each icon, but be stored in the mentioned density-specific resource directories. Android devices will load the proper resources according to the screen density of the device.
Below are a few ‘before and after’ views of a few icons that went through the process. The icons appear much crisper, have sharper edges, and are now fully transparent. The end result provides a much more professional looking Android App, whereas the icons enhance the menu navigation by providing the user with a clearer interpretation of each graphic symbol.
We’re looking for both designers and developers who are students, recent graduates, or more experienced candidates making a techology or career change to come on as Apprentices. If you are interested in applying, please visit our jobs page. If you know someone who might be a good fit, please pass it on.
The paid apprenticeship lasts for three months and during that apprentices will work alongside members of the thoughtbot team on actual shipping software and be paired up with individual developers and designers at thoughbot who will act as their mentor. They also get to take any workshops we offer during their apprenticeship at no charge.
At the end of the apprenticeship we may offer them a position as a web designer or developer at thoughtbot.
We’ve had interns, particularly in the summer, for several years now. Over the past few years we’ve increasingly been contacted by more experienced developers who are just getting started with Ruby and looking to find a place where they can be effective, while still learning.
At thoughtbot, we also don’t have different levels of developers or designers. Everyone should essentially be capable of operating at the level of senior developer or designer (or be able to soon after starting). We do this to ensure that we can operate effectively without project managers or salespeople. However, from time to time we interview people who we think may be a good fit eventually, but need more experience. In the past, we’ve sometimes offered these people an internship as a chance to learn on the job and potentially quickly grow into the developer we need them to be.
When offering these people an internship, it never quite felt right to call them “interns” but it was the best word we had. Additionally, over time we refined the internship program to really be a path to potentially getting an offer to be a full web designer or developer at thoughtbot.
With this in mind, along with some other lesson’s learned from the previous interns, we sought to have a more structured program in place. Out of that emerged our new Apprentice program.
We think that the changes we’re making now should make the Apprentice program worthwhile to everyone involved, and we’re looking forward to the first batch of Apprentices joining us in May.
Our event, Developers Developers Developers Developers, is this weekend.
When the amount of registrations reached the capacity of the venue, we removed the registration form from the website.
However, we left the Rails route and controller around and encouraged students to register by reading the source code of the application and coding their way in. We pointed them to the staging app so they could practice before registering via the production app.

So we just need to POST to /registrations with the right params, right? Right. However, “the right params” needs to include Rails’ authenticity_token, which the framework uses to combat CSRF. The payload also needs to include a cookie because the authenticity_token depends on it.

So here’s the cURL solution.
Step 1:
curl http://dddd-staging.heroku.com --cookie-jar cookie | grep csrf
That will store the cookies in a file named “cookie” and print out the authenticity_token you need (it’s the value of the content attribute on the csrf-token meta tag):
<meta name="csrf-param" content="authenticity_token"/>
<meta name="csrf-token" content="sNMk592JV2wwHn6DPJ8C5oy/hHDnjIlZBOHyngtTbpQ="/>
Meanwhile, the contents of the cookies file looks like this:
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_dddd-staging.heroku.com FALSE / FALSE 0 _dddd_session BAh7ByIQX2NzcmZfdG9rZW4iMXdNWm5kUWRLWGRWWGlUZSswT0VFRFN6NHl5dkNWL1NuLzZ1alh3c2lndU09Ig9zZXNzaW9uX2lkIiUwNzNmYmI2MTA0MmI5ZTgxNmUxODA0MzJhOTIyNTk2Yw%3D%3D--fb9ee7c9f96cea60d7be43ff87ce1ac9a8e53548
Step 2:
curl http://dddd-staging.heroku.com/registrations --data "registration[name]=Dan Croak®istration[twitter]=croaky®istration[school_name]=Holy Cross®istration[role]=Developer&authenticity_token=sNMk592JV2wwHn6DPJ8C5oy/hHDnjIlZBOHyngtTbpQ=" --cookie cookie
This adds the authenticity_token and also includes the cookie from the first request.
The output will be the original HTML that we fetched and replaced on the page via Ajax when registration was still open:
<div class="student">
<div class="avatar">
<img src="http://avatar.statusok.com/croaky?size=73" />
</div>
<div class="student-details">
<div class="name">Dan Croak</div>
<div class="twitter">@croaky</div>
<div class="role-and-school">
Developer, Holy Cross
</div>
</div>
<h2>Thanks for registering! We can't wait to see you!</>
<h3>Follow @<a href="http://twitter.com/thoughtbot">thoughtbot</a> and @<a href="http://twitter.com/greenhornboston">greenhornboston</a> for updates.</h3>
<h3>We also invite you to join our private <a href="http://groups.google.com/group/developers-developers-developers-developers">mailing list</a> for speakers and attending students.</h3>
</div>
However, we’re living in the future here, folks. It’s 2011, and we’ve got a GUI for everything - no need to get Terminal all over your hands.

So let’s load the site normally in a web browser, view the HTML source to grab that authenticity token, insert a form into the DOM, then submit it.
I’ll be using Chrome and the WebKit Inspector here, but you could also use Firefox and the excellent Firebug plugin.
Step 1: Find the authenticity token
Here I view the HTML source and look for the authenticity token in the element:

Step 2: Insert a form into the HTML
Here’s the registration form that we’ll add back into the page. I made sure to insert the right authenticity token:
<form action="/registrations" method="POST">
<input type="text" name="registration[name]" value="Jason Morrison" />
<input type="text" name="registration[twitter]" value="jayunit" />
<input type="text" name="registration[school_name]" value="RIT" />
<input type="text" name="registration[role]" value="Developer" />
<input type="text" name="authenticity_token" value="iKSXdP4+Ir80ABwsmwvX5LjUKdto3n6p99E/+pgmegI=" />
<input type="submit" />
</form>
You can insert the form anywhere. Let’s overwrite this paragraph:

Paste in the HTML:

Step 3: Submit the form
Click submit, and you’re off to the races.

See you at the event!
Most of my thoughts about design spawn from asking myself what makes a project successful. Well, what does? Most will agree that good design does. This is not speaking exclusively about the graphic design or implying that everything rests solely upon the shoulders of the Designer. Everyone is a designer. Design is a fundamental part of everything. Keep this philosophy in mind for the entirety of the project.
thoughtbot has always been known primarily for its Rails expertise and as such the projects have been driven majorly by the development, headed by a Lead Developer.
Over the last year or so, with the addition of new designers to the team, we were able to focus much more on design. We’ve started with design first, as we should, and this has been quite successful. The general practice was to do our research, form our wireframes, and move onto the visual design. The problem is, once we got past the initial design steps our process would splinter a little. Design would still be important and never forgotten but a detachment formed between the design and the development.
Now, we want to fix this. We need to make sure that whatever we’re working on is the most beneficial thing to the end user. We work off user stories and shouldn’t pick ones to work on because they’re easy or need to get done eventually. The user stories should be prioritized with good design in mind. We must stay vigilant in creating the best possible product for the target audience. A great way to accomplish this is to keep the design of all things at the forefront of our thought processes. Keeping a project driven by design will help this happen.
As of late we’re beginning to drive projects with design from start to finish. As I hinted at already, this does not mean a project should revolve around the graphic design or visual aspects. This means the design of everything should be well thought out. From things as simple as structuring the meetings well, to things as complex as building the code properly, to things as crucial as wireframing the flow of the app. Design should be at the forefront of our thoughts in every step of the building process.
We’ve had great success with a few things lately. None of them are new ideas but sometimes we just forget about them. They are all things that both a designer and/or a developer can accomplish.
Recently on one of our projects we wanted to test out a proposed flow for a new app. In a day or two we were able to bust out some very unsexy but very understandable HTML wireframes. They were clickable, buttons did what you expected them too, and you could navigate between pages. The app didn’t have any real functionality but it helped both the client and us easily identify trouble spots and conversely figure out what was working best. This was immensely helpful and saved quite a bit of time in the long run.
On another recent project we wanted to get something in front of people as early as possible. Similar to the wireframes in the last section, the app did not work. It was a little more polished but really just a pretty wireframe. The difference between this and the previous method was the people running through the app were not part of the team. Even having a few people unfamiliar with the app click through and share immediate thoughts let us rapidly modify the app and only a week later, test again. Over the course of 5 weeks we did this 3 times. The client is pleased (and enjoyed listening to the feedback) and the app is undoubtedly in better shape than it would have been if we waited longer to user test.
One of the biggest problems, in my opinion, is having the design and development relationship splinter as the project grows, both roles will just work on what they feel is best without consulting one another.
There are a few things you can do to help avoid this. The biggest aid, in my opinion, is designers, developers, and clients work physically close to each other. Members of teams at thoughtbot all sit together, and we’ve undeniably had our best results when the client was able to work with us in person. We can easily verbally communicate at a moments notice. We’ve found that asking user and goal related questions, discussing as a team, and coming up with the best solutions really helps to keep us on track and work as one unit. Questions like:
To facilitate these ideas, whoever is best fitted and most comfortable to fill a role that focuses on designing for the user experience should be the project lead. This can be a designer or a developer. Everyone is a designer. Everyone helps the design process. So, if you haven’t tried this process yet, give it a shot on your next project. Embrace well thought out design in all aspects of your project, and see if you don’t feel better about the end result.
This week, Matt and I were converting pagination in an app to Ajax pagination. In the process, we broke the build.
The failing feature looked something like this:
When I follow "Next page"
And I comment on "Ford" with "Fjord is a better name for a car."
Then I should be on the second page
And I should see the "Fjord is a better name for a car." comment
The implementation of “I should be on the second page” expected that this query string existed: page=2. When we switched to use Ajax, we could no longer check the query string in the same way.
We came up with the following implementation, and used Akephalos to make sure the Javascript was integrated into the test:
When I follow "Next page"
And I comment on "Ford" with "Fjord is a better name for a car."
Then the comment on "Ford" should have been made via Ajax
And I should see the "Fjord is a better name for a car." comment
It uses this code from features/support/ajax_recorder.rb:
class AjaxRecorder
def self.clear
@@records = []
end
def self.save(env)
@@records << env
end
def self.has_path?(path)
@@records.any? { |record| record['REQUEST_URI'] == path }
end
end
class AjaxRecorderApp
def initialize(app)
@app = app
end
def call(env)
if env['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'
AjaxRecorder.save(env)
end
@app.call(env)
end
end
Capybara.app = AjaxRecorderApp.new(Capybara.app)
Before do
AjaxRecorder.clear
end
If it’s not clear, we wrote a Rack app that records Ajax requests into the @@records class variable on AjaxRecorder, and inserted it as middleware into our Cucumber/Capybara/Akephalos stack.
We were then able to use AjaxRecorder.has_path? via RSpec in features/step_definitions/ajax_steps.rb:
Then /^the comment on "(.*)" should have been made via Ajax$/ do |value|
response = fetch_moderated_response(value)
path = clients_moderated_response_moderated_comments_path(response)
AjaxRecorder.should have_path(path)
end
One reason this might be insane is that it appears to be testing implementation instead of behavior. Users don’t care about “Ajax”, they care that the site loads the new comment quickly, on the correct page.
There are at least two advantages to this test, however:
There are certain factors of a web application that are important but a little difficult to capture in Cucumber scenarios. Factors like:
Maybe they’re not impossible to capture if we’re willing to use implementation details such as XMLHttpRequest as a proxy for those factors, then tie that implementation to our user experience intent using language in our Cucumber steps:
Then the comment on "Ford" should have been posted quickly, without reloading the page, and with brief visual feedback
“without reloading the page” would be implemented using our AjaxReloader, “posted quickly” could be implemented using a timer/benchmark, and “brief visual feedback” could check that we pulsed/highlighted the new comment.
What do you think? Is this insane?