May 2009

I just finished asking Diana what she thought about cancelling cable TV while the budget was tight. (She was OK with the idea since she has Hulu.) I come back to GMail and see this ad at the top:

TV Service Too Expensive? - www.DishNetwork.com

Oh my God, I thought, Google did develop mind-reading technology.

Well, no. But they may as well have. They probably displayed that because my last two sent e-mails were:

Reminder: Jobs: Next: Check Chase bank statement for payments to cancel.

I have to backtrack - it looks like the travel budget will be too tight in June. Don’t think we’re going to be able to make it. :(

general

Permalink

Laid off…

Well, it looks like I don’t escape this downturn unscathed. Integrum just laid off half their staff, including me.

Three guys were suddenly called into one office for a meeting. The rest of us were called into the board room. “Oh, no,” I thought, “they’re laying them off and this is to apprise us of the situation and reassure us that we still have jobs.”

Well, I was half right - the larger group was the one getting laid off. My ears were actually ringing for most of this… “There’s no easy way to say this… The first two quarters were really rough… I hate doing this… I’ll give any of you a glowing letter of recommendation…”

The unlucky ones met up at a restaurant afterwards to talk and plan. Those with savings were going to look into consulting and side jobs for a while. Those without were going on unemployment and starting job hunts. Nobody was really angry at Integrum, just numb and sad.

I’m sad too. This was the best bunch of people I’ve ever been privileged to work with. Hopefully I will be working with them more, just in other venues…

development
friends

Permalink

Zyps at MofoCamp

Zyps was one of two chosen topics for Mofocamp last night. I wasn’t really expecting that, so I was totally unprepared, but we piled into one of the breakout rooms and started hacking away.

I said Zyps was ideally suited for simulations or shooter-type games, and someone raised the idea of an Asteroids clone. I said not only could it be done, but half the code was written already (ExplodeAction, WrapAround, ShootAction, etc.). The only uncertain area was keyboard input (and 10 minutes of wxRuby research took care of that).

It was definitely not my cleanest work ever; we copied the entire Zyps repo since the last gem is so old, and ripped the entire contents of bin/zyps as a basis. I didn’t realize it was loading an empty environment from a YAML file, so when I wasn’t answering questions I was trying to figure out why the Asteroid and Ship objects (coded by Andrew Bowerman and Roy VandeWater) I was dropping in were mysteriously disappearing.

Thanks in part to that, we were 40 minutes late for presentation time (which was OK because the Processing team left without presenting), but we finally had a working demo. Lots more to be done, but not bad for two and a half hour’s work.

Code (in “zyps” subdir)
Wiki

Zypseroids

development
ruby
zyps

Permalink

is.gd at command line…

Saved this on my PATH as shrink_url…

#!/bin/sh
curl "http://is.gd/api.php?longurl=$(echo $@ | sed 's/\ /+/g')"

Which lets me do this:

$ shrink_url http://current.com/items/90029658_death-star-destroys-enterprise.htm
http://is.gd/xHYe

Pipe to clipboard and you’re ready to paste into a browser. I suppose I could also enclose the result in a $() call to my favorite command line Twitter client, but I’m not feeling that fancy yet.

$ shrink_url http://current.com/items/90029658_death-star-destroys-enterprise.htm | cb
$ cb
http://is.gd/xHYe

development

Permalink

Yet more XBox Live avatar fun…

On this page, Microsoft actually encourages linking to their cache of your avatar image. These actually update as you change your avatar, too.

So here’s a group shot of me and my friends, as we appear on Live currently, apparently with a strong wind blowing from the left…

Continue Reading »

friends
games

Permalink

Notes from Anil Jain (Slipstream Labs) - The Harsh Realities of Entrepeneurship

Anil Jain of Slipstream Labs came to Gangplank today for a brown bag talk. Here are my notes:

Ideas are a dime a dozen - it's ability to execute that's key.
People matter most.
        They are root cause of failure (or success).
        Motivators vary, weaknesses vary.
        Be careful who you choose to collaborate with!
        Misconstrued expectations are a key danger.
Risk is inherent in every decision you make.
        Ask questions of others who've done it before
        Don't rush into anything.
        What are tradeoffs in a decision?  Write down pros and cons.
Failure is necessary.
        Learning the hard way helps future decisions.

Machiavelli:
        "It ought to be remembered that there is nothing more difficult to take
        in hand, more perilous to conduct, or more uncertain in its success,
        than to take the lead in the introduction of a new order of things.
        Because the innovator has for enemies all those who have done well
        under the old conditions, and lukewarm defenders in those who may do
        well under the new. This coolness arises partly from fear of the
        opponents, who have the laws on their side, and partly from the
        incredulity of men, who do not readily believe in new things until they
        have had a long experience of them."

Important abilities:
        Healthy tolerance for ambiguity.
                Change is constant, especially if you're the one bringing it
                about.
        Foster belief.
                Get others on board with your idea.
                        Employees, attorneys, the media, and more.
                        It's the difference between having people help you and
                        facing closed doors.
                        If you don't believe in the idea yourself (if you're in
                        it for the money), you won't convince anyone.
                Conviction is not Arrogance.
                        Entrepreneurs need a certain amount of stubbornness,
                        but if you don't respond to outside feedback, you'll
                        fail in real-world conditions.
