Profile
Summary
I previously joined redPear through the acquisition of OpenRain, a company I co-founded that offered full web development services including planning, design, implementation, hosting, and scaling of Ruby on Rails web applications. We also sold a web-based content management application platform designed to be used for marketing purposes.
For the last few years I have been working in web development with Ruby on Rails. I was a Masters student in Computer Science at Arizona State for a year before I dropped out convinced that I should pursue entrepreneurship instead.
I am a techie a heart who loves technology and working at startups.
In my free time, I run the Phoenix Android developer group, a meetup for Android and mobile related development. I'm also active in Phoenix's Ruby community.
Experience
- 2011 - PresentCTO / iPatient, Inc.
- Jan 2011 - Oct 2011Principal / Self-Employed
- Oct 2008 - May 2011Organizer / Phoenix Android Developer Group
- Nov 2009 - Oct 2010CTO / redPear
- Jan 2010 - Sept 2010President and lead organizer / SunnyConf
- Sept 2007 - Oct 2009Founder, CTO / OpenRain, LLC
- Oct 2006 - Sept 2007Software Engineer / Mitel (formerly Inter-Tel)
- Jan 2005 - Oct 2006Software Engineer / Unicon, Inc
- May 2003 - Jan 2005Application Developer / Thomson Financial
- 2001 - 2002Intern / Cisco Systems
Education
-
1999 - 2003Arizona State UniversityBachelor of Science in Computer ScienceActivities: Association for Computing Machinery (ACM), ASU Satellite Team (ASUSAT)
Repositories
-
1 fork/1 watcher/Pushed 36 hours ago
-
HTML, CSS, and JS toolkit from Twitter1 watcher/Pushed 2 days ago
-
ActiveBlog1 fork/1 watcher/Pushed 3 days ago
-
wordpress1 fork/1 watcher/Pushed 7 days ago
-
heroku-buildpack-wordpress1 fork/5 watchers/Pushed 7 days ago
-
1 fork/1 watcher/Pushed 8 days ago
-
Just benchmarking Sinatra applications running on Thin and Unicorn1 fork/1 watcher/Pushed 9 days ago
-
1 fork/1 watcher/Pushed 10 days ago
-
Nginx buildpack.1 fork/1 watcher/Pushed 2 weeks ago
-
Is it No Burn Day in Phoenix?1 fork/1 watcher/Pushed 3 weeks ago
-
1 watcher/Pushed 7 weeks ago
-
4 forks/4 watchers/Pushed 2 months ago
-
The oEmbed Spec1 watcher/Pushed 2 months ago
-
Gisting is an open source Ruby implementation of Google's MapReduce programming paradigm3 forks/22 watchers/Pushed 3 months ago
-
Official mirror of the AWS SDK for Ruby. For more information on the AWS SDK for Ruby, see our web site:1 watcher/Pushed 5 months ago
-
Logo, on Heroku.1 fork/1 watcher/Pushed 7 months ago
-
This doesn't work on heroku1 fork/1 watcher/Pushed 7 months ago
-
Instantly search EOL for images of animals1 fork/2 watchers/Pushed 8 months ago
-
Ruby API for the Encyclopedia of Life1 fork/2 watchers/Pushed 10 months ago
-
Shhhh1 watcher/Pushed 11 months ago
-
NOTICE: official repository is https://github.com/jm/rails_upgrade1 watcher/Pushed 11 months ago
-
Yet Another Rails Template1 fork/5 watchers/Pushed 13 months ago
-
Arkayne Ruby on Rails plugin1 fork/1 watcher/Pushed 17 months ago
-
Calculates volume discharged due to a recent dam bust at Tempe Town Lake. PS. I'm not a civil engineer1 fork/1 watcher/Pushed 18 months ago
-
BOOTSTRAP SCRIPTS BABY!1 fork/3 watchers/Pushed 20 months ago
-
LiquidPlanner API1 fork/1 watcher/Pushed 20 months ago
-
Yumi's Calendar1 fork/1 watcher/Pushed 22 months ago
-
1 fork/1 watcher/Pushed 23 months ago
-
A rubygem that calculates the tf-idf of a corpus.2 forks/8 watchers/Pushed 2 years ago
-
A Ruby library for finding memory leaks. Patched for 1.8.7. Please adopt and use with caution!1 fork/2 watchers/Pushed 2 years ago
-
Cappuccino sandbox2 watchers/Pushed 2 years ago
-
A Sinatra application demonstrating S3's Browser-Based Uploads using POST3 watchers/Pushed 2 years ago
-
home is where the heart is1 watcher/Pushed 3 years ago
-
ruby2ruby code for my rubyconf08 talk1 fork/3 watchers/Pushed 3 years ago
-
A library of algorithms and collections for Ruby.2 watchers/Pushed 3 years ago
-
The test Rails app for prototyping drtest1 watcher/Pushed 3 years ago
-
Distribute Ruby \ This is an experiment! \ Here be dragons... duck!5 watchers/Pushed 3 years ago
-
These are not the tweets you're looking for1 watcher/Pushed 3 years ago
-
Bits of code from around the world1 watcher/Pushed 3 years ago
Updates
-
Ski-bi-dibby-dib yo da dub... dub. #codedeploysongs12 hours ago from web | Reply, Retweet, Favorite
-
@squanderingtime I click on all of your links. You are my reddit.17 hours ago from web | Reply, Retweet, Favorite
-
@gangplank That's the Startup Speed Dating thing, right?17 hours ago from web | Reply, Retweet, Favorite
-
The 2012 Data Design Diabetes Challenge is up! Complete survey & help healthcare innovators: http://t.co/rdnAyicE18 hours ago from web | Reply, Retweet, Favorite
-
@hmason Done. (1) That's a great way to solicit feedback (2) I hope they share the data they collect. Many perspectives I never considered.18 hours ago from web | Reply, Retweet, Favorite
-
@gangplank Is Roadmap to Launch tonight? Nothing on the roundup: http://t.co/4AIrXyfB18 hours ago from web | Reply, Retweet, Favorite
-
@tenderlove I hear you like PostgreSQL's hstore. I wrote an adapter awhile ago. Any interest in folding it in to AR? http://t.co/teQTpOU635 hours ago from web | Reply, Retweet, Favorite
-
@dneighbors Let's attend while dressed in Gangplank t-shirts.2 days ago from web | Reply, Retweet, Favorite
-
@peterjhart It's opt-in. What's humiliating? Some of these sites a pretty good.3 days ago from web | Reply, Retweet, Favorite
-
@leshill Bahahaha. Google for "hogan assets"3 days ago from web | Reply, Retweet, Favorite
-
Sites built with Bootstrap--@twbootstrap. http://t.co/oHhlawk63 days ago from web | Reply, Retweet, Favorite
-
3 days ago from web | Reply, Retweet, Favorite
-
3 days ago from web | Reply, Retweet, Favorite
-
@joakime Same thing, but you eat instead and it's especially popular amongst Chinese3 days ago from web | Reply, Retweet, Favorite
-
Remember folks, Chinese New Year lasts for 15 days. There's a lot of food to be eaten.3 days ago from web | Reply, Retweet, Favorite
-
I highly recommend doing dim sum with friends.3 days ago from web | Reply, Retweet, Favorite
-
Read these comments from Picnik users about Google shutting down their favorite photo editor: http://t.co/PbDZ4f6G (SPOILER: They hate it.)6 days ago from web | Reply, Retweet, Favorite
-
@jonbischke I've heard good things about Flagstaff re: Building a City Startup http://t.co/FjQkjf5q. cc: @sarapresler @nacet6 days ago from web | Reply, Retweet, Favorite
-
A City Is A Startup: http://t.co/FjQkjf5q. Does your city have a Mayor-entrepreneur?
-
The story of how Amit Gupta found a bone marrow donor: http://t.co/MsypTZuu6 days ago from web | Reply, Retweet, Favorite
Posts
I go to lots of conferences. Each year, I meet more and more people who have Twitter accounts. Broadcasting updates with Twitter also happens to be a convenient way to self-organize.
For example, if you want to tell your friends at RubyConf that you’re going to grab sushi? Perfect: write tweet, use the #rubyconf hashtag, press Tweet. Folks in your circle will know how to find you. Unfortunately, everyone else will have no idea what you’re talking about. “rub y conf? Who is 'y' and why are we rubbing him?”
I’m a private individual. I’m also a considerate individual who hates cluttering up someone else’s stream. About a year ago, some friends and I setup Twitter so that we could send group text messages between each other privately. Tweets sent to an account were broadcasted to everyone who followed, and followed back, by that account. It’s a free group texting hack.
If you’re a technical person, here’s how it works.
-
Setup a separate Twitter account. Let’s call it @nerds_list. This account will act as the group’s hub. Direct messages sent to this account will send those direct messages to everyone else in the hub.
-
Install Linux, setup Ruby, and run the following program.
require 'twitter'
client = Twitter::Base.new(Twitter::HTTPAuth.new('nerds_list', PASSWORD))
last_id = 1408167803 # or whatever the previous was
loop do
client.direct_messages(:since_id => last_id).each do |dm|
client.update("#{dm.sender.screen_name}: #{dm.text}")
last_id = [last_id, dm.id].max
end
sleep 60
end
-
Tell your friends to follow @nerds_list and have @nerds_list follow your friends back. It’s important that the follow relationship goes both ways.
-
Tell your friends to update their profile with the mobile number and to turn on DM notifications.
-
To broadcast a message to the group, send a DM to @nerds_list. The server will receive your message and broadcast the update to all your friends.
Not a technical user? Not to worry several amazing applications have popped up, over the last year, that allow you to do private group chat much easier.
-
Belugapods is a private group messaging service made ridiculously easy with the availability of mobile apps on both iPhone and Android. Beluga is done really done well.
-
Convore is a quick way to instant message with groups of friends in real-time. You can join public and private groups to talk about anything.
-
Privatelyapp, which was built by Les Hill who wanted to have private conversations with his Twitter followers. I’m @heisenthought on Twitter, follow me and I’ll send you an invite.
Special thanks to Tom Robinson for writing this script.
If you’re a software professional in Phoenix, Arizona, here are several active developer groups that I recommend. This list isn’t comprehensive, but it is a summary meet ups that I think are worth checking out.
-
Phoenix Java User’s Group. The PhxJUG is the largest gathering of Java developers in Phoenix. Past topics have covered a broad range of JVM related technologies including Grails, Scala, JRuby GWT, and other real world applications of the Java programming language. The PhxJUG is one of the oldest and longest successfully run developer groups in Tempe, AZ.
-
Phoenix Ruby User Group and Phoenix Rails User Group. The Phoenix metro has two Ruby-centric user groups, RubyAZ and PhxRails. The former focuses on broader Ruby topics while the latter focuses on areas around Ruby on Rails. Both groups host monthly presentations and have strong community participation. Occasionally, the groups hold a demo-night, where developers can showcase their latest tech, and a hacknight where developers can collaborate with each other.
-
Phoenix Android Developer Group. The Phoenix Android developer group has grown into the place to meet other Android software developers, hardware hackers, and mobile enthusiasts in Phoenix and the greater Phoenix metropolitan area. The current set of monthly presentations are aimed at novices. There’s also a monthly hacknight where developers can collaborate with each other. Disclaimer: I organize the Phoenix Android Developer Group.
-
For OS X, iPad and iPhone developers. There’s a lot going for OS X and Cocoa developers. For iPhone and iPad developers, the iPhone Developer Group hosts a monthly presentation. For general OS X and Cocoa development, the Phoenix CocoaHeads host a monthly meeting. And if you want to collaborate with other developers, there’s also weekly NSCoderNight.
-
Phoenix Scrum User Group. Practice Agile? That’s great, because Phoenix also has a very well organized Scrum user group, PhxSUG. Past topics have included presentations on Agile techniques, featured speakers, and role playing games involving audience participation.
-
HeatSync Labs. If you enjoy working with both hardware and software, own a subscription to Make magazine, and don’t mind getting your hands dirty, then you may want to join HeatSync Labs. HSL hosts weekly meet ups as well as a monthly Arduino meeting.
-
Various lunch meet ups. The best part of a meet up, is after hour dinner and drinks. Developers in Phoenix have three meet ups aimed at lunch time nerding: Tempe Nerds, Tech South Lunch, and Geek and Eat.
In addition to the monthly and weekly meet ups, there are several local conferences put on by our local developer community.
-
Developer Ignite Phoenix. Developer Ignite is based on the Ignite model of presentation delivery, where speakers have 5 minutes and 20 slides automatically transitioning. Though the presentations are brief, it’s a great way to hear about technologies from software developers around Phoenix.
-
Desert Code Camp. Desert Code Camp is the longest running camps organized by developers and for developers. I’ve been attending Desert Code Camp since 2006. Even though the talks are dominated by Microsoft technologies, it’s still a great way to network and meet other passionate developers in the community.
This year also saw the creation of two new developer groups.
-
PhxData. PhxData grew out of the Great American Hackathon which I organized last year. After the hackathon, we realized that mixing journalists and technologists produced remarkable ideas. I co-founded PhxData to unite technologists in the Phoenix area who are engaged in data mining, parsing, visualization, etc. It also serves as a platform for journalists and government officials to connect with technologists who want to take public data and make it useful.
-
JavaScript-AZ. The JavaScript group is just starting out, but I expect it’s popularity to grow over the next few months.
You can learn a lot by meeting and connecting with other developers. I highly recommend taking the time out of your week to connect up with a group and even offer to give a presentation.
“What is a haiku?”
From wikipedia:
“Haiku is a form of Japanese poetry, consisting of 17 syllables, in three metrical phrases of 5, 7, and 5 syllables respectively.”
Personally, I prefer the way Stephany, an early haikuist describes the way of the haiku:
To write a Haiku
Five then Seven, Five again
Simple, yet complex
And with that, I’d like to introduce you to a fun project that I’ve been working on for a few months. It’s called the Haikuist and it’s aimed at people that love composing haiku poetry.
“What is haikuist.com?”
Haikuist.com
Poetic micro-blogging
for haiku lovers.
Haikuist first began as a place to keep track of my random acts of haiku writings. Also, it stemmed from my deep frustration of the growing number of badly formed haiku being published on the internet. Counting syllables should be easier, so I did what every problem solving software engineer would do: write code!
Syllable detection isn’t technically the most trivial thing to solve, but what started as a 200 line Ruby1 program eventually grew into what you see today at haikuist.com.
I’m extremely excited about Haikuist. It’s fast, simple to use, and offers fascinating insight into the minds of creative people. I am surprised at how poetic people can be.
Haikuist is a work in progress and will continue to improve over time. Sign up at today and invite your friends along for the ride, you may be surprised by what they say.
-
A programming language that, appropriately, originated in Japan.
↩
This past Labour Day weekend, I redid this entire blog in HTML 5. Here are some of the notes I took while diving into HTML 5.
The first thing to keep in mind is that HTML 5 is a work in progress and will continue to be until there exists two browsers with complete HTML 5 implementations. Remember this as you read the various W3C specs, wiki entries, and blog posts–including this one.
Web Developer’s Guide to HTML 5
-
The Web Developer’s Guide to HTML 5 is a good introduction to HTML 5 from an HTML author’s perspective. The biggest takeaway is that there are two syntax modes to HTML 5: Regular HTML syntax and XHTML syntax.
-
After understanding the differences between HTML and XHTML, going with XHTML makes more sense. The syntax is more strict, yet simpler and consistent since it follows XML syntactic requirements. HTML mode permits all sorts of exceptions, which ends up being a PITA to remember. For example, empty attributes (
<input disabled>...</div>) is valid HTML, but invalid XHTML. I almost never remember this. I suspect that HTML support is for backwards compatibility reasons (since shipping a browser that breaks ten trillion web pages is evil). -
For the rest of this post “HTML” means HTML 5 in regular HTML mode, and “XHTML” means HTML 5 in XHTML mode.
-
Using XHTML requires content to be served with a Content-Type of
application/xhtml+xml, though in practice this doesn’t seem to be causing a huge problem. There are reasons for not obeying this, for instance HTML 5 allows authors to publish polyglot documents which conform to both HTML and XHTML. More on this below. -
The other big note is the DOCTYPE, which is used to determine quirks mode rendering.
-
The DOCTYPE declaration isn’t technically required for XHTML documents since they are meant to be delivered with the correct XML MIME type thus instructing the browser to process it as XML in no quirks mode. I set it anyway since it ensures the most standards compliant rendering (It also gives me warm fuzzies).
HTML5 differences from HTML4
-
The next good read is HTML5 differences from HTML4. The most interesting thing I gleaned from this document is when it’s authors consider HTML 5 complete: “The HTML5 specification will not be considered finished before there are at least two complete implementations of the specification. This is a different approach than previous versions of HTML had. The goal is to ensure that the specification is implementable and usable by designers and developers once it is finished.” Pragmatic and competitive. I like this approach as it allows future browser implementors (however unlikely they are) to have access to two reference implementations.
-
To help you decide whether or not to adopt HTML 5, you can review the current state of the various browser implementations and also the comparisons between HTML 5 layout engines. Also make sure to check out the W3Schools’ browser statistics, which lists browser usage and trends on a month-by-month basis.
-
It’s very clear that HTML 5 is going to be a lot of things. It looks like they’re revisiting a lot of existing semantics (such as “the definition of URL” and “the origin concept”) and standardizing on their definitions.
-
I previously mentioned that HTML 5 allows authors to construct polyglot documents. One reason for this is so other markup languages like MathML and SVG can be included in the same document, but only in HTML mode.
-
The document then goes on to outline changes in elements and attributes. There are well over two dozen new elements addressing everything from document publishing (
<section>,<article>,<header>,<footer>,<nav>), accessibility (<hidden>,<progress>), typography (<ruby>), and visualization (<canvas>) needs. Elements are also removed, notably support for<frames>which we all know has brain damaging affects on usability and accessibility.
Practical Resources
-
This blog’s initial layout is inspired by an article on designing a blog with HTML5 at the HTML5Doctor. They’ve also got a growing number of articles on the various new HTML 5 elements:
<header>,<footer>,<nav>, and<aside>. -
Internet Explorer 8 (and 6 and 7) doesn’t handle these new elements correctly. Fortunately there’s a workaround. You can learn how to enable HTML 5 in IE and the technical reasons (why and why) behind the solution.
-
There’s also a good review of the new elements in HTML 5 by IBM’s developeWorks.
-
One terrific reference (though a work in progress) is Mark Pilgrim’s Dive Into HTML 5. At the moment, there are two chapters on HTML 5, drawing with
<canvas>and detecting HTML 5 features which are both highly recommended reading.
If you have any other great sources on getting started with HTML 5, make sure to share them in the comments below.
What follows are some strong opinions I have regarding software development. Most of these aren’t original, but together, they form the framework for how I think about software and it’s design and development in a production environment.
In no particular order:
-
Software engineering is a discipline. You don’t master the art of software engineer just because you have a passion, a hobby, a degree from a university, or a book titled “C++ in 365 days”. These factors may help, but it’s discipline that keeps you practicing, studying, and applying the scientific method, which ultimately makes you a better software engineer.
-
Focus on delivering value to customers. If you’re write it, test it, buy it, sell it, pay for it, run it, own it, or use it, you are a customer. Any single project or organization will have multiple customers. Figure out who your customers are and how to maximize their collective goals.
-
Reading software should be a pleasure. Good software reveals it intentions by following conventions and using design patterns. If software is primarily read by other software engineers, it should be written in a manner for other software engineers to read. Sometimes this manner is called a domain specific language.
-
Learn to build, follow, and break conventions. Conventions exist everywhere either by accident (a recurring pattern) or intentionally (by design). A team should follow conventions and also establish them when they don’t exist or capture them when they begin to emerge. Keep in mind that even conventions can have scalability issues. Teams should recognize when an existing convention stops scaling and introduce new ones. For large bodies of software every piece should have a place, and every place should have it’s piece.
-
Keep things simple by recognizing high compute costs. Never try to design everything up front and all at once. When developing new features, it’s easier to do so on top of components that are small and decoupled rather than large and complex. That’s why it’s important to start work by doing the simplest thing possible.
-
Testing is important, but not as important as strong team communication. A program with 100% test coverage doesn’t imply that it’s 100% functional. In fact, that opinion is extremely dangerous since it’s possible to have a busted program with 100% test coverage. Better communication will always beat better coverage.
-
Building products is a team sport. Finding the right people, motivating them, and putting them in the right positions is key to the success of a product. Don’t just hire someone for what they already know, hire them because of their ability to learn. The idea that great products are built by people in silos is no longer the truth. Collaboration and different perspectives make a better team and build a better product.
-
Writing testable code is the trick to writing reusable code. If you’re having a hard time isolating a piece of code, it’ll generally imply you’re going to have a hard time reusing it.
-
Code reusability isn’t as important as code usability. An API should be usable much like a user interface: it should be clear to users, simple to use, provide shortcuts for commonly completed activities, and consistent.
Closures are commonly used to abstract over an expression or a statement.
Ruby gives you–not one–but three ways of creating closures from a block: Using Proc.new, the Kernel#proc method, or the Kernel#lambda method. So what’s the difference between these three techniques?
In Ruby 1.81, Kernel#lambda is an alias for Kernel#proc, so they actually behave identically. Proc.new, on the other hand, has slightly different semantics.
stargate$ cat a.rb
def kernel_proc
proc { return "within proc" }.call
return "kernel_proc"
end
def proc_class
Proc.new { return "within Proc.new" }.call
return "proc_class"
end
def kernel_lambda
lambda { return "within lambda" }.call
return "kernel_lambda"
end
if $0 == __FILE__
puts "return from " + kernel_proc
puts "return from " + proc_class
puts "return from " + kernel_lambda
end
With Ruby 1.8:
stargate$ ruby a.rb
return from kernel_proc
return from within Proc.new
return from kernel_lambda
JRuby 1.1.52 also observes the same semantics:
stargate$ jruby a.rb
return from kernel_proc
return from within Proc.new
return from kernel_lambda
Ruby 1.93 has a different story.
In Ruby 1.9, Kernel#proc will behave identically to Proc.new. The reason behind this is described by David A. Black in this post to ruby-talk:
Matz agreed that it was confusing to have
procandProc.newreturn different things, and said he would deprecateproc.
Eigenclass.org also confirms that proc is now a synonym of Proc.new further describing that both receive their arguments with multiple-assignment (block) semantics.
With Ruby 1.9:
proc{|a,b|}.arity # => 2
proc{|a,b| "bacon"}.call(1) # => "bacon"
Proc.new{|a,b|}.arity # => 2
Proc.new{|a,b| "bacon"}.call(1) # => "bacon"
With Ruby 1.8:
proc{|a,b|}.arity # => 2
proc{|a,b| "bits"}.call(1) # => wrong number of arguments
Proc.new{|a,b|}.arity # => 2
Proc.new{|a,b| "bits"}.call(1) # => "bits"
Unfortunately, this change means that Kernel#proc may lead to undesirable side-effects in your code:
With Ruby 1.9
stargate$ ruby1.9 a.rb
return from within proc
return from within Proc.new
return from kernel_lambda
With MacRuby 0.34
stargate$ macruby a.rb
return from within proc
return from within Proc.new
return from kernel_lambda
When in doubt, go with Kernel#lambda. It’s a safe bet.
Updated: Pending further review, I’ve omitted the bit about Proc.new violating Tennent’s Correspondence Principle.
My first unit test
I remember my first passing unit test well.
It was written for a lab assignment for an undergraduate computer science course I took during Spring 2000 at Arizona State University, CSE200, an Introduction to Object-Oriented Programming, or something like that. Back then, though, it wasn’t called a unit test.
CSE200 had close to a hundred students every semester with each student responsible for writing about a dozen lab assignments.
As part of your assignment, you had to write a main function which read input from cin (or System.in) and passed along any arguments to the rest of your program for processing. When your program was done processing, it would write the results to cout (or System.out). To test your lab assignment, the tester (aka the QA TA) would run main and pass in arguments to your assignment. The tester would record your actual output and compare it against the expected output, complaining if there was a difference. There were many factors that went into your assignment’s final grade such as documentation, and your code’s overall object-orientyness, but generally, the more complaints recorded by the tester, the lower your grade.
For fun, I’m told, you could ask the professor to run your assignment against the extra credit data set which basically threw all sorts of data (good and bad) at your program.
Students taking this class were forced to make a decision: either they rose to the challenges of writing code to spec, or they dropped the class before the first lab assignment was due.
All code starts out as exploratory
I’d be lying if I said that I could sit down at a computer and write a program that ran perfectly, without making a single mistake. Most engineers can’t do this, nor should they.
When writing new code, most of my time is spent exploring ideas and intentionally proving to myself that the computer is doing what I’m telling it to. Programmers like to call this hacking, as in “I have a cool idea, give me a couple of hours to hack something out.”
A programming language geared towards this kind of exploratory hacking always come with an interactive console sometimes referred to as the REPL1. Languages like Ruby, Python, JavaScript, Erlang, Groovy, and Lisp ship out of the box with a REPL, while languages like C++ and the Java programming languages don’t2.
The REPL serves a single purpose: to allow programmers to freely experiment with their ideas both interactively and iteratively. It’s a forgiving environment. It neither cares if you make mistakes nor requires you to write ceremonious amounts of code in order to prove an idea works. A REPL lets you write and verify that your code works, so it often inspires or serves as the early revision of your program.
Have you ever gotten one of those “ah hah” moments when learning something new? I’m sure you know what I’m talking about. They’re the moments that further your domain knowledge on a subject. The moments that build on each other, eventually bridging the distance between novice and master. Frequently using a REPL to learn a programming language causes “ah hah” moments all over the software part of your brain.
You can think of exploratory hacking as the first step to writing solid code.
Writing solid code
In the <insert your industry here> industry, the most important thing you need to learn is how to communicate ideas effectively. To a software engineer, this means learning how to communicate ideas with your code which–depending on the collective professional experience of you and your team–ultimately means writing tests which communicate and enforce design.
There’s a ridiculously large body of knowledge on the topic of testing, addressing important questions such as:
- Whether you should strive for 100% test coverage
- Which testing framework you should use
- Would Danica Keller code first, or test first
My personal philosophy on testing is simple:
We test software to drive communication between team members, to define and enforce the behavior of software, and to share mental assertions against what might one day eventually be an extremely large body of code.
This means that a team sometimes needs to write a lot of tests, and sometimes it doesn’t. It also means you can get away without tests if you’re single person working on a prototype.
At OpenRain, when a new engineer joins our team, before they start building features, they’re assigned the task of writing tests for an existing project. Periodically, this catches them by surprise and the reaction isn’t always positive. I reassure them that this is not the case:
We’re not telling you to write tests because we think you’re a bad programmer. We’re not trying to torture you. We know you’re smart. You’ve got a long and successful track record of building software, you play four instruments, you teach the Argentine Tango, and you can program in six languages. But we didn’t hire you to work for us, we hired you to work with us and in order to do that effectively, you need to know how the software works. The process of writing tests will help you do just that. It will give you a chance to explore the code, to learn how different pieces relate to each other, and to make your own assertions about the way things work.
From a talk I gave at RefreshPhoenix on January 5th, 2009.
From 1999 to 2004, the number of mobile subscribers in Africa jumped from 7.5 to 76.8 million1, an average annual increase of 58 percent. Asia, the next fastest-expanding market, grew by an annual average of 34 percent in that period.
In the first half of 2006, Nokia delivered 153 million mobile devices2 to consumers, out-shipping the entire PC industry by a factor of close to three.
By the end of 2006, there were almost 50 device makers churning out Windows Mobile devices3. The really small and compact ones ones with full QWERTY keyboards.
Apple launched the iPhone on June 29th, 2007 and sold 270,000 iPhones in the first 30 hours4 alone. By the end of Q4 2007, they sold 1,389,000 iPhones5. In 2008, they sold over 10 million6.
Google launched the G1 on October 22nd, 2008. As of this writing, neither Google nor T-Mobile have released any official numbers, but I wouldn’t be surprised if they’ve activated close to a million devices.
Both Apple and Google phones ship with browsers based on Webkit, which is the popular rendering engine used by all the cool kids these days7. According to Android’s roadmap, they’ve added support for an optimized JavaScript engine (Squirrelfish–also used in Safari) and synced up with a Nov 2008 Webkit release, which likely means better support for the -webkit-transition family of properties.
So it looks like your mobile device will run the same stack of web technologies as your personal computer.
This is great news, right? There’s just one small problem.
Just because there are 900 gajillion Internet-powered mobile devices running around, doesn’t mean that people are using it to surf the web, especially the JavaScript-intense, round-corner powered, 2.0 web.
M-Metrics, mobile research firm, released a report on mobile content consumption. 85% of iPhone users browse the web on their phones vs. 58% of Smartphone (Windows, Symbian, Blackberry) vs. 13% of the overall US mobile market. Download.
Why is that? Because designing for the mobile web isn’t just about designing your existing website around form factor constraints. It’s convenient to think that building a mobile website means taking what you have, and making it work on a smaller form factor. This is frustrating for users because they don’t need or want the full blown experience.
Users on mobile devices are moving around. They’re environment is constantly changing. They’re eating at restaurants, walking through customs, working out at the gym, getting a hair cut, bargain hunting, checking up on the latest movie times while their date is in the restroom, or checking up on movie times while in the restroom.
A user behind a personal computer with 24 tabs open on their browser behaves differently than a user on a hot date. Your users are hard real-time systems that need information extracted with surgical precision.
When designing for mobility, design for users on the move. Design for their context. That’s the key to building a successful mobile application.
The W3C has a Mobile web best practice document which suggests that the mobile experience should be specifically designed in mind for your end users.
-
Cell phone frenzy in Africa, world’s top growth market
↩ - ↩
- ↩
-
Apple sold 270,000 iPhones in the first 30 hours
↩ -
Apple shipped 1,119,000 iPhones in Q4 2007
↩ -
Apple officially surpasses 10 million iPhones sold in 2008
↩ -
Apple’s Safari, Google’s Chrome, Adobe’s AIR.
↩
A small tribute to Guy Decoux, an early Ruby programmer who once walked the Ruby parse tree to answer a simple operator precedence question posed by Matz.
Read Matz’s question and Guy’s answer. Today, we can answer the same question with the following code:
hoktauri$ cat guy.rb
if $0 == __FILE__
require 'rubygems'
require 'parse_tree'
require 'parse_tree_extensions'
require 'yaml'
pt = ParseTree.new
y pt.parse_tree_for_string("a b c, d")
end
hoktauri$ ruby guy.rb
- - -
- - :fcall
- :a
- - :array
- - :fcall
- :b
- - :array
- - :vcall
- :c
- - :vcall
- :d
Guy passed away earlier this year. His genius was admired and he will be missed by the entire Ruby community.
One more gotcha on operator precedence.
According to the Programming Ruby chapter on expressions, the difference between the && (double ampersand) and and operators, is precedence ordering: && has higher binding than and.
>> false and true ? 'chunky' : 'bacon'
false
>> false && true ? 'chunky' : 'bacon'
"bacon"
>> (false and true) ? 'chunky' : 'bacon'
"bacon"
The or and || (double pipe) operators behave similarly.
These two code snippets also have very different abstract syntax trees. Seeing the difference will also further clarify things.
>> y pt.parse_tree_for_string("false and true ? 'chunky' : 'bacon'")
- - -
- - :and
- - :false
- - :if
- - :true
- - :str
- chunky
- - :str
- bacon
>> y pt.parse_tree_for_string("false && true ? 'chunky' : 'bacon'")
- - -
- - :if
- - :and
- - :false
- - :true
- - :str
- chunky
- - :str
- bacon
In Ruby, there’s a handy dandy way to get a string representation of a method.
hoktauri$ cat method_to_ruby.rb
def bacon
"chunky"
end
if $0 == __FILE__
require 'rubygems'
require 'ruby2ruby'
require 'parse_tree_extensions'
require 'pp'
pp method(:bacon).to_ruby
end
hoktauri$ ruby method_to_ruby.rb
"def bacon\n \"chunky\"\nend"
Earlier this year I gave a talk on ruby2ruby at my local Phoenix Users group. I followed up with a longer and more technical talk at RubyConf 2008. Not wanting to show up with a lack of code, I demonstrated the power of ruby2ruby by writing a couple of programs.
One of the programs I wrote is called Gisting, which is an open source, Ruby implementation of Google’s MapReduce framework which simplifies writing distributed data intensive applications.
inputs = args
spec = Gisting::Spec.new
inputs.each do |file_input|
input = spec.add_input
input.file_pattern = file_input
input.map do |map_input|
# 2722 mailbox 2006-05-23 00:08:39
# 217 - 2006-05-23 15:41:48
# 1326 www.crazyradiodeals.com 2006-05-23 18:00:30
# 2722 mailbox 2006-05-23 00:08:39
# 2722 mailbox 2006-05-23 00:08:42
# 2722 jc whitney 2006-05-23 00:25:47 1 http://www.jcwhitney.com
words = map_input.strip.split("\t")
Emit(words[1], "1")
end
end
output = spec.output
output.filebase = "/Volumes/gisting/datasets/output"
output.num_tasks = 2
output.reduce do |reduce_input|
count = 0
reduce_input.each do |value|
count += value.to_i
end
Emit(count)
end
result = MapReduce(spec)
pp result
After the talk, I got so much positive feedback that I decided to build a releasable version of the software. The software is almost ready for a public release, but before that happens, I’d like to announce an early preview.
There isn’t much documentation available just yet, but I wanted to show just how easy it is to write MapReduce programs with Gisting. Here’s a snippet that performs a Frequency count for the AOL search logs:
Keep in mind that this is an early preview, so I’m well aware that it needs a lot of TLC before I’ll be happy making a 1.0 release, such as:
- A test suite :(
- A screencast of Gisting basics
- A homepage/website with examples and documentation
- Running Gisting in the clouds (Amazon EC2).
That said, I’m planning to release a gem in a few weeks. In the mean time, I hope you enjoy this early preview of Gisting.
Recently, Google released the Chrome web browser, which they describe as being the next step in web browsers for the current gamut of JavaScript intensive web applications. One new feature I’m particularly excited about is process affinity. The online comic describes each tab as a separate running process.
Why is this important?
The short answer is robustness. A web application running in your browser, is a lot like an application running on your operating system, with one important distinction: Modern operating systems1 run applications in their own separate process space, while modern browser2 run web applications in the same process space.
By running applications in separate processes, the OS can terminate a malicious (or poorly written) application without affecting the rest of the OS. The browser, on the other hand, can’t do this. Consequently a single rogue application can suck up mountains of memory and eventually crash your entire browser session, along with every other web application you were using at the time.
Chrome differs by running each web application in a separate process space. By doing this, Chrome–or a user–can terminate a single web application without affecting the other tabs you have open.
Process affinity in Chrome
Chrome’s process model is extremely sophisticated. The web comic only mentions the default behavior, but you can configure Chrome to manage processes differently: one process per web site, or one process per group of connected tabs, or one process for everything.
Process-as-site-instance
By default, there are two main Chrome processes, the Browser and the Renderer. The single Browser process is responsible for transporting messages to and from the Renderer, which in turn is responsible for rendering webpages to the user.
1 Browser process communicates with N Renderer processes.
Each Renderer process has two threads: one Render thread–which renders web pages, and one IPC thread–which transports data in a thread-safe, non- blocking manner between the Render thread and an IPC counterpart sitting in the Browser process. The Renderer process manages 1 IPC thread and 1 Render thread.
Completely separate visits to the same site are managed by different processes, so if you had two tabs open to mail.google.com, one of them could crash without affecting the other. Chrome treats separate browsing contexts as separate processes.
If you’re on mail.google.com, and you navigate to hotmail.com, the tab’s underlying process may switch. In this case, Chrome switches your browsing context because you navigated to another site.
If a web page pops up another webpage (via JavaScript), then the sites are considered connected, and managed by the same process. Chrome uses a single Renderer process to handle a browsing context.
This is Chrome’s default behavior and is called process-per-site-instance. It’s intuitive in that your tab count is (more or less) your process count.
Process-per-site
Since multiple tabs can be assigned to a single Renderer process, wouldn’t it be neat if the Renderer process could manage a group of sites?
That’s what process-per-site does. Chrome defines a “site” similarly to the Same Origin Policy with subdomains added into the mix.
For example, in process-per-site mode, mail.google.com, docs.google.com and reader.google.com are all managed by a single Renderer process. If one of those web applications crash, then the responsible Renderer process will crash, thus taking down the entire collection of tabs.
Unlike the previous process model, a tab does not imply a separate Renderer process.
Process-per-tab
The third and most intuitive process model is called process-per-tab.
In this model, tabs have their own process but unlike process-per-site-instance and process-per-site, none of the underlying process switching logic is applied.
Each tab has it’s own process for the life of tab, so a tab will never change process even if a user consecutively visits hotmail.com, gmail.com, and ymail.com.
One process per tab, forever.
Single-process
Finally, the fourth and simplest process model is the single-process behavior. You can run Chrome in a mode that combines the Browser and Renderer process into a single process. This makes Chrome behave a lot like the browsers we have today2.
Choose your Process model
Anyway, if you made it this far down, then the take away from all this is that, the various process models define different ways of assigning tabs to processes, therefore your user experience will vary depending on your OS, your browsing behavior, and the websites you frequent.
To use a specific process model, you can launch Chrome with one of the following arguments.
--process-per-site
--process-per-tab
--single-process
If you’re interested in reading more about memory isolation and the challenges in building a browser like Chrome, check out Charlie Reis’ paper on Using Processes to Improve the Reliability of Browser-based Applications. Chrome’s process model is derived from this paper.
Thanks to Ben Smith, and the developers in #chromium (irc.freenode.org) for reading drafts of this article.
Updated: Charlie dives into the reasons for a multi-process architecture browser.
-
Vista, Linux, Unix, OS X, pretty much anything after Windows 2000.
↩ -
I’m specifically referring to Firefox 3 and Safari 3, which run in a single process. I’m not familiar with Opera, Konquerer, or Explorer’s process model, so there may already be browsers which do a great job at isolating processes or managing threads (Like Opera, I love Opera).
↩
In less than a year, OpenRain went from this:
Ruby, ruby, ruby
I miss the guitar
And the Elliptical.. in our conference room
to this:
Seating area
Hacking area
Eating area
To celebrate, OpenRain is throwing our first open house tonight. In addition to friends and family, this is an open invitation to folks in Phoenix, AZ interested in the design, development, and business of web software.
In other words, you’re invited.
Why a celebration?
Officially, it’s because OpenRain recently moved into a new office in sunny Mesa, AZ, and to commemorate this upgrade, we’re throwing a “1.0 Release Party.”
Unofficially, it’s to celebrate just how far OpenRain has come from two guys programming in the spare bedroom. Personally, I’m delighted with just how much growth we’ve experienced in the last nine months and even though the best is yet to come, it’s important that we take a moment to celebrate our recent successes.
Congratulations to entire OpenRain 1.0 Team.
Labor Day 2007 was the day of reckoning. Inter-Tel and Mitel, after spending who-really-knows-how-many months courting the possibility of a merger, had finally decided to bite the bullet and “combine portfolios in order to increase range across the spectrum of market segments” at $25.60 a share.
It’s always calm before the storm.
The great firing at Inter-Tel took place a few months only a few months after the great fire at Inter-Tel, which took out a small portion of the roof and caused massive damage to the 2nd floor. Fortunately, no one was hurt… by the fire.
On 10AM, the Monday after Labor Day, Marsha (not her real name) approached my desk and requested I follow her to the conference room. Even through Marsha’s glasses, you could see right through her poker face.
There were about a dozen of us, sitting around the table. Was this a secret award ceremony for the top 12 associates at Inter-Tel? Were we going to be taken out for dinner and told that we could work on a new industry strength, open source PBX written in Erlang? Scrapping the decades old legacy system written in a mix of languages?
Not quite.
Due to the recent merger, your positions have been eliminated. Here’s your awesome severance package.
By 10:10, I was restructured out of a job and by 10:20, I was escorted out of the building. It was fast.
I got into my car and drove off. I made three phone calls.
The first, was to the dear friend who recommended me for the Inter-Tel interview.
I said jokingly, “Sorry, but you’re not going to get your full referral bonus”
Inter-Tel required new associates to stay for a year before the referrer received the full bonus.
We chatted for awhile and made plans for lunch later in the week at our usual Japanese hangout.
The second, was to my dear girlfriend. It does seem strange that I didn’t first call the love of my life, but I knew the conversation would last a while. We were planning to purchase a house together.
“Don’t worry…”
“No, really don’t worry. Yes we can continue the house search…”
“Yes, we’ll have enough money”
”I’ll find a job.. don’t worry, seriously.”
This went for awhile until I realized that I was just around the corner from my destination.
“I got to go, hugs and kisses”
I dialed the third number.
”I’m coming over.”
I pulled up outside Preston’s house.
“Like, right now.”
It’s been less than a year, and OpenRain has done superbly well.
I never had any illusions about how easy it would be to start a company. I knew it would be constantly challenging. And, it is.
When I think about how I got here, I am truly surprised that it stemmed from a single event that Labor Day just under a year ago.
In The Matrix, Neo is given a choice between the blue pill, a life of simulated reality, or the red pill, an opportunity to awaken and given a chance to change the real world.
I wasn’t courageous enough to take the red pill. I had thought about it, but in the end someone had to force it down my throat.
Taking the red pill, turned out to be more fun, more challenging, and more rewarding. If you ever find yourself at this crossroads, take the red pill, I highly recommend it.
A quick note for our Subversion fans, OpenRain’s new source code repository is now located at code.openrain.com.
Now that the videos are out on Confreaks, here’s my mini review. Ruby readers beware: this is my first Ruby conference since starting fulltime at OpenRain, so our levels of interest might vastly differ.
My favorite sessions on Ruby
Patrick Farley on Ruby Internals. Patrick gave a great overview of how C-Ruby works. He started out by explaining about the relationships between several C structs, such as RBasic and RObject, which he then used to explain the magic behind Ruby’s runtime object hierarchy. A fascinating talk, if you’re interested in the nitty gritty internals of Ruby. Makes me appreciate the work being done by the Rubinius team on their Ruby virtual machine.
Tammer Saleh on Behavior driven development with Shoulda. If you’re starting out with Rails for the first time and you’d like to ramp up on best testing practices, then this talk is for you. Don’t get me wrong, you’ll still need to spend time on learning the details and getting use to the develop-test (or test-develop) cycle but listening to this talk will expedite the process by pointing you in the right direction. If you’ve been working with Rails for awhile and you’re wondering what the story behind behavior driven development is, then this talk is also for you. My thoughts: you don’t need a new tool do BDD; you can get away with Rails integration tests. Think of this talk as a +8 to your Testing ability.
Phillipe Hanrigou on What to do when Mongrel stops responding. Answer: Debug with GDB and DTrace. I recently came from C++ land, so seeing Phillipe live debug a halted Ruby processes with GDB was personally useful. Even with the amazing work done by the Eclipse and Netbeans teams, GDB isn’t going away anytime soon. Phillipe also put out a PDF titled Troubleshooting Ruby Proesses where he describes strace and lsof, in addition to GDB, as valuable debugging tools.
My favorite sessions not-entirely-about-Ruby
Giles Bowkett on Code Generation: The Safety Scissors Of Metaprogramming. The premise of the talk was that, like Lisp, writing code which generates data which generates code is a Good Thing. The demo he gave wasn’t super glitzy but the ideas behind it were incredibly thought provoking. Giles is a great speaker; I know this since I was having a hard time devoting attention to my own note taking. Realizing and figuring out how the code generation in Rails works is an “ah hah” moment and a mental model you need to construct if you’re ever going to fully understand Rails. His talk will take you there. Lastly, did you notice that almost every speaker included a slide with a photo of Darth Vader-wearing a-Sombrero? That’s Giles’ fault.
Jan Lehnardt on Next Generation Data Storage with CouchDB. CouchDB is a document-oriented storage system that doesn’t support full relational models. It can replicate in real time making it highly available, and accessible over RESTful HTTP making it scalable. It’s also written in Erlang, which is the poster child for highly scalable programming.
Why might you care? Since the dawn of computing, databases have generally come in one kind of style: the relational kind. In fact, it’s a very common paradigm to use relational databases to manage all sorts of, you know, relational data. Like a database of Customers, with shopping Carts, filled with items from a product Catalog, sold by Vendors, from different States at different Tax rates. If you’re working with data and money, say terabytes of data and billions of dollars, then sometime during development, two questions arise: How do I scale all this data? How do I make this highly available for our millions of paying customers? There are a bunch of approaches and patterns which have stood the test of time, but they typically involve adding more hardware, or caching large parts of the system in memory. Both solutions also scale budgets and complexity.
There are two notable database storage systems which aren’t relational: Google’s BigTable and Amazon’s SimpleDB which is likely inspired by Dynamo. Both store structured data, neither support full relational models. Let me rephrase that: two very large software shops dealing with far more data than I do have concluded that scaling data using traditional RDBMS techniques could be easier. It’s the potential for being easier with CouchDB that excites me. As of this writing, the version of CouchDB I’m running is 0.72 and some of details in Jan’s talk is still under active development.
I hope you’re paying attention, database paradigms are shifting right now.
Use Ruby? Like to parse XML–who doesn’t? Using Ruby’s XmlSimple library? Don’t do that… like, ever, ever.. EVER.
But if you must, take heed of the following advice.
Test #1: What do the Ruby defaults do?
Now let’s take a look at XmlSimple in straight up Ruby:
>> xml = "
<xml>
<head/>
<list>
<item id='1'>chunky</item>
</list>
</xml>"
>> XmlSimple.xml_in(xml1)
=> {"head"=>[{}],
"list"=>[{"item"=>[{"id"=>"1", "content"=>"chunky"}]}]}
Ugh, every key returns an array of hashes so you’ll end up doing things like hash["head"].first or hash["item"] to access values. It looks nasty, but it actually makes sense since there’s no way to know a priori whether list or head contain 1 or many items.
Let’s try that with the XmlSimple option of forcearray => false.
>> XmlSimple.xml_in(xml, "forcearray" => false)
=> {"head"=>{},
"list"=>{"item"=>{"id"=>"1", "content"=>"chunky"}}}
A little cleaner, but problematic as we’ll see later.
Test #2: XmlSimple uses content to reference element values, so what happens if you have an attribute called content ?
>> xml = "
<xml>
<head/>
<list>
<item id='1' content='chunky'>bacon</item>
</list>
</xml>"
>> XmlSimple.xml_in(xml, "forcearray" => false)
=> {"head"=>{},
"list"=>{"item"=>{"id"=>"1", "content"=>["chunky", "bacon"]}}}
By default, both values for the attribute and the element named “content” are returned in a single array. There’s no way to distinguish between the two.
Test #3: What happens if you have more than one <item> in a <list>?
>> xml = "
<xml>
<head/>
<list>
<item id='1'>chunky</item>
<item id='2'>bacon</item>
</list>
</xml>"
>> XmlSimple.xml_in(xml, "forcearray" => false)
=> {"head"=>{}, "list"=>{
"item"=>[{"id"=>"1", "content"=>"chunky"},
{"id"=>"2", "content"=>"bacon"}]
}}
In this example, note that <item> returns an array of two hashes. Like I previously mentioned, there’s no way for XmlSimple to know that an element will have 1 or many items. With the "forcearray" => false option, a key could return a Hash or an Array depending on the XML. Not desirable, but you can probably coerce the correct behavior with the right XmlSimple configuration options.
Now, let’s take a look at XmlSimple embedded and mixed-in with the Hash class, as it is in Rails.
Test #4: What do the Rails defaults do?
>> xml = "
<xml>
<head/>
<list>
<item id='1' content='chunky'>bacon</item>
</list>
</xml>"
>> Hash.from_xml(xml)
=> {"xml"=>{"head"=>nil, "list"=>{"item"=>"bacon"}}}
No id attributes.
Yikes!
Test #5: Similarly to before, what happens if you have more than one item, like in the case of xml2?
>> xml = "
<xml>
<head/>
<list>
<item id='1'>chunky</item>
<item id='2'>bacon</item>
</list>
</xml>"
>> Hash.from_xml(xml)
>> {"xml"=>{"head"=>nil, "list"=>{"item"=>["chunky", "bacon"]}}}
Same as before, the id attributes are removed, and <item> references both element values with a single key.
By default, Hash.from_xml in Rails will eat your attributes.
In summary, Ruby’s XmlSimple is bork^H^H^H^H surprising to use and in Rails, doubly so. Actually this really shouldn’t be surprising since most of these cautions are already mentioned on the XmlSimple homepage.
Updated: January 3rd, 2009: What to use instead of XmlSimple?
Check out libxml-ruby and more recently HTTParty. Check out HTTParty examples.
Recently, I spoke at the Phoenix Rails Users group about Amazon’s EC2 services.
The presentation started off with a basic introduction of EC2:
- Virtual computing environment,
- Running RedHat FC4,
- With a pay-as-you-grow, no long term contract payment plan
Since EC2 is a web service (SOAP), there’s no shortage of freely available tools that help you manage your EC2 instances, including:
- The official EC2 command-line tools
- The Firefox browser extension, EC2UI
- The amazon-ec2 RubyGem
- If you’re feeling particularly ambitious, the WSDL file is available too
After the introduction, I talked about some of the deployment architectures that we’ve been using, including a 1-box, 2-box, and an N-box approach. Since it was a Ruby/Rails talk, I included some notes/gotchas on various configuration files and deployment scripts.
Finally, I demoed a 2-box instance running MPICH2 and MPI Ruby, which is a set of Ruby bindings for MPI.
Derek Neighbors posted a recap of the event.
Chris Matthieu recorded the presentation over at Rubyology
Here are the slides to follow along.
Thanks to IntegrumTech for hosting the event.
A few years ago, I read about the city of Beloit’s recreation of George Seurat’s “Sunday Afternoon on the Island of LaGrande Jatte”
Beautiful.
Last year, my friends and I went to Chicago. We stopped by the Art Institute of Chicago and did a recreation of our own.
Recently I’ve been doing a lot of Ruby programming. I’ve done a lot of Java and C++ in the past, so it’s always interesting to compare styles and design techniques between languages.
Ruby has closures which, amongst other things, allows the language to operate on collections in a compact and concise manner. For instance, take for-loops. Ruby has for-loops, but you rarely use them.
Take the following list:
list = ["matz", "eats", "sushi"]
Instead of looping over it with:
for i in list
puts i
end
A common Ruby idiom is:
list.each {|i| puts i}
The power, in this case, comes from expressiveness balanced with brevity.
There are a whole bunch of other collection methods such as select, find, and collect.
For a bunch of reasons, my favorite method is collect.
Say you had a collection of User objects with the method first_name. To get a list of first names, you could do something like this:
users = [...]
first_names = []
for u in users
first_names << u.first_name
end
But as before, idiomatic Ruby looks like:
first_names = users.collect { |u| u.first_name }
Again, brevity with expressiveness.
Just for comparison, let’s try and do this in Java6-land. Assuming a User object with the method getFirstName(), one easy approach might look like:
List<User> users = ...
List<String> first_names = new ArrayList<String>();
foreach(User user : users) {
first_names.add(user.getFirstName())
}
But what if we wanted to call User.getLastName(), or User.getAge() which returns a totally different type. Without closures, the only approach is to duplicate the same for-loops over and over again, each with a different method call and return type.
Is a closures-like approach possible in Java6? Let’s give it a shot.
First, since Java6 doesn’t come with closures, you’re going to have to model one.
public interface Closure<R, T> {
public R call(T t);
}
A closure in this case is simply a function that accepts an object, type T, and returns an object, type R. Seeing a concrete implementation will help clear things up.
A User object, which we’ll skip. Just keep in mind that it has a method called getFirstName() which returns a String and getAge() which returns an Integer.
An actual closure implementation which looks like
Closure<String, Person> nameColl = new Closure<String, Person>() {
public String call(Person t) {
return t.getFirstName();
}
};
And finally, the Collect method:
public static <T, R> List<R> collect(List<T> list, Closure<R, T> clo) {
List<R> res = new ArrayList<R>();
for (final T t : list) {
res.add(clo.call(t));
}
return res;
}
A test harness:
List<User> list = new ArrayList<User>();
list.add(new User("marc", 26);
list.add(new User("michelle", 25);
List<String> results = collect(list, nameColl); => ["marc", "michelle"]
To get a list of ages, your closure implementation would look like this:
Closure<Integer, User> ageColl = new Closure<Integer, User>() {
public Integer call(User t) {
return t.getAge();
}
};
A test harness:
List<Integer> results = collect(list, ageColl); => [26, 25]
As you can see the Java solution is much longer. In Java, more Typing means more typing.
An open challenge: Is a more concise approach possible in Java6?
Frustrated with all that typing? Don’t worry, there is ongoing work to make closures part of the Java programming language.
Happy Chinese New Year.
I admit I was caught by surprise at how early Chinese New Year starts this year.
I’ve been extraordinarily bad about keeping the traditions alive in my house.
Specifically the one about cleaning.
In previous years, just before the New Year, I usually spent a few weeks cleaning the entire house. You see, the Chinese culture believes that in order for good fortune to spread throughout the household, all the garbage, and rubbish, and dust, and crap must be removed before the new year. Superstitious? You bet it is. There’s even a whole process for sweeping the dirt away.
Sweeping during the new year, sweeps your good luck away. This means no mops, brooms, brushes, or Roombas. Sorry, no Roombas allowed during Chinese New Year. Turn those gizmos off.
Xing Nian Quai Le
Previously, how to celebrate the Lunar New Year
Last week I was invited by US Southern Command to speak at COPECO about the use of face recognition as a form of biometric identification during times of crisis. (Disclaimer: I work at OpenRain which is an affiliate of img surf where I developed Mugr)
COPECO (Comisión Permanente de Contingencias) is the equivalent of America’s FEMA. They’re the organization responsible for making sure Honduras and her neighboring nations are well prepared for handling various disaster scenarios like earthquakes, tsunamis, and hurricanes.
This was the first time I’ve been to Honduras and the first time I’ve traveled out of the United States since becoming an American citizen.
I learned a lot from this trip.
-
Honduras has hundreds of bilingual schools at the preschool, primary, and secondary levels, which is the American equivalent of K through 12. One preschool taught French and Spanish: Spanish-speaking students learning French from French teachers.
This is amazing for two reasons: 1) the students are learning two languages and 2) they start learning at a much younger age. This should be the way we teach multiple languages in America. It doesn’t have to be Spanish, because I believe there should be options like Arabic or Chinese, but we ought to encourage our kids to learn to speak multiple languages.
Learning a new language is actually quite fun, but difficult to do if we’re only taught three to four times a week beginning at the 9th grade, as it’s done in American public schools.
-
COPECO’s headquarters is built on a Honduran military base. The construction of COPECO was a joint effort between Honduras and America. Funding for half of the building was contributed by Honduras, and the other half by America. This was done through the efforts of the U.S Agency of International Development.
Entrance to COPECO
Honduras’ Flag
From the American People!
During this trip, there were several other organizations demonstrating a variety of technologies aimed at supporting Honduras during a crisis.
-
A yurt is an easily dismantled and transportable man-made shelter used by various nomadic tribes in Central Asia. A hexayurt is a hexagonal shaped, man-made shelter, built from local resources for as little as $200USD per shelter.
During a natural disaster, one challenge that arises is providing shelter for thousands and thousands of disaster victims. If your country doesn’t have a stadium or a bunch of cancer-causing trailers lying around, one option might be to construct a hexayurt.
Hexayurts are quickly deployable, cheap to construct, and environmentally friendly which makes them highly useful for meeting human needs where available services are inadequate.
The hexayurts we constructed in Honduras were made out of compressed wood, string, and super-powered tape.
Dan making the roof
Col. Bartone building the walls
A smaller hexayurt
Completed hexayurts. Honduran army + students from local university. (Not the entire Honduran army)
-
The U.S. Geological Survey (USGS) provides a boatload of information geared towards assessing an earthquake’s impact.
PAGER (Prompt Assessment of Global Earthquakes for Response) is an automated system that provides information about the scope of the potential disaster so that various agencies can prioritize their disaster response. It does this by combining information from ground instruments as well as feedback from actual people, which effectively makes it a social web application for measuring earthquake impact.
ShakeMaps are another neat service. Earthquakes are typically measured by magnitude and epicenter. It turns out that the complexities of the Earth’s crust (rock and soil) influences the propagation of seismic waves (ground shaking) through out a region. Instead of providing simply the magnitude and epicenter, a ShakeMap represents the ground shaking produced by an earthquake.
-
The presentation by Pat McArdle on solar cooking pretty much blew my mind away. A solar cooker is a device that uses sunlight to cook. That’s it. No wood, no gas, no coal. Just sunlight.
A solar cooker
Chicken del la Solar
Chocalate cake
These devices are deceptively simple looking and yet they work remarkably well. Pat made a chicken dish, pasteurized water, and even baked a cake. You can build one easily or you can buy one online. If I didn’t believe in science, I would still be in complete disbelief that something so simple could work so well.
-
On the last day, a small group of participants were invited to the local children’s hospital. The situation, I’m sad to share, is grim. The hospital has 400 beds, 8 intensive care units, and only 2 critical care units. The infant mortality is 23/1000. The hallways are packed and patient occupation is at 139% often resulting in two children to a bed.
-
The military personnel responsible for organizing the event were among the brightest, most talented, and incredibly motivated group of individuals I’ve ever met.
-
I felt incredibly ignorant (not in the pejorative sense) for not knowing more Spanish. I live in Phoenix, Arizona dammit, why don’t I already speak it?
Some fun things I learned:
-
You can buy Cuban cigars in Honduras and bring back a small amount for personal use. I’m talking 3 or 4 cigars, not 13 or 14 boxes. In order words, try not to look like you’re a dealer.
-
The local word for “awesome” in Honduras, is “micizo,” pronounced mee-sue-so.
-
Google.com will redirect you to Google.hn and localize all your results in Spanish. All your results will take you to the Spanish version of the website, if one exists.
-
There’s a city of Arizona, Honduras. It has a population of about 5,000. Tegucigalpa, the capital city is home to about a million people.
An evening in Tegucigalpa
-
According to our translator, Tegucigalpa is home to the the largest soccer stadium in Central America. Go fútbol!
-
Honduras spends a large portion of it’s national budget buying down the price of oil.
-
The president of Honduras does not live in the Presidential palace.
Check out more photos
It looks as though famed cartoonist Scott Adams revealed the secret to finance success in Dilbert and the Way of the Weasel. At least one person smarter than myself thinks it’s worthy of a Nobel Price in Economics. I graduated a few years ago, so I’ve had time to formulate my own thoughts on personal finance, but let’s see how I stack up against Dilbert.
-
Make a will
Nope, haven’t done that one yet.
-
Pay off your credit cards
Yep. In full, every month.
-
Get term life insurance if you have a family to support
I don’t have my own family, but in the past I’ve usually take the default plan my company offers.
-
Fund your 401k to the maximum
Definitely. I’ve taken the 401(k) route with every company I’ve worked for. At the very least, you should put in whatever your company matches, and the yearly limit if you can afford it ($15,500 in 2007). My current company doesn’t do this right now, but we’re just starting out.
-
Fund your IRA to the maximum
Most definitely. Since the yearly limit is $3k, it’s easy to max out your Roth or IRA account.
-
Buy a house if you want to live in a house and can afford it
The housing market is tanking, so if you’ve been saving up for a rainy day, certainly now is the time to look into buying a house. Also, according to this MarketWatch (01/08) article, it looks like people are house shopping again.
M and I bought our house back in October 07. -
Put six months worth of expenses in a money-market account
And done.
-
Take whatever money is left over and invest 70% in a stock index fund and 30% in a bond fund through any discount broker and never touch it until retirement.
Kind of. I have a Vanguard Target Retirement Fund. The fund diversifies investment according to age. Since I’m young, apparently I can take risks like Indiana Jones, so it invest in stocks. As I get older, it plays it safe and invests in things like bonds and peanut butter.
-
If any of this confuses you, or you have something special going on (retirement, college planning, tax issues), hire a fee-based financial planner, not one who charges a percentage of your portfolio
I’m not really in either of those positions so…
Not a bad list. I’m lucky for a guy working in his own start up. Should they have taught subjects like this at ASU? I’m not sure, but it sure would have been more useful than, say, UNI 194 - Introduction to being a Student aka How To Study.
How do my fellow readers do?
My site will be eventually moving to a Joyent powered Accelerator as well as receiving a much needed makeover.
I hope to minimize the inconvenience, so please bare with me as I make these changes.
I’ll write up about the redesign later, as well as the reason I haven’t been posting recently. I’ve also got a huge backlog of drafted articles in Google Docs just waiting to see the light of day.
There are a few reasons I’m moving: I’ve been writing here for a few years now, but I’ve always been a little frustrated with the Wordpress format. I like to write articles that are a little longer than usual, intermixed with short blog posts, and I just never felt that was happening from a visual perspective. It’s time to change that.
I’ve also been spending an awful lot of time developing in Ruby on Rails, so it makes sense to power my personal site with a Ruby-powered blogging/CMS software.
Update your RSS feed, to something a little hotter.
Stay tuned.
This would be the second New Year’s greeting that I’m seven days late for.
This Lunar New Year is special since it’s the Year of the Golden Pig, which occurs every 600 years. According to the placemat at the Chinese restaurant we had new years lunch at, the pig represents traits such as fortitude, loyalty, and honesty.
Singaporeans, and perhaps all Asians, have an important concept called saving face. Ingrained since my childhood, saving face is a way to resolve a situation in a way that minimizes or avoids embarrassment. When in doubt, the guiding principle on saving face is to never disrespect anyone or hurt someone’s dignity. Honesty, I think, conflicts with saving face.
Some recent and not so recent conversations on honesty:
From The Pie (Seinfeld season 5, episode 15):
Audrey: Ah! Poppie.
Poppie: Sweetheart, hello.
Audrey: Poppie, this is Jerry.
Poppie: Welcome (shakes Jerry’s hand)
Jerry: Hello Poppie.
Poppie: Don’t fill up on the bread. I’m making you a very special dinner. Very special. (he leaves)
Jerry: The pies. I’m going to the bathroom. You know. (he leaves)
Jerry and Poppie in the bathroom. Jerry washes his hands while Poppie flushes and gets out of the stall
Poppie: Ah, Jerry! Tonight you in for a real treat. I’m personally going to prepare the dinner for you and my Audrey.
He zips up and leaves without washing his hands. Jerry notices it. back at the table with Audrey, Jerry can see Poppie in the kitchen with his hands in the dough, making dinner
Audrey: Jerry are you OK?
Jerry: Huh?
Audrey: Is anything wrong?
Jerry: No, Nothing.
Audrey: You look like you’ve seen a ghost.
Jerry can’t talk and he’s staring at Poppie’s hands. Poppie smiles and winks at him
Later, while eating pizza and talking to P about the Seinfeld episode
M: You’re telling me if I caught the chef doing that, you wouldn’t want to know?
P: No, I wouldn’t. I just want to enjoy my pizza.
Years later, while talking about P’s recent break up.
M: I wish I had told you about her, but I just didn’t know if that was OK.
P: What do you mean?
M: Well, it’s like that pizza conversation. Even though I knew you two wouldn’t get along, I just thought you might not want to know about it.
The truth is harder to set free when you’ve been raised with a cultural predisposition to avoid it, especially if it’s embarrassing. It would be much easier if I could ask all my single friends if they would rather eat pizza or hear my honest thoughts.
- Write test cases.
- ...
- Profit. No, I mean refactor.
Actually, all your ”compiler.misc.base.membership” class do, in fact, belong to Java. Don’t worry. According to Peter, that compile error can’t occur and is left there for sentimental reasons.
When I read Seth’s recent post on apologizing to customers, I couldn’t help but observe a similar approach one takes when dealing with software bugs.
There are many incorrect ways to handle a software bug, but only a few correct ones. If you’re blessed with tact, technical know how, and a burning desire to right the wrong, then you probably already knew this.
On a scale of 1 to 10, where 10 is the best approach
- “I didn’t do it.” (-1). Actually, you did. Last Friday at 1:42 PM. Honesty, and good source control, is the best policy.
- “It’s not my fault.” (1): It’s not personal, it’s bug triage. Your team is trying to determine what to fix, and who should fix it. No one is trying to assign blame.
- ”I’m not done with it yet, don’t use it.” (1): Fair enough, but if you checked it in, you should at least write a unit test to go along with it, even if it explicitly fail()’s. This way, we know it’s not suppose to work and nobody is caught by surprise. Type II errors, or false negatives, are a huge liability for a development team because the tests are believed to be verifying the intended behavior of the software.
- “It’s not my fault; the spec is wrong.” (2): Not a problem. Mention the behavior to a colleague or notify the team lead about the discrepancy. If two heads see a problem, then there’s probably a genuine problem. Don’t get too defensive about it and be careful not to start with “The spec is wrong…”
- “It’s not my fault the spec is wrong.” (1): What did I just say about getting defensive?
- “It’s not a bug, it’s a feature.” (3): Oh? Really?
- “Yes, it is a bug.” (5): Well, all right then, these things happen. What are you going to do to fix it?
- “Yes, it is a bug. Stop by in a few hours and I’ll either have a fix, or I’ll have an idea for a fix.” or “Yes, it’s a bug, but a fix is already in the works and should be in by tomorrow’s build.” (9): Brilliant and spot on. This is pretty much the response everyone wants to hear, but it doesn’t mention what actions you’ll take to prevent the bug, or similar bugs, from occurring in the future. The complete approach is:
- “Yes, it’s a bug. I have a fix. In addition, I also wrote a unit test that makes sure that bug, and bugs similar in nature, will never occur again. This way, we can prevent a whole class of bugs from occurring with one fell swoop. This is a good thing because life is too short to only use an approach for testing that relies solely on people’s ability to execute a series of mouse clicks and keystrokes when the processing power that makes computers so useful can be leveraged to execute these tests, freeing testers from especially mundane or repetitive testing so that their brains can be used for higher order tests that computers can’t do yet.” OK, so in truth, you probably won’t say something like this, but that shouldn’t stop you from doing it.
Last year, when Warren Buffet announced a massive donation to the Bill and Melinda Gates Foundation, he left the foundation’s CEO Patty Stonesifer one piece of advice.
Two, more recent, encounters I’ve had about going deeper.
How To Become a Better Programmer by Not Programming
Passion for coding is a wonderful thing. But it’s all too easy to mindlessly, reflexively entrench yourself deeper and deeper into a skill that you’ve already proven yourself more than capable at many times over. To truly become a better programmer, you have to to cultivate passion for everything else that goes on around the programming.
The more things you are interested in, the better your work will be.
Use your time, all your time, to sell just one thing.
Two experiences with the Lisp programming language.
The Ducati of programming languages. An extension of mind and body.
Volkswagen Lisp. Infinite reconfigurability. Beyond college, I haven’t had much experience with Lisp, but with my recently renewed passion in programming languages, perhaps it would be a good time to test drive Lisp again.
Marking blogs as read
Happiness is mustering enough courage to say “F*ck it,” opening Google Reader and clicking “Mark all as read.” As odd as it sounds, it feels like a great burden has been lift off my shoulders. I have no idea why I have this obsessive need to stay up to date with the latest news on the tubes. In a way, it’s a bit like revolving your life around TV, which is quite ridiculous and thankfully is something I don’t do.
New goal: I’m going to use ”Mark all as read” more often, even for my favorites.
Reading blogs as Marc
The blogs I enjoy reading are the ones that make me realize I still have so much to grow, at least professionally and technically, like in the area of building kick ass software. Realizing this, of course, immediately throws my personal ass kicking machine into overdrive and this usually means major nerding. I also enjoy reading anything that completely obliterates one of my preconceived opinions and allows me to look at the world (or a problem) with a completely new perspective. Contemplation and reflection is fun.
That being said, here are ten blogs that are currently in my “daily-reads” category.
- Artima Developer. Artima is a great all around community about building software. What I like about this community, is that they discuss a wide variety of programming topics. Since I recently got engaged to C++, I’ve found it’s the closest thing to Javalobby that the C++ community has.
- Data Mining. This is probably one of my new favorite blogs. I discovered it last year while I was taking a data mining course. Matthew does a terrific job at pointing out observations and trends using terminology that won’t give you an aneurysm. Make sure to check out the articles in the data mining category.
- How to Change the World. Guy Kawasaki: Macintosh evangelist, venture capitalist, author, and speaker. Also kicks more ass than Jackie Chan.
- Joel on Software. He writes software, he writes about writing software, and he writes about the business of writing software. How couldn’t I read his blog?
- Raganwald. Also a new addition to my top ten and also a blog about software. The first time I ran across Reg’s blog, it was regarding his favourite interview question which I still think about once in awhile.
- Seth Godin. Remember what I said earlier about learning to look at the world with a different perspective? This is just a swag, but I’d guess that 70% of Seth’s posts cause me to do that.
- Signal vs. Noise. I love the 37signals guys, and if you love the idea of software that is simple to use, you should too. If you read two things, make it Getting Real, their book on building software, and their manifesto. I don’t agree with everything they wrote in their book, but I certainly appreciate their pragmatic approach to building software. (Don’t write a spec… seriously?)
- Stevey’s Blog Rants. Just when I think I get programming, Steve comes along and turns my entire world upside down. Three things Steve made me do: learn Emacs, read Refactoring, and write more. I spent a month in Emacs writing C++ before reverting back to Eclipse. Two out of three isn’t too bad.
- The Old New Thing. Raymond Chen scares the sh*t out of me. Ever notice the side bar when you Google for him? Yea that’s right, Google/Jobs bought an AdWord with his name.
- The Dilbert Blog. I am shocked by everything Scott Adams writes, yet I am wildly excited that he chooses to share it with the world. It pays to have a good sense of humour.
Well that’s it. In a nutshell, seven blogs are about building better software, two are about changing the world, and one keeps me laughing while I do the other two.
Me: ”I’ve been so busy,” I said to M, “I don’t even have time to read my blogs.”
M: “You should be able to catch up this weekend.”
Me: ”I’ll probably just read the good ones and mark the rest as read”
M: “The good blogs?”
Me: “Yes,” I reply, delighted I get to explain my blog reading strategy, “I have a folder of good blogs that I read first. It’s a bit like going to a restaurant and ordering the good wines first and the not-so-good wines later. As the night progresses, you drink more wine and, eventually, your palette can’t tell the difference between good or bad wine.”
M: “But you break out in hives when you drink bad wine.”
Me: …
No, I don’t break out in hives when I read bad blogs, but I probably should. I blame Google Reader for my allowing my RSS addiction to flourish. With Bloglines, I found that I could subscribe to about 200 blogs before category management became a nightmare, so I had to be picky about what I subscribed to. With Google Reader–the “New Hotness” edition–I am able to break that barrier since I can manage my categories much more intuitively with the use of labels (aka tags).
Trust me, it’s a bad thing :-)
It helps to read Digg, Reddit, or dzone.com as they tend to aggregate the popular links, which the majority of people tend to regurgitate blog about.
Updated 1/28/2007: I picked up this tidbit from a comment by Robert Scoble over at CrunchNotes:
| Subscriptions | Read | Starred | Shared | |
|---|---|---|---|---|
| Scoblelizer | 504 | 26,308 | Zilch | 1,473 |
| Chung | 266 | 1,213 | 5 | Nada |
That’s RSS-tastic!
How hard is it to cancel a service?
Quite hard, according to this PCWorld article, ”Just Cancel the @#%$* Account!”
But it really shouldn’t be. If I were the CEO of an awesome company, of course I would be upset that users are leaving my service.. my super awesome Web 2.0 service.. after all, these users would likely include my friends and family. And I hate disappointing friends and family.
So instead of focusing my energy on cheap tactics designed to complicate life for loved ones, I would learn why they want to leave. It might suck in the short run, but if understanding why 10 users are leaving prevents 100 more from doing so, isn’t that a better choice in the long run?
There’s no such thing as a free lunch. As a consumer, I believe this. I dread providing my personal identity elements to companies because I know they’ll just spam me, trade it away, or lose it on a laptop. Do you really need all my information to provide a rock solid service?
Two consumer empowering websites
- The Consumerist - Been burned by a company? BBB not doing it for you? Then bite back at The Consumerist.
- GetHuman - Calling a company’s 1-800 number? Tired of navigating the menu system? Not getting the high quality phone support you’re use to? Then use GetHuman to find the key stroke combination separating you from a real person.
It’s seven days into 2007 and I’m finally getting round to writing down my goals and resolutions for the year. I have four; they are quite modest. First, some thoughts…
I’ve always thought New Year’s resolutions were a silly concept. Don’t get me wrong, I’m all for ambitious ideas, attaining the unattainable, doing the impossible, yada yada yada. But the thought of using the new year as an opportunity to create unrealistic and unreasonable (though super sexy) resolutions for myself just doesn’t appeal to me. And I know I’m not the only one who has repeated this pattern for the last 20+ years. To me, it’s more important to have goals that are constantly evolving and not something you redo simply because it’s a new year.
Anyway, on to the goals:
- Write for 30 to 45 minutes a day, no longer than an hour. It’s just a way to manage my thoughts for the day, possibly crystallizing them on this blog.
- Read more. Not just blogs, or websites, or programming books, but real books. The ones made from pulp. I want to churn out at least two or three books a month. I do this now with technical references, and it’s just not the same. Programming languages come and go but Shakespeare will always be Shakespeare.
- More triathlons. Last year, my girlfriend and I did a sprint triathlon together. We did it by going to the gym and swimming, biking, and running three to five times a week. I want to do more sprint triathlons.
- Make more mistakes. OK, I stole this one from a friend of mine. In our college days, we were extreme perfectionist programmers, to the point where it became impossible to release any software. It’s been awhile since our college days and we’ve both learned that being perfect isn’t exactly what life is about. It’s not even that much fun.
Only 358 days left.
Top three blog posts of 2006.
- Performing a JSF GET. I’m surprised that the JSF spec still doesn’t make this easier to do.
- Automating SSH logins with PuTTY
- My (Fake) Demo 2006 Review. Day one and two. A personal favorite.
Step 1. Write a popular post reviewing Demo 2006 without even attending the conference.
Step 2. …
Step 3. Free guest pass for Demo 2007?
Which 7th generation gaming console did Saint Nicholas and his six to eight black men bring you for Christmas?
Last week, I wrapped up my first grad-level class, CSE 572-Data Mining. It was hard. Not prove ”P = NP” hard, but “juggling new job, real life, gymming, and awesome girlfriend” hard. The class was fun, I got to learn a lot about the usual algorithms like decision trees and stumps, k-nearest neighbors, Naive Bayes classification, bagging, boosting, classifier comparisons, lots of clustering techniques–top-down, bottom-up, distance-, graph-, and density-based methods, and techniques for mining association rules, like apriori, which I’ll write about in a future post. I even got to argue with the CTO of an upcoming startup over his approach for social suggestions, which was fun, until he IPOs and I don’t :-).
But I have to say, the really fun work was the project and all the stuff I learned outside class which, in another nutshell, includes distributed computations, first-class functions, concurrency issues, and techniques for (trivially?) parallelizing really, really, space and time intensive computations. I got to work with Amazon’s EC2 (Thanks Mike), a platform providing scalable hardware and bandwidth as a service, the recently released AOL search logs, and techniques for mining association rules. For my project, I decided to perform an analysis on the AOL search logs. Specifically, deriving association rules from the logs similar to the market-basket problem.
Market-basket analysis.. old and busted, or new hotness?
Let me take a second to talk about the market-basket problem. In this problem, we are given a set of all items, let’s call it A, and a large collection of transactional data. Each transaction (or basket) is a subset of A. Now the task here is to find relationships between the items within these baskets based on various factors.
Too complicated? OK, let’s try that again.
The canonical example of the market-basket problem is the supermarket (where the problem gets its name from). Now, instead of “the set of all items”, think “everything Safeway sells” and instead of “large collection of transactional data” think “what people purchase per visit.” Now we can find what products people tend to buy together. Knowing this, Safeway can stock their inventory, plan their sales, and market accordingly. This of course, increases ROI, embiggens synergistic… powers, and makes our lives easier overall. That’s the theory anyway.
Snap back to reality
My project was to analyze the AOL search logs in a very similar fashion. Instead of “the set of all items,” think “all unique queries in the search logs” and instead of “large collection of transactional data” think “what people search for per search session.” Now I can find out what searches people tend to make together. And what did I learn? Damn. People search for the craziest things. And by craziest I mean sexually explicit. And by people I mean you. No, not you, the person sitting next to you.
As I previously mentioned, the project was easily the most interesting component of the course. The third and current iteration of the code is under development. It turns out that, for a variety of reasons I won’t get into right now, implementing a scalable and efficient algorithm to mine association rules is a non-trivial task. Stay tuned, I’ll try to write more about it in the future.
To my friends and family, whether it’s Christmas, Hanukkah, Yuletide, Kwanzaa, Lohri, Winter Solstice, Gantan- sai, Eid-ul-Adha, the Day of Santa Lucia, Theophany, Epiphany, Hajj, the Feast of St. Basil, Las Posadas, Twelfth Night, World Religion Day, or Festivus (for the rest of us)–may your holiday festivities be filled with love, peace and happiness for you and yours.
A personal thank you to Mr. Jose F. Ina for sending me such a culturally assorted seasons greeting, O Nevo Bersh!
From Tim Bray’s Ongoing:
Remember: However many forks there are, it ain’t Java unless it’s called “Java” or has the coffee-cup on it. If it has the name and cup, it is Java and it’s compatible. And Sun will absolutely enforce that in court if we have to. We have in the past and we will again.
In one short, sweet, and concise paragraph, Tim alleviated concerns I had that evil-doers could flood the market with cheap Java knockoffs. I’m as much for open source as the next software engineer, but the thought of supporting 9 different compilers, 10 API implementations of the class libraries, and 3 VM platforms sends shivers down my spine. By enforcing Java strictly, Sun is giving people a way to distinguish the official Java platforms from renegade implementations.
The facts from Mr. Bray:
- Unmodified GPL2 for our SE, ME, and EE code
- GPL2 + Classpath exception for the SE libraries. This means that the developers are free to link non-GPL code to the Java libraries; similar to LGPL.
- Javac and HotSpot and JavaHelp code drops today
- Expect libraries to follow. The rest of the stack will be released in 2007
- External committers are a design goal
- No short-term changes in the TCK or JCP
By maintaining control over the TCK/trademark process, Sun gets to keep a high bar of quality and also prevents new functionality from breaking backwards compatibility. I like how this is panning out. Hats off to Jonathan, Rich, Tim, and James for doing a great job of raising their baby and enbiggening open source.
Check out more information at sun.com/opensource/java.
Update: A Noble Spirit Embiggens the Smallest Man
Riya just released Like.com, a visual search engine geared towards women and their collective billions.
Imagine this, you’re walking down ASU Palm Walk and of all the people in the world, you run into Jessica Alba who is sporting a pair of black shoes. Since they looked incredible on Jessica, the first thought that runs through your mind is to get your girlfriend a pair just like it. The problem is, you lack the basic knowledge required to purchase female foot accessories. So you do the next best thing: you take a picture of her shoes in the hopes that one day, someone will invent a search engine where you can search for shoes, visually. Then one day, you meet a guy who runs a Silicon Valley start up called Like.com. Like.com let’s you search for images, visually. According to TechCrunch, Like.com creates a “visual signature” for the query image, where the signature is a mathematical representation of the image using 10,000 variables. If enough variables are identical, Like.com decides the images are similar. Right now, the site seems to be geared towards female accessories like shoes, bags, watches, etc. Some interesting tidbits from a data mining perspective:
- I remember Riya when it’s facial recognition software caught headlines back in early 2006; there were rumors of being bought out by Google. Good thing they didn’t because the work with Like.com looks promising.
- It turns out that doing facial recognition was too complicated, at least according to user feedback, so they changed the game by going after a different market: women and non-geeks.
- The engine needs to work on high-resolution versions of the image.
- The software deconstructs these images into approximately 10,000 data points (or, I’m guessing attributes), which include:
- Characteristics like color, texture, material, shape, pattern, brand, style, and blingness, etc.
- To process the jewelry set takes 20GB of RAM.
- Shoes and bags are the easiest items to search for. Which is just as well since they are probably the easiest to shop for.
Now, you can take that picture of Jessica’s shoes and start punching in words that describe it. Black. Shoes :-). Ok, ok, Black, open, toe, polka, dot, shoes. Viola.
I showed my girlfriend the website:
Michelle: Type in Manolo Blahnik Me: Umm, [as I type in “M-a-n-a-l-o B-l-a-n-i-k”] and how do you spell that [Hits Enter]? Oh cool, it made a spelling suggestion, look “Manolo Blahnik.”
Pretty cool stuff!
I don’t know how other people do it, but I find it hard to tune out work or school mode.
Last weekend, my girlfriend and I saw 2 Pianos and 4 Hands:
Richard, playing as a Conservatory teacher: Good afternoon, this is your 7th grade examination at the Conservatory. This means you’ll be tested on techniques, terminologies, history, hearing tests, arpeggios, and, of course, you’ll play scales in a key of my choosing, which I’ve decided to be C. Sharp.
It’s funny how much I think about code (or algorithms) on a daily basis.
The show was a blast. I couldn’t stop laughing at the dialog, and I thoroughly enjoyed the musical performance.
Computer Programmer Clinton Eugene Curtis testifies that Tom Feeney tried to pay him to rig election vote counts. Feeney was Speaker of the Houe of Florida at the time, but is currently US Representative representing the Florida 24th
Congress: “Assuming for the moment that such software to rig a vote was used in one or more machines in Ohio or Florida, could you today detect that, if you could look at the source code?”
Clinton Eugene Curtis: “If you can get the machine, and they have not been patched yet and then take those machines, decompile them, which I couldn’t do, but possibly a [person from] Microsoft or MIT could do. You might, you might, be able to see them.”
C: “You might?”
CEC: “Yes, you might, it depends on how good they are destroying what they had.”
J: “Destroying what they had by tampering with the machine they had access to or destroying the instuctions on the machine in the first place.”
CEC: “Either or both. You didn’t actually see what’s in there , so you don’t know if the code is running in a single executable or if the code is running in various modules. if it’s running in modules, you can make the code actually eat it self.”
… audience expresses amazement …
October 16th, the day before America hit 300 million users citizens.
Robert Siegel: “Justin Timberlake, whom you’re listening to, you of course knew that already, is hot right now. I’ve never heard this song before but it is the nation’s number one pop single and it’s called Sexy Back”
It has come to my attention that the good folks over at the SEI forgot one important software metric.
From jwz’s ”Groupware Bad”
So I [jwz] said, narrow the focus. Your “use case” should be, there’s a 22 year old college student living in the dorms. How will this software get him laid?
That got me a look like I had just sprouted a third head, but bear with me, because I think that it’s not only crude but insightful. ”How will this software get my users laid” should be on the minds of anyone writing social software (and these days, almost all software is social software).
“Social software” is about making it easy for people to do other things that make them happy: meeting, communicating, and hooking up.
From a recent Newsweek Q&A with Steve Jobs, ”Good for the Soul”
Newsweek: Microsoft has announced its new iPod competitor, Zune. It says that this device is all about building communities. Are you worried?
Steve Jobs: In a word, no. I’ve seen the demonstrations on the Internet about how you can find another person using a Zune and give them a song they can play three times. It takes forever. By the time you’ve gone through all that, the girl’s got up and left! You’re much better off to take one of your earbuds out and put it in her ear. Then you’re connected with about two feet of headphone cable.
From a Slashdot comment
Of course, I mention that I know BASIC. Next night, we’re at my apartment, using my room mate’s TI Silent 700 to log into the Wellsley PDP/11 (Simmons didn’t have their own computer) via its acoustic coupler and the phone’s handset. I check her work, fix a few mistakes, and run her program. Looking over the results, printed out on that thin thermal paper, our eyes meet…
Yeah, BASIC got me laid. Perl, not so much.
Layability: A runtime quality of the system which describes the ease at which the end user can get laid. Not to be confused with Interoperability.
A programmer walks into a C++ Kung Fu Studio and has the following conversation with the resident master1.
Programmer: I want to learn C++. I’m willing to spend time and money learning. How long will it take me to master C++?
Master: It will take you 10 years to master C++.
Programmer: But master, I cannot wait that long. I will do anything you tell me to do. I’ll even work for you for free.
Master: Hmm, well in that case, it will likely take you 30 years.
Student: Master, first you said 10 years, then you said 30 years. I will work far more intensively than anyone else. How long would it take me?
Master: Well in that case you will have to remain with me for 50 years. Someone in such a hurry as you are to get results seldom learns quickly.
I don’t know about you, but whenever I need to learn a new language, there’s such a strong temptation to buy a dozen “Teach yourself XYZ in 24 hours” or “Learn ABC in 30 Day” books.
Overcome it.
As Norvig writes in ”Teach Yourself Programming in Ten Years,” it takes a lot more to be successful at programming. Some ingredients I can relate to:
- Do it because it’s fun. Seriously, if you’re going to have to put in 10 years, you really need to find programming fun.
- Talk to other programmers.
- Write code often. More importantly, improve code often.
- You don’t have to be the best programmer on all projects. It’s ok to be the worst, provided you learn what the best ones do… and what they don’t do.
- Maintain software. By doing so, you will inevitable curse, spite, and learn how to design your programs to make it easier for those who will maintain it after you.
- Learn different programming languages. Different paradigms (OOP, functional, parallel, declarative) allow you to think differently.
- Participate, but be careful, in a language standardization efforts. Don’t shave the yak.
1 老子/孔子, 请原谅我.
Scared of spinach? Here are some vitamin and mineral packed dark, leafy green alternatives:
- Swiss chard
- Baby bok-choy
- Collard greens
- Kale
- Turnip greens
Thanks NPR!
Data mining the world for anti-U.S. sentiments
The new software would allow much more rapid and comprehensive monitoring of the global news media, as the Homeland Security Department and, perhaps, intelligence agencies look “to identify common patterns from numerous sources of information which might be indicative of potential threats to the nation,”” a statement by the department said.
<snip>
The approach, called natural language processing, has been under development for decades. It is widely used to summarize basic facts in a text or to create abridged versions of articles.
But interpreting and rating expressions of opinion, without making too many errors, has been much more challenging, said Professor Cardie and Janyce M. Wiebe, an associate professor of computer science at the University of Pittsburgh. Their system would include a confidence rating for each “opinion” that it evaluates and would allow an official to refer quickly to the actual text that the computer indicates contains an intense anti- American statement.
Let’s hope that something like M-x spook on Emacs doesn’t render the $2.4 million system ineffective
Imagine an organization so secretive, the index and bibliographies of their internal publications were hidden from the public, for the last 40 to 50 years, until just recently.
Browsing through the PDFs, I’m surprised (and a little sad) to find topics about software engineering that may still be relevant today.
- Prototyping Man-Machine Interface to Facilitate Early Identification of Software Deficiencies - Winter 1986
- Structured Testing as a Learning Tool - Winter 1991
- Error Messages: The Importance of Good Design - Spring 1992
- Designing Secure Reliable Software -A Methodology - Fall 1976
- FUZZY: An Evolutionary Model for Data Structures - Summer 1979
- Software Maintenance -The Other Side of Acquisition - Summer 1978
- Software Maintenance: Putting Life Back into the Life Cycle - Winter 1987
- Work Breakdown Structure: A Better Implementation to Manage Software Overruns - Fall 1980
Some other topics relating to data mining and information retrieval.
- The Apparent Paradox of Bayes Factors - Winter 1965
- Full-Text Searching: Coming of Age - Fall 1989
- The Association Factor in Information Retrieval - Winter 1961
- Information Storage and Retrieval - Fall 1963
- The use of the B-Coefficient in Information Retrieval - Fall 1968
- Probabilities of Hypotheses and Kullback-Leibler Information-Statistics in Multinomial Samples - October 1956. (When creating decision trees, KL can be used to partition the datasets.)
- Reference Patterns for Nearest Neighbor Rule - Winter 1977
- So You Want to Correlate - Spring 1965
Looks like they also did book reviews.
-
Book Review: Structure and Interpretations of Computer Programs - Fall 1990
Precisely why big movie studios simply don’t get it.
So Jobs compromised just a bit: Most older movies will sell for $9.99. The price goes to $12.99 for certain Disney classics like Bambi and Cinderella, along with new movie pre-orders and new movies in the first week of availability. After that, the new movies will be $14.99.
The studios still hate that, because they think digital movie downloads should be priced higher than physical DVDs, even though there are no physical production, distribution or inventory costs. They should cost more, the reasoning goes, because of the added convenience to consumers.
Now, if I could just figure out how to rename my “tags” AND magically star all the older articles I’ve checked “Keep New” under that other popular blog reader.
Ironically, you can’t search the feeds you’re subscribed to. And, it doesn’t render correctly with Opera.
Update: Sometime in the future around 2009: Search is integrated and more than awesome. Reader still doesn’t work well under Opera.
A year late, but interesting since I’m currently taking a Data Mining course. According to the Sept 2005 edition of Nature, chimps and humans share 96 percent of the same genetic material.
Clint the chimp was the source of the DNA that scientists used to map the chimpanzee genome.
National Geographic: Chimps, Humans 96 Percent the Same. With a statistic like that, journals and articles should really make an effort to provide screenshots. I’m not talking about bar graphs or pie charts; I mean some sort of visual eye candy that makes me say “Oh sh*t, that does look like 96%.” Something like what Dr. Eamonn Keogh out of UC Riverside did with his work on visualizing the similarity of human and chimp DNA. Make sure to watch the video comparing human and chimp DNA.
The first article is a short tutorial on the Eclipse Modeling Framework (EMF) and the Graphical Modeling Framework (GMF). What is the EMF? From the EMF website, “EMF is a Java framework and code generation facility for building tools and other applications based on a structured model.” Let me paraphrase: EMF allows you to describe your object model in a neutral structure, the XML Metadata Interchange (XMI).
There are several ways you can generate/write this XML:
- XML-heads can create the XMI document directly, using a text editor
- Hard core UML OOA/D-_icts_ can generate XMI using tools like Rational Rose
- Java-heads can annotate Java interfaces with model properties
- Finally, if you’re writing an application that must read/write XML, you can use XML Schema to describe the model
Now why would you, Java Master/Mistress of the Universe, want to do any of this?
Because the EMF provides the foundation for interoperability between other EMF-based tools and applications. You can create a single model, in EMF, and your organization can develop several tools and applications based on that model. Since the majority of an Eclipse RCP application consists of Editors and Views, the advantage of EMF becomes obvious after you’ve developed your 15th Editor, and you begin to discover that there’s a significant amount of boilerplate code that each Editor needs, such as validation, listening to model changes, tracking model versions, etc.
This is where GMF gets exciting. From the GMF website, “GMF provides a generative component and runtime infrastructure for developing graphical editors based on EMF.” Let me paraphrase: GMF takes your model (generated in EMF) and transforms it into a full-blown graphical editor. Both EMF and GMF are projects under development and hosted at the Eclipse Foundation.
Learn Eclipse GMF in 15 minutes
The second article is about how to draw custom Table and TreeItems. If you’re getting started with Eclipse RCP, and you had to pick one component to learn masterfully, I would highly recommend the SWT Table–as well as the JFace TableViewer, TreeViewer, and TableTreeViewer components. As I mentioned before, the recent release of Eclipse Rich Client Platform 3.2 offers significant improvements to the Table component, that this article describes very well.
Custom Drawing Table and Tree Items.
Finally, the third Eclipse link is to the eRCP, where the “e” stands for embedded. From the eRCP website, “the intent of the eRCP project is to extend the Eclipse Rich Client Platform (RCP) to embedded devices.” This release provides support for the Nokia Series 80 and the Windows Mobile 2003/5 mobile platforms. Why is this important? Two observations:
- Last year, Nokia, outshipped the entire PC industry by a factor of close to three, delivering 153 million mobile phones to consumers. Almost all almost all those devices ship with a version of the Java ME. [Source: Altima, Future of Mobile Java].
- Today, there are around 50 device makers churning out Windows Mobile devices, such as Cingular 8125, T-Mobile’s SDA and MDA, Treo 700, HP’s new line-up, the Motorola Q, and the new Samsung i320 [Source: GigaOm, Revenge of Windows Mobile]
According to the Center for Science in the Public Interest, a nutritional advocacy group, the Starbucks Frappuccino is equivalent in calories to a McDonald’s coffee plus 11 of their creamers and 29 packets of sugar
Imagining later today:
Hi, Could I get a Quad Ristretto, Venti, 1/2 Breve, 1/2 Organic, Decaf, Upside Down, Double Blended Frappuccino with Caramel Sauce, Extra Ice, and Whipped Cream.
You know, I better make that sugar-free and non-fat instead.
Priceless
Happy Days is my favorite theme song I could sure kick your butt in a game of ping pong I’ll ace any trivia quiz you bring on I’m fluent in JavaScript as well as Klingon
Check out the video on YouTube: Weird Al Yankovic’s White and Nerdy. Finally, since it was obviously the first question on your mind, the physics equation seen throughout the video is the time-independent form of the Schrödinger wave equation.
An attacker who gets physical access to a Security Analysis of the Diebold AccuVote-TS Voting machine or its removable memory card for as little as one minute could install malicious code; malicious code on a machine could steal votes undetectably, modifying all records, logs, and counters to be consistent with the fraudulent vote count it creates. An attacker could also create malicious code that spreads automatically and silently from machine to machine during normal election activities — a voting-machine virus.
The latest findings on Diebold’s voting machine isn’t pretty. Physical access to a machine is all it takes to inject vote stealing code: the lock to side door containing the memory card can be picked, and the memory card can be replaced with evil code which can be loaded in the system. Check out the full research paper and the video demonstrating an attack.
Is it possible for an energy company to advocate power conversation in the household? A brochure from SRP sure makes me think so.
- Every degree you raise your thermostat saves you approximately 2-3% on cooling costs. Crush your energy bill by installing a programmable thermostat. Set it between 78°F (23.8°C) and 80°F (26.6°C) degrees when home and 85°F (29.4°C) or higher when away. Use a ceiling fan if possible.
- Keep it cool with electric bills. Place sun screens over windows and save on air-conditioning. Shaded windows can save up to 25% of the cost of air-conditioning, when compared to unshaded windows.
- Run your dryer during morning or late evening to avoid adding heat to your home when it’s warmest out. Keep it cool. Dry clothes during the cooler part of the day.
- Nearly 90% of energy used to wash clothes goes to heat water. Defeat the enemy of inefficiency in laundry. Wash in cold water when possible. BONUS: Your clothes don’t shrink.
- Compact fluorescent bulbs use 75% less energy and last up to 10 times longer. Don’t be lured in by energy-wasting glow of incandescent light. Use compact fluorescent bulbs. Ikea sells bulbs that require fewer watts but provide just as bright light
Just doing my part to reduce my daily energy consumption.
A friend of mine recently wrote about his experience with the free online file storage service, Box.net. I admit I wasn’t surprised to hear about his less than stellar experience, as I ran into several situations where the Box.net crew left me wondering if they were actually serious about running their company.
I have a similar list of issues, but not from the perspective of a user, but as a developer of their public API.
Flashback to February, Aaron contacted me with a request to do a review on the relaunch of Box.net. I really didn’t want to write a review, but I wanted to do something useful for them, so when I noticed they had a developer API, I decided to do them a favor and provide an implementation in Java. It started out easy enough; a very simple REST API–you send HTTP, they send XML.
Fast forward a few months, several emails, and no results later, the list of problems with their API had grown, or perhaps I had just discovered all of them. Since sending email to them doesn’t seem to have any positive effect, I thought it would be nice if I provided issue tracking services by listing the bugs (and gripes) I have with their API. So, in no particular order:
- None of the developers hang out on the chat room anymore.
- The documentation is terrible; there are values that aren’t documented, and there are results that aren’t even mentioned.
- There is an error on line 141 of /var/www/box/mod_Account_Upload.php
- File uploads don’t work if the file already exists. In addition, the response doesn’t indicate a failure.
- If the request is incorrectly constructed, a PHP fatal error occurs. An XML response with details on what I missed would be helpful.
- Of course, you couldn’t prove any of this since the API documentation page is password protected and requests for access fall on deaf ears.
The last bullet point really made my day. All of a sudden and without warning, the page–you know the one documenting the publicly available API–became private.
Now, if you’re reading this, you might be asking yourself: “Jeez, why is this guy making such a big deal about a bad API?” You know what, in the grand scheme of things, it probably isn’t. In fact, by tomorrow, I will likely forget what I wrote for bullet point 4. But then again, the same guys running the company wrote the API… the buggy, undocumented, and closed API.
Getting started with a new framework is not an easy task, especially if it’s a UI toolkit such as Eclipse’s SWT. One way, I’ve found, that works with me is to peruse snippets of code that get straight to the point. The org.eclipse.swt.snippets project in the Eclipse CVS repository does just that. The project, which can be checked out via Eclipse, is an excellent illustration of techniques and UI widgets available to an SWT developer. I highly suggest you check out the project and run each snippet. Ok, maybe not each snippet, but you should definitely spend some time browsing them.
For instance, Snippet231 illustrates an SWT Table with multi-line columns. Before Eclipse 3.2, a third party SWT library had to be used to emulate that functionality.
To check out the Snippets project from Eclipse
-
File > New > Project
-
CVS > Projects from CVS
-
Create a new respository location with the following information
$CVSROOT=:pserver:anonymous@dev.eclipse.org:/home/eclipse
-
Or just enter the following details
Viola, you should be playing around with SWT snippets in no time. Visit SWT Snippets for more information.
I remember watching this video as a child and having my thoughts instantly occupied with dreams of science and discovery.
I still feel the same way today. BTW, there’s a kiosk at the Skydeck atop the Sears Tower in Chicago with the same video.
An interesting comparison between voter turnout for the 2006 American Idol Finale and the 2004 U.S. Presidential election.
Source: ZabaSearch
Update: Looks like the Huffington Post agrees: Hicks Wins Idol After “63.4M Votes Were Cast This Season”…More Than Any US President In History Has Received…
This past Tuesday (5/23) I attended an ATW meeting where I got to hear Bob Parsons speak about the secrets to his success: luck and perspective. This was the first time that I had met Bob Parsons but I read his blog frequently and listen to his podcast occasionally, so I had a pretty good idea of what to expect. As it turns out, I was mostly familiar with his story, but it was still a huge pleasure to hear him speak. From the perspective of a software engineer, here’s what I got out of the talk:
- His companies were started from scratch and with no investors. As of today, he is still GoDaddy’s single and only investor.
- He is definitely a nerd. He taught himself BASIC on a short flight and wrote software to do everything he needed.
- Perspective is knowing how to think about a problem; doing this will allow you to be in control of the problem.
- Luck.. is just that, luck. But he also took risk, broke rules, and worked incredibly hard.
- Borrowed $5k to buy an IBM/PC when they first came out.
- MoneyCounts was priced at $99, then $69, and finally $12 before it finally made a ton of sales.
- MoneyCounts had a 5.5 day release cycle.
- Today, GoDaddy has over 30 software development teams.
- Intelligence has nothing to do with business success.
Bob also took a moment to share his 16 rules of survival. I’m listing it here, even though you can read it over at his blog.
- Get and stay out of your comfort zone.
- Never give up, if it were easy, everybody would be doing it.
- When you’re ready to quit, you’re probably a lot closer than you think. The temptation to quit is greatest when you’re just about to succeed.
- Make it a point to accept the worst thing that could happen to you. Very seldom will the worst consequence be anywhere near as bad as a cloud of “undefined consequences.”
- Focus on what you want to have happen. If you dream it, it will happen.
- Take things one day at a time
- Always be moving forward. Remember the Japanese concept of Kaizen: Small daily improvements eventually result in huge advantages.
- Be quick to decide.
- Measure everything of significance. If you measure it, it will improve.
- Anything not managed, will deteriorate.
- Pay attention to your competition, but pay closer attention to what you’re doing.
- Don’t get pushed around.
- Life is not fair.
- Solve your own problems. Don’t follow others.
- Don’t take yourself seriously. We’re usually in less control than we think; Luck plays a bigger role.
- Always have a reason to smile- Find it. “We’re not here for a long time; we’re here for a good time.”
Thanks Bob!
Today, Google announced their new Chinese new name, 谷歌.
At long last, the Chinese names for the GYM triumvirate is finally complete:
Google - 谷歌 - gǔ gē - Valley Song
Yahoo! - 雅虎 - yǎ hǔ - Elegant Tiger
Microsoft - 微软 - wéi ruǎn - Small & Flexible
Valley Song is a song by Jars of Clay.
Incidentally, Elegant Tiger is the nick name of a character from the chinese xiao shuo, Water Margin. In the story, Elegant Tiger, or Yan Shun, is known for his strength.
Thanks, Eden for the great CE dictionary.
In less than 24 hours, hundreds of thousands of people will be gathering across every metropolitan city across the United States to protest the Border Protection, Antiterrorism, and Illegal Immigration Control Act of 2005 (H.R. 4437).
Every year, thousands of immigrants from Mexico and South America come to the United States to seek a better opportunity for themselves and their families. They take up jobs that most Americans won’t perform and do it outrageously low wages. H.R. 4437 is going to make it a crime for illegal immigrants to be in the United States. It also places a set of broad powers in the hands of the Department of Homeland Security to take sweeping actions without any checks and balances.
You should check out this thoughtful piece by danah boyd on why she opposes h.r. 4437.
Writing a good API is not an easy task. Like any other piece of software, you need time to talk about requirements, get some design going on a whiteboard, and do lots and lots of testing. If you work hard, at the end of the day, you’ll have another component to add to your arsenal of software, which you’ll be glad to have when you run into a similar problem down the road. I’ve learned some good and bad things about API design, mostly by practice (read: making mistakes) so I thought share some thoughts about what I think makes a good API. If there’s a flaw or a gaping void, please leave a comment, as I’d like to hear your thoughts on the subject.
- Be Focused. You’ve got to focus on the problem. To do this well, you must do two things. First, you have to dig for those requirements. They aren’t going to come to you, so you have to go after them, which leads me to the second point. Speak with your intended audience. Become intimate with the problems they are trying to solve. Bounce ideas off each other and listen to feedback.
- Document. Be fanatical about documentation. Document everything from HTML-friendly Javadoc at the method, class, and interface level, to suggested working examples of how your API should be used in your project’s homepage, release notes, and/or blog. Document exceptions, parameters, constructors, and packages (overview.html). Tossing in an image of the “big picture” won’t hurt. Document intention, as it’s far more valuable to know what the programmer intended. Don’t just duplicate your source code in the documentation, otherwise you’re just repeating yourself and you run the risk of having the documentation drift out of sync with the source code.
- Be Intuitive and Simple. Did you read the previous point? Did you document every iota of your API inside and out? Do you even have a blog that you use to post advice on how to best use your API? Great. By the way, nobody is going to read it, well not at the very beginning anyway. You have to apply the “don’t make me think” approach to your API. It’s like a really well polished UI that requires very little training and is easy to pick up. If you make it intuitive to use, people will get a good impression with it from the start. Similarly, you need to get that initial positive reaction to your API and one way to do this is by making it intuitive to use, even without documentation. Things are intuitive if they fit into a person’s mental model. Keep things simple and people will love you for it.
- Ask (Hard) Questions. Should this API support generics? The
enumtype instead of aStringobject? Should my factories be singleton objects lying around in memory forever? Should I return null, throw an (unchecked or checked) exception, or return an empty, non-null array of zero length? How much boilerplate code should I place in an abstract class? Will this be thread-safe? Immutable and reusable? between n-threads? Should I load all limited resources up front and manage them in a pool or a lazily initialize them? The answers will vary slightly by kind of API you’re developing and the requirements you have, but make sure you ask them. - Use Interfaces. In your API, always make the type as generalized as possible. If you use
Mapinstead ofHashtableyou insulate yourself against future changes to the choice ofMapimplementations. Similarly, your Super XML/REST parser should accept anIXmlParserinstead of aConcreteDomXmlParseror aConcreteSaxXmlParser; let your users decide which strategy to use. Now, don’t go refactoring every method in every class you have out to an interface. Figure out what can be reused and remember to keep details of how an implementation works to a minimum. - Eat your own dog food. That’s right, you wrote an API, now write a program that uses the API. Better yet, write three. If you’re writing an API that manipulates images, write a quick desktop app that can return the image as an SVG, or a web app that returns it as a JPG. Or better yet, do both. An API should be about how the user thinks, eating your own dog food forces you to do this. If you’re releasing an XML/RESTful API, pick a language and write an XML-to-Object parser and maybe even an Object-to-XML parser. By doing this, you’ll find out just how easy it is to parse your own XML, or figure out that a service is returning too much XML, or if there are too many inconsistencies, etc. Remember, your APIs first user will be your test cases. Write them early and assert everything. If you find your API too cumbersome to use or too complicated to test, you may want to rethink some decisions. Refactoring makes this process trivial.
- Minimize visibility. Dealing with visibility is a tricky issue. On one hand you don’t want to make everything private since it may conflict with the reusability or extendability factors of your API, but on the other you don’t want users of your API doing things that they shouldn’t be doing. The argument can be made either to make everything
protectedto maximize reusability or to minimize visibility and increase scope later, if the need arises. I take the latter, though I’ve heard good reasons for the former. Either way, you’re going to have to document those reasons; if a class or a method is not meant to subclassed, specialized, or overridden kindly mention why. Always deliberately pay attention to the scope your methods and variables have. - Have a friendly license. Choose a license that deliberately communicates your intent. If you want to be friendly to businesses, make sure you find a license that let’s developers take your API, build something cool on top of it, and not have to worry about any legal repercussions. If you want to enforce the rule that all software built on top of your API is to be freely available, there are licenses for that too. Either way, you’ll want to make sure your intent is clearly communicated.
- Grow. Finally, if you’ve decided to release your software to the public, thank you. Doing this is no easy task, especially if you have something that people really want to use. This final point is meant to highlight the relationship you’re going to have with the community. Make sure you a process (forum, blog, newsgroup, defect tracker, wiki, etc) that let’s you listen and respond to the feedback of your users. Just like any social software community (frameworks like JSF, platforms like Eclipse, OSes like Linux) you have to listen to your users, tweak and retweak the API so that it can grow. Be careful not to go feature crazy, otherwise you’ll swamp yourself with work, violate the principle of simplicity, go outside the bounds of your original problem, and end up with something completely unmanageable.
These are just a few heuristics I’ve found work best for me. You shouldn’t blatantly violate them, but you also shouldn’t follow them blindly. You’re going to find that achieving API nirvana is next to impossible, but you should try anyway.
Updated a few hours later: Wrote closing statement & fixed grammar.
”..kena pay all the time, bankrupt all my money”. Pulling up a satellite view of Singapore using Google Maps brought back some good memories.
Although I haven’t been back in about 12 years, I still remember good things about her.
- Cuisine. I could talk for hours about what I remembered. Newton Hawker Centre, Cuppage Centre, Adams Road Hawker Centre, Indian food, Chinese food… It just doesn’t stop. You can’t claim to be a food lover, and not have been to Singapore. Satay, kuay tieu, roti, pratha, curry, dim sum, nasi goreng, laksa, durian.
- MRT (SMRT). Awesome public transportation. I remember taking Somerset to Yishun to watch movies at the Yishun 10 Cineplex.
- Singlish. Add one part tamil, one part malay, one part english, and one part chinese and you’ve got an local slang that you either love or hate. I haven’t practiced in years though, so I’ve completely forgotten how to speak it. :(
- Soccer. Two words, Fandi Ahmad. Boo ya ka shaw.
- Nightlife. Not just clubbing, but in general places don’t close at 1 or 2am like they do here in Phoenix. I’ve heard the nightlife is amazing, but I was too young to be interested.
- Orchard Road, Centerpoint, Yishun 10, Jurong Bird Park, Haw Par Villa, Botanical Gardens, Far East Plaza, Lucky Plaza, even Changi Airport were fun places to visit as a kid.
- Chinese New Year. Especially festive with my family
- Malaysia. There’s not much I remember about Johor Baharu or Penang, other than cheap movies, eating a lot, and the Golden Sands Hotel.
I’ll have to write about a list of things I don’t miss about Singapore. Oh, and that lyric was by a local Singaporean band (at the time, >10 years ago) called the Kopykat Klan that doesn’t seem to be around anymore.
Updated Mar 8 2006: Ran spell check on “Johor Baharu”
“Technology gives you a chance at marketing.” What an unsual, mind twisting, nail biting, nerve wracking, unpossible new idea for a software engineer like myself to comprehend–I freaking love it. See Seth Speak
It’s been a pretty crazy day (not being) at DEMO 2006. (Not actually) Going to this event has taught me a lot about what makes a great demo. Here is the remaining review of the companies and their services or products:
- mypeople: Looks like an unlimited coast-to-coast cell phone service plus a personal concierge service for cell phones. Reminder calls, wakeup calls, sport scores, etc.
- Eqo communications: Here’s the use case: Someone calls you on Skype (PC). EQO’ installed software routes the call to your handset, all this without high-speed wireless or being on a 3G network.
- Zink kat: Chili, according to their webpage, really doesn’t look like anything. It looks like a box, and I think music is involved. According to TJ and Jeff’s page, it looks voice activated, and it plays more music than you can chuck a stick at.
- Transparensee: It looks like another discovery/recommendation engine. Understanding relationships between items is complicated. Take restaurants for instance. It’s easy to recommend restaurants based on genres, or cars based on specifications, but what about dating? Hair color–brunette, eyes–brown, height–5’ 6”, ok, and what about chemistry? How do you recommend chemistry?
- Nexidia: Audio mining; speech analytics; NLP. Freaking Cool!
- Kosmix: I’ve also been hearing a bit of buzz about Kosmix’s subject- oriented search engine. For now, the three subjects are health, travel, and politics. I hope to see more subjects like real estate, or automobile repair, or even a legal search (sort of like Westlaw).
- Truveo: Video search. It’s like YouTube or Google Video without the community, the videos, or the remotely accurate search engine.
- Panoratio Database Image: A technology spun off by Siemens. Put confusingly, it’s a tool that can reduce the size of the result set without losing any details. I’d like to hear what sort of mathamagical compression algorithms they are using since it sounds too impressive.
- Zimini: Ok, so I have an idea: I’m going to write this program that people will download. They can then submit their personal information (providing us as much as they want, of course) and in return we’ll give them coupons. Right!
- Sproutit: It seems like an email management service for small businesses. It reminds me of Basecamp or Salesforce.com. I have to admit, I didn’t know there was a demand for outsourced email management.
- Eeminder: No, not reminding, eeminding. They push “reminders” to your cell phone. I can’t even pretend to be excited about technology like this.
- Iotum: Looks like a highly configurable rules engine that can route incoming office calls to IM, email, your calendar, your companie’s bluetooth enabled toaster, etc, etc. I guess this is perfect for the kind of person that get’s a ton of calls. To do all this, the software taps into your company’s IP-PBX. Sounds neat.
- Open Connect: Old and busted: “Mainframes and green screen” New hotness: “Web-based UIs and web services”. soaComprehends takes your mainframe interactions and builds a custom web-application that optimizes your user mainframe interactions. If you know what all of that means, I feel truly sad for you.
- Sharpcast: Transparently share photos between your PC and your phone. I guess this would rock if your phone has a lot of memory and a nice screen.
- LocaModa: I text message a phone number, and the message appears on a medium. (See live example).
- BroadRampCDS: “BroadRamp CDS™ Content Delivery System is the world’s first multimedia content delivery system that delivers a broad spectrum of media by converting existing content into online interactive multimedia.” Let me translate: “Broad spectrum” = AVI, MPEG, DIVX, XVID. “Online interactive multimedia” = “Flash, whatever the latest version is”.
- Vizrea: Looks like another cell phone photo management service. Looks like they are exclusively running on Nokia phones.
- Smilebox: An online scrapbook service. I hope it’s simple enough to use. My gut feeling tells me that it sounds like the sort of software that should run on the desktop, as opposed to on the web.
- Newsgator: I like where Newsgator is going: feed ubiquity. They released a Hosted Solution service.
- VividSky: “Have you ever found yourself sitting at a sporting event with your attention away from the action only to hear the roar of the crowd?” No, not really. I suppose if you were to put wireless access points in football stadiums, accessing unlimited game content was the next logical thing to do. I’d like to see a real fan do this. Let me put my beer down, shove my popcorn under my left armpit, lick my fingers clean, whip out the latest Treo 700w, and "access" that content.. Meanwhile, the play is being shown over and over again on 10 of the 50 ginormous overhead projectors, and my buddy is screaming at me for spilling the beer. Right.
- Simplefeed: I wish the website cut down on the ROI talk, and focused on getting me signed up. From the “About” page, it looks like an RSS manager (like Feedburner), except that there doesn’t seem to be any possible way to signup.
- Azos AI: Looks like two products which convert your phone into SUPER CRISIS PHONE during an emergency.
- StrikeForce: “WebSecure’s breakthrough technology proactively stops keylogging programs by encrypting keystrokes at the keyboard level and rerouting them directly to your browser.” Cute. My beef: it works only under Internet Explorer; it’s a bandaid covering the real problem–that you have a keylogger; and if someone really wanted your keystrokes, they could tap into the browser and read every FORM input field on the webpage. Quite a false sense of security
- MI5: A rack mountable unit capable of detecting spyware traffic, spyware in webpages, spyware in “phone home” applications, spyware infections, and pretty much any sort of malware in your enterprise. It sounds incredibly comprehensive. I’d like to see it in action.
- Astav: Fraud protection. Can’t really tell from the website. Apparently it’s a password-replacement technology. Not sure how it’s integrated with existing systems.
- PayWi: Not to be confused with Pei Wei, Pay Wi let’s you pay bills, transfer money, purchase stuff online with your cell phone. Doesn’t the rest of the world do this already?
- Pay By Touch: No need for credit cards or checkbooks, or cash, now you can pay with your thumbprint.
- Shimon Systems: No need for passwords, now you can login to wireless network with your thumbprint.
- Cesura: Uptime management services. You get a page or a text message if your system is down.
- Fortify Software: Fortify Application Defense appears to be a J2EE application protection tool that guards code by injecting extra boundary checks at the bytecode level. The demo looks like it manipulates the bytecode of your deployed WAR file. Just a couple of things <puts on Java hat>: that application was pretty terribly written to begin with. 1) Strings should be sanitized and escaped before being placed in an SQL statement (or just use a PreparedStatement) 2) Never let your servlet container display stack traces. Always redirect the user to a friendly 404 page.
- IronPort: From TJ: “[T]heir newest product today scans all inbound web traffic and gives all of them a reputation ranking. Only traffic with a certain ranking goes through. So basically it is a spam filter not just for your inbox but for your whole network working with 1GigBit/s.” Cool!
Well that’s all folks. For a real account of what happened at this year’s DEMO 2006, please visit TJ or Jeff.
DEMO 2006: If I were attending this year’s DEMO conference, this is a review of my first day might look like:
- Moobella: It’s an entire ice-cream factory on the go. If you’ve always wondered what a twinkie ice-cream would taste like, Moobella answers that question. My (tasty) suggestion: Apply some sort of collaborative filtering technique on flavors.
- Blurb: Blurb let’s you convert your digital content into a paperback. If you’re a blogger, a digital scrapbooker, or that guy with a ton of grandma’s old recipes, and you want to produce a book from your writings, then you should check out Blurb.
- Bones in Motion: Think of software that tracks your location through your cell phone. The flagship product appears to be a piece of software that tracks your outdoor fitness achievements via the cell phone/GPS. The idea itself doesn’t sound terrible exciting (since I eat Krispe Kreme and Twinkies for breakfast), but the underlying technology fascinates me. Developing an application that runs on multiple cell phone platforms AND provides location- based services via GPS–now that’s cool!
- MP3Car: Commoditized Car PC parts.
- Digismart: You know that scene in Star Wars where R2D2 projects a 3D animation of Princess Leia? It looks like these guys are stepping in that direction. Digismart let’s you project your image from handheld devices on to a wall about three feet away.
- Accomplice: I hope the world is ready for yet another To-Do list application.
- Grassroots Software: I couldn’t really find out too much about this product, but I guess if non-linear presentation software AND taking on Microsoft head first is your thing.
- Network Streaming: Ok, let me sum these guys up. 1) Download Joel Spolsky’s Aardvark specification 2) Implement said specification (smart summer interns optional) 3) Prof^H^H^H^H DEMO 2006.
- Peppercon: KVM-over-IP? In 2006?
- TinyPictures: Tiny niche. I hope they do something 100x more awesome than TextAmerica and Flickr.
- Ugobe: “We develop and market revolutionary robotic technology that transforms inanimate objects into lifelike creatures exhibiting stunning, organic movement and dynamic behaviors.” It’s Furby 2.0.
- Zingee: Share files. Great idea, but I’m biased since I did something like this back in college. One small problem, the Windows client relies on the NET 1.1 Framework. Well two problems really: 1) Where are the Mac and Linux clients? 2) Users have to download the .NET Framework 1.1. If you really want wide adoption, may I suggest using MFC or WTL. Maybe even consider wxWidgets for those cross platform needs.
- Garageband: It looks like some sort of socialized rating system for music. I wonder what they’re doing differently than Pandora or Yahoo! Launch.
- Multiverse: A small step towards the commoditization of the World of Warcraft, Second Life, and all those other incredibly addicting MMORPGs.
- GuardID: A secure USB keychain for computer passwords. Appears to work only on Microsoft Windows.
- biggerBoat: “The Internet’s most comprehensive, entertainment industry-specific search engine delivering cross-category, cross-format, and cross-retailer search results to online entertainment consumers. We currently provide music and movie results to our partners, with television, video games, and books coming soon.”Sounds like something Amazon’s obidos engine can handle.
- Gravee: A community powered search engine. Not a bad idea. When they do achieve some sort of critical mass, I wonder if results could potentially be skewable by the community. Results are taggable (finally, an adult-themed tag-cloud) and there’s even a specialized blog search.
- Polyvision: An electronic virtual whiteboard. I want to replace the whiteboards, currently covering the walls of my company, with this technology. There is definitely a need for more tools that let virtual teams work together.
- VSee: If you think video conferencing software sucks, then chances are you’re not using Apple’s iChat, which is just as well since the VSee demo appears to be Windows-only.
- Kaboodle: Hmmm, social shopping? I personally take recommendations from friends and specialty review sites. With the guerilla marketing tactics I’ve been reading about lately, it’s even more important to me that recommendations can have some degree of trust associated with it. I’m not sure how Kaboodle handles this.
- Plum: Collect, Share, and Discover content. Cool! Sounds a little like Google Base.
- RawSugar: Sharing knowledge is good. The site goes down randomly, so I couldn’t figure it out
- Riya: I remember hearing about this idea a few months ago. It’s basically one of the first facial recognition web applications. I wish they would team up with Facebook or Orkut or Picasa to do something cool.
- Tagworld: If MySpace is ghetto by design, then maybe Tagworld is the opposite.
- Miaplaza: Social recommendations? You’re kidding, right?
- Krugle: Search engine for publiclly available source code. 1) I wonder if I can search for examples of specific design patterns 2) Screenshots primarily list Java, can I search for a hash map implementation in Scheme? 3) If krugle searches mailing lists, how does it tell if the code is a “good” or a “bad” example? 4) Can I annotate and mark up code?
- Jitterbit: Looks like a really amazing web services management tool. From what I can tell, you can control (through their downloadable client) a ton of web service APIs from Amazon, eBay, Google, Eventful, etc. The tool lets you make XML (SOAP/REST) requests to the various web services and displays the results immediately. From the screenshot, it looks like you can schedule calls, perform XSL transformations, and mashup results from different services. I hope results are persistable to a database. Written in Java (NetBeans RCP?), so it’ll run on everything.
- IPSwap: Think Craigslist or eBay for intellectual property. Definitely by developers, for developers.
- Loglogic: Looks like a Log analyzing engine for all sorts of logs. HTTP, SSH, Samba, FTP, Proxy, SMTP, etc. Works on Unix and Windows environments
- Persystent Technologies: Virii, worms, registry malfunctions, deleting key files are no longer the problem when you can restore the system to a previous state with very little intervention from IT or NetworkStreaming.
- Avokia: It looks like a high availability solution for “The Enterprise(TM)”. They appear to take the “We scale everything horizontally” approach.
- Extricom: According to the press release, it looks like they released a wireless LAN product that boosts channel capacity three-fold. In other words, more internets for everyone.
- iGuitar: A simple USB adapter that connects your guitar to your PC or Mac, allowing you to capture music on your companyer. Very cool.
So that wraps up my first fake day at DEMO 2006. For real and actual coverage, check out TJ’s Day 1 coverage here and here, as well as Jeff’s Day 1 coverage.
Dear DEMO 2006: I need a feed. I want minute-by-minute coverage of the actual demos. I need a website that doesn’t behave badly under Firefox. And while I’m up here, why are you advertising for DEMOfall 2006 already? You’re not even done with DEMOnow?
<falls off slippery box> I can’t seem to find that much live coverage of DEMO 2006. I found a pretty good write up at TJ’s Weblog here and here. I also managed to find a complete list at the DEMO.com website. From what I can grep, it looks as though this year’s underlying theme is all about providing services with a more human touch (the technorati call this, “Web 2.0”). Lots of old ideas look like they’ve come back with a vengeance and an emphasis on being more specialized, personalized, and socialized.
Simplicity. Take a moment out of your software writing, caffeine inducing, image photoshopping, animation authoring, interaction designing day and remember that technology should be making our lives less complicated.
The ability to simplify means to eliminate the unnecessary so that the necessary may speak.
–Hans Hofmann, Introduction to the Bootstrap, 1993
A well-designed and humane interface does not need to be split into beginner and expert subsystems.
–Jef Raskin, The Humane Interface: New Directions for Designing Interactive Systems
Simple things should be simple and complex things should be possible.
–Alan Kay, Disney Fellow and VP of R&s;D, The Walt Disney Company.
Simplicity is the ultimate sophistication.
–Leonardo Da Vinci
Things should be made as simple as possible, but not simpler.
–Albert Einstein
It is simplicity that is difficult to make.
–Bertholdt Brecht
Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius - and a lot of courage - to move in the opposite direction.
–E.F. Schumacker
Life is really simple, but we insist on making it complicated.
–Confucius
To my friends, colleagues, and family, may you have a Happy and prosperous new year filled with good fortune.
This Chinese new year (春节 - chūn jié) falls on a Sunday the 29th of January and is also known as the Year of the Dog. Chinese new year (or “The Spring Festival”) marks the first day of the lunar new year. It ends 15 days later on the second full moon of the lunar new year also called “The Lantern Festival”)
In case you’re feeling left out, I’ve come up with a short list of things you can do to make your Chinese new year more enjoyable.
- Learn to offer seasonal greetings in Mandarin. Practice saying 恭喜发财 (gōng xǐ fā cái), which means “Wishing you a prosperous new year.” 新年快乐 (xīn nián kuài lè), which means “Happy New Year.” And my personal favorite: 国际化软件不容易 (gúo jì huà ruǎn jiàn bù róng yì), which means “Software internationalization is non-trivial.”
- Eat a lot. In Mandarin, the Lantern Festival is written 元宵节 (yuán xiāo jié). Yuanxiao phonetically sounds like 圆宵, which literally means “round overnight.” You see, during this week, massive amounts of sweet or meat filled dumplings are consumed by about 3 billion people.
- Chinatown. Head down to your local Chinatown and partake in the festivals. Celebrations go on for not just 1, not just 8, but 15 days. FIFTEEN.
And of course, in the spirit of maintaining balance, here are three things you shouldn’t do on Chinese new year.
- Do not get a Chinese tattoo. Because showing off your new tattoo that’s above your ass, to your asian friends, really isn’t that spiritual, especially if it says “Beef and Broccoli.”
- Do not wear black. Black clothes signify bad fortune. Instead, wear something red or gold which signifiy happiness and good luck.
- Do not buy a chihuahua and walk around like Paris Hilton. Ok, I was really going to finish up with “Don’t clean your house.” Sweeping your house during this time is considered the equivalent of sweeping away your good luck.
平安顺心 (píng ān shùn xīn) - Be safe and well
Jeremy’s entry about his first web server brought back fond memories of my own web server that I ran during my college years just over 5 (golly) years ago.
It was a Pentium 3, 256MB, 20GB running FreeBSD 4.x off a Qwest 256Kb/s downstream connection. In a time before blogs, Gandalf.MarcChung.com was a convenient way for my friends to run their personal websites and for myself to learn UNIX. I was webmaster, sysadmin, and customer support rep all rolled into one. One day I’d be fixing a friend’s HTML, and the next I was using setting up Apache+SSL, MySQL, and PHP using the usr/ports system.
Some websites I ran (that are still up today) are Cork, AwareLabs, Artique.ro, Vivin.net, and my personal website. My college roommate (chapter president of the ASU BMES club) also ran his club’s website on Gandalf. Later, as chapter president (but of the ACM), I also ran the ASU ACM website. It was eventually moved over to ASU’s campus and eventually lost in the great sea of red tape.
For “fun”, I wrote a personal information manager in PHP that kept track of my daily To-Do items, managed my online writings/rants/diary, and even let me upload and download files between school and home.
Like Jeremy, this experience also led to my first “web programming” job at a Startup 1.0 during my time at ASU.
I maintained Gandalf, until the terrible hard disk crash of 2003, just after graduation, and fortunately just after I setup my last “client” with a Real Webhosting Company (TM). These days, Gandalf sits quietly in my storage closet slowly gathering dust and dreaming of a day where it will one day run another startup. Or at least prototype one.
恭喜发财.
In less than week, it will be the year 4703, the Year of the Dog. Before 4702, the Year of the Properous Cock (Rooster) is over, I’m going to take second to summarize my year.
January:
- I got a great new job writing desktop applications for a software company.
- Visited Seattle.
February:
- How hard is it to buy a house?
- Knights of the Old Republic II consumes me
- Rotaracter
- Igniter
March:
- Dayong’s Power Hour
- Reconnecting with old high school and college friends
- Dear EVDB: Please make me a beta tester
- Boxing
April:
- I think I should start up MarcChung.com again
- Viva il Papa!
- 1 GB of memory should be enough for anybody
- Ruby… on Rails?
- Walking to End Violence
May:
- Four words: World of Fracking Warcraft
- Happy Birthday
June
- Buying a house is a non-trivial activity
- Who is the Phantom of the Opera?
July
- Eve: The Exciting Venues and Events Browser
- The Shuttle is grounded
August
- Intelligent Design, Church of Pastafarianism.. so many religions, so little time
- I BOUGHT A CONDO
September
- Went to Chicago
- Googlewhacking
- “Brownie, you’re doing a heck of a job.” –President Bush after Hurricane Katrina devastated New Orleans
October
- XBox 360
- Playstation 3
- Nintendo Revolution
November
- Me gusta Ubuntu
- Preparing for GRE
- Sony almost fracks me with a rootkit
- Happy Thanksgiving
December
- Merry Christmas
- Vivin goes to Iraq
- Pablo Francisco talks about chicken pot pie.
- Mommy, what’s a Jellicle Cat?
With two years of full time professional employment under my belt, two of the most important things I’ve learnt so far don’t even have anything to do with my software engineering background.
The first was by a former software engineering professor of mine at ASU.
Be tactful. I hear stories from industry about a new kid right out of college attending his or her first meeting and they would just start shouting out their thoughts on how this and that design should be. Don’t Do That.
And the second was by one of my former boss’ at Thomson Financial:
Never make your boss look bad.
Every once in a while, I’ll read or hear about a piece of advise that on some personal or professional level, I believe in. When I find one, I reach for the closest pen and paper and write them down. Inspired by 37signals manifesto, I started placing my writings in my personal manifesto.
Feel free to share your thoughts.
I am the guy that comes up with the ‘idea’. For the longest time, to me, the words ‘entrepreneur’ and ‘idea’ went hand in hand. I’d think to myself, “Wow, I have such great ideas, I’m such a great entrepreneur.” Sometime during my sophomore year, I learnt that being an entrepreneur wasn’t about having ideas.
You need a business model, the skills to bring the idea to life, and the discipline to execute it all.
Entrepreneurs aren’t idea people, everybody and their brother has ideas. Entrepreneurs are people that exploit ideas by matching them to market needs, executing them despite scarce resources and designing a business model that makes the idea profitable.
… I popped my Googlewhack cherry. Too bad I can’t actually tell you what it is (I hope I’m not violating some GoogleWhack TOS).
Update: The phrase was “Ultrasophisticated briton” and ceased being a Googlewhack sometime in 2007. Here’s the full copy I wrote when Googlewhack came to Phoenix:
The following is a transcript of a spoken essay available at KJZZ.org.
This is KJZZ’s morning edition, I’m Dennis Lambert. This morning, an East Valley teacher speaks out against two recent decisions to water down AIMS test standards. One was the State Board of Education’s decision to lower passing scores for the AIMS test. The other, the State Legislature’s decision to allow students to use course work on core courses and other factors to supplement their AIMS test scores.
I’m Elizabeth Viator. I’m a teacher at Dobson High School and the Mesa Public School District, and I am your child’s teacher.
After reading about the latest debacle regarding lower passing scores on the AIMS test, I’m reminded of a line from a Tom Petty song, “Don’t Back Down.” I would have begged our legislators not to back down. I would have pleaded with them not to weaken the system by providing an alternative to the AIMS test. Not yet. Not until we took it all the way to the end. Arizona has invested far too much money, time, and effort to see this test, that the state legislators insisted we needed, be watered down. But it’s too late. In an act of political spinelessness, that’s just what the Legislature and State Board of Education did, back down.
Under the old scoring standards some seniors wouldn’t have graduated next spring and received their diplomas. That was the point. The kids who needed extra help might actually have taken it seriously next year. Next year, if they buckled down and worked hard, many could have actually passed; they could have risen to the standard. Now, however, they’ll never know what they could have achieved.
The AIMS test was intended to wake up students, teachers, and parents. It was implemented and touted by legislators as the great cure for education. This had some success. If the state legislators would have found their back bones, we could have seen some real gains in education in the next few years. If the legislators could have stood tall, it would have meant that this state did indeed stand behind its self-made policy. If the legislators could have stood tall, it would have meant that kids and their parents would have had to be more responsible for their own education.
Years ago the State of Arizona said that simply attending class and earning A’s, B’s, and C’s was not good enough and a whole lot of educators agreed. Many of us actually cheered and rallied behind a solid, valid test. Now, however, the alternate path to augmenting low AIMS scores places the pressure solely and wrongfully on the shoulders of teachers. Why was the AIMS test initiated at all? Let me remind you: too many kids earned diplomas but lacked minimal skills. Too many educators found it easier to pass students rather than deal with angry parents and thus succumb to a modern day adult bullying. As a result, they passed students who did not deserve to pass. Many teachers offered extra credit. These extra assignments, anything from bringing in a box of Kleenex to writing a report on the benefits of Benadryl, artificially boosted the student’s grade enough to fah la pass the class, everybody’s happy. But what did the student learn? The lesson learned here is that if the system provides enough loop holes, anyone can pass to the next level–without skill, without accountability. Welcome, to the new loop hole! With this new plan, many teachers will again resort to inflated grades to pass undeserving student so they can augment their AIMS score and keep parents happy. With this new plan, teacher shopping will be more plentiful than shopping for the latest outfit at Abercrombie and Fitch.
Initially I thought the AIMS test was going to be the great equalizer. It would finally show what I’ve known all along: some teachers just don’t teach. My secret hope about the AIMS was that all the inept teachers who offered extra credit would be sued by the parents of those students who did not pass the AIMS test. Pathetic, I know. I also naively thought parents would be more engaged with their kid’s education and students might pay more attention to their own learning. But why should they work hard now? The Legislature and the State Board of Education just made it easier, a whole lot easier for kids to pass.
At a time when we all could have risen to the occasion, the state legislators pulled the rug out and have returned us to a mediocre mire of miserable mush. It won’t be long before I walk away from teaching English and start teaching Yoga.
Elizabeth Viator is an English teacher at Dobson High School in the Mesa Unified School District. You can hear this essay again at KJZZ.org.
I grew up in Singapore where every year from Primary 1 to Pre-U 2 (the equivalent of 1st through 12th grade in the States) a final exam determines whether or not you move on to the next grade. There is a test for every subject, English, Math, Science, and Mother tongue (Chinese, Malay, or Tamil). You don’t past, you don’t move on. No politics, no mollycoddling. Nothing good will come from lowering education standards, especially with the current job climate where the marketplace is competitive and global.
Remembering that you are going to die is the best way I know to avoid the trap of thinking you have something to lose.
Stop reading this and go get it done!
Update: A local copy of Jobs’ speech.
I spent some time using PHP5 to screen scrape a web page so that I could generate an RSS feed from it.
Textdrive forbids the usage of wget or fetch so I had to grab the file directly using a socket connection:
$host = "www.example.com";
$address = gethostbyname($host);
$port = getservbyname('www', 'tcp');
$result = socket_connect($socket, $address, $port);
$in = "GET /index.html HTTP/1.1\r\n";
$in .= "Host: $host\r\n";
$in .= "Connection: Close\r\n\r\n";
socket_write($socket, $in, strlen($in));
while ($out = socket_read($socket, 2048)) {
$html.= $out;
}
socket_close($socket);
Run it through tidy and you’ve got yourself a clean DOM tree which the following three lines of code will load and extract all <font> tags from.
$dom = new DomDocument();
$dom->loadHTML($tidy_html_string);
$fonts = $dom->getElementsByTagName("font");
I created an RSS feed for from the shadows which was severely lacking one. I’m also playing around with FeedBurner to manage feed statistics. Since FeedBurner fetches the feed periodically, it also behaves like a cron job, so I don’t have to set one up.
So without further adieu, here is the FTS RSS feed. It relies on screen scraping and the FTS crew’s request not to take it down, so in other words, it might not work forever.
Updated: November 5th, 2005: I’ve removed the feed, please link to the FTS feed directly
Summer of 2000, my friend and I started a web design company aimed at small to medium sized companies that wanted an internet presence. We did this right around the middle of my first year at college. We had good people, we didn’t spend too much money, but we didn’t make anything that people really wanted to use. I learnt, several ideas and startups later, that the last point I mentioned is typically the one you get wrong when you’re inexperienced.
Lesson learnt: Make something that people want.
I picked up a Treo 650 the other day. It wants to say something.
I am Marc’s Treo 650. I was purchased online with a 50% off coupon from SeeTreo.com. Straight out of the box, I am spectacular piece of eye candy, but I know that my looks won’t be able to hide the fact that both me, and the applications I come with are unusable.
Let’s start with my keyboard. Do you remember that Simpsons episode where the operator tells Homer that his fingers are too fat? That comes to my mind whenever I get mashed on. My keyboard buttons are too small and too close to each together. If you thought the stylus I come with allows you to do Graffitti (out of the box), like my old and busted brothers, you are sorely mistaken.
And my software? My Address book is an eye sore, my Calender hasn’t changed since the Palm III, and my Todo list is neither easily accessible nor usable for that matter. When you do find it, you’ll get so frustrated from all the keyboard mashing that you’ll forget what you were writing down to do. Notes and memos? You got to be kidding. I am a Treo 650. I don’t take notes. I don’t organize your life. You want to get organized? Too bad, organization is a process I can’t offer you.
On the bright side is, well, my screen… Seriously, have you seen it? It’s gorgeous. Just make sure to protect it. I can also play MP3s and take pictures too.
That’s about when I told it to shutup. Overall, it’s a decent phone. I’ll have to spend a few hours looking at software available and hopefully find some better replacements.
I love Nintendo. From the buckle, the band that covers their music, the Minibosses, the pianist that covers their music, the blind folded pianist, an A cappella group performance, and of course the big f-ing NES controller. Growing up, I never actually owned a Nintendo1.
Update: Download the Super Mario Theme song covered by the Video Game Pianist
-
Updated: Until the Wii came along.
↩
Check out Duncan Mills example of a drilldown pattern using JSF. It’s illustrated with a simple user interface that displays the index page, and provides links to a page where details can be changed. I just wanted to point out some good JSF practices. If you take a look at the the faces-config.xml:
- Each JSF/JSP page has a backing bean stored in the request.
- The equivalent of a DAO class is placed in the session.
- An instance of the object type being modified is also loaded as backing bean.
Letting JSF handle these objects allows them to be acquired through the JSF framework. Also, the tabular and edit backing beans end up being simpler to write, and result in fewer objects being created per JSF session. My only beef with this example is that String action() methods are usually meant for returning the next path in the workflow, and should not be doing work. Instead, work should be placed in void actionListener(ActionEvent ae) methods.
It’s a pretty good post. Developers new to JSF should give it a quick read.
Update: It appears this article is the number one hit on Google for the terms “JSF GET” Neat!
Eugene Hedley: [referring to something I don’t recall, circa 1995] So what do you think about that?
Me: I don’t really have anything important to say about it.
Eugene: Ha! Whatever! That’s never stopped you before!
10 years later, it probably hasn’t either but don’t worry, I don’t plan on making too much noise here. I’ve found that the blogs I enjoy reading the most focus on specific topics. Keeping this in mind, I came up with a list of things I thought would be fun and important, at least for me, to write about. The original list was long, so I narrowed it down and came up with the following:
- An entrepreneur aspiring engineer.
- My continually growing software engineering body of knowledge
- And, from time to time, dancing
As far as content is concerned: 70% of the time, I will be writing about my shit. 20% of the time, I will be linking to, and writing about someone else’s shit. And 10% of the time, I’ll be writing about completely random shit. So there you have it, for the next few months we’ll see how much signal or noise I can make.
At my first job, I was responsible for write three core components simultaneously. I had to design, code, and test production level components that were on a deadline (read: really quickly). My coding process was to blink out the design on a whiteboard, and refactor iteratively. The results were three on-time, production-ready, well-designed components.
So I thought to myself:
Self: If I just had the time to come up with the design, I wouldn’t need to accommodate a refactoring stage, and I could have arrived at the same well-designed components a lot quicker, right?
Not quite. I realized now that it’s not that I didn’t spend enough time on design. It was because I was failing quickly, and I was learning from my mistakes even faster. This shouldn’t have come as a surprise since success is really about knowing which paths lead to failure and deliberately avoiding them.
So I guess what I have to say is, when engineering a piece of software, you’re going to make mistakes, but you better damn well learn from them. And the faster you make mistakes, the faster you’ll arrive at success.
Step-brother: Virtual hosting is cheap these days, why do you ask? Oh God! You’re not going to put up a blog and write about the shit you do all day, are you?
That was about 9 months ago, when in fact, I did want to start a blog and write about the shit I do all day. And when I thought about it, it did sound pretty stupid (thanks Stef).
<thinking>What’s the point? I don’t want to just write about stuff. Who gives a shit about what I ate for dinner, or what I did this weekend? Even the word ‘blog’ drives me nuts. It would get lame so fast.</thinking>
Yes, it would, but the itch didn’t go away. I tried to think about what I could contribute and what I would get out of it, and here’s what I came up with.
Writing. I want to be a better writer. It’s actually part of my new year’s resolution. Communicating effectively is an important skill to have. Practice makes perfect and this outlet will allow me to do just that.
Building relationships and networking. I’m human and I crave social attention and interaction. I love to talk about business and technology. I require it to live. What’s frustrating is that I live in a city where the level of intellectual dialog isn’t very high at all. This is changing! Fortunately, I have a network of friends who share the same interests. With this blog, I’m hoping to meet a lot more people to geek out with. Networking is good for the career and blogging is just another way to network.
In the end, nothing ventured, nothing gained. By blogging, I’ll be able to track my thought process over the years. Down the road, will my ideas on life, the universe and everything change? Or will I have quit blogging a long time ago.
Who knows?
According to several JSF forum posts (here and here), A JSF GET is not something a developer can convienently do.
In fact, it is a recommendation that all form submissions are done via the POST method. Well, over the past 3 months, I have adored JSF too much to allow this one lacking feature to get in the way of practical and simple use cases.
So here’s how I did a JSF GET:
- Create the link to an URL which maps to a filter
- Use the ServletRequest to fetch the link’s arguments.
- Using those arguments, create a backing bean of the appropriate state and put it in the HttpSession.
- Create and update the FacesContext object
- Forward the user to the correct JSP/JSF (UIView) page
You’ll need to construct a link in your JSP/JSF page. You can do it by hard coding an actual link, but in this example I’ve chose to do construct my link using the JSF HTML taglibs:
<h:outputLink id="x" value="jsf.get">
<f:verbatim>Some Link</f:verbatim>
<f:param name="editItem" value="00004"/>
</h:outputLink>
This will emit the following link in your JSP/JSF page.
http://localhost/context/jsf.get?editKey=00004
Now we add a filter to listen to requests for “jsf.get”:
<filter>
<filter-name>JSFGet Filter</filter-name>
<filter-class>com.JSFGet</filter-class>
</filter>
<filter-mapping>
<filter-name>JSFGet Filter</filter-name>
<url-pattern>*.get</url-pattern>
</filter-mapping>
Now, you need a filter that handles incoming GET requests properly. Included below is a stripped down version. I hope this bit of code will help anyone trying to accommodate GET requests with JSF.
import com.SuperBean;
import java.io.IOException;
public class JSFGet implements Filter {
private FilterConfig filterConf;
private ServletContext servletContext;
public void init(FilterConfig filterConfig)
throws ServletException {
this.filterConf = filterConfig;
this.servletContext = filterConfig.getServletContext();
}
public void doFilter(ServletRequest req,
ServletResponse res,
FilterChain fc)
throws IOException, ServletException {
FacesContext facesContext = getFacesContext(req, res);
req.getRequestDispatcher(facesContext.getViewRoot().getViewId()).
forward(req, res);
}
public void destroy() {
this.filterConf = null;
this.servletContext = null;
}
/**
FacesContext.setFacesContextAsCurrentInstance method is
protected.
*/
private abstract static class ProtectedFacesContext
extends FacesContext {
protected static void setFacesContextAsCurrentInstance(
FacesContext facesContext) {
FacesContext.setCurrentInstance(facesContext);
}
}
/** Here's where the Filter/JSF integration takes place. */
private FacesContext getFacesContext(ServletRequest req,
ServletResponse res) {
/** Try to get it first */
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null)
return facesContext;
// Use the FactoryFinder to grab the Lifecycle object
FacesContextFactory contextFactory = (FacesContextFactory)
FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
LifecycleFactory lifecycleFactory = (LifecycleFactory)
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle =
lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Put my Bean into HttpSession
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpSession httpSess = httpReq.getSession();
SuperBean editor = new SuperBean();
String key = req.getParameter("editKey");
editor.setEditKey(key);
// If your loadSomething method requires a FacesContext object,
// call it after it has been constructed
editor.loadSomething();
httpSess.setAttribute("SuperBean", editor);
// Here's where the ProtectedFacesContext comes in.
facesContext = contextFactory.
getFacesContext(servletContext, req, res, lifecycle);
ProtectedFacesContext.setFacesContextAsCurrentInstance(facesContext);
// Create a new ViewRoot. Default behavior returns null
UIViewRoot view = facesContext.getApplication().
getViewHandler().createView(facesContext,"edit.jsf");
facesContext.setViewRoot(view);
// Call loadSomething(FacesContext)
// editor.loadSomething(facesContext);
return facesContext;
}
}I am an avid Firefox user. I donated, I beta tested, and occasionally I have convinced my non-geek friends to take it for a spin, only to usually have them flip out over tabbed browsing, the built-in pop up blocker, and lots of themes. Recently, while convincing a friend, I came up with a great analogy between Firefox and safe sex.
Surfing the internet with Internet Explorer is like having unprotected sex with strangers. If you are going to have sex, be smart and take the necessary protection. Firefox is that protection. It allows you to be visit all the websites you want while protecting you from getting infected, which will happen.
Source: Flickr