George Willman: Patents for the Startup

This is part of my set of notes from the Startup School 2006 sessions at Stanford.

There are two major sets of issues with intellectual property: avoiding liability, and creating value.

Major forms of Intellectual Property

  • Trade secrets: Secret information, not only technology (could be business secrets) core to the product the business offers to customers
  • Trademarks: Marks that serve the communication function of signaling the source of the good or service to the customers
  • Copyrights: Cover original works of authorship, but not ideas. Cover things like book, music, etc.
  • Patents

Protection v. cost

  • In order of increasing protection v. cost: copyright, trade secret, trademark, patent
  • Copyright does not protect against independent development of something that duplicates your work; only protects against out-and-out copying of the final product
  • Patents are at the opposite end of the spectrum than copyrights

Patents

  • Government granted right to monopoly
  • Requires that you file an application, unlike some other forms of intellectual property protection
  • Exclusive Right – Right to exclude, not right to practice. Patent is a right to sue someone
  • Basic patent requirements: utility, novelty, non-obviousness, description

Timing

  • Statutory bars: if you haven’t filed your patent within a year of printed publication, public use, offer for sale (even if confidential or not actually sold) it may not be patentable. In other countries, this is covered by the concept of absolute novelty – rule is that they’re generally stricter, have to get patent on file before the product ships or details published.

Patent Process

  1. File application
  2. Office actions: USPTO responds the application
  3. Prosecution/amendment: Pushing the patent through the process, amending to address issues flagged by USPTO
  4. Allowance
  5. Issuance: Patent actually issued to the inventor
  6. Not covered: Abandonment – abandoning the application may occur if you don’t respond in a timely fashion. Avoiding this is the responsibility of your patent attorney. You may also choose to abandon an application on purpose.