Glamour is fleeting.
        The initial excitement wears off quickly.
        You need perseverance to last through the hard/painful parts.
        Even if people tell you, you won't understand HOW hard it is till you
        do it.

Kurt Vonnegut:
        "I want to stand as close to the edge as I can without going over. Out
        on the edge you see all the kinds of things you can't see from the
        center."

Drama is inevitable.
        The future is ambiguous.
        People are illogical and unpredictable.
        Drama is the result - be prepared.
        Example:
                A founder was expressing doubt to investors behind the backs of
                rest of board.  Rest of board didn't know why investments
                started slowing, and when they found out they had to work to
                restore faith.
Your personal life:
        At some point in time, your family/friends will NOT understand what
        you're doing.
        Supportive or no, they will eventually question your plan.
                Especially when doubt is introduced by money shortages,
                partners leaving, etc.
        It's not their fault - you need to keep the faith and get them back on
        board.
        Work/life balance is a myth.
                The two cannot be separated for an entrepreneur.
                Being an entrepreneur is a life choice.
                        You’ll be checking your Blackberry while changing
                        diapers.
                The list of things to do will grow just as fast as you complete
                items (or faster).
There is always work to do.
        If you’re asking yourself “what do I do now?”, you’re missing
        something.
        Tasks you can always do more of:
                Analyze competitors.
                Seek more funding.
                etc.
        If you don’t want to be involved with this business the rest of your
        life, either don’t start it, or have an exit strategy.
There is no formula.
        Anyone trying to sell you one is lying or delusional.
        Instead, rely on common sense.
        Learn lessons from others, but don’t copy verbatim.
                You should not necessarily do everything Michael Dell
                did (but feel free to borrow some ideas).
Capital
        How much do I need?
                What resources do I need and how much will they cost?
        What types and sources should I seek?
        What am I willing to do to get it?
        Customer funded development:
                Give a customer a good deal, with contract that you keep
                ownership of developed product (or portions thereof).
Professionalism matters.
        It’s good to be scrappy and get things done on a shoestring.
                But you have to be professional.
        Maintain standards of quality:
                In product.
                In communications.
                        With customers.
                        With vendors.
                        With investors.
Instinct alone is dangerous.
        Be aware of what your gut is telling you - we are animals that run on
        instinct.  But it should only be part of decision making process.
        You may miss feedback that shows reality of situation.
Partnering is a double-edged sword.
        Gives you access to partner’s contacts, skilled workers, etc.
        But you give up control, more communication overhead, etc.
If any company has right of first refusal on your business, no other company
will invest in the research needed to buy you.
        If other company decides they like you, company with first refusal
        would just buy you.
Open source software may not be for you.
        Unless your chief goal is philanthropy…
        Capitalism is good, understand it.
        You’ve invested time, money, and research on a product.
                You and your shareholders should get a return on your
                investment.
        What is the objective benefit to us?
        What are we in business for, and does this deal fulfill those goals?
Simple microeconomics principles provide guideposts.
        Opportunity cost
        Price the market will support
        Value proposition to potential customers
Greed kills.
        It leads to bad decisions.
        Asking too much.
        Not offering enough in return:
                To investors.
                To customers.
