Conroy Whitney is a Software Engineer, Web Developer, and Android Application Developer. http://www.google.com/profiles/conroy.whitney
Posts by Conroy Whitney
I often think about whatever job I’m doing as a “struggle against entropy”. Entropy, as Muse explains it:
All natural and technological processes proceed in such a way that the availability of the remaining energy decreases.
In all energy exchanges, if no energy enters or leaves an isolated system the entropy of that system increases.
Energy continuously flows from being concentrated to becoming dispersed spread out, wasted and useless.
New energy cannot be created and high-grade energy is being destroyed.
An economy based on endless growth is unsustainable.
We all know that entropy is going to win, eventually. That’s considered a given in physics. And empirically we can say that’s true in our own lives. Our laundry goes from clean to needing to be cleaned; our meals go from cooked to eaten; our bodies go from born to dead. Even when we make efforts every day to slow or reverse these processes, eventually, inevitably, entropy will win.
Some jobs, the amount accomplished vs. the effort put in forms a sort of logarithmic graph. For example, working as a bartender: at the end of the day, after all your customers have been served, your bar is clean, your glasses are clean, your trash is taken out, you have re-stocked, and you are ready for the next shift. If you don’t do everything well, you’ll be behind the next day, and things will be harder going; the lack of effort compounds to form a morass of difficulty. However, there is no getting ahead; even if you clear every ashtray and wipe every counter as soon as they are dirtied; even if you restock every cold beer as soon as it is served; you still can only reach a certain output. You still, at the end of the day, will end up with clean floors, clean glasses, and a fresh start for a new shift. Any optimizations on top of that (a better inventory or POS system, batching work when mixing drinks, etc.) only gains a small amount of additional output. Hence the logarithmic graph. Eventually you come to the limit of how much you can optimize that type of job.
Other jobs, however, form an exponential graph in terms of amount accomplished vs. inputted effort. Technology plays a key role in these situations. Any time when you can replace work that a human normally needs to do with a (semi-)automated system, you are increasing your output relative to input. And if your job is to create said technology, then your input outputs an output that in return multiplies future inputs: exponential. It’s acceleration: applying the same amount of force equally over time results in a compounded velocity. It’s a form of bootstrapping: companies (specifically startups), building ideas and systems around existing ideas and systems until they can impact 10, then 100, then 1,000, then 100,000, then 1,000,000 users; not with 1,000,000 times the effort, as it would be if you were trying to run a bar with 1,000,000 customers; but instead with (roughly) the same (probably less than a factor or two of 10) amount of man-hours.
And that’s our ultimate weapon in the struggle against entropy: our time. Some things require linear relations for our efforts: sleeping, exercise, hobbies, volunteering, time with family, watching TV. But for me, work — where I spend at least 1/3 of my day — is an area where I constantly look for areas to improve my multiplier. If there is a task that I am frequently needing to perform that seems like a good candidate for automation, I need to automate it. Why? Because if I don’t, I feel like I’m stuck in a hamster wheel running in the same circle over and over. I don’t want to solve the same problems every day, day in, day out. I want to solve new problems; interesting problems; problems that make tomorrow better than today. Because these types of problems mean that in the struggle against entropy, I’m not just entrenched, holding the line, content to not be losing ground; no, I’m winning battles, advancing forward, and marching towards a goal that grows ever-nearer. And in this struggle against entropy, technology is my rearguard, allowing a retreat to a safety zone of automated processes and analyzable numbers so that even when I lose a battle, all is not lost. We can pick up our wills and fight the struggle against entropy for yet another day.
An oldie but a goodie from 1990 on choosing names for servers: http://tools.ietf.org/html/rfc1178.
Most of the document is about what *not* to do and why, but here’s really the core of what is considered best-practice when choosing a naming scheme for multiple machines in a group:
Naming groups of machines in a common way is very popular, and enhances communality while displaying depth of knowledge as well as imagination. A simple example is to use colors, such as “red” and “blue”. Personality can be injected by choices such as “aqua” and “crimson”. Certain sets are finite, such as the seven dwarfs. When you order your first seven computers, keep in mind that you will probably get more next year. Colors will never run out. Some more suggestions are: mythical places (e.g., Midgard, Styx, Paradise), mythical people (e.g., Procne, Tereus, Zeus), killers (e.g., Cain, Burr, Boleyn), babies (e.g., colt, puppy, tadpole, elver), collectives (e.g., passel, plague, bevy, covey), elements (e.g., helium, argon, zinc), flowers (e.g., tulip, peony, lilac, arbutus). Get the idea?
We’ve all been burned providing our email address to websites. Maybe you did it out of the best intentions: wanting an e-book; or a set of tips sent by email; or simply just to get past a content gate. But you always know, deep down, that your inbox is going to hate you for subjecting it to yet another onslaught of poorly-targeted “email blasts” or other such spam.
Have you ever been linked to a blog post where, before you can even get a chance to read the first sentence, a modal pops up asking you to “SUBSCRIBE TO OUR BLOG SLASH NEWSLETTER! FOR THE WIN!”. You don’t even know who they are, or what they do, or what other type of content is on their site. There’s no way in hell you’re going to give out one of your most guarded public secrets (your email address) to these complete strangers.
So if you are so wary of providing your email address, why do you expect your users to?
Don’t ask users for their email address at the expense of them being able to actually use your site. It’s a turn-off, and they’re not going to convert. Instead, how about asking them in a CTA at the bottom of the article? And how about, instead of it being “Subscribe! Subscribe! Subscribe!”, perhaps it can be “Learn more about X Topic You Just Read About.” Imagine that. Email subscriptions targeted to the type of content they are interested in.
tl;dr Yes, ask for emails; but be classy about it. You might just end up with higher value leads.
If you are seeing this capybara error:
Unable to find css "[element_id]" (Capybara::ElementNotFound)
Make sure that you actually call
visit before trying to
find an element!
I was trying to use a regular capybara selector
This should have been cut and dry. Since capybara’s
find() selector uses
#id by default, and since my page had that specific element on it, there should not have been any issue. But no matter what I tried — more different selectors, xpaths, etc — I kept getting the same frustrating error:
Unable to find css "[element_id]" (Capybara::ElementNotFound)
I thought I was going crazy, or that I had completely lost my ability to program, or both!
My problem was that I had forgotten to call
visit before calling
As soon as I called
visit, my error went away
visit '/' find("element_id").should be_visible
This makes sense, though, right? If you don’t call
There is no HTML content in which to find your element!
It would be nice if capybara had a more descriptive error when you try to call
find without having first called
visit. That way this type of error would not frustrate so many people for so long!
I hope this helps!
Have you received this error message while trying to run bundler, or start your rails server?
did not find expected key while parsing a block mapping at line 1 column 1 (Psych::SyntaxError)
The problem is that your
database.yml file is not being parsed properly because of inconsistent indentations.
Can you pick out what’s wrong with this code?
default: &default adapter: postgresql encoding: unicode pool: 5 development: &development <<: *default database: <%= ENV["HEROKU_POSTGRESQL_DATABASE"] %> username: <%= ENV["HEROKU_POSTGRESQL_USERNAME"] %> password: <%= ENV["HEROKU_POSTGRESQL_PASSWORD"] %> host: <%= ENV["HEROKU_POSTGRESQL_HOST"] %> port: <%= ENV["HEROKU_POSTGRESQL_PORT"] %>
This code causes the
did not find expected key while parsing a block mapping error while trying to start the rails server.
The underlying problem is that the YML inheritance line
<<: *default is indented at the same level of
development: &development instead of the same level of
database:. The correct code would be:
development: &development <<: *default database: <%= ENV["HEROKU_POSTGRESQL_DATABASE"] %>
This should get rid of the
did not find expected key while parsing a block mapping error you receive when you try to run your rails server or bundler, or anything that parses your
Hopefully this solves your problem. Good luck!
All day long, our brains are chugging away, one thought after another. Do I press snooze or go for a run? Oatmeal or smoothie? Black shirt or blue shirt? Time to go to work. Work, work, work. OK, work’s done. Do I go for a run? What’s for dinner? Go to bed or open one more reddit link?
When we work, is it because of what we want to give to the job? Or because of what we want the job to give us? In the first situation, we are motivated by the work itself; we have clear goals and reasons for participation and, if they are no longer being met, we are free to switch our focus to something else on which we want to spend our time. In the latter situation, we are motivated by the effects of the job, such as money or career advancement; the job is not inherently special to us; it’s simply a means to an end.
Take a moment and reflect on why it is that you do what you do. Have some meta-thoughts: thinking about why it is that you are thinking what you’re thinking. The only way to change the future is to notice the present decide to act.
One might argue that the more versions of ruby and rails your gem supports, the more valuable it is to the general population. Well, I guess it does also depend on what your gem does (rainbows and unicorns?).
Thoughtbot has done it again with appraisal, a neat and nifty gem for testing your gem in different ruby and rails environments. It’s especially useful when combined with Travis to specify which continuous integration environments should be used or ignored. (see gringott’s travis.yml for an example).
Note: appraisal’s README on github is curently for for the 1.0.0.beta2 version. This can be confusing since the current rubygems version (and what you get if you just do
gem "appraisal" is 0.5.2. You can either use the beta version with
gem "appraisal", "1.0.0.beta2", or, you can use the 0.5.2 version of the README
As mentioned in the README, you can run your spec and cucumber tests against these ruby/rails versions using appraisal. What’s not mentioned, though, is that you can also run your local webserver against your different appraisals as well.
Since appraisal essentially just pre-compiles the bundles that you are going to use for your different appraisals (e.g., rails-3.2, rails-4.0), you can use that to your advantage:
First, find out the path to the bundle that you want to test locally:
Look for the line that like:
bundle check --gemfile='/pathbot/to/rails/engine/gemfiles/rails_4.0.gemfile'
We are going to hand that path to our webserver so it knows what bundle to use. However, instead of using the –gemfile option, we are going to pass it as an inline environment variable:
BUNDLE_GEMFILE='/path/to/rails/app/gemfiles/rails_3.2.gemfile' bundle exec rails server
Or, if you are developing an engine, you can run your dummy app’s rails server using
BUNDLE_GEMFILE='/path/to/rails/engine/gemfiles/rails_3.2.gemfile' bundle exec spec/dummy/bin/rails server
Note: spec/dummy is the location of your engine’s dummy app. This might instead be in test/dummy, depending on how you set your engine up.
Running a local webserver against different ruby/rails appraisals is useful for being able to manually play around with why a particular test might not be working in a particular bundle (e.g.,only on firstname.lastname@example.org).
One last thing, maybe this was just something quirky on my end, but I ended up having issues when running my rake tests against my rails-3.* appraisals. I kept encountering this error:
undefined method `migration_error=' for ActiveRecord::Base:Class
Unable to find a solution, I am embarassed to say that I instead took the lazy (and very time-consuming) way out of repeatedly pushing to github after every commit so that Travis would run my rails-3.* tests for me so I could debug where my issue might be occurring. That wasted not only a lot of my time (5 minutes between fix and result), but also a lot of Travis’ server hours… Sorry guys! Let me know how I can show you some love.
Anyway, the hidden clue to the solution to the
undefined method issue was hidden in one of the comments on one of the unaccepted answers of one of the StackOverflow questions. As Iliya Stepanov points out,
It was one string in config/initializers or environment. I don’t remember exactly what string it was, but check carefully that files if you rolling back from Rails 4 to 3 and facing similar problems.
It turns out that in
spec/dummy/config/environments/development.rb there is this line:
config.active_record.migration_error = :page_load
I commented that out, and everything worked hunky dorey. It doesn’t make me happy to think that I am suppressing potentially useful errors, but there were no migrations that needed to be migrated. Also, I’m pretty sure that might have only been related to the fact that I created a rails4 engine, then was trying to backport its dummy to rails3. Pretty sure.
Rails 4 introduces a new way of signing cookies that differs from the previous method in Rails 3. When you upgrade to Rails 4, you are likely to receive a warning:
DEPRECATION WARNING: You didn't set config.secret_key_base.
As pointed out in the guide for upgrading rails, you can simply run
to generate a new secret, and paste that into
However, do we really want this crucial security key to be hard-coded in our application and pushed to our repository? What if our repository is public, like in the case of an open-source app like the gringotts demo?
Well, my friends, we can simply use an ENV variable to store the secret. In
config/initializers/secret_token.rb, put this line:
*YourRailsApp*::Application.config.secret_key_base = ENV["SECRET_KEY_BASE"]
Now, we can check in
config/initializers/secret_token.rb without worrying about anyone ever seeing the secret key that our application uses to encrypt cookies. But now we need to make sure that
ENV["SECRET_KEY_BASE"] will actually be set, both locally and for Heroku.
Locally, we can use the nifty figaro gem to set ENV variables quickly and easily. Following the instructions on the figaro github page, we add
gem "figaro" to our
rake figaro:install, then edit our
config/application.yml to add the line:
SECRET_KEY_BASE: (really long string output of rake secret)
For Heroku, we could use figaro’s helper rake task for updating Heroku’s config vars (
rake figaro:heroku). However, what if we accidentally check in our
config/application.yml file? We’d be sharing the secret key used to encrypt our cookies on our production server. Noooo good!
Preferably, we can generate a separate secret key for Heroku
heroku config:set SECRET_KEY_BASE=$(rake secret)
Just realize that when you change your secret key base, all previous versions of your cookies will no longer be valid.
And that’s that. We are now Rails 4 compliant (no more DEPRECATION warning), and we have the added bonus of keeping our secret a secret.
Google’s “deep learning” clusters (aka the Google Brain) are responsible for figuring out what the hell we intend to communicate when we type broken Spaglish into Google Translate or what words we used when we mumble to Google Voicemail on a windy afternoon.
The deep learning cluster is also being developed in order to recognize objects (and, *sigh*, yes, faces) in photographs. So far this system is really good at identifying cats in YouTube videos (which, that alone, is worth the price-tag) and, as it turns out, paper shredders.
Wait. Paper shredders? What gives? Who cares?
Well, according to Google engineers at the recent Machine Learning Conference in San Francisco, the paper shredder phenomenon is anecdotal evidence that the algorithms underlying these deep learning machines have started to develop their own way of looking at the world that is different from our puny human brain.
“Google researchers can no longer explain exactly how the system has learned to spot certain objects”
This is a two-parter. First, off the programmers themselves were unable to come up with any ideas explaining how these algorithms are able to distinguish paper shredders in images. Secondly, us meat-sacks did an even worse job at identifying this particular type of office supply than our computer counterpart.
So there you have it. The future is here; it’s bright; it’s now; and it’s somehow related to paper shredders.
I really enjoy reading Cindy Alvarez and I highly recommend that any product managers read and internalize her advice. If we all did, the world would be a much easier place with which to interact. Recently, I appreciated her post titled Good Enough vs. Good Enough Never Is about how the phrase “good enough” is *not* an end, but rather a means to an improved product.
To rephrase: “Good enough” is not an acquiescence to mediocrity; but rather an admission of ignorance and a dedication to learning.
Cindy makes a great distinction that is a twist on the old adage “You are not your customer.” Her distinction helps you decide when your product is “good enough” to release:
- There are things in my recently released product which make me cringe.
- There are things in my recently released product which make our customers cringe.
It is a conscious effort for me to detach myself from something that I do not consider to be ready for release and to say “This is good enough.” However, Cindy’s distinction helps make that decision easier: at the current stage, does the product provide value to the customer without making them cringe? Nevermind what I think; I am not my customer.
There is always a trade-off between the time you spend on a product and the value a customer gets out of it. What we as product managers may see as “glaring” errors or omissions in the product may not be noticed or missed by the customer.