What to Patent?

  • Look to core technology that will exist across versions of the product, a fundamental piece of technology that provides you with competitive advantage
  • Note that in an ideal world, this technology may have applications in other fields
  • Note that you can patent things that aren’t actually in your product – you can patent alternatives to you product. You don’t have to have implemented the technology, merely filed the patent. May be used to preemptively protect future enhancements you are planning to add to the product to block competitors.
  • Walkthrough of Starbucks cupholder patent (#5,205,473) ; Noah’s Bagels patent on similar item (5,826,786) – note the citation of Starbucks patent as reference.
  • It has been resolved that you can patent software, business methods
  • Business process patent for Data Processing System for Hub and Spoke Financial Services Configuration (#5,193,056?)
  • Secure method and system for communicating a list of credit card numbers over a non-secure network (#5,715,399)

Patent Strategy

  • Patent clustering: For example – Razor blades have several patents, the blade, the packaging, the handle, the moisturizing strip. This allows you to block someone from entering.
  • Patent bracketing: People patenting information around another patent held by the innovator to force cross licensing. Example: a telephone patent holder, and a long distance routing patent holder will need to cross license because you can’t do one without the other.

Ann Winblad: How to Write a Fundable Business Plan

This is part of my set of notes from the Startup School 2006 sessions at Stanford.

Ann Winblad is the co-founding partner of Hummer Winblad, a VC firm in Silicon Valley focused solely on software. She started off with a number of general observations on the state of the venture capital and software markets:

  • The market has been very constant over the past three years, with about $21B a year invested on average. Around 35% of all dollars invested go to software companies
  • Microsoft stock took the hardest hit it’s taken in the past five years, down 11%. The winning stocks? Saleforce, new analytics companies
  • Winning used to depend on platform shifts (PC to client/server to Internet distributed); now, if you’re an incumbent it’s like playing wack-a-mole with the competition. We’re at the beginning of a four-year step function of innovation. For software, the real boom is now.

The challenge for founders is really understanding the customers, creating competitive advantage, and turning that into a business.

Starting Your Software Business Plan

  • What is your idea? The goal is to hook them in 15 minutes. For example, consider one of their portfolio companies, Hyperion. Jim and Bob walked into Hummer Winblad office, and Jim unfurled a list of all the customers he was going to call – after one meeting, Hummer Winblad started due diligence. In another case, Voltage Security, Ann saw their pitch as a finalist judge in a business plan competition and immediately knew it was a fundable business because they had been able to distill the essence of their idea: “Voltage Secures Anytime, Anywhere business communications”.
  • Do you understand the market? Unmet customer need + growth – the VCs are expecting any startup to say it’s a billion dollar market. What’s really important is to talk about the customer, their needs, and if you solve that customer’s problem/interest, will you have an ongoing revenue relationship with that section of the market? Is it a vitamin or a painkiller?
  • Are you defining the market or jumping hurdles already in place? You have to define the market, as opposed to having the market defined for you. You need to be creating the barriers to entry.
  • Who are your competitors? Put together a picture of who you’ll be up against – even if you don’t show it to anyone, do this exercise.
  • Is this a product or a company? Companies do not live in the Products section of their corporate web site.
  • Will customers beg? Are you creating the Newton or the iPod? How is this product inspiring? Biggest challenge in the consumer market is to make the product inspirational. In Enterprise, it’s about tight fit to consumer need.
  • Who are your customers?
  • What is the secret sauce? What is really giving you that competitive advantage that no one else can reproduce? In the case of Voltage, it was math. What’s your advantage? Technology/IP? Business Process? Partners? Domain Knowledge?
  • Engineering roadmap: Can the product be built in less than one year? Anyone that comes to them that can’t bring the first release of the product to the market in less than a year is not going to get funded. Sit down, write out your engineering roadmap to show how you’re going to get there.
  • Can you attract excellence? 80% of the companies Hummer Winblad funded that were acquired were run by the founders. They are seeing the old world retiring, finding that most of the people they fund are doing it for the first time. Do not try to pack in your whole management team. The companies they’re funding are lean and mean, small. One company recently funded had five employees; another had three employees.
  • Do you know what you don’t know? It’s fine to go into VCs and say “These are our assumptions” – it’s important to know what are assumptions, and what are facts. Michael Porter’s value chain is a good guide. Who do I think will be competitors? What do I think my route to customers will be? Write down your top ten assumptions, and track how they change over time.
  • Do the numbers make sense? Do the numbers reach software economics (80% gross margins, 20% EBITDA)? Are services a major fraction of revenue? Is the total capitalization less than $15< ? Are COGS (Cost of Goods Sold) > 30%? Are sales and marketing commissions and quotas in line with industry? Does the Engineering plan match the Operations plan? Is the G&A < 10%, is it outsourced? Is the quarter over quarter growth? What’s the revenue per employee? How long will the initial investment last?

The Market Bats Last

  • “I only swing at strikes” – Warren Buffet
  • Ultimately, the VCs will call customer to ascertain if they believe in your product and team. Do the customers have budget to buy you product? Is there a common problem across customers, or does it need to be customized for each customer? And do you have a way to reach the customer (example: carriers in mobile applications)? How do you reach customers in a reasonable time, at a reasonable cost?

What VCs Bring to the Table

  • 3 P’s: People, Partners Process
  • 65 companies got their A round from professional investors in 2005
  • The money does give you some competitive advantage, but not a lot. It’s the partnerships that you can leverage that build that advantage.

Do I Need to Write a Business Plan?

Not at first, but they will eventually to see your thought process. Six pages should cover it. In addition, you’ll need a pitch presentation consisting of 10 slides to cover the basics:

  • Executive Summary
  • Team
  • Market Analysis
  • Secret Sauce Overview
  • Key Assumptions
  • Customers (Potential or references)
  • Product Plan
  • Engineering Plan
  • Sales model and marketing outline
  • Business Model / Financials / Cash Flow

Audience Questions

  • How would you respond to Joe Kraus’ philosophy of taking on money? It depends on the business in question. For one of the companies they funded, they only put in $650K – this company had major assumptions outlying that needed more interactions with customer to figure out which way to go forward. The VCs are interested in where this money will get you, and if it will get you to a milestone that will be of interest to follow-on investors. The worst situation is companies that try to take too little, and they haven’t achieved any milestone when the money is gone.
  • Do you have a lower limit on the size of company you consider funding? Do you consider companies that are going to exit via acquisition differently than via IPO? Hummer Winblad focuses on startups that are going to become big companies. Ask yourself: Could I describe this company as a public company on an S-1? Even in the case of companies that got acquired, they made a choice to get acquired rather than to go for IPO. But an IPO was always an option. You want to be in a position to turn down an acquisition. Anyone operating such they need to be acquired to achieve an exit is in a precarious position. Companies are bought, not sold.

Mark Fletcher: Lessons Learned Birthing and Building Web Startups

This is part of my set of notes from the Startup School 2006 sessions at Stanford.

Mark Flecter is a two-time entrepreneur with two successful companies under his belt:

  • OneList: At the end of 1999 merged with Egroups, acquired by Yahoo in June 2000. Product is now Yahoo Groups, and has 140K users
  • BlogLines: Launched in June 2002, this company was totally self-funded. Put in a total of $200K from start to finish, build it using only one salaried employee, four stock-only compensated employees, and outsourced labor hired through eLance. BlogLines was bought in 2005 by Ask Jeeves.

Garage Philosophy

Mark has his own “garage philosophy” – secrets to success for startups:

  • Passion for the idea: He’s been driven by solving problems he has himself. OneList was driven by his need to have an easy way to set up a mail list. BlogLines was driven by the problem of having an enormous bookmark list that he visited every day. If you solve a problem that you have, other people most likely have the same problem. It’s easy to get enamoured by the technology, and do things because you can. Instead, focus on the stuff that interests you, solves a problem for you. This will be your life 24×7, so you’d better enjoy what you’re doing.
  • Cheap technologies: Design around the idea of cheap hardware and open source.
  • It doesn’t have to be perfect: Many people try to get it perfect before they launch. This should be avoided – launch early, launch often. OneList was really ugly at first, and missing huge chunks of functionality. Doing this kick-starts the “virtuous cycle” where active feedback from customers drive development. Half of customer support email sent to BlogLines are feature ideas. Also engages customers, ties them more to your service as you address their needs.
  • Moonlighting limits risk: He worked a full-time job when starting BlogLines – he had a mortgage to support.
  • Friends/Family funds: When you do raise money, look to family/friends. The longer you can go without raising VC funding, the better position you’ll be in. BlogLines didn’t take VC funding until they had a million users. This put them in excellent negotiating position.
  • Free services = less pressure: You don’t have to worry about high availability when you’re offering a free service. People will cut you some slack.
  • Hire a lawyer: When he did OneList, he used an online service to incorporate in Delaware. Ended up having to redo things entirely and in the end it didn’t really save much money or time.
  • Outsource to eLance/Rent A Coder: Althought Mark wouldn’t recommend outsourcing core pieces of technology development, it can still be useful. For example, BlogLines has a notifier application – BlogLines put together a proposal, posted it on eLance and had some guys from Kazakstan/Russia write the application to their exact specifications in two days. Ditto for translation services – they extracted all of the text, posted the proposal to eLance, and for $3500 had the service translated into 6 languages. Graphics is also a good place to try using outsourced labor. In general, Mark recommends making the proposal as specific as possible to guarantee success.
  • PR is cheapest marketing you can do: The only way to value your service is in the growth of your user base, and the buzz surrounding your service. Anybody can come along and be smarter than you, but they can’t copy your users. Focus on viral growth – motivate users to be your best cheerleaders. Make it valuable for them to have their friends on the service. OneList pulled people in because people created mail lists for their friends – you couldn’t create a mail list that didn’t encourage people to sign up. Also, PR is cheap. Find someone who can develop relationships with reporters. BlogLines had great press coverage, four write ups in the Wall Street Journal. PR person was working for stock!

Design Philosophies

One great resource that summarizes it better than Mark ever could: Amy Jo Kim’s presentation at Etech – Putting the Fun in Functional.

Technical Aspects

Software choices

  • Linux/Apache
  • C/C++/bash/python
  • DJB/qmail/DJBDNS/Daemontools (http://cr.yp.to)
  • ClearSilver (http://www.clearsilver.net)
  • Berkeley DB (http://www.sleepycat.com)
  • Memcached
  • Avoid NFS
  • Avoid table-level locking in MySQL
  • The faster your web site is, the more pageviews you get. Whenever BlogLines slowed down, they threw more hardware at it and saw 30% more pageviews, not from more users, but more use of the product from the existing users

Hardware choices

  • Dedicated servers v. Buying/Hosting: For BlogLines, they bought their own hardware. They had to find machines, the co-lo, and deal with the network issues. Thought the advantage is that it’s cheaper in the long run, but would not do this again in the future. Renting the machines is the way to go – it just doesn’t cost that much.
  • eBay is a great place to buy hardware – you can find several wholesalers who will put together any machine you want, even new hardware.
  • APC PDUs for remote power cycling
  • HP ProCurve
  • Avoid Seagate Ultra-SCSI drives – they had 50% failure rate
  • A good phone for SSH which allows remote problem solving. He’s been in a casino, in front of a slot machine, fixing a server from his phone!

Architecture Choices

  • Copying files v. Client/Server: The BlogLines News RSS Feed is basically a text file that they copy between servers; copying files scales infinitely, and is a good solution for a lot of things. Not ideal for everything, but something to consider.
  • Calculate on the fly v. Cache: BlogLines generated cached pages of user accounts for spiders to crawl.
  • Memory v. Disk: Notifications in OneList – they were keeping track of how many emails were sent to a mail list in memory.

Storage Choices

  • Relational DB v. flat files: Don’t underestimate the power of flat files. BlogLines uses subscriber information in a sleepycat DB, and blog articles are all in flat files.
  • RAID v. Redundant hardware: OneList was storing mail list articles on RAID, which doesn’t lose data in case of failure, but results in data being unavailable. With BlogLines, they replicate blog posts across machine, not just at the disk level, ensuring that even if storage failed, service was still available.
  • Linux Software RAID: Prefer software RAID over hardware

SysAdmin Choices

  • DNS round robin for web servers – no need for hardware load balancers
  • Hot backups for offline-processing
  • Worry about cooling at the co-lo. If you find yourself with a lot of hard drive failures, you should suspect a cooling issue. (Unless you determine, as they did, that Seagate drives suck).

Avoid making stupid bets

While working on OneList, he made bet that if they were successful, they’d have a big party and that he would shave his heads. They were successful – baldness ho!

Audience Questions

  • What is your strategy for choosing what to outsource? Choose isolated pieces of functionality that can easily be developed separated from the rest of the code. He has experienced disaster outsourcing core functionality. Put a boundary around what you will or won’t outsource.

Page Mailliard: How to Think About Legal Issues

This is part of my set of notes from the Startup School 2006 sessions at Stanford.

Page Mailliard is a partner at Wilson Sonsini Goodrich & Rosati, a law firm that has been responsible for taking many companies public. In her session, she covered the basics of setting up a company.

Setting Up a Company

Every company is different, and everything you face will be unique to you. You need to be sure to do it right the first time – get a lawyer who knows what they’re doing, and get the tried and true documents in place. Page, for example, is going to give you one option plan, one proprietary inventions agreement, etc. These are documents that have been distilled to perfection from experience. Doing it wrong can ruin your company, so get the legal structure in place correctly. Get it done, so you can get it out of the way and focus on your business. Doing so will save time, money, and, potentially, catastrophic errors.

Page recommends formation as a Delaware corporation, a C corporation; this is a company under which you can provide options to employees. Incorporation in Delaware is preferred because it has better case law – simple is better. The basic steps to incorporation (not doing into great details, given the audience) as a Delaware corporation:

  • Decide the amount of authorized stock: 20M common stock, 10M preferred, 3-5M founders’ shares
  • File your certificate of incorporation with the state: With Delaware, you can fax it direct to them and it will be handled immediately.
  • Establish the Board of Directors and the Officers of the company: Don’t distribute these too freely. Be very careful before you put someone on the board, because the board has a lot of power over you. Maybe start with a small board – maybe one or two members. The alternative is to put people you trust on a board of advisors instead of the Board of Directors. They can still be given options and help you, they just won’t be on the Board of Directors.
  • Enter into a stock agreement with the founders: Consider a vesting schedule for founders which distributes stock over time. This protects the company against a founder walking away with a stake in the company without staying and contributing to the company. If you come with more than one person and you don’t put vesting in place, there will be trouble when circumstance either fall out between the founders, or force them to leave the company for personal reasons.
  • Make sure the founders assign all their intellectual property to the company
  • Adopt standard documents: Adopt standard documents for the company bylaws, proprietary information agreements, option plans, etc – it just makes the whole thing a lot simpler. One thing to think about at this stage is what happens to options in the event of an acquisition. This is a big decision. You probably will want to reward your employees by accelerating options in the case of acquisition; however, many VCs will not invest if you have 100% acceleration in the event of acquisition. The reason is that they want to see that people still have a stake in the company and stick around after the acquisition to continue operating the business.
  • Seek trademarks and patents: This will be covered in another section during the sessions.

Two Important Questions to Answer

  1. Who owns the technology?If you can’t say who owns the technology, you don’t have a company. Investors will scrutinize if you own what you say you own. Three problem scenarios:
    • The former employer: You want to start a company, and have an idea while working at another company. They own ideas created on their time, with their resources. Example scenario: One company they worked with involved a programmer who used his current employer’s server to check out something he was working on – they’re had to rewrite some of the code, and give his employer some money because of his error.
    • The Microsoft intern: Let’s say there’s bunch of friends working on stuff. One of the friend gets and internship with Microsoft. Microsoft generally owns everything you dream up while working for them. To avoid this situation, you shouldn’t have anything to do with that person for the summer.
    • The Genentech Material Transfer Agreement: Company had used some genetic material from Genentech in their project for a technology to grow heart cells. Took the company years to get out of the agreement.
  2. Who owns the company?
    • No napkin promises: You should know who has the stock, shares, options, and can prove it. Don’t want some person to come out of the woodwork. They always show up at the acquisition or IPO, touting previous promises. Get the deal in writing. Always.
    • No tithing: For one company in the midwest, they got forecast of the revenues that had a funny vague footnote. Turned out the company had tithed 10% of their revenues to God. In the end, the lawyers had to argue scripture in order to have the 10% of revenues tithed to God to come out of the founder’s piece, not everyone’s.

Financing Considerations

  • Note on preferred stock: Always give preferred stock to investors; this forces them to pay more for those shares.
  • Interesting consideration: As employee option pool is non-voting, don’t forget to look at the effective voting rights distribution in a deal. Otherwise, a 50/50 split between the current company investors and a new investor in a new round may result in the new investor effectively running the company.

What About That First Term Sheet? (And How Do You Get It?)

  • Be very clear on the value proposition, the market opportunity and the significant ramp-up in the value your company can achieve.
  • Keep your slides and presentation short (10 slides – 15 minutes). These guys have listened to sooo many pitches and they have short attention spans. You need to talk to people about your idea and your presentation, revise each time. Don’t show all the backup evidence, but have it ready for when they ask.
  • Be credible. Do your homework on the fund, the people you will be meeting, your market projections, and your reference accounts
  • Bring “A” players on your team
  • Listen to others
  • Listen to yourself. While it’s true that you should get information from others – but at the end of the day you need to be able to go with your gut.
  • Your best leverage is another term sheet. Avoid the “no-shop” agreement; unless you completely have a deal in place, you will end up shooting yourself in the foot.
  • Get the best business partner you can – not necessarily the highest valuation – and the best board representatives

Audience Questions

  • What other recommendations do you have to avoid getting sued by current company? When you’re at the company, ask yourself is what you’re working on similar to what they’re doing. If it’s not significantly different, you might consider sitting down and talking with them. It’s all about relationships – talking with them will affect how they respond. If you give them time, tell them what you’re doing, you’re much less likely to have a problem. It’s always good to know who’s litigious.
  • What does it cost to get a lawyer? In this area, it’s more common for the lawyers to want to be part of risk of the company. At the same time, lawyers are very expensive. The way it usually works with their firm: if you’re really legitimate, we’ll write it such that there is a limit ($10-15K) that you can use without having to pay in the event you aren’t funded.
  • Is it normal for the seed investors to be diluted the same as the founders? Sometimes it can be a situation where they’re treated exactly the same, sometimes there may be an extra “kicker” for the seed round investors.
  • How can you resist bloat on the Board of Directors as you take on investors and complete subsequent investment rounds? It is really difficult to get people off the board. One entrepreneur commented that the biggest thing they learned was not to give away titles, as it made it difficult to hire new “A” players into the right position. Avoid putting people on the board in the first place if at all possible, or limit the number of seats taken by investors in each stage.
  • Is it common for the law firm to take a stake in the company? In some cases, yes. They may want to participate in the upside, perhaps even putting in money themselves. They have to be careful to avoid conflict of interest. But in general, no, they don’t expect to take any stock in the company.
  • How do you avoid innovating during “company time” when you’re salaried? One entrepreneur took an extended vacation to avoid this completely. As a general rule, make sure it’s not during normal business hours (9am-6pm), Monday-Friday.
  • But how do you avoid innovating using company resources when you have company-provided ADSL or cell phones? Don’t think they would win based on that, but easy to mitigate by buying another cell-phone, or paying for the service yourself.
  • What do lawyers like to hear from a company, as opposed to VCs? Are they credible, passionate, professional, and committed to the business? If you believe in what you do and have back-up for it, then they will too.
  • What’s the compensation you give to the board of advisors? 25K shares, regardless of the outstanding shares (which is kind of ironic). In the case of really big names, they might demand a percentage of the company, like 1%. It may be the right decision, given who they are and what they can do for the company. Of course, it would be a good idea to put vesting on it.
  • How do you protect yourself against corporate proprietary agreements? Make sure to disclose your prior inventions. As long as you’re doing it on your time, you should be protected.

Joe Kraus: Confessions of a Startup Addict

This is part of my set of notes from the Startup School 2006 sessions at Stanford.

Joe Krause is addicted to startups, and during his session he offered seven lessons he’s learned from his time at Excite and JotSpot. In addition, he summarized the major differences he sees between the environment for entrepreneurs in 1996 and 2006.

Lesson #1: Persistence pays

Netscape (early on in 1995) put two buttons from its browser (the web search and web directory buttons) up for bid. There were three bidders: Infoseek, MCI, and Excite. Excite had $1M, but bid $3M – the thinking was that if they won, they would figure out how to raise that much money – unfortunately they lost the bid. Instead of packing it in, they continued to pester Netscape, acting as if the negotiations weren’t over. MCI failed to meet their goals 21 days later and Excite won the bid. In the end, the difference between Excite being a $6.7B company, and nothing ended up being 21 days of persistence.

Lesson #2: It’s all about hiring

Joe’s core hiring philosophy: no false positives. Bad hires really screw up your company. A players hire A players; B players hire C players; and C players hire Losers. Although it’s hard to resist the urge to hire for the short term – but don’t give in. Hire slowly and carefully – it will make the difference between success and failure

Lesson #3: You make what you measure

Only measure the goals you want to achieve. For example, all subscription-based businesses (like JotSpot) measure ARPA, Average Rev per Account. The idea is to figure out how much money you’re getting from the customers of your business. Jotspot had two problems: it wasn’t measuring it initially, and it wasn’t going up. To turn this around, they started reporting on it every week. The first time they did this, the ARPA was $17.36; the second week, it was $31.72. By putting the measurement in front of of everyone and giving people the right feedback, you’ll generate the right results.

Lesson #4: Better to be a trend-spotter than a trendsetter

It’s better to be an early trend-spotter, than to create something entirely new and educate the market. No startup has enough money to move the market. For example, Jotspot is positioned as wiki – but why? Because it would take too much work to position as collaborative website. By leveraging the existing focus on wikis, they can use that coverage to gain awareness, and then branch out from there later. Being early is the same as being wrong – so many companies are great, but ahead of their time.

Lesson #5: Opportunities create opportunities

When you’re looking at deals, you can never predict where a given deal will take you. It’s hard to make rational decision. As Joe’s grandmother used to say, when someone offers you a cookie, take the cookie! You never pass up a cookie that’s put in front of you.

Consider the chain of events that led to Excite getting funding:

  • Joe’s college girlfriend gave him a book called Accidental Empires by Bob Cringley.
  • In his book, Bob encouraged people to call him up (“I’m a cheap date”) – and ended up introducing Joe and his team to InfoWorld.
  • Infoworld was looking to put archives online and needed a searchable index; they offered Joe and his team $100K to help this out. Plus, if they did a good job, InfoWorld promised to introduce them to IDG.
  • They did a good job and got introduced to IDG
  • At an IDG board meeting, met Steve Coit, a VC from Boston for Charles River Ventures. To do a deal, Steve needed a west coast partner, and thus introduced Joe and his team to Geoff Yang.
  • Geoff didn’t know what to do with them, and so introduced them to Vinod Khosia
  • In a meeting with Vinod, Vinod asked how the Excite technology would scale – unfortunately, Joe and his team couldn’t afford hard drive large enough to test large database indices. Vinod bought them one, ordering a $10K drive on the spot.
  • Through that relationship raised $3M without a business plan.

The moral of the story: it’s better to take the opportunities and see where they lead.

Lesson #6: Put your business model into beta when you put your product into beta

Jotspot screwed this up, by putting their product into beta without testing business model. The problem with this is that it resulted in skewed feedback. How you make your money is equally relevant in how people perceive your product.

Lesson #7: Celebrate your successes

Startups are a lot like the Olympic trials – a series of progressive milestones. As you cross the finish line in each stage, you think to yourself, “Wow, I made it!” And half a day later, you think to yourself, “Oh my God. I made it.” You’ve finished in first, but all that does is qualify you for the next heat, where you’re competing against similar companies who made it through the last round. No milestone is the finish line. As a result it makes it very important to celebrate every success you have.

How is 2006 different from 1996?

  • It’s easier than ever to start a company: Hardware is cheaper, Open Source software is free to use, there’s plentiful offshore labor, and search advertising allows you to cheaply reach audience
  • It’s no easier to start a business: It’s still difficult to get loyal customers
  • Funding is more available than ever
  • There’s a new funding model: As it’s a lot cheaper to start a company, it takes a lot less money. When you raise less money, it means that there are more successful exits than ever, especially with people who want to buy your company. Counterintuitively, taking more money may mean less opportunities for success. Considered two scenarios: Let’s say that you need/take $250K, selling 1/3 of the company to raise that amount and resulting in a post-money valuation of $750K; to generate a 5X return means that the company must be sold for $3.75M – lots of companies that can afford to buy you for that! Compare that to a case where you need/take $5M, sell 1/3 of the company to raise that amount and resulting in a post-money valuation of $15M; to generate a 5X return means that the company must be sold for $75M – not many companies can afford to buy you for that.

Ruby + SOAP4R + WSDL Hell

I’ve been spending a bit of time lately playing around with Ruby on Rails the last couple days, giving it a bit of a test to see what everyone’s raving about and understand how it could be used. Overall it’s a pretty impressive framework, and worth a little time investment to give it a whirl. For those without the patience, I highly recommend viewing the impressive presentation that demonstrates development of a blogging tool in 15 minutes.

That said, all is not sunshine and chocolate in the world of Ruby. I spent the better part of today trying to get some basic SOAP functionality operating to allow me to interact with Amazon Web Services’ E-Commerce Service. I was using Hiroshi Nakamura’s soap4r library to auto-generate Ruby class definitions from a WSDL file, but I was running into a bit of pain. There seems to be next to no information out there about how to use soap4r and the associated wsdl2ruby class generation utility, and even less about the current shortcomings of the current stable release of the library. In the interest of saving someone a day of time, I thought I’d put together some details about the wsdl2ruby tool, the files it generates, and what does and doesn’t work.

To complete this exercise, I assume you have already:

  1. Downloaded and installed Ruby (I used 1.8.2)
  2. Downloaded and installed soap4r (I used 1.5.5)
  3. Downloaded and installed http-access2 (I used 2.0.6)
  4. Signed up for an Amazon Web Services developer token (it’s free)

Just a disclaimer: I’m no whiz in the whole SOAP/WSDL arena, but I think the information I’m about to provide you with will be enough to help you figure out what’s going on when using soap4r. Your mileage may vary.

Generating Classes with wsdl2ruby

To create applications capable of accessing web services via SOAP, you could compose raw SOAP requests yourself (see the “Behind the Screens” article for more detail), but that would be a bit painful and require a fair amount of manual labor. I’m a lazy, lazy programmer, and I’m betting you’re the same.

A better approach is to use a framework that can automatically generate class definitions for a framework that can be used to create objects, map those objects to SOAP, and vice-versa. This is exactly what soap4r and the wsdl2ruby provides. Using soap4r, a developer can easily generate both client and server classes to handle consuming and providing SOAP-accessible services. For my purposes, I’m only interested in generating client code to allow me to develop an application that can consume services.

The wsdl2ruby application does exactly what it name implies: it takes a Web Services Description Language definition of a web service, and transforms it into Ruby code. For this exercise, I’m going to use the 2006-03-08 WSDL definition of the Amazon Web Services’ E-Commerce Service web service available here.

To generate client code for the Amazon.com web service from the WSDL description, run wsdl2ruby like this (your platform may require the path to be set appropriately):
wsdl2ruby.rb --wsdl http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl --type client --force

This command will generate three files:

  • AWSECommerceServiceClient.rb: An example client that provides skeleton code for exercising the web service. This code can’t really be run “out-of-the-box”, something I’ll talk about in a moment.
  • default.rb: The set of class definitions for all elements defined by the WSDL file. Using these class definitions, a developer will be able to produce and consume the various building blocks required to interact with the web service without needing to search an XML tree, or perform any other similar ugliness.
  • defaultDriver.rb: This file contains a single class, AWSECommerceServicePortType, which is used to conduct all requests of the web service.

Although I won’t be doing it for this exercise, you could easily rename default.rb and defaultDriver.rb as you see fit; however, you’ll have to make sure to update any require statements to reflect your new naming.

Using the Generated Sample Client

AWSECommerceServiceClient.rb provides a skeleton application that initializes a AWSECommerceServicePortType object:

#!/usr/bin/env ruby
require 'defaultDriver.rb'

endpoint_url = ARGV.shift
obj = AWSECommerceServicePortType.new(endpoint_url)

# run ruby with -d to see SOAP wiredumps.
obj.wiredump_dev = STDERR if $DEBUG

and then uses it to call each of the operations made available by the web service. The wsdl2ruby application auto-generates a skeleton for each operation that looks something like this:

# SYNOPSIS
#   ItemLookup(body)
#
# ARGS
#   body            ItemLookup - {http://webservices.amazon.com/AWSECommerceService/2006-03-08}ItemLookup
#
# RETURNS
#   body            ItemLookupResponse - {http://webservices.amazon.com/AWSECommerceService/2006-03-08}ItemLookupResponse
#
body = nil
puts obj.itemLookup(body)

Notice that body is set to nil, whereas the web service requires an ItemLookup object to work. To make this code work, you’d need to create an ItemLookup object – as it turns out, ItemLookup relies on ItemLookupRequest, so you’ll have to create one of those as well. The parameters required to create these objects are determined by the WSDL definition, and the order of parameters to pass to new are documented in part in default.rb; the meaning of those parameters are given in the Amazon Web Services’ E-Commerce Service API documentation.

As an example, let’s say I want to perform a simple lookup for an item with an ASIN of B00005JLXH – which just happens to be the unique Amazon identifier for Star Wars, Episode III (it was the first thing I saw on the Amazon home page, I swear). First I create the specific ItemLookupRequest object for that item:

itemLookupRequest = ItemLookupRequest.new("", "", "", "", "", "", "", ["B00005JLXH"], [], "", "", "", "")

Note that the class constructor generated by wsdl2ruby requires all parameters to be specified (their default value is nil), so you need to provide all the parameters. Use empty strings for the ones you don’t need or want to provide.

Next, I create an ItemLookup object, adding both my developer token and the ItemLookupRequest object I created above.

body = ItemLookup.new("", "Your Amazon Web Services developer token goes here", "", "", "", "", "", [itemLookupRequest])

Finally, I call the itemLookup method on my AWSECommerceServicePortType instance to execute the call to the web service, and print some output using the resulting ItemLookupResponse object as the source of the response data:

itemLookupResponse = obj.itemLookup(body)
 
itemLookupResponse.Items.each do |item|
  item.Item.each do |innerItem|
    puts "ASIN: #{innerItem.ASIN}"
    puts "Detail Page URL: #{innerItem.DetailPageURL}"
    puts "Title: #{innerItem.ItemAttributes.Title}"
  end
end

If you run the AWSECommerceServiceClient application with the –d option and you’ll see should see something like this:
Wire dump:

= Request

! CONNECT TO soap.amazon.com:80
! CONNECTION ESTABLISHED
POST /onca/soap?Service=AWSECommerceService HTTP/1.1

SOAPAction: "http://soap.amazon.com"

Content-Type: text/xml; charset=us-ascii

User-Agent: SOAP4R/1.5.5 (/114, ruby 1.8.2 (2004-12-25) [i386-mswin32])

Date: Sat Apr 01 19:59:04 Pacific Standard Time 2006

Content-Length: 1136

Host: soap.amazon.com

< ?xml version="1.0" encoding="us-ascii" ?>
<env :Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</env><env :Body>
<itemlookup xmlns="http://webservices.amazon.com/AWSECommerceService/2006-03-08">
<marketplacedomain></marketplacedomain>
<awsaccesskeyid> Your Amazon Web Services developer token goes here</awsaccesskeyid>
<subscriptionid></subscriptionid>
<associatetag> </associatetag>
<validate></validate>
<xmlescaping></xmlescaping>
<shared></shared>
<request>
<condition></condition>
<deliverymethod></deliverymethod>
<futurelaunchdate></futurelaunchdate>
<idtype></idtype>
<ispupostalcode></ispupostalcode>
<merchantid></merchantid>
<offerpage></offerpage>
<itemid>B00005JLXH</itemid>
<reviewpage></reviewpage>
<searchindex></searchindex>
<searchinsidekeywords></searchinsidekeywords>
<variationpage></variationpage>
</request>
</itemlookup>
</env>

= Response

HTTP/1.1 200 OK

Date: Sun, 02 Apr 2006 04:00:37 GMT

Server: Server

x-amz-id-1: 1KSRGANDWP7TE6SSCSPP

x-amz-id-2: aO3Y8m2+yt5uR7NPGKwLAeY6RG9w0BfZ

nnCoection: close

Transfer-Encoding: chunked

Content-Type: text/xml; charset=UTF-8

607

< ?xml version="1.0" encoding="UTF-8"?><soap -ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"></soap><soap -ENV:Body><itemlookupresponse xmlns="http://webservices.amazon.com/AWSECommerceService/2006-03-08"><operationrequest><httpheaders><header Name="UserAgent" Value="SOAP4R/1.5.5 (/114, ruby 1.8.2 (2004-12-25) [i386-mswin32])"></header></httpheaders><requestid>1KSRGANDWP7TE6SSCSPP</requestid><arguments><argument Name="Service" Value="AWSECommerceService"></argument></arguments><requestprocessingtime>0.0273821353912354</requestprocessingtime></operationrequest><items><request><isvalid>True</isvalid><itemlookuprequest><itemid>B00005JLXH</itemid></itemlookuprequest></request><item><asin>B00005JLXH</asin><detailpageurl>http://www.amazon.com/exec/obidos/redirect?tag=brendonwilson-20%26link_code=sp1%26camp=2025%26creative=165953%26path=http://www.amazon.com/gp/redirect.html%253fASIN=B00005JLXH%2526tag=brendonwilson-20%2526lcode=sp1%2526cID=2025%2526ccmID=165953%2526location=/o/ASIN/B00005JLXH%25253FSubscriptionId=0VS96BNQBVY904T3XZ02</detailpageurl><itemattributes><actor>Hayden Christensen</actor><actor>Ewan McGregor</actor><actor>Natalie Portman</actor><productgroup>DVD</productgroup><title>Star Wars, Episode III - Revenge of the Sith (Widescreen Edition)</title></itemattributes></item></items></itemlookupresponse></soap>

0

Once the request completes, the itemLookup method will return an ItemLookupResponse object, which will allow you to programmatically access all of the returned data in a simple programmatic fashion via the accessor methds generated by wsdl2ruby. In theory.

In theory, Communism works. In theory.

Unfortunately, wsdl2ruby is still seems to be a work in progress, and therefore doesn’t work as cleanly “out of the box” as one might like. For one thing, it seems to have some difficult with complex types. The example above will undoubtedly choke with something like:


C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/mapping.rb:202:in `const_from_name': private method `sub' called for nil:NilClass (NoMethodError)
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/mapping.rb:221:in `class_from_name'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:302:in `add_elements2stubobj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:298:in `each'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:298:in `add_elements2stubobj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:283:in `soapele2stubobj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:265:in `any2obj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:59:in `soap2obj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/mapping.rb:146:in `_soap2obj'
... 11 levels...
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/driver.rb:178:in `call'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/driver.rb:232:in `help'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/driver.rb:227:in `help'
from D:/Permanent Backup/Development/soap4r-1_5_5/sample/wsdl/test/AWSECommerceServiceClient.rb:20

This problem arise from the lack of a class name being generated for the OperationRequest associated with an ItemLookupResponse. As defined by the WSDL, an ItemLookupResponse is defined as:

<xs:element name="ItemLookupResponse">
<xs:complexType>
<xs:sequence>
<xs:element ref="tns:OperationRequest" minOccurs="0"/>
<xs:element ref="tns:Items" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>

Which results in the following code:

class ItemLookupResponse
  @@schema_type = "ItemLookupResponse"
  @@schema_ns = "http://webservices.amazon.com/AWSECommerceService/2006-03-08"
  @@schema_qualified = "true"
  @@schema_element = [["operationRequest", [<strong>nil</strong>, XSD::QName.new("http://webservices.amazon.com/AWSECommerceService/2006-03-08", "OperationRequest")]], ["items", [<strong>nil</strong>, XSD::QName.new("http://webservices.amazon.com/AWSECommerceService/2006-03-08", "Items")]]]

The problem here is the two highlighted nil class names generated by wsdl2ruby. The ClassDefCreator class in soap4r is responsible for generating this class definition – I took a lookup at the definition and found the following issue in dump_classdef (follow along in your own install of Ruby, in {ruby install path}lib/ruby/1.8/wsdl/soap/classDefCreator.rb):

if element.type == XSD::AnyTypeName
  type = nil
elsif klass = element_basetype(element)
  type = klass.name
elsif element.type
  type = create_class_name(element.type)
else
  type = nil      # means anyType.
  # do we define a class for local complexType from it's name?
  #type = create_class_name(element.name)
  # &lt;element&gt;
  #   &lt;complextype&gt;
  #     &lt;seq ...&gt;
  #   &lt;/seq&gt;&lt;/complextype&gt;
  # &lt;/element&gt;
end

The problem is that last type = nil statement. Basically, if ClassDefCreator encounters a complex type in the WSDL, it assigns a nil type. What’s odd is that there appears to be a perfectly good solution currently commented out of the code. If we change:

type = nil

to

type = create_class_name(element.name)

and regenerate the only the class definitions using wsdl2ruby:


wsdl2ruby.rb --wsdl http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl --classdef –force

then the definition of schema_element in the ItemLookupResponse class changes to:

  @@schema_element = [["operationRequest", ["OperationRequest", XSD::QName.new("http://webservices.amazon.com/AWSECommerceService/2006-03-08", "OperationRequest")]], ["items", ["Items[]", XSD::QName.new("http://webservices.amazon.com/AWSECommerceService/2006-03-08", "Items")]]]

Now, the soap4r framework will be able to find the appropriate class to use to represent the OperationRequest when transforming the response SOAP XML into a object. I’m a little puzzled why this fix is currently commented out in ClassDefCreator – I assume there’s probably a good reason. In all likelihood, this solution is probably commented out because the class name alone isn’t enough to avoid namespace clashes. I’m sure for a more complicated application consuming several web services this would undoubtedly be an issue, but for my purposes, this is not an issue.

Everything works flawlessly. Kinda.

Running the AWSECommerceServiceClient with these changes in place, the application throws another error:

C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:71: warning: Object#type is deprecated; use Object#class
C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/wsdlliteralregistry.rb:71:in `soap2obj': cannot map SOAP::SOAPElement to Ruby object (SOAP::Mapping::MappingError)
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/mapping.rb:146:in `_soap2obj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/mapping.rb:59:in `soap2obj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/mapping.rb:55:in `protect_threadvars'
from C:/Program Files/ruby/lib/ruby/1.8/soap/mapping/mapping.rb:55:in `soap2obj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/proxy.rb:479:in `response_doc_lit'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/proxy.rb:478:in `collect'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/proxy.rb:478:in `each'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/proxy.rb:478:in `collect'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/proxy.rb:478:in `response_doc_lit'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/proxy.rb:444:in `response_doc'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/proxy.rb:348:in `response_obj'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/proxy.rb:149:in `call'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/driver.rb:178:in `call'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/driver.rb:232:in `help'
from C:/Program Files/ruby/lib/ruby/1.8/soap/rpc/driver.rb:227:in `help'
from D:/Permanent Backup/Development/soap4r-1_5_5/sample/wsdl/test/AWSECommerceServiceClient.rb:20

Further investigation reveals that wsdl2ruby did not generate a Header class, required as part of the HTTPHeaders returned as part of the ItemLookupResponse:

<xs:element name="HTTPHeaders">
<xs:complexType>
<xs:sequence>
<xs:element name="Header" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="Name" type="xs:string" use="required"/>
<xs:attribute name="Value" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>

Hence, soap4r is unable to map the returned Headers XML to a Headers class. For some reason, wsdl2ruby seems to choke on nested complex type definitions. Saving the WSDL as a local file and changing the code above to:

<xs:element name="HTTPHeaders">
<xs:complexType>
<xs:sequence>
<xs:element ref="tns:Header" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Header" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="Name" type="xs:string" use="required"/>
<xs:attribute name="Value" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>

And regenerating the class definitions using

wsdl2ruby.rb --wsdl AWSECommerceService.wsdl --classdef –force

tricks wsdl2ruby into generating the correct Header class definition. As this similar construct exists throughout the WSDL, I performed similar changes throughout – primarily I changed the Arguments WSDL definition to make sure an Argument class is properly generated.

With those changes in place, regenerate the class definitions as before, and run the AWSECommerceServiceClient. This time it should provide the desired output:

ASIN: B00005JLXH
Detail Page URL: http://www.amazon.com/exec/obidos/redirect?tag=ws%26link_code=sp1%26camp=2025%26creative=165953%26path=http://www.amazon.com/gp/redirect.html%253fASIN=B00005JLXH%2526tag=ws%2526lcode=sp1%2526cID=2025%2526ccmID=165953%2526location=/o/ASIN/B00005JLXH%25253FSubscriptionId=0VS96BNQBVY904T3XZ02
Title: Star Wars, Episode III - Revenge of the Sith (Widescreen Edition)

Ah, Closure

Lesson of the day: my pain is your gain. While the wsdl2ruby utility is not fully baked to handle the full flexibility provided by WSDL, it can be cajoled into doing the right thing to get the results you desire. Although I was able to get my simple example working, I’m sure there’s any number of esoteric cases that the soap4r libraries don’t currently handle. Until they do, you’ll have to tinker a bit to get them working. Good luck!

On Immigration

Well, lucky me! I just got notice that I’m now a legitimate holder of a US green card – no more TN-1 visa for me! A pretty straightforward affair, made all the easier by the fact that I have an American wife. Yah, legitimacy!

Fight Club DVDAnd in other immigration news, I couldn’t help but recall a certain message from Tyler Durden in “Fight Club” as I watched the news from last weekend’ massive immigration-related demonstration in LA for undocumented alien rights:

We do your laundry, cook your food and serve you dinner. We guard you while you sleep. We drive your ambulances. Do not f–k with us.

Seriously, someone in the White House might want to consider who does a lot of the backbreaking work that actually keeps the country running.

Less Software, Please

A couple weeks back, I watched in horror as Microsoft Word insisted on butchering a contract that I was working on with my company’s general counsel. No matter what he did, Word unhelpfully shifted formatting and mangled clauses. An arsenal of editing tools, over a dozen years in the making, and yet it still fails making a basic word-processing task simple.

Now, in the past I’ve blamed the user for not learning how to use their tools. Sure, I thought, office productivity software requires some education, but even a pencil requires effort to learn how to use (remember grades one through seven) – why should general office productivity be any different? Shouldn’t we expect some general level of proficiency from a user?

Therein lies the problem – the user needs to invest in learning a set of generalized functionality that far exceeds the actual functionality they need to achieve their given task. The company lawyer doesn’t need a generalized word-processor, he needs an application that understands the standard form of legal contracts (clauses, sections, subsections), and provides limited spell-checking and redlining capabilities. Instead, Word provides a plethora of infinitely reconfigurable editing and formatting options that simply make no sense in the context of the production of a contract. The application is simply too powerful.

Users are paying for it – not only in terms of the price of a piece of software that contains more functionality than they could even hope to use, but also in terms of lost productivity.


The Innovator's Dilemma
Prior to this realization, I didn’t really think online word-processing tools like Writely, ZohoWriter, and Writeboard could hope to compete against Word. Now I’m not so sure. A little refresher of the tenets of disruptive innovation highlights the characteristics that indicate online word-processors may have what it takes to undermine Word over the long term. According to “The Innovator’s Dilemma“, disruptive technologies generally:

  • Underperform established products in established markets
  • Are cheaper, simpler, smaller, and, frequently, more easy to use
  • Provide features that a few fringe (and generally new) customers value

The last point is the critical one – providing new features that a few fringe customers value. Perhaps profession-specific toolsets might be one such way to achieve such differentiation from the behemoth that is Microsoft Word. Provided they don’t give Microsoft too many free ideas along the way.