Know what you know.
        Know your strengths.
                Helps you sell to investors, customers.
        Know your weaknesses.
                Get partners who are stronger in those areas.
In a strong wind, even turkeys can fly.
        Any company can succeed when economy is strong.
        Almost any partner is good enough when cash flow is good.
                More skills and dedication are needed when you encounter
                trouble.
        Hire slowly, fire fast.
Hiring - Past success not indicator of future potential.
        Partners that worked well in prior jobs may not work well with
        your company.
                Do they believe in your product?
                Will they work well with your investors and partners?
A customer in the hand is worth a thousand in the plan.
        Attractive to investors.
        Shows proof of what you’re selling.

general

Permalink

Me with Jason Seifer and Greg Pollack (The RailsEnvy guys) after their talk at RailsConf Thursday.

RailsEnvy

If you’re a Rails developer and haven’t been listening to their podcast, you need to start!

development
rails
ruby

Permalink

Notes from RailsConf - Starting Up Fast: Lessons from the Rails Rumble…

Hosted by Nick Plante (Nth Interactive)

Would’ve liked to give attributions for these quotes, but it wasn’t practical. Sorry!

Rails Rumble:
        48 hours to design, develop, and deploy a micro-app.
        Public voting.
Panel:
        Joe Fiorini
                Grand prize winner, 2008
                meetbetween.us
                Team of 4
        Ben Scofield
                Solo Division, 2007, 2008
                Forever Home (down)
        Chris Saylor
                Grand prize winner, 2007
                tastyplanner.com
                Team of 4
        James Golick
                Most Useful, 2008
                "What Does This Error Mean?" site
"How is the Rumble like working on a normal Web project?  How does it differ?"
        Time constraint means you won't be building a social network, etc.
        What can you cut out?  Do you need a login system, for example?
        People likely to visit site, make snap judgement on first page, and
        leave again.
"Is it possible to build a real product this way?  Have you continued to
develop your entry apps?"
        Real Simple Magazine did a couple hacknights later.  Someone contacted
        them to acquire it later.
        Joe got approached by yellowpages.com, though nothing has materialized
        yet.
        No matter how great your initial idea is, you don't REALLY know what
        you want to build until you start.
                Getting app active and getting feedback is great.
"What sort of up-front planning and design work did you do?"
        Complete wireframe on pen and paper (digital wireframes not allowed),
        assignment of tasks to developers.
        "None."
        5 or 10 stories in Pivotal, not much.
        Color selection, finding stock photos.
"How much time did you spend in prep, and does that affect the spirit of the
Rumble?"
        You can plan as much as you want if you're not creating digital assets.
         Much of this is on the honor system.
        "We didn't want to spend 48 hours thinking, [so we planned up front]."
        Moderator: We want to encourage use of the sea of third-party plugins
        that are out there.
        "We got shit marks for design, probably because we didn't do any."
"How did you plan for the 80/20 rule?  (20% of small tasks take 80% of the
time.)"
        We ensured that even if there were small tasks we hadn't completed, we
        could still deploy.
        Ben Scofield expounds: Version he was working on at deadline had a bug,
        but version control let him back out to a stable version.
        We talked about features we wanted up front.  Got a backlog going.  Our
        mantra: "Think of Google".  Try to have nothing but a search box and a
        couple buttons.
        A 48-hour competition is a terrible place to mentor someone.  Make sure
        you know all the
"Did you use automated testing when you built your application?"
        No.  TDD can make you faster for big apps, but it slows you down on
        small ones.
        Yes, some.
        Yes.  Automated tests are great for catching regression.  It's just a
        good development practice.
        Testing is a method of design.  If I need to get something done quickly
        and can't test, I do 'design by wishful thinking'.
                Write the code the way you want to see it, then go implement
                it.  [Sounds like comment-driven development to me.]
        Don't let them fool you.  You can still win if you don't do testing.
"What plugins/gems/tools did you find most helpful?"
        Plugin by James Golick helped build RESTful contollers without need to
        code.
        Starter apps - Bort, Blank.
        Moderator: Rails 2.3 Templates offer starter-app-like functionality.
        Factory Girl, Shoulda, Mocha.  Make Resourceful.
        New Relic RPM - it helped us at one point when LifeHacker post
        generated 2000 hits during voting period.  MySQL fried, not Rails, and
        RPM helped spot that.
        Almost everyone used Campfire.  Inline paste, inline images, chat
        history are nice.
        Basecamp.
        Pivotal Tracker.  Super-lightweight tool to keep organized without
        eating our time.
