Friday, September 10, 2010
Last post on this blog
But nonetheless, I think it's time to retire this blog. It's been fun y'all, but I think it's time to move to another phase. I think I was more prolific before, since I was learning a lot. Nowadays, I'm still learning, but have been less inclined to write about it. But, I'm breaking that habit and making it a point to write again. If you'd like to follow me over, I'm at:
http://iamwil.posterous.com/
Thanks everyone for reading this blog. It's been fun. I'll see you on the other side.
Wil
Wednesday, September 01, 2010
Gotchas to getting started in Titanium
After promising myself to blog more, I ended up with my head down programming. But I'm back to let you know what I learned! About a week or two back, I got started using Appcelerator's Titanium. It's basically a framework that lets you to write native mobile apps in javascript that you can compile across multiple mobile platforms.
Titanium is actually set up like Shoes. Most of the application code is written in javascript, and then some of this code delegates its execution to Objective-C, like how in Shoes, it's Ruby up top, and for slow parts, the execution is proxy-ed to C. Therefore Titanium doesn't really "compile" to native Objective-C code, but rather, it's written in native Objective-C and uses the already built-in javascript to tie things together at the top application layer. On android, just replace Objective-C above with "Java".
I think it's a much better idea to have a scripting language on top of native code to tie things together at the application layer. Developer time goes much faster, and you definitely make less mistakes with memory management. However, there's a bunch of gotchas in getting started with Titanium. And while their marketing copy makes it seem like it's pretty painless, there's actually enough potholes in the way to stop you from even getting started.
To start, you need the correct combination of the iPhone SDK and the Titanium SDK in order to get it started and working. So make sure you have the latest SDK. I'm on the iPhone 4.0 SDK and Titanium Developer 1.2.1 with Titanium SDK 1.4.0. For those of you wondering, you can compile with a iPhone 4.0 baseline, but still compile to a lower iOS. I have a 2G iPhone running 3.1.3 firmware, and it runs fine since I'm not using any new APIs.
The other gotchas have to do with the javascript API. For example, when creating a button, we do something like this:
var logoutButton = Ti.UI.createButton({ title: "Logout", top: 55, left: 10, right: 10, height: 35 }); settingsWin.add(logoutButton);
Seems pretty easy, except the documentation doesn't mention that while you can have left and right co-exist to set left and right margins, you can't actually have both top and bottom co-exist to set top and bottom margins. If you do, it simply won't display your button, and you have no idea why.
Alternatively, there is no mention of what are required options and what are optional options. For example, for textfields:
var blurbField = Ti.UI.createTextField({ hintText: "Enter Note", height:35, top: 65, left: 10, right: 10, borderStyle:Ti.UI.INPUT_BORDERSTYLE_ROUNDED }); contactWin.add(blurbField);
It seems pretty elementary, but it's required that you specify the borderStyle, or else your button and textfield will simply not be displayed with no error. Buttons and textfields also require a height, otherwise, the chosen default is the full size of the screen! That doesn't make any sense. Also, when using tableViewRows, all rows with a different layout need to have a different className, for the native app to be able to conserve memory.
None of these gotchas are intuitive, and confuses the heck out of people, but I realize they're obvious to those that have first worked in Objective-C and then in Titanium. Given the goal of Titanium is to provide web devs an "in" to writing native apps without writing in native code, I'd say it's not there yet. Titanium is at best a leaky abstraction on top of the native code.
The worst part about using Titanium is its include mechanism. It isn't at all like include or require in other languages. It's actually more basic then that--essentially just a cut and paste of code. After I realized it's not a mature javascript development environment that you might be use to with in-browser javascript or node.js, things went a lot smoother. In a later post, I'll talk about Ti.include() and the follies that come with it, so you save yourself some headaches down the road.
Tuesday, August 10, 2010
Details of CouchDB Implementation
Found a detailed piece hidden away in the mailing list archives of how Couchdb works. It's from way back in 2008, but I think most of it still holds true. It's a good read, especially because to me, mysql and postgres has always been black boxes.
CouchDb's architecture seems simple enough to understand as a whole, and while the devil's in the details, it goes to show that CS 225 was super important
Monday, August 09, 2010
A short script to start work and block sites
Sometimes, I'm able to focus and I can have noise in the background, but at other times, it can be hard. If you find yourself starting to type "faceb..." every time you hit upon a slightly hard problem, then maybe what you need is to block websites that you frequently go to when you're bored.
There are plenty of services that lets you do this, including Rescuetime, I believe. Anyway, being a techie, you should know that you're able to do this just by editing your etc/hosts file.
But, I know that I need something where in order to block sites, the barrier is low, and in order to unblock them, the barrier should be high. That way, I can still unblock something when I need it, but really, it's mostly just an awareness that's needed. Once you hit upon "This website can't be found" a couple times, you really just buckle down every time there's a hard problem, instead of dodging it.
All you need to do is put the startwork script file somewhere in your execution path, and then edit your /etc/hosts files with the websites that you want blocked pointing to your localhost (127.0.0.1).
In order to run it, just type "sudo startwork". And then in order to unblock a site, "sudo [use your favorite editor] /etc/hosts" and then comment out the sites you do want with "#". Yay. Now get to work.
Wednesday, August 04, 2010
If MVP fell out of the sky and wiggled on your face, would you know it?
Minimum viable product. It's something that most of us working on a product or project know we should do, but hard to actually do in practice.
For me as an engineer, it was particularly hard because you have the ability to build, and you like doing it. Therefore you're use to building something first, and then showing it to people. That's because just telling people that you have something without having actually built it just seems like...lying.
Half the problem of an MVP is picking the right scope for your problem. But beyond that, there are other reasons that might derail you from building an MVP.
Often times, we don't know what actual MVP might look like. Other times, we have fear that gets in the way of letting us release MVP. I'll tackle the first, and then the latter in a future post.
When you're thinking about the solution to your problem, think of the simplest thing that could still work. Then cut and have it do less. Does it still solve the problem? If it doesn't, see if you can shrink the scope of the problem. If does, see if you can shrink the solution. Keep going until you only have one basic unit of good/help that you're giving to the world.
This basic unit of good is your core value proposition, and it's also what you're testing to see if it's something people will want and find useful, because at this point, you don't really know. You might know whether you'd find it useful, but you may not know if others will.
If the core proposition of your product is compelling, your users will forgive all sorts of un-polish. Don't fall into the trap of thinking that the next feature you add will be what brings the boys to the yard. There will not be just one feature that rockets you into the stratosphere. You'll just end up building fluff and throw pillows on top of a cornucopia of crap features. I think it's what they call polishing a turd (or putting lipstick on pigs).
Think about software for an airport control tower. What's its main core value proposition? To land planes. If it doesn't do that, it doesn't matter that it can land big planes, small planes, on any number of different frequencies, or how many it can do at once. No one will care because it doesn't land planes.
Another good example is Mixpanel's reporting. They report all their times in UTC, probably because they just didn't want to mess around with timezones. You'd think that in building the MVP for web analytics, you'd need to show the stats in the user's timezone. Apparently not. Mixpanel's core proposition is real-time tracking of events generated by your visitors.
Delicious's bookmarking (and by same reasoning, Flickr) is another good example. It's core value proposition is for me to save web pages and organize it easily for recall later. It's useful to me even if there's no other users around. However, the public nature of the bookmarks and tags has the added side-effect of having aggregations. It has to be first useful to a single user, even without other users around. Many new startups ignore this aspect and concentrate on the benefits when there are already a lot of users. Very rarely will you have a scale of users to leverage in the beginning.
You can much more easily position and market yourself when more focused. And when it comes to partnering, or being acquired, there's less chance for conflict. This is all so logical and, yet, there's a resistance to focusing. I think it comes from a fear of being trivial. Just remember: If you get to be #1 in your category, but your category is too small, then you can broaden your scope—and you can do so with leverage. - Evan Williams
Using quizzes to train your brain as an L1 cache for recalling people
Today, we launched quizzes at Noteleaf, where Noteleaf generates quizzes about people based on the notes you've taken of them. You can either start it from the web, or Noteleaf will email you a quiz every week. You can change the setting to 'every day', or if your memory is perfect you can set it to 'never'.
Quizzes came about from feedback and our own experiences. Usually, we have time to look people up on Noteleaf before we go and talk to them. However, there are times where we're expected to remember people on the spot, especially when we just run into them. In these cases, we can't take the time to look up people on our devices--until we have bio-implants with an interface to the web that is.
While we don't have bio-implants, we realized that we could use our brains as sort of a cache. It just needs a little bit of nudging for recall, and that's where quizzes come in. It's a fun way to review the things that you've written and use that to strengthen your brain cache.
As basic as it is, it's actually pretty fun to take the quizzes, especially if you have a lot of notes. Alex Trebec, eat your heart out.
It had meant to be a short quick feature that we pumped out, but it ended up taking more than twice the amount of time. In hindsight, the estimation was right. Quizzes didn't take that long at all--maybe two or three days. But what we didn't take into account was all the infrastructure that goes with it. The background processing jobs. The cron script setups. The mixpanel analytics. The copy.
So next time that you're doing estimation, take those things into account as well.
Sunday, August 01, 2010
Running Resque Web
1 2 3 4 | Rails::Initializer.run do |config| #....... config.middleware.use 'ResqueWeb' end |
Monday, July 19, 2010
If they can copy a fighter jet, they can copy your damn website
They copy computers, cellphones, cameras, video players, watches, bags, and everything man-made—but did you know that the Chinese also copy entire combat airplanes? It's simple: They buy one and measure every part and system to clone it.
Lately, I've taken note of both ASmartBear's It's not a Competitive Advantage and Sachin's assertion (can't find the quote right now) that when investors ask him about defensibility, he replies that they don't understand the internet.
If they can copy a fighter jet, they can copy your damn website.
What's missing from a copy? I'd say intent is one of them. Especially if your product iterates and always tries to do something hard. It'll take them longer to copy, and they'll always be on the defensive. For actual competitive advantages, check out another list by the bear.
Friday, July 09, 2010
More dead than alive
At some point soon we’ll start having an awful lot of dead people around. I’m very sure Google and other search engines will start to filter for deceased people search. It won’t be long at at until we have way more dead people online than live people online.
That's a thought I never thought about. But it may be true.
But what would even be more memorialistic(?) is if we could have online versions of ourselves running around the online world commenting and participating, as if we were alive.
I remember thinking this when I saw "I, Robot", where Will Smith talks to a holographic 2D projection of a dead investigator for clues, but the investigator can only reply to what he knew up to the point of his death.
Though I'm not sure we can recreate something like what's in the movie, it's not infeasible to be able to feed all the text archived in all your chat logs, emails, wall posts, and status messages into some machine learning algorithm so given some text directed at you, it would be able to generate what you would mostly likely say in reply. It may be just an elaborate hidden markov model or something else, but either way, just a elaborate quote machine--that quotes you.
It could be a service that you'd go to, in order to talk to someone dead--like at an oracle, shrine, or memorial. Or it would be a service that let your personality loose online and your facsimile would participate in the diggs, reddits, and facebooks of the day.
I don't even want to think about what this would mean for future religious figures born today. Imagine if you could talk to Jesus or Budda's quote machine.
It's a bit creepy, to be able to talk to a facsimile of a dead person. But it could be it's just because we're not use to the idea. I suppose it's the same as when photographs came out and you could see dead people.
However, just as the dead can't reach out from photographs to the present, quote machines of the dead wouldn't be able to reach out from the past into the present. At least, I don't know that they should.
Thursday, July 08, 2010
Picking the right problem
Nowadays, software can be updated continuously and iteratively. This lets us build what we often call minimum viable product, or MVP, and improve it from there. However, most of us don't end up building MVP despite best intentions.
The reasons are varied, from fear of negative feedback, not knowing what MVP really looks like, or thinking that your early customers want more than they actually do. The first problem founders-to-be come across when doing MVP is actually picking the scope for the problem.
When you're first building a product, you spend time thinking about what features should be included and what the benefits would be to the end-user. Then you start thinking of all the things that a user might need before they start using it. The vision for your product is big and could go in any number of directions. The opportunity and potential may be huge!
I think this is the wrong way to go about it. Before you start thinking about all that, you need pick one problem to focus on. This problem is what you're going learn whether people even want this problem solved.
But even when you find a problem that people want solved, the next most common pitfall is picking the wrong size of problem to work on. We often try to solve a version of the problem that's too big. Don't try save the world on first shot. If you can subdivide the problem into smaller problems, if it's a problem to different types of people, or solves related problems in different contexts, your problem is too large.
The advantages of picking the right, focused problem are many. It makes the product easy enough to do, it's tractable, and you can see an end in sight--which is extremely motivating. In addition, it's easy to explain to others. Don't underestimate the power that stems from the ease of conveying your idea and the problem it's trying to solve.
Don't worry about the problem being too shallow. All problems are interesting when you look deep enough.
Paypal on the surface seems easy enough in the beginning. It's like a web-bank that only does transfers, and you don't even need to connect to financial institutions for paypal to paypal transactions. But what people don't realize in trying to copy paypal is that fraud will increase the more popular your service gets, and that will eventually kill you unless you get it under control.
Twitter seemed easy enough as well in the beginning. Search the web and you'll read a lot of naysayers back in 2006-2008 where they can't understand why posting a message to the web generates so many fail whales. By nature of the interconnectedness of the data in producing the feeds for a given user with a specific set of followers, it's actually a non-trivial problem.
Groupon has been interesting because it changed how people thought of the intersection between local businesses and online ecommerce. With groupon, you go into group buying agreements with other strangers on the web to get deals. However, it's actually a small part of a larger set of problems that you could solve with a similar set of mechanics, such as group campaigning and petitioning. Instead of trying to solve all these problems, the founder decided to just focus on one: group buying.
Tuesday, June 22, 2010
Integrating Facebook into Rails
Recently, I integrated facebook’s new Graph API into Noteleaf. Though it’s far far easier than the old API, which almost didn’t warrant a blog post. However, authorization took a little bit of figuring out, so I thought I’d share.
If you’re using the languages blessed by Facebook, such as PHP, Javascript, Python, Objective-C and Java Android, then there’s already an SDK for you.
However, as a rubyist, we were on our own. Since we’re using Authlogic, we should be able to find a plugin for authenticating facebook.
On the Authlogic docs, it has authlogic_facebook_connect listed. It also depends on the most popular ruby gem for facebook integration, facebooker. However, facebooker’s documentation is shabby and the tutorials are out of date. I didn’t want to be digging around in something that wasn’t our core value proposition. So I didn’t end up going that route.
I was digging for alternatives, but in all the wrong places. It wasn’t until I was reading the facebook api docs more carefully, that I realized I should be looking for an OAuth2 module for Authlogic. After that, it was a breeze.
The instructions for authlogic_oauth2 are pretty clear, but here’s some tips. Beyond the instructions in authlogic_oauth2, make sure you set the oauth2_scope to request offline_access. If you don’t, when the user’s facebook session expires, your oauth_token that you stored in the user’s database will be expired. That means that after a while, the user won’t be able to log back in without requesting another token.
class UserSession < Authlogic::Session::Base oauth2_scope "offline_access,email" end
And if you do store the user’s facebook id locally, make sure it’s a big int.
class AddFacebookIdToUser < ActiveRecord::Migration def self.up add_column :users, :facebook_id, :bigint, :limit => 8 end def self.down remove_column :users, :facebook_id end end
which you can subsequently set in a before_create filter in User model.
class User < ActiveRecord::Base before_create :populate_oauth2_user private def populate_oauth2_user return if oauth2_token.blank? response = oauth2_access.get('/me') user_data = JSON.parse(response) if !user_data['id'].blank? self.facebook_id = user_data['id'] end end end
You may also want to consider using the provided javascript SDK. That way, you’d be able to load your page first, and have the client’s browser request the rest of the facebook data, so it appears you page loads faster.
Monday, June 21, 2010
APK Downloads for Android Projects - GitHub
For all you Android developers out there, we now will automatically detect when you upload an Android package (.apk) file and will give you a QR code page link on your download page list, like this:
Friday, June 18, 2010
Boosting my social memory
I've changed what I'm working on, as I decided to table Graphbug as a side project. Everyone said public data would be a good thing for lay-people to browse through easily, but no one could specifically think of what datasets they'd want. Like going to the dentist, it's something that's good for other people, but not themselves. In hindsight, I should have picked data to visualize for apartment hunting and moving as the niche problem to solve. Otherwise, I was trying to boil an ocean.
But that's ok, as I've moved on to found a startup to do something I've really wanted for a long long time. We're working on Noteleaf, something to boost your social memory by making it easy to take notes and follow up on the people you know and meet.
I have terrible social memory. It's not just not merely remembering people's names. That can be done with a little bit of effort and mental hacks. I can't remember what other people are doing in their lives, whether they're graduating, moving, or looking for a job. I can't remember what the name of their kids are, their girlfriend, or fiancé.
One fine day in May, I called my friend Amy up and said, "Congratulations!". She replied enthusiastically, but puzzled: "Thanks! But for what?" I told her, "For graduating dental school." She laughed, "Ahh, thanks, but I graduated last year, and you called me then to congratulate me too."
It's not that I don't care. I just can't remember. I have disparate groups of friends, so I don't get gossip about other friends to remind me of what they're doing. My friend ranges from college-aged to recent parents with kids. With everyone in different stages of life, I can't keep track. I have enough things to keep track in my own life that it's hard to have bandwidth to think of others.
Thoughtfulness has to be both relevant and timely. Relevant, because it makes no sense to congratulate someone on their new job when they are still at their old one. Timely, because wishing someone happy birthday on a day that's not their birthday doesn't have the same effect.
We wrote Noteleaf to help us do both. By taking simple notes about others, you can recall what you talked to them about last time and start right where you two left off. And by scheduling automatic followups you can be thoughtful on your own time, and they get it when it's timely for them.
Facebook has been nice in getting news about friends old and new. However, not everything you'd want to remember about them comes on the news feed. There's a transient nature to the news feed, that chances are, you won't remember whether a friend left for vacation this week or next, and you meant to give them some travel tips.
With business contacts, you may not even be facebook friends. While important, you may meet them even less, so the details of their lives are even more fleeting. It's a leg up to getting things done, when you can remember who they are and what's important to them.
Noteleaf is still in closed beta for the time being, but just put yourself on our email list, and we'll let you know when we open the gates. In the meanwhile, we also started a noteleaf blog.
For all of our busy lives, I think it's important that we are involved in the lives of those we care about, and keep making connections to new and interesting people. Because beyond the glory of work and career, the trappings of fame and accolades, and enticement of money and prestige, deep connections to people we care about is one aspect of life that fulfills us and makes us whole.
Sunday, June 13, 2010
How to generate forms in rails helpers
This is more of a note to myself than anything, since I find myself having to generate forms from helpers in Rails every once in a while. This is for Rails 2.3.5. I don’t know if Rails 3 has this problem.
I wrote my own in-place editor for model fields, and it generates a form through a helper.
1 # used internally to generate the form for the en_place editor 2 def en_place_form(record_or_array, field_name, 3 options = {}, html_options = {}) 4 # process the options, and other misc details 5 form_block = proc do 6 form_for(record_or_array, :html => html_options) do |f| 7 concat(f.text_field field_name, :class => "en_place") 8 concat(f.submit "Update") 9 end 10 end 11 is_haml? ? capture_haml(&form_block) : capture(&form_block) 12 end
All you have to do is capture a block that calls form_for or form_tag. And then inside of the form, you can to call concat on the fields that you want inside of the form.
Then lastly, you have to capture the block. If you’re using haml, you have to call capture_haml() instead.
Saturday, June 05, 2010
A left merge versus a right merge
Recently, I found out that you can set the default winner in a merge for a hash. I wasn’t going to write about it since I figured it was pretty basic. But then again, I hadn’t written in a while. Been busy. So something easy to get me back on the wagon.
I’ll call it a left merge and a right merge. Let’s say we have some options, like default options and new options in a method, and we want merge them together, where options override default options, but you store it into options.
1 # some options 2 default_opts = { :a => 1, :b => 2 } 3 opts = { :b => 3, :c => 4 }
Well, the normal way of merging things won’t work:
1 # the normal default merge 2 opts.merge!(default_opt) # => { :a => 1, :b => 2, :c => 4 }
Well, that’s not right. We want the default options to be overridden by the new options and store it in the opts variable. We could do it like this:
1 # one way of doing things 2 opts = default_opts.merge(opts) # => { :a => 1, :b => 3, :c => 4 }
But then here’s another
1 # the other merge 2 opts.merge!(default_opts) { |k,o| o } # => { :a => 1, :b => 3, :c => 4 }
Yay!
Tuesday, June 01, 2010
BrowserCouch is CouchDb for browsers
BrowserCouch Documentation
BrowserCouch is an attempt at an in-browser MapReduce implementation. It's written entirely in JavaScript and intended to work on all browsers, gracefully upgrading when support for better efficiency or feature set is detected.
Not coincidentally, this library is intended to mimic the functionality of CouchDB on the client-side, and may even support integration with CouchDB in the future.
Why?
This prototype is intended as a response to Vladimir Vukićević's blog post entitled HTML5 Web Storage and SQL. A CouchDB-like API seems like a nice solution to persistent storage on the Web because so many of its semantics are delegated out to the JavaScript language, which makes it potentially easy to standardize. Furthermore, the MapReduce paradigm also naturally takes advantage of multiple processor cores—something that is increasingly common in today's computing devices.
Things to do
To learn how to use BrowserCouch, check out the work-in-progress tutorial.
Aside from that, you can run the test suite and the semi-large data set test, though they're not particularly exciting. In the future, we'd like to make CouchDB's Futon client work entirely using BrowserCouch as its backend instead of a CouchDB server, but that's a ways away.
If you'd like to see more code samples of what the BrowserCouch API currently looks like, check out the annotated source code for the test suite. You can also read the primary source code documentation for more on BrowserCouch's implementation.
This is really awesome. I thought about doing this, but figured it was a massive undertaking. I'm glad someone's doing it. CouchDb's replication features (while not implemented yet in BrowserCouch), is something to really look forward to, especially if it's available for mobile browsers.
Friday, May 21, 2010
I am one of the creators of the first "synthetic" bacterial cell. AMA : IAmA
More specifically, I am one of the authors of this paper. I was primarily involved in the assembly of the synthetic genome. I will answer your questions to the best of my ability, and to the extent of which I am allowed to discuss these things.
Monday, May 10, 2010
Whenever I hear "I'm not good at math", it's like people telling "I can't read, and it's ok"
Granted, thinking statistically is tricky. We like to construct simple cause-and-effect stories to explain the world as we experience it. “You need to train in this way of thinking. It’s not easy,” says John Allen Paulos, a Temple University mathematician.
That’s precisely the point. We often say, rightly, that literacy is crucial to public life: If you can’t write, you can’t think. The same is now true in math. Statistics is the new grammar.
Whenever I hear "I'm not good at math", it's like people telling me "I can't read, and it's ok."
Thursday, May 06, 2010
Friday, April 30, 2010
Henry Ford's "Thoughts on Horses"
The idea of gas engines was by no means new, but this was the first time that a really serious effort had been made to put them on the market. They were received with interest rather than enthusiasm and I do not recall any one who thought that the internal combustion engine could ever have more than a limited use. All the wise people demonstrated conclusively that the engine could not compete with steam. They never thought that it might carve out a career for itself. That is the way with wise people--they are so wise and practical that they always know to a dot just why something cannot be done; they always know the limitation...
Recently, a friend was telling me that DSLR cameras will never be supplanted by cameraphones. As of 2010, it seems a silly proposition. But that's seeing camera technology as they are now, not what they will be.
I don't think DSLRs will ever go away, like the radio never went away. But I don't think it's infeasible that cameraphones will get better and better so that for many DSLR users now, it would get 'good enough'.
I sent him the post I wrote on this subject. But I don't think he read it.
Thursday, April 29, 2010
Back to HATEOS and APIs
REST-like discoverability could also be a boon for some services. What if Twitter provided something like this along with a tweet’s JSON?
{ "actions": { "Retweet" : { "method":"POST", url:"/1/statuses/retweet/12345.json" }, "Delete" : { "method":"DELETE", url:"/1/statuses/destroy/12345.json" }, "Report Spam" : { "method":"POST", url:"/1/statuses/retweet/12345.json", params:{"id":12345} } } }
YES. I had talked about this in the HATEOS post that I wrote a while back. Right now, only html is self-discovering. XML and JSON docs should also have self-documented descriptions of next actions a client can take. That way, you'd cut down on the amount of documentation requires to understand or use an API.
One good point brought up in the comments in that last point was that if I had internal links, a client is likely to know what to do with what it gets back. But if I linked outside of my service, say geonames.org, how would I understand the schema? There's no standardized set of tags for geolocation data, like there is hypertext data.
Until we get standard media types for specific kinds of web applications, I'm afraid we're stuck.
Tuesday, April 27, 2010
How to kill an unresponsive ssh session
approach has been to switch to another terminal window or shell and then killing the process in question. Today I happened to be skimming through the ssh client’s man page and I found a section about escape characters. Suddenly I gazed upon the glory of the disconnect key sequence: a newline followed by ~.
. It works like a charm. As always, I thought I should
That's something I've been looking for a while now. I don't know if this is just bad user interface, or if it's awesome that it has a surprise feature.
Friday, April 23, 2010
Monday, April 12, 2010
Facebook | A Dismal Guide to Concurrency
Two people can paint a house faster than one can. Honeybees work independently but pass messages to each other about conditions in the field. Many forms of concurrency [0], so obvious and natural in the real world, are actually pretty alien to the way we write programs today. It's much easier to write a program assuming that there is one processor, one memory space, sequential execution and a God's-eye view of the internal state. Language is a tool of thought as much as a means of expression, and the mindset embedded in the languages we use can get in the way. [1]
There's a really interesting idea in this post. It's that in the CAPs theorem, consistency usually get the boot, and we find that it's not the end of the world. Updated state needs to propagate through the system, and hence, you get a speed-of-light effect like in the real world: light(information) has a finite speed, and you need light-cone diagrams to show you what you're talking about.
Speed up Rails tests when using Compass
So here's a little tidbit. When you're using Compass with Rails, check to see if it slowed down your tests. I used test_benchmark, and saw that it increased my test times 3 fold. I narrowed it down to the initializer/compass.rb files that gets loaded. Tests should need to use Compass at all to make it work, and just wrap its contents, like so:
if RAILS_ENV != "test"
require 'compass'
# If you have any compass plugins, require them here.
Compass.configuration.parse(File.join(RAILS_ROOT, "config", "compass.config"))
Compass.configuration.environment = RAILS_ENV.to_sym
Compass.configure_sass_plugin!
end
And that'll do it.
I got too lazy to put this in a gist. It'd be really nice if posterous let you edit gists in-place in their editor.
Friday, April 02, 2010
More Ubuntu-ing, less ranting about the iPad
The technorati over at HN are talking about Cory Doctrow's rant on the iPad.
Much of the sentiment that I hear opposing it seem to be in the vein of:
The point is, Cory Doctorow is in a small, small minority. The minority isn't small because people don't know what he's saying -- it's small because they don't care. He's protesting the very philosophy that gives Apple products the quality that people who buy Apple products desire. And honestly, making the openness of Apple products your raison d'etre is a bit like getting furious about the mechanical details of your favorite brand of dishwasher. The answer is always the same: don't like it? Don't buy it.
- Comment on HN
I think what Cory Doctrow is saying matters, but I don't think it's sufficient.
It might not matter much to most people in the world, at least not directly, if you assume most people are just consumers, not makers. But it should matter to us as makers, and matter to those of us that want to cultivate and provide a place for future creatives. Without a sandbox to tinker, you have less tinkerers.
And in addition, we've seen that when you lower the bar, and invite "most people" to tinker, they will. They'll be rough around the edges, but they will, and some of the stuff they produce are some good shit. How many writers and video producers would you never heard of if not for blogging and youtube?
What's dangerous is not the iPad itself, but the perpetuating notion that people are just consumers. The world can only suffer from less makers and tinkerers.
I do agree that iPad is a fine machine. And that Apple has presented their wares, and we have brought into their conditions. To me, that means instead of railing against closed platforms like the iPad, open platforms really need to step up their game. Open platforms need to take user experience and design into account, like what Ubuntu has done for linux.
Open source/hardware are very good at building well known and well understood platforms, not new and innovative platforms.
The best that open tablets can do is be very good and fast followers. It's not sufficient just to rant.
Tuesday, March 23, 2010
The emergence of dudebro
What is it about some internet communities that band together to do something? Is it perhaps for the lulz? In this case, it reminds me of some group projects I had to work with these other guys in junior high. If we had some project to do, it would turn into a large production. It was often imagination running wild, mostly for the laughs of the idea, since we couldn't actually do them.
But here, I guess is not only imagination rampant, but people can do something about it. So as a form of oneupsmanship, they start putting up screenshots, mockups, which stirs the imagination of others to join in on the oneupsmanship.
And perhaps it's because it's so ridiculous that people realize it could never be done elsewhere, so it might as well be done here. Because no one's going to be losing their job over Dudebro. And like snakes on a plane, it just seems like something that should exist.
If someone has a clue, enlighten me. Because as far as I can tell, the most HN's been able to produce has been co-founder dating sites.
Saturday, March 20, 2010
Game mechanics roundup
Monday, March 15, 2010
Chat roulette as a platform for new video content formats
I thought this was pretty interesting use of chatroulette.
When we first got TV cameras, we just video broadcasted radio shows--which became late night talk shows. Eventually, we figured out that you can shoot shows with different formats, from sitcoms to reality TV.
It seems like we're exploring different formats of internet video, chatroulette being one of them. Sure, you can chat with people, with chatroulette, but if you can come up with something interesting that interacts with the person on the other end, you essentially have a never-ending stream of people as an audience on chat roulette.
In addition, when you record your performances to one person over the chat, you can broadcast it on justin.tv or youtube. Plenty of enjoyment to be had from watching these records, as shown by the video above, as well as the original people in the video getting their 15 mins of fame.
Whoever figures this formate out first is going to have a lot of fast followers and land grab. This is the story that journalists are looking for on chat roulette, not that chatroulette is like playing russian roulette with cocks in five of the chambers.
One of the YC companies in our batch did something like chat roulette, but as video speed dating facebook app. I thought it was pretty brilliant, but somehow they never pursued it. I have no idea why.
Wednesday, March 03, 2010
How to alter columns in postgresql
So here's a goodie for those of you using postgresql.
Let's say you have a migration to do where you need to change a column from an integer to a boolean. So if you're doing a rails migration, you might write something like
And then postgresql throws up (well, it does on Rails 2.3.5):
== ChangeDatatableAttributes: migrating ======================================
-- change_column(:datatables, :is_numeric, :boolean)
rake aborted!
An error has occurred, this and all later migrations canceled:
PGError: ERROR: column "is_numeric" cannot be cast to type boolean
: ALTER TABLE "datatables" ALTER COLUMN "is_numeric" TYPE boolean
Well, that's no good. The web was not exactly much help here, but I managed to find this in the postgresql docs:
the USING expression is not applied to the column's default value (if any); the result might not be a constant expression as required for a default. This means that when there is no implicit or assignment cast from old to new type, ALTER TYPE might fail to convert the default even though a USING clause is supplied.
Looks like you need to drop the default also, and then set it afterwards.
Or if you'd like, create a method that you can throw into a module to mixin.
And use it like so:
Or if all else fails, you can just follow Heroku's advice and just drop the column and create another. Tip!
Sunday, February 28, 2010
Yeah, I use Google Wave to 'sign off' on informal agreements
Thursday, February 25, 2010
It sucks to visualize public data
A while back, I made a graph overlaying the senate party majority with the national debt. While correlation isn't sufficient for causation, I did learn a lot about the shape of the national debt as well as assertions between political party and national debt is not as clear cut as political commenters and pundits would like you to believe.
However, the entire experience of producing the graphs in those blog post left me dumbfounded with how tedious it was just to see the shape of the data.
As a programmer, I can figure out how to find and graph the data, however painfully. But it's completely inaccessible to regular everyday person that uses the internet. There's a lot of pubic data out there, but people aren't able to access it easily. If it doesn't show up on google's search, that's where they stop.
This is why I'm working on Graphbug--making public data more easily accessible through visualizations. Some questions are best answered visually.
Saturday, February 20, 2010
What to listen for from technology scrooges
Consider today's online world. The Usenet, a worldwide bulletin board, allows anyone to post messages across the nation. Your word gets out, leapfrogging editors and publishers. Every voice can be heard cheaply and instantly. The result? Every voice is heard. The cacophany more closely resembles citizens band radio, complete with handles, harrasment, and anonymous threats. When most everyone shouts, few listen.
I saw this short opinion piece from 1995, and it's related to the technology myopia I wrote about recently, even amongst the technologically well-versed.
Once again, it's easy for us to say Mr. Stoll here is a fool. But that's not what we should glean from this. We now know that even if every voice can be heard cheaply, that data can be easily accessed in text form, and someone will come up with an algorithm to organize it all. Not only that, there's more than one algorithm. Some, like Pagerank is all in a computer. Others, like Digg, Reddit, and HN, are computer-human hybrids that require a bit of social engineering. So while Mr. Stoll correctly identified the problem, he let that stop him there. It was beyond his imagination if, much less how, that problem would be solved.
The same goes when any technology pundit talks about the current new crop of technologies. He might just not have the background to know whether it's possible at all, or he might just not have the imagination. You need both to see clearly.
That's not to say you should ignore everything these pundits say. Instead, listen carefully. The hard part of product development is making something people want. What pundits have done is the hard part of identifying the problem. It's up to you to figure out how to prove them wrong.
Friday, February 19, 2010
I take it back. Haml's got some vinegar for a reason.
I take it back.
I gave HAML a second shot, and I rather like it. The conversion was pretty easy, and having emac's haml-mode saved a lot of indentation headaches--even moving blocks left and right in indentation.
How come I liked it better the second time around? The first time I saw it, it was written by someone that ignored convention and just powered through nesting HAML div elements 10 to 12 levels deep in one file. You know what? You're doing it wrong.
Writing HAML from scratch this time, and reading Haml Sucks for Content, I've found that HAML is designed with intentional weaknesses to make you stay clean and clear. Indentation too far in an HTML document? Chances are, there are repeating elements. Refactor it out to a partial, and you get to start at column zero again. Have the urge to make multi-line ruby statements? Refactor it out to a helper. You'll live longer that way.
By making some things intentionally hard to do--giving them some syntactic vinegar, you'd hope that your users end up Doing the Right Thing™. But then again, some people just are immune to having code indent 10 to 12 levels deep, or name their variables 'ii' and 'jj' when they're not programming in Fortran.
Saturday, February 13, 2010
Who would pay for a message sent to nobody in particular?
Consider books. I still buy and read all of my books in the form of compressed wood pulp. There are newfangled e-book readers, but I don't want one. Why? Because the only places I read are 1) In the bathtub, and 2) Lying in bed. Taking a computer into the bathtub is generally not a good idea, and holding a Kindle above my head for 3 hours is awkward compared to lying a (3-D) book on the bed beside me with one page bent up so I can read it.
via briancarper.net
It's something I hear often about new technologies--"Why would I want to do that?" I hear it on flamebait blog posts. I hear it in person during meetups. When I hear something like this, I'm reminded of quotes about technologies that we take for granted as being obvious now.
Let's start with the radio. Back before radio as we know it now (as radio stations), when people said 'radio' in the 1920's, they meant the wireless transmission of messages over the air. They considered it as a communication medium to relay news, like the sinking of the Titanic. Because of that, people use to pay directly to send messages. No one was using it as a way to broadcast music like the way we know it now--the concept of a radio station. And hence, there was no sense of imagination that advertisers would pay ads alongside music broadcasts. And when David Sarnoff was pioneering the idea, what was the reaction by his potential investors?
By 1916, along with Armstrong and de Forest, [David Sarnoff] was using his newfound fame to push the idea of commercial radio, something he called the "wireless music box," although this idea was before its time. Even as late as 1920, one potential investor wrote him to say, "The wireless music box has no imaginable commercial value. Who would pay for a message sent to nobody in particular?" Even the Marconi Company, his employer, rejected the idea of radio as anything but a communications medium. So he went to work for the Radio Corporation of America [RCA] in 1920.
-- Radio Pioneers enter story of the wire on David Sarnoff's associates in response to his urgings for investment in radio. [emphasis mine]
"While theoretically and technically television may be feasible, commercially and financially I consider it an impossibility, a development of which we need waste little time dreaming."
-- Wikiquotes -- Lee DeForest, American radio pioneer and inventor of the vacuum tube,
No wireless. Less space than a nomad. Lame.
via Slashdot