"How did you find other people to work with and decide that you could work with
them?  Is it anything like finding co-founders for a startup?"
        Talked to good friends first.  At last minute, had to call every local
        Rails developer we knew to replace a dropout.  Worked out well.
        Find a well-rounded team.  Sysadmin, DB design, graphic design,
        developer.
        Good friends from local developer community.  Wound up hiring two of
        them.
        Local user groups.  Refresh to find designers.  Ruby User Groups for
        developers.
"What was the most rewarding part?"
        Getting to work with awesome people.  Did screencast too.  It was a lot
        of fun.
        Getting to know people better.  Getting to release a completed app- so
        often, real life interferes with completing a project; not here.
        You get so bogged down working on large apps for an employer.  This
        reminds you what's great about coding.
        Moderator: "Launching shit is awesome."
"How much sleep did you get?"
        4 each.
        6 each.
        4-6 each.  One member went to concert, but coded in car on way there
        and way back.
        6 hours per night.
        You don't have to work 44 of the 48 hours, just set realistic
        expectations.

development
rails
ruby

Permalink

Notes from RailsConf - Rails 3: Step Off the Golden Path…

Hosted by Matt Aimonetti.

Rails philosophy:
	Convention over configuration
Merb philosophy:
	Performance
	Framework agnosticism
Rails 3 philosophy is also a merger:
	Performance
	Modularity
	Framework agnosticism
What you get:
	Public API (It was closed for Rails 2)
	Mountable apps (mount your blog app in your CMS app)
Default stack:
	ActiveRecord
	Test::Unit
	Prototype
	ERB
But, it's less opinionated:
	Other Javascript frameworks:
		jQuery
		MooTools
		ExtJS
		Yahoo!
	Other templating engines:
		Haml
	Other ORMs (turn DB records into objects):
		DataMapper
		Sequel
		CouchRest
	Other test frameworks:
		Cucumber
		RSpec
When to step off the golden path:
	If your templating, JS, ORM, or performance requirements differ.
	Otherwise, use the default stack- it's real-world tested.
Datamapper:
	Procrastination as a virtue:
		Lazy Loading - Don't pull fields until they're asked for specifically.
		Strategic Eager Loader
		ActiveRecord:
			Student.all.each.books.map {|b| b.name}
			select * from "students"
			select * from books where student_id = "1"
			select * from books where student_id = "2" #etc. This is slow!
		DataMapper:
			Student.all.each.books.map {|b| b.name}
			select id, name from students order by id
			select id, name, student_id from books where
				(student_id in (1, 2, 3, X)) order by id --Faster
	Multiple "repos" (databases)
		Config:
			production:
				adapter: mysql
				database: production-app
				host: localhost
				...
			repositories:
				nightly_backup:
					adapter: sqlite3
					database: shared/nightly.db
				weekly_backup:
					...
		Then set up a task to copy from DB to repo:
			Article.copy(:default, :nightly_backup, :created.gt => 1.day.ago)
		Legacy databases:
			class Page
				include DataMapper::Resource
				property :id, Serial
				property :name, String
				#Specify different fields when talking to legacy database:
				repository(:legacy) do
					property :name, String, :field => "title"
				end
			end
	Query::Path
		#Joins people with addresses, finds records where street column LIKE '%street%'
		Person.all("addresses.street.like" => "%street%")
	Many adapters:
		RDBMS
		file system
		IMAP
		YAML
		SalesForce
		REST APIs
		your API here - write your own.
Sequel
	High performance
	Sharding
	Prepared statements
	Highly customizable SQL statements
Hibernate
	Built in sharding
	ActionORM
	JRuby
	Many Java libraries for legacy databases
Non-RDBMS systems
	AppEngine::DataStore
	CouchRest for CouchDB
	Redis, Tokyo Cabinet, etc...
More customizations available:
	File structure (including very_flat)
	Custom router DSL
	Custom request handlers
		class Presentation < ActionController::Http
			def index
				self.response_body = "Hello!"
			end
		end
		Presentation.action(:index).call(Rack::MockRequest.env_for("/railsconf"))

development
rails
ruby

Permalink

Notes from RailsConf - Getting to Know Ruby 1.9…

Hosted by David A. Black

1.8.6:
	> Object.new.to_a
	[#<Object...>]
	> "one\ntwo\nthree".to_a
	["one\n", "two\n",...]
1.9:
	> (0..10).to_a
	[1, 2, ...]
	Above 1.8 items don't have .to_a, though.  After all, why *should* an object know how to wrap itself in an array?
	> Array(Object.new) #Array now has the responsibility.
	[#<Object...>]
1.9:
	> "abc".to_i
	0
	> Integer("abc")
	Exception
1.8:
	> {1, 2, 3, 4}
	Hash
1.9:
	> {1 =>2, 3 => 4}
	Have to use hash rockets.
1.8:
	> String.ancestors
	[Enumerable, String, Comparable, ...]
	> "1\n2\n3".each{|s| puts s}
	1
	2
	3
	> "abc\ndef\nghi".map {|s| s.reverse }
1.9:
	String does not mix in Enumerable
	> "".each
	NoMethodError...
	> "abc\ndef\nghi".lines.each {|l| puts l.upcase}
	> "abc\ndef\nghi".each_line {|l| puts l.upcase} #Equivalent
	> "abc\ndef\nghi".bytes.each {|l| puts l.upcase}
	> "abc\ndef\nghi".code_points.each {|l| puts l}
1.9:
	> str = "Give me 100\u20ac"
	"Give me 100<Euro symbol>"
	> str.bytes.to_a.size
	14
	> str.chars.to_a.size #Shorter than .bytes due to Unicode character.
	12
1.8:
	> str = "This is\na three-\nline string"
	str[6] #Gives the ordinal.  (Kinda hacky...)
	115
	> str[6, 1]
	"s"
1.9:
	> str = "Give me 100\u20ac"
	> str[2] #Gives the character (I like this better).
	"v"
	> str[2].ord
	118
	> str[2, 1]
	"v"
	> str[2, 5]
	"ve me"
1.9:
	> h = {:one => 1, :two => 2}
	> h = {one: 1, two: 2, three: 3} #New hash separator!
1.9:
	> link_to "click", controller: "users" #That's a hash as the last argument, braces are optional.
1.8:
	> {1 => 2, 3 => 4, 5 => 6} #Non-deterministic, could give {5 => 6, 3 => 4}
1.9:
	> {5: 6, 1: 2}.each {|k, v| p "#{k}: #{v}"} #Order is deterministic.
	5: 6
	1: 2
1.9:
	Beware: Hash#sort still returns an Array of Arrays, not a re-ordered Hash.  That may change.
	Hash#select still returns a Hash.
1.9:
	Enumerable module has new methods.
	> a = (1 .. 10).to_a
	> a.each_slice(3) {|slice| p slice}
	[1, 2, 3]
	[4, 5, 6]
	...
	[10]
1.9:
	> a.each_cons(3) {|cons| p cons} #Moves result start by 1 index each time.
	[1, 2, 3]
	[2, 3, 4]
	[3, 4, 5]
1.9:
	> a.one? {|i| i == 2}
	false
	> a.all? {|i| i == 2}
	false
	> a.any? {|i| i == 2}
	true
1.9:
	> ('a'..'c').cycle(2)
	#<Enumerator>
	> ('a'..'c').cycle(2).to_a
	['a', 'b', 'c', 'a', 'b', 'c']
	.cycle with no args loops forever.  Fun, but dangerous.
1.8:
	> x = 1
	> [10, 20, 30].each {|x| puts x * 100}
	1000
	2000
	3000
	> x == 30
	true #WTF?  Why not 1?  Wasn't x in the block scoped only to the block?
	> [10, 20, 30].each {|@var| puts @var}
	10
	20
	30
	> @var
	30
1.9:
	> x = 1
	> [10, 20, 30].each {|x| puts x * 100}
	1000
	2000
	3000
	> x
	1 #There we go, it wasn't overwritten.
	[1, 2, 3].each {|@x|}
	SyntaxError: formal argument cannot be an instance variable.  (That's a good thing to me.)

general

Permalink