tag:blogger.com,1999:blog-183330452009-02-21T05:04:51.317-06:00blog.mauricecodik.commaurice codik's blog about sofware development, programming languages, and technology.Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.comBlogger41125tag:blogger.com,1999:blog-18333045.post-83476441289074842922008-02-26T20:48:00.007-06:002008-02-26T22:19:25.771-06:00Dancing Gophers: Amazon Your Video WidgetFellow Amazonian <a href="http://www.rdicker.com/home/2008/02/dancing-gopher.html">Russell Dicker</a> reposted his <a href="http://www.amazon.com/review/RRNSFP7H938KL/">customer video review</a> of the Caddyshack dancing gopher doll on his blog using the new Amazon associates <a href="http://widgets.amazon.com/Amazon-Your-Video-Widget/list/">Your Video Widget</a>.<br /><br />The Your Video widget lets Amazon affiliates annotate their videos with Amazon.com products and share them on their website. Check out this video for an example:<br /><br /><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" align="middle" height="318" width="368"><param name="wmode" value="transparent"><param name="movie" value="http://ws.amazon.com/widgets/q?ServiceVersion=20070822&MarketPlace=US&ID=V20070822/US/russdick-20/8011/ea2cc970-3694-4471-b951-d6a8ae3d3bbe&Operation=GetDisplayTemplate"><embed src="http://ws.amazon.com/widgets/q?ServiceVersion=20070822&MarketPlace=US&ID=V20070822/US/russdick-20/8011/ea2cc970-3694-4471-b951-d6a8ae3d3bbe&Operation=GetDisplayTemplate" wmode="transparent" type="application/x-shockwave-flash" flashvars="ServiceVersion=20070822&MarketPlace=US&ID=V20070822/US/russdick-20/8011/ea2cc970-3694-4471-b951-d6a8ae3d3bbe&Operation=GetDisplayTemplate" pluginspage="http://www.macromedia.com/go/getflashplayer" align="middle" height="318" wmode="transparent" width="368"></embed></object><br /><br />Since this widget is part of the Amazon associates platform, the creator of the video widget earns a referral fee for all Amazon purchases made by viewers that click through on the links in the video. This is true even for embeds of the video on other websites: Russell is going to make all the associates cash for purchases made from the video on this post.<br /><br />I think this widget has great revenue potential for associates. If you create a popular viral video and publish it as a YVW, you can end up with thousands of your associates links all over the internet. It's ideal for publishing product review videos or for trying to monetize all of the funny videos you have laying around.<br /><br /><span style="font-style:italic; font-size: small">Disclosure: I'm an SDE on the team that developed the Your Video Widget. This is not an official Amazon message. All opinions expressed are my own and not of Amazon.</span><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-8347644128907484292?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-40158014568939406482008-02-08T21:06:00.000-06:002008-02-09T13:10:10.995-06:00Actionscript 2 is terribleI've been doing a some flash development for work recently. It mostly involves adding features to an already existing flash project, which means its written in Actionscript 2. <br /><br />I was really excited to learn AS2. Javascript is already one of my favorite languages, but it's sometimes a pain to deal with because of cross browser API and language differences. Since actionscript is an ecmascript dialect as well, I hoped that working with AS2 would be just like writing JS, but without the JS headache.<br /><br />The reality was totally different: Flash 8/AS2 is the most painful to use development platform I've ever had to deal with. No joke. Here are some highlights:<br /><br />1. In any sane dynamic language, what would you expect the output of this to be?<br /><pre><br />var x = undefined;<br />x.doIt();<br /></pre><br />I'd expect it to kick and scream. What does AS2 do? absolutely nothing. It just proceeds happily along as if nothing happened. You can imagine the silent failures and the hard to debug problems this can cause.<br /><br />2. Speaking of debugging, if you were hoping to see a stacktrace anywhere, you can forget about it. This is also one of the most annoying things about working in javascript as well.<br /><br />3. setTimeout is a pretty useful function. In fact, its so useful that it was added in the AS2 standard library. However, if you try to call it from an actionscript class, it'll fail to compile: it was just left out of the namespace! Thankfully, it's still callable if you tell the compiler to bugger off:<br /><br /><pre>_global.setTimeout(function () { ... }, 300);</pre><br />I'm amazed Macromedia's QA let this product launch with this bug. I'm even more amazed it was never fixed in any flash 8 player/compiler updates.<br /><br />4. When the Flash CS3 compiler detects an error, it adds a line of text into a "compiler errors" window, which by itself isn't too bad. However, it still outputs a SWF and tries to execute it anyway. Not only does this slow down the development cycle, but it also squashes your perfectly good SWF from your previous compile.<br /><br />5. AS2 doesn't include regular expressions in it's standard library. Awesome.<br /><br />There's a lot more I could whine about: combo boxes that stop working once your SWF is dynamically loaded in another, buttons that stop responding to click events once you give focus to a text entry box, tedious manual merges of FLA files, strange delayed initialization issues, etc. Overall, it's really terrible. It's pretty clear to me that Macromedia didn't really care about flash as a development platform, and were happy with it just being used for animation. <br /><br />Thankfully, AS3 seems to be much more pleasant to work with. I don't know if this due to Adobe's influence, or if Macromedia finally started to take flash as a dev platform seriously after flash 8. If you are starting a new flash project now, don't bother with AS2, just do it in AS3. Flash 9 already has 96%+ penetration in the US, the upgrade process is relatively painless for most flash 8 customers, and your developers will be much happier.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-4015801456893940648?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-63878761160015732002008-01-22T09:53:00.000-06:002008-01-22T10:09:36.189-06:00HAppS ExperiencesLast year I was working on a series on how to use <a href="http://www.happs.org">HAppS</a>, a haskell web applications framework, to build simple webapps. I was basing that series on my experiences developing the new version of the Openomy apis, which we <a href="http://api.openomy.com">finally launched</a> a few weeks ago!<br /><br />HAppS is a pretty nice framework.. even though its meant to be for generic web apps, I really think that building REST apis is its sweet spot: it's really good at generating xml out of your haskell types, and the HaXml xml parsing library is one of the nicest ones I've ever used (using combinators really beats hand rolling a SAX parser or hammering out an XSD). <br /><br />Unfortunately, HAppS is moving very very quickly. The posts I wrote last March are almost completely obsolete now. We ended up having to rewrite a sizable chunk of the API service when we upgraded to the much nicer HAppS 0.9.1.<br /><br />Ian wrote up some more details about our experience on the <a href="http://blog.openomy.com/2008/01/case-study-using-haskell-and-happs-for.html">Openomy blog</a>.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-6387876116001573200?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-84716814590323214722007-03-27T21:59:00.001-05:002007-03-27T23:05:27.231-05:00Building a Haskell Web Service, Part 2: The "Hello,World" Service<span style="font-style: italic;">This is the second post in a series about implementing the next major revision of the Openomy external API as a web service written in Haskell. Instead of focusing on the problems we faced getting started as I mentioned in the last post, I figured it would be more useful to show some code instead. I'll leave the rants for some other time ;)<br /><br /></span><span><a href="http://happs.org/">HAppS</a> is a web container in Haskell. Along with HTTP, it supports receiving emails via SMTP, has libraries to make DNS requests, has code to add ACID capabilities to your arbitrary in memory data structures, and apparently they are implementing integration with Amazon S3 and EC2: very awesome. At first glance it does seem to be a slightly bloated framework -- there is a <a href="http://hackage.haskell.org/trac/summer-of-code/ticket/1112">Google Summer of Code project proposal</a> out there to implement a more lightweight web framework -- but in practice all of that extra stuff doesn't really get in your way if you don't want to use it.<br /><br />My only real beef with HAppS is that the documentation could use some major updating-- it seems that the API is changing so quickly that the <a href="http://www.haskell.org/haskellwiki/HAppS_tutorial">HAppS tutorial</a> isn't keeping up. Thankfully, the authors of the framework all hang out on #happs on irc.freenode.org and are really helpful. The tutorial does have some working examples and the general concepts are still accurate, but some of the code samples don't even compile. Here is the working the "Hello world" web service in HAppS, that I wrote when trying to learn the framework. </span><span>From now on I'm going to assume basic knowledge of working in Haskell and that you're using HAppS 0.8.8.<br /><br />HelloWorld.hs:<pre>module Main where<br /><br />import HAppS<br /><br />-- define the data type you will be returning from your handlers.<br />-- for simplicity, we will just use a File, which is represented by<br />-- its filename and its id number.<br />data ServiceValue = File String Integer<br /><br />-- a handler that just responds with a File named test.txt<br />getFile () () = respond $ File "test.txt" 1<br /><br />-- since our web service will return XML, we need to tell HAppS<br />-- how to convert a ServiceValue to XML. This is done by creating<br />-- an instance of the ToElement typeclass. HAppS provides<br />-- a few XML primitives that makes generating XML pretty simple.<br />instance ToElement ServiceValue where<br /> toElement (File filename fileId) = listElem "file" [] [<br /> textElem "id" [] (show fileId)<br /> , textElem "name" [] filename<br /> ]<br /><br />-- we also dont want any stylesheets attached to our returned XML.<br />-- HAppS uses the ToMessage type class to convert values to<br />-- the actual message sent down the wire. this calls<br />-- the default toMessageM which knows how to use ToElement,<br />-- and adds other things such as the right content-type and<br />-- an XML prolog<br />instance ToMessage ServiceValue where<br /> toMessageM = toMessageM . XML NoStyle<br /><br />-- glue it all together: make the getFile function listen to<br />-- the GETs to the /file url. noState tells the type system and<br />-- HAppS that this service is stateless.<br />main = stdHTTP [ h ["file"] GET $ ok getFile, noState ]<br /></pre></span><span>The comments should give a basic overview of how it works. To compile this with ghc, run: <pre>ghc -package HAppS -o helloWorld HelloWorld.hs</pre>Running it starts serving our simple requests from http://localhost:8000/file.<br /><br />HAppS models the handling of web requests as a list of filters, which are passed into the stdHTTP function which implements the server's main event loop. The "h" function lets you bind a particular handler to a URL and HTTP method, in this case our simple getFile function. The rest is telling HAppS how to turn your internal values into XML, and generating these values based on the requests being received. The use of type classes makes the framework extremely flexible: returning other formats is just a matter of creating your own instances of ToMessage (HAppS also includes support for JSON out of the box).<br /><br />In the next post of the series, I'll show how we're using HAppS' filters to validate incoming service calls and handle user authentication.<br /><br /></span><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-8471681459032321472?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com1tag:blogger.com,1999:blog-18333045.post-15893524906199072182007-03-26T10:58:00.000-05:002007-03-28T11:21:17.618-05:00Building a Haskell Web Service<span style="font-style: italic;">This is the first post in a series about implementing the next major revision of the Openomy external API as a web service written in Haskell.</span><br /><br />One of the cool things about having a website outside of your normal job is the ability to experiment with different technologies. We've done this pretty successfully with <a href="http://openomy.com/">Openomy</a>: it started out as a monolithic C# mod_mono + mysql application that stored files on the local disk and has now evolved into a much smaller mod_mono frontend, 4 services (3 in rails, 1 in java) and backed by Amazon S3 storage.<br /><br />The next part of the original application we wanted to reimplement was the handlers for the <a href="http://documentation.openomy.com/">Openomy API</a>. The current implementation was inflexible, hard to extend, and was poorly suited to our new backend infrastructure.<br /><br />We chose to implement the API bridge in <a href="http://www.haskell.org/">Haskell </a>for a few reasons:<br /><ol><li> You can model the external API as two functions: one that maps the client's input to the XML we send to our services, and another for our services return XML to our external output. This made us think that it may be fun to do it in a functional style.</li><li>We were worried about library support, but it turned out that Haskell had all of the libraries we needed: a <a href="http://www.happs.org/">web container</a>, a powerful and flexible way to <a href="http://haskell.org/HaXml/">transform XML</a>, an <a href="http://www.haskell.org/http/">http client</a>, and simple <a href="http://www.haskell.org/crypto/">cryptography libraries</a>.<br /></li><li>After reading the <a href="http://haskell.org/HaXml/icfp99.html">paper on HaXml</a>, I was really looking forward to using their combinator library to produce the XML mapping functions we needed. It seemed like a very powerful and flexible framework, without being as tedious and error-prone as working with other XML libraries in other languages.<br /></li><li>Most importantly, it would be the most interesting: I've been wanting to learn Haskell for some time now.<br /></li></ol>However, there were also a few arguments against picking Haskell:<br /><ol><li>It's one of those languages that will stretch your mind, especially if you're coming from a mostly object-oriented programming background. Picking it for a major project is a large risk and may delay getting the new service out the door.<br /></li><li>Haskell is mostly a research language: the community isn't very large and we didn't know any people that had successfully used it for a mainstream application.<br /></li><li>The API bridge is heavily IO dependent (making service calls over HTTP). Haskell's monadic IO system takes a little time to get used to and understand.<br /></li></ol>About a month ago, I bought a copy of the <a href="http://www.amazon.com/Haskell-School-Expression-Functional-Programming/dp/0521644089/">Haskell School of Expression</a> and started learning the language. Shortly afterwards, I convinced Ian to start learning it as well, and soon we had started. We were both a little nervous about it-- the day we started working on it, we observed that this may be the beginning of the worst software project in the years we've been working together. We've also been tracking how many times we've said "we're f*cked" during development. I'm sure we're well into the double digits by now :)<br /><br />After a few initial bumps on the road, the project is moving along nicely now. The problems we had getting started will be the subject of the next post.<br /><br />UPDATE: <a href="http://blog.mauricecodik.com/2007/03/building-haskell-web-service-part-2.html">Part 2 has been posted</a>.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-1589352490619907218?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com3tag:blogger.com,1999:blog-18333045.post-1157611855094105252006-09-06T23:20:00.000-05:002006-09-07T01:50:58.726-05:00Long time no seeIt's been a couple of months since I've last written, but I assure you there will be much more to read here soon. Some updates and short thoughts:<br /><ul><li><a href="http://www.amazon.com/Ruby-Cookbook-Cookbooks-OReilly/dp/0596523696">The Ruby Cookbook</a> was just recently released. It's huge, and has a lot of useful recipies for all-around ruby hacking. I contributed an adaptation of <a href="http://blog.mauricecodik.com/2005/10/ruby-meta-programming-software.html">this old blog post of mine</a> as one of the recipies entitled "Enforcing Software Contracts" on page 367. Hope it helps you all add some metaprogramming sauce to your programs.</li><br /><li>I recently moved out to Seattle, WA to take a job as a Software Development Engineer for Amazon.com as a member of the Community Content team. I'm really enjoying the switch so far, and I'm looking forward to becomming a regular to the seattle.rb events soon as I become more settled. An update to the "About Me" post is coming soon.</li><br /><li>While signing in to write this blog post, I stumbled upon the new <a href="http://beta.blogger.com">Blogger beta</a>. It looks like blogger is finally catching up to the state of the art in blogging platforms. However, the beta still doesnt support publishing to other domains, which is a total dealbreaker for me for now. Hopefully that feature is coming back soon. On another note, the beta supports a new <a href="http://code.google.com/apis/gdata/blogger.html">GData powered API</a>.</li><br /></ul>That's it for now-- more coming soon.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-115761185509410525?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com1tag:blogger.com,1999:blog-18333045.post-1151623011007816492006-06-29T17:45:00.000-05:002006-06-29T18:16:51.136-05:00Google Checkout will not kill AmazonThe blogosphere is going nuts about <a href="http://checkout.google.com">Google Checkout</a> today. The most controversial opinion comes from <a href="http://news.com.com/2061-12572_3-6089368.html" rel="nofollow">Rafe Needleman over at CNET</a>, which calls Checkout an "Amazon Killer"<br /><br />He couldn't be more wrong: People don't shop at Amazon just because you have your credit card information saved there-- almost all major e-commerce sites let you save your credit card info. People shop at Amazon because of low prices, huge selection, cheap/free shipping and great reliability. Google checkout provides none of this-- it is not a store, just a system to store credit card info. It is merely the Google version of <a href="http://wallet.yahoo.com/">Yahoo Wallet</a>. Amazon and eBay have nothing to worry about. In fact, there's nothing stopping them from supporting Checkout themselves (aside from potential not-invented-here reasons).<br /><br />Checkout is certainly significant, but not for the reasons Needleman mentions: The best part about Checkout comes by integrating it with Google advertisements. Forget cost-per-click, it's now cost-per-sale! This change makes click fraud is no longer something to worry about, which was one of the thorns in Google's side, at least in terms of Wall St perceptions of their business model. <br /><br />I think Needleman's post is just another example of people <a href="http://blogs.zdnet.com/web2explorer/?p=224">gaming the blogosphere</a>, as Richard MacManus ranted about the other day-- just write any "XYZ vs Google" post with an sensationalist headline and watch the hits roll in (this is the #3 post on techmeme right now). For this, Needleman gets a "nofollow" on my link-- this type of stuff shouldn't be encouraged.<br /><br /><a href="http://technorati.com/tags/google+checkout" rel="tag">google checkout</a> <a href="http://technorati.com/tags/amazon" rel="tags">amazon</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-115162301100781649?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com4tag:blogger.com,1999:blog-18333045.post-1151277217312227192006-06-25T17:37:00.000-05:002006-06-25T18:13:37.376-05:00RailsConf '06 WrapupRailsConf 06 just finished a few hours ago, and overall it was a great conference. Here are the day by day highlights:<br /><br />- Intro to Capistrano: This session had people sitting out the door trying to listen. I hadn't seen cap in action at all til the conference, and I was really really impressed. We're seriously considering switching to cap instead of our current NUnit-based deployment and build cycle for Openomy.<br /><br />- Rails Optimization: This talk started out a little slow, but then was amazingly impressive. Stefan Kaes demonstrated how to optimize your Rails app- what types of things to avoid, etc. He developed a view compiler which does some automatic optimizations on you views (such as pre-computing url_for calls, inlining some helpers, etc) which cause almost a 5x performance increase on complex pages!<br /><br />- Demos & Lightning talks: Lots of really cool stuff was shown off. I was really impressed with <a href="http://www.tunecore.com/">Tunecore</a>, a service that allows artists to submit albums to a variety of music services. <a href="http://rightcart.com/">Rightcart</a> was also a really cool way to embed a shopping cart to arbitrary webpages.<br /><br />- Keynotes: All of them were fantastic. Martin Fowler was an excellent speaker, and Paul Graham presented a great essay as usual. I already blogged about <a href="http://blog.mauricecodik.com/2006/06/instant-rest-on-rails-activeresource.html">DHH's great talk last night.</a> Dave Thomas' opening keynote a Hilbert-style "3 big problems for Rails adoption," which was a good call to action to kick everything off. Interestingly enough, by the time the conference was over, a few people had announced solutions to a few of these.<br /><br />- Metaprogramming: There were 4 pretty good talks on the use of DSLs, metaprogramming, and other advanced Ruby. The best was Scott Halloway's "MetaRails" talk, which explored how a few of the more interesting features of Rails are implemented (ex, class reloading). <br /><br />Overall, the conference was phenomenal-- you can never beat the excitement and energy of a "first conference." RailsConf '07 will be co-sponsored by O'Reilly, so it promises to be a much bigger show. I'll definitely try to make it out to that.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-115127721731222719?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com3tag:blogger.com,1999:blog-18333045.post-1151209522327222322006-06-24T22:55:00.000-05:002006-06-24T23:25:22.360-05:00Instant REST on Rails: ActiveResourceDHH gave his keynote at <a href="http://www.railsconf.org">RailsConf</a> tonight, and it was totally awesome. It focused on the new CRUD features that will show up in Rails 1.2, and all of the niceness that comes out of them. <br /><br />Taking a page from REST protocols such as <a href="http://www.ietf.org/internet-drafts/draft-ietf-atompub-protocol-08.txt">Atompub</a> and the related <a href="http://code.google.com/apis/gdata/">GData</a>, Rails will support "resources." These resources are designed to support basic CRUD operations, which are driven by the full set of HTTP verbs: GET, POST, PUT, and DELETE. This, combined with the #respond_to and #to_xml methods already in Rails, as well as some enchancements to the Routes package, allow programmers to build very DRY RESTful websites and webservices. <br /><br />The coolest part of the keynote was the Steve Jobs-esque announcement of the ActiveResource library, which DHH just started building a few days ago. This new library would abstract a REST webservice built following certain conventions, similar to how ActiveRecord currently abstracts a relational database. For example, you would write:<br /><blockquote><pre>Person = ActiveResource::Struct.new do |p|<br /> p.uri "http://www.myhost.com/people"<br /> p.credentials :username => "maurice", :password => "pass"<br />end<br />person = Person.find(1)<br />person.name = "Maurice"<br />person.save!<br /></pre></blockquote><br />Which would connect to the REST resource located at the give URI, and then use GET/POST/PUT/DELETE to interact with it-- essentially giving your REST webservice a free library that enables you to consume it. In this example, it would call "GET /people/1", turn the resulting XML into a struct. Then it would POST an updated copy of the struct to the service.<br /><br />ActiveResource will make it almost trivial for Ruby programs to consume RESTful services and make it really easy to integrate multiple Rails applications, all while keeping a very simple API. Overall it looks great, and I'm really looking forward to be able to play with it.<br /><br />Tags: <a href="http://technorati.com/tags/railsconf" rel="tag">railsconf</a> <a href="http://technorati.com/tags/activeresource" rel="tag">activeresource</a> <a href="http://technorati.com/tags/rest" rel="tag">REST</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-115120952232722232?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-1151025846767703592006-06-22T19:36:00.000-05:002006-06-22T20:24:06.780-05:00Windows Live integration is going to be HUGE<a href="http://news.com.com/2100-1012_3-6085363.html">An article on CNET</a> the other day described Microsoft's announcement of an SDK that would allow deskop applications with Windows Live ID. <a href="http://blogs.zdnet.com/web2explorer/?p=216">Richard MacManus commented</a> shortly afterwards about how big this for Microsoft:<br /><blockquote>This strategy will define Microsoft's future, because in many ways it's the bridge between the old world (desktop software and the Windows OS) and the new world in which Google is a pioneer (web apps)</blockquote>I totally agree-- Microsoft is one of the few companies with the reach to be able to take the web application mainstream. Just the Live ID API has potential to be the ultimate single sign-on solution: imagine being signed on to all of the windows live services just by starting a user session in Windows. Users may never have to sign in more than once again, and Microsoft would have an instant audience for its Live services. <br /><br />This has implications for the online storage space as well: MSFT could automatically give all its users a small <a href="http://arstechnica.com/journals/microsoft.ars/2006/4/19/3668">Live Drive</a> account, sign-on to it on start up, and integrate it with Windows Explorer. Depending on how well this is executed, it could totally change the game for the many online storage services out there (including <a href="http://www.openomy.com">Openomy</a>).<br /><br />It will also be interesting to see is how tight the integration will be: Microsoft has gotten into a lot of trouble before by integrating IE and Windows Media Player into the OS. Successfully integrating the desktop with Windows Live would make life a little more difficult for many web startups and reignite antitrust concerns. With all the changes going on at MSFT recently, I'm really looking forward to seeing how this one plays out.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-115102584676770359?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-1150851479028296262006-06-20T18:48:00.000-05:002006-06-20T22:16:44.210-05:00Econ 201: Oligopolies suckBasic economic theory explains that oligopolies are inefficient, and should be avoided in favor of a free market with many many competitors. In college, we even mathematically "proved" it (with a few simplifying assumptions, of course)! Even if it is a fact, it's still great to see real-world examples that prove my old Econ 201 prof right.. there have been a few in the news recently: <a href="http://online.wsj.com/article/SB115047057428882434-email.html">DRM</a> and <a href="http://www.weeklystandard.com/Utilities/printer_preview.asp?idArticle=12348&R=ECCBA034">Net neutrality</a><br /><br />What's missing in both cases is a good dose of competition. Unfortunately it's the <a href="http://blog.mauricecodik.com/2005/12/innovators-dilemma.html">innovator's dilemma</a> again: their significant market power makes these companies lazy and gives them the ability to do as they please. Telcos can provide over-priced, slow service to users, and then can threaten to charge web companies for being able to interact with their customers. The entertainment industry can impose DRM'ed content on all of us, essentially taking full control over how content is used and distributed. Both of these issues would go away immediately if consumers had viable alternatives. <br /><br />Where the heck are all the companies that are trying to disrupt the current state of these industries? I can think of many that have tried, but none that have made a lasting impact.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-115085147902829626?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-1149882439471407692006-06-09T14:14:00.000-05:002006-06-16T15:19:40.506-05:00H1-Bs and startups<a href="http://blog.meebo.com/?p=147">This post on the Meebo blog</a> the other day about their experience with H1-B visas caused quite a stir in the comments. This year the H1-B quota was all used up about 2 months, leaving a lot of companies and a lot of people in a pretty bad situation: now two of meebo's new team members cant work in the US for another year and a half! Thats *aaages* in internet time. When this happens for a large corporation its already bad enough, but for a company the size of meebo, those two new employees represent like 20% of their workforce!<br /><br />When the topic of immigration policy comes up, there's always a pretty fiery debate. The comments were full of stories about abuse of H1-B workers and the standard protectionist economics arguments in favor of the quota. While the protectionist argument does make a lot of political sense-- the people that benefit directly from it are the ones with the larger voting power-- economically it's probably the wrong solution.<br /><br />If you want to make sure that Americans get the best jobs, then focus on making Americans the most qualified for that job and optionally provide businesses with an incentive to hire them. Depending solely on articifial barriers, such as an immigration quota, only avoids solving the true problem and creates the wrong incentives. For example: the most common suggestion given in the comments was to open a meebo office in another country. The current quota program encourages companies to send jobs offshore, where the workers wont be paying US taxes or contributing to the US GDP.<br /><br />The truth is that the kind of people Meebo is looking for really are in short supply: not any schlub that knows some javascript is going to cut it. They want the smartest and the most innovative people they can get-- if the first ones they find happen to be born outside of the US, then so be it. It is more costly for the economy for companies like meebo to either have to lower their hiring standards or to wait for a local hire to appear, than it is to bring someone in from another country. (While it may only take an extra month to find a local hire, by that time meebo could've pushed out two new releases of features to their servers!) These startups and technology companies are keeping the US on the cutting edge of technology, and it is in the country's best interest to make sure they have the workforce they need to keep it that way. <br /><br />I'm not advocating totally removing the quota either... there were many examples in that thread of comments that describe why this is undesireable. A better system must exist between these two extremes. Hopefully, now that immigration reform has become a mainstream political issue, there will be some dialog that results in a better system for both businesses and Americans. <br /><br /><em>Disclaimer: I'm on an H1-B visa in the USA, and I'm really grateful for the opportunity to be here. However, this may cause me to be a bit biased on this issue ;)</em><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114988243947140769?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com2tag:blogger.com,1999:blog-18333045.post-1149872019694437292006-06-09T11:31:00.000-05:002006-06-09T13:51:53.593-05:00The State Pattern, Ruby-styleOne of the cool things about using a language that allows for metaprogramming is that you can reduce the amount of boilerplate code you have to write. Common patterns can be put into libraries, and give you a small DSL that you can use to replicate this pattern all over your code. A good example of a common pattern with lots of boilerplate is the state pattern: where the behavior of an object changes depending on the internal state of the object. This can be accomplished by using a simple 'if' statement, or by modeling a finite state machine.<br /><br />Check out a sample implementation <a href="http://wiki.rubygarden.org/Ruby/page/show/StatePattern">on the RubyGarden wiki</a>. We have a class for each state, a common parent class for the states, and a context class that delegates to the current active state class. That's a lot of code that doesnt really do much. Enter the StatePattern module, which puts all of this boilerplate in a small mix-in module, and ties everything together with some metaprogramming glue. Now we can write:<br /><blockquote><pre><br />class Connection<br /> include StatePattern<br /> state :initial do<br /> def connect<br /> puts "connected"<br /> transition_to :connected, "hello from initial state"<br /> end<br /> def disconnect<br /> puts "not connected yet"<br /> end<br /> end<br /> state :connected do<br /> def initialize(msg)<br /> puts "initialize got msg: #{msg}"<br /> end<br /> def connect<br /> puts "already connected"<br /> end<br /> def disconnect<br /> puts "disconnecting"<br /> transition_to :initial<br /> end<br /> end<br /> def reset<br /> puts "reseting outside a state"<br /> transition_to :initial<br /> end<br />end<br /><br />c = Connection.new<br />c.disconnect # not connected yet<br />c.connect # connected<br /> # initialize got msg: hello from initial state<br />c.connect # already connected<br />c.disconnect # disconnecting<br />c.connect # connected<br /> # initialize got msg: hello from initial state<br />c.reset # reseting outside a state<br />c.disconnect # not connected yet<br /></pre></blockquote><br />.. and the boilerplate is all gone. How's it all work? Each call to state defines a new subclass of Connection that is stored in a hash. Then, a call to transition_to instantiates one of these subclasses and sets it to the be the active state. Method calls to Connection are delegated to the active state object via method_missing. This was a tricky one to get right! Download the source from <a href="/projects/ruby/state_pattern.rb">here.</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114987201969443729?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com2tag:blogger.com,1999:blog-18333045.post-1147242089450273972006-05-10T00:27:00.000-05:002006-05-10T01:21:29.510-05:00Domain Specific Languages and their LimitationsIt seems that a lot of people are raving about the use of domain specific languages in Ruby these days-- where clever uses of eval, load, etc make normal Ruby code look like the language of the problem domain. Rails has a few good examples of this, such as ActiveRecord, which can be considered to be a DSL for describing data models. <br /><br />It's really great to see these ideas becoming more mainstream.. However, I'm concerned that it's an idea that can be taken too far. Here's an example from <a href="http://jayfields.blogspot.com/2006/05/dry-code-damp-dsls.html">Jay Fields:</a><br /><blockquote>if the '$5-$10 Limit' list is more than 12 then notify the floor to open</blockquote><br />A business user can read this and think: This looks like English, I can speak English so therefore I can edit this with out a problem. Let me specify that this can only happen after 5pm:<blockquote>if the '$5-$10 Limit' list is more than 12 and it is later than 5pm<br /> then notify the floor to open</blockquote><br />What happens then? most likely, the program will break with a strange error about "it" being undefined. The key issue is that we are only simulating English: in reality it is still Ruby, which has a strict syntax and requires methods to be defined before they are used. From an HCI perspective, allowing users to pretend to write English code gives them an illusion of freedom-- which can cause significant frustration if the expectation of freedom is not met. The only way I can see around this is to make sure that the users of the DSL understand the basics of programming languages and are trained to understand the limitations of their particular DSL. I'd be interested to hear about how Jay and his team are dealing with these issues.<br /><br />In the long run, I don't think the main value from DSLs will come from allowing non-techincal users to encode business rules, but instead in helping programmers make their programs more DRY. The best examples of DSLs from the Ruby world, such as ActiveRecord, Rake and Capistrano all fall into this category.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114724208945027397?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com3tag:blogger.com,1999:blog-18333045.post-1146934852677036182006-05-06T11:35:00.000-05:002006-05-06T12:00:54.200-05:00That's not a bug, it's a feature!I spent about an hour trying to fix a bug in a javascript calendar I was working on... see if you can spot it:<br /><br />I had dates in MM-YYYY format, that I was trying to parse the month out of. My code (simplified):<br /><pre><blockquote><br />function parseMonth(mmyyyy) {<br /> var splitMMYYYY = split('-', mmyyyy);<br /> return parseInt(splitMMYYYY[0]);<br />}<br /></blockquote></pre><br />Now the bug: month was being set to 0 for dates in August and September, both in IE and Firefox. See if you can figure out why.. <a href="http://www.faqts.com/knowledge_base/view.phtml/aid/8108/fid/53">here's the answer</a>. <br /><br />If thats not a bad default, I dont know what is.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114693485267703618?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-1145664546961125522006-04-21T18:10:00.000-05:002006-04-21T19:09:07.010-05:00More on walled gardens and protocols<a href="http://blogs.zdnet.com/web2explorer/?p=165">Richard MacManus</a> linked to my <a href="http://blog.mauricecodik.com/2006/04/gdata-end-of-googles-walled-garden.html">previous post on GData</a>. One particular sentence right at the end caught my attention:<br /><blockquote>I'm not sure if this points to less of a walled garden, or paradoxically more of one because Google is defining the protocol now.</blockquote><br />This is misleading: Yes, GData is a new protocol in some sense, but its really just sending plain XML over plain HTTP. No wacky binary transmissions that need to be reverse engineered, nothing truly proprietary. It's certainly not an old-Microsoft-style "embrace and extend" trick-- It's based on open standards and the provided libraries are open source (Apache licensed).<br /><br />I think that "protocol" has become a slightly loaded term. It's really just a convention used to communicate between two endpoints. So by this definition, any API (even the <a href="http://documentation.openomy.com">Openomy API</a> I work on) can be considered a protocol. I think the past has left negative associations with the word protocol-- hearing a company say they are creating a new protocol just naturally raises red flags of vendor lock-in and closed tools. <br /><br />I'm still optimistic about GData-- I'm sure there's nothing like that to worry about here.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114566454696112552?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-1145634951732617802006-04-21T09:50:00.000-05:002006-04-21T15:47:13.500-05:00GData: The end of Google's walled gardenGoogle's recent release of the <a href="http://code.google.com/apis/gdata/protocol.html">GData</a> protocol has caused <a href="http://www.buzzmachine.com/index.php/2006/04/21/google-syndication/">some confusion</a>. <br /><br />It's a matter of interpreting it correctly: GData is not a stand-alone application, <b>it's just a protocol</b>. It is a general framework for posting/editing/deleting XML data to already existing feed. <br /><br />For example, check out the <a href="http://code.google.com/apis/gdata/calendar.html">Google Calendar API</a>. Here it is, in a nutshell: Google has an XML schema that lets you describe events on your calendar. Adding/editing/removing events on your Google calendar is just a matter of using the GData protocol to put/update/delete the XML representation of an event to a feed provided by Google Calendar. GData just handles all the infrastructure stuff, such as authentication, versioning, etc.<br /><br />Other objects in Google-land have their own XML schema (Google calls these <a href="http://code.google.com/apis/gdata/common-elements.html">kinds</a>). For example, the Message kind can be used to represent an email, a blog entry, a comment on a blog post, and a posting on a newsgroup. The Contact kind can represent a person, a location, or venue. Using the GData protocol, Google can create APIs that let you interact with each of these kinds.<br /><br />Now, what does this all mean? In the past, Google has taken a lot of flak for being a walled garden: the data that users put on a Google app, is only accessible thourgh that application (<a href="http://base.google.com">Google Base</a> is the most famous example of this). GData changes the situation completely: it provides a framework for Google to easily and consistently create APIs for all of their applications. <br /><br />Put simply, GData means that the walled garden of Google's applications is coming to an end. I'm really excited to see what will come out of this.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114563495173261780?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com1tag:blogger.com,1999:blog-18333045.post-1145419241932720492006-04-18T22:42:00.000-05:002006-04-18T23:00:41.970-05:00Hash Auto-vivificationOne of the more convenient (but sometimes bug-creating) features in Perl is autovivification: a variable is created just by referring to it (or, comes to life on its own). This is useful for creating composite data structures out of hashes or arrays-- for example, writing '$a{"a"}{"b"} = 3;' creates a hash of hashes called %a for you automatically.<br /><br />Ruby doesn't have this "feature" by default, but like many other things in Ruby, you can work around it. Here's one neat way to autovivify hash-of-hashes, using recursion and Hash default procs <a href="http://www.ruby-forum.com/topic/61303#61910">(posted by Bill Kelly on ruby-talk)</a>:<br /><pre><br />HashFactory = lambda { Hash.new {|h,k| h[k] = HashFactory.call} }<br /><br />irb(main):181:0> x = HashFactory.call<br />=> {}<br />irb(main):182:0> x['abc']['def']['ghi'] = 123<br />=> 123<br />irb(main):183:0> x<br />=> {"abc"=>{"def"=>{"ghi"=>123}}}<br /></pre><br /><br />Awesome...<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114541924193272049?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-1145332065235125742006-04-17T20:52:00.000-05:002006-04-18T23:22:19.616-05:00Unfair competitive advantages don't exist on the web<b>UPDATE:</b> Here's another good post on this same topic over at <a href="http://earlystagevc.typepad.com/earlystagevc/2006/04/what_are_your_b.html"><br />EarlyStageVC</a><br /><br />When Ian and I presented about Openomy at the Techdirt Greenhouse this past March, we spoke right after <a href="http://www.andykessler.com/">Andy Kessler</a>, an author and successful investor. He was a pretty tough act to follow-- he was a really good speaker and had some pretty interesting things to say. When discussing his invesment philosophy during his talk, he mentioned that when he is evaluating a potential investment in a business, he looks for what he calls an "unfair competitive advantage."<br /><br />Yes, having an unfair advantage would be excellent, and from an investment point of view, I agree it would be ideal. However, I think its a totally unrealistic expectation, especially when it comes to investments in web applications. The vast majority websites out there are just a product of good ideas, programmer-hours, and good execution. None of these things are a source of a sustainable advantage: any innovative website will spawn many many copy-cats, some of which will be run by people just as talented and motivated as the creators of the original site. This is completely unavoidable. If you honestly believe that no other company can copy or improve on your creation, you are kidding yourself.<br /><br />Coincidentally enough, the folks at Techdirt did a pretty good job at explaining why insisting on an unfair advantage is silly in <a href="http://techdirt.com/articles/20060414/0120234.shtml">a post this past weekend about patents</a>:<blockquote>[...] in a competitive market there is no such thing as a sustainable competitive advantage. It's a myth -- and a somewhat dangerous one for those who believe in it. Instead, the way to succeed isn't through sustainable competitive advantage, but through continuous innovation -- that is, through a series of fleeting competitive advantages. You don't need patents for that -- just a smart, motivated team and a market to serve.</blockquote> <br /><br />So what does this mean for people building web applications? Should you be worried that you don't have an "unfair" competitive advantage? I really agree with Mike here: as long as you have a smart, passionate team that is capable of moving quickly enough, I think you will have a fighting chance at success.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114533206523512574?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-1144817621804498092006-04-11T22:14:00.000-05:002006-04-17T09:56:22.820-05:00"Whats the next big thing in Information Technology?"One of the cool things about travelling a lot is all of the people you meet. A few weeks ago, I was at the airport waiting for my flight home and I decided to try out this new restaurant that opened up in the terminal. There was a sizable line outside of this place. The restaurant didnt want to seat a small group to a larger table, so they started combining multiple groups into one table.<br /><br />A co-worker and I sat with an older gentleman on his way to visit his daughter in Florida. We started chatting, and after a while he asked us: "So, what's the next big thing in information technology?"<br /><br />You would think that an IT consultant would have a semi-intelligent answer to this question, but I totally blanked: there's so much cool stuff happening that I didn't know where to begin. After a few seconds of thought, here's what I came up with: "Not too much is really brand new. Most of the cool things happening now are a result of people using existing technologies in new ways." He seemed very underwhelmed by this answer, and for good reason I think: Instead of hearing about whiz-bang cool stuff, he got an answer that seemed to imply that there was nothing worth getting excited about (which is really very far from the truth). <br /><br />What would you have answered? How have you tried to explain what's going on in the world of web applications to a non-technical person?<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114481762180449809?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com1tag:blogger.com,1999:blog-18333045.post-1144811161371483262006-04-11T21:08:00.000-05:002006-04-11T22:06:01.466-05:00The Great Ruby RewriteIts been a while since I've really liked something <a href="http://joelonsoftware.com">Joel Spolsky</a> has written.. here's a gem from his latest entry, <a href="http://joelonsoftware.com/articles/DevelopmentAbstraction.html">the Development Abstraction Layer:</a><br /><blockquote>These companies are harder to find because in most circumstances they keep quietly to themselves, polishing code in a garret somewhere, which nobody ever finds, and so they fade quietly into oblivion right after the Great Ruby Rewrite, their earth-changing refactoring-code code somehow unappreciated by The People.</blockquote><br />The funniest part about this is that I constantly pester Ian with the same suggestion: We should rewrite Openomy using <a href="http://rubyonrails.com">Ruby on Rails</a>. Of course I'm not serious, but it the mere suggestion annoys him like no other. <br /><br />I really think Rails is great, and any new web application I write will most likely be written in it. However, is the small productivity boost really worth the 4-6 months of no development on the current live site? I don't think so.. <br /><br />Take <a href="http://kiko.com">Kiko</a> for example. They launched a pretty cool web-based calendar application last September. At that time, there weren't too many of these around (the <a href="http://www.techcrunch.com/?p=194">techcrunch post</a> on their launch only mentions one real competitor). A few months after their launch they decided that the site should be totally rewritten in Rails. They thought it would only take a month -- <a href="http://jkanstyle.infogami.com/blog/lessons">it really took them 6</a>! <br /><br />Here's what happened in the mean time: 30boxes launched, Zimbra launched, and many others did too. They went from being one of the only ajax online calendars out there to being just <a href="http://www.techcrunch.com/2006/01/30/spongecell-an-ajax-calendar/">one player in a crowded market</a>. Would they have been better served by just gradually refactoring the current codebase as they add new features? Probably.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114481116137148326?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0tag:blogger.com,1999:blog-18333045.post-1140493774043940912006-02-20T21:23:00.000-06:002006-04-11T21:08:35.813-05:00Taazza - Indian news, Web 2.0 styleMy good friend (and my career manager @ Sapient) Arjun Ramarathnam is working on a really cool side project: <a href="http://taazza.com">taazza.com</a>, a news site geared towards the Indian subcontinent (<a href="http://taazza.wordpress.com/2006/02/19/what-on-planet-earth-is-taazza/">Taazza means 'fresh' in Hindi</a>).<br /><br />I'm really impressed with what I've seen so far, especially since it comes from a guy that claims that he can't code! ;) . Just check out the <a href="http://taazza.com">screenshots</a> on the landing page now: he uses Google Maps to let people read stories by regions, gives quick access to related content, lets you read both the blogosphere's and more traditional news coverage, and its all written in Ruby on Rails. <br /><br />Now compare these slick features to the current largest Indian news website, <a href="http://www.samachar.com/">Samachar</a>. Taazza is just going to blow these guys out of the water-- its a good example of the cool stuff you can do by mashing up freely available sources of data. <br /><br />Sign up on the <a href="http://taazza.com">main page</a> for email updates, or just subscribe to the <a href="http://taazza.wordpress.com">Taazza blog</a>.<br /><br /><b>UPDATE:</b> Arjun demo'ed Taazza at <a href="http://taazza.wordpress.com/2006/04/08/taazza-barcamp/">BarCamp Chennai</a> and got rave reviews.. I keep hassling him to launch this thing already! :)<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114049377404394091?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com3tag:blogger.com,1999:blog-18333045.post-1140059213078340322006-02-15T19:54:00.000-06:002006-02-15T21:06:58.660-06:00What's with all the Firefox hating?The blogosphere has been picking on Firefox a lot recently: They claim it's slow, it's a memory hog, it crashes all the time. I find that really odd-- I've never had a problem with Firefox 1.5 on Windows. I've had a few issues with the older version available on Ubuntu Breezy (1.0.7), but very few that I couldn't blame on plugins. Even if it did hog my memory and crash regularly, I would *still* use it: It's so much more badass that IE. (I've been told that badass is my favorite word)<br /><br />Regardless of what you think of Firefox, this little splurt of posts complaining about Firefox are a symptom of more general problem in many internet communities: The transaction cost on ideas is very low-- especially in the blogosphere. All it takes is for one popular blogger to complain about a well-known and well-liked product and the rants spread fairly quickly. Unless, of course, you're totally wrong. In which case you probably wont be a popular blogger for much longer.<br /><br />I really make an effort to not fall into the blogosphere groupthink. I rarely link to anything without adding any value, as us consultants like to say. If you see me fall into that trap, please yell at me.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-114005921307834032?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com3tag:blogger.com,1999:blog-18333045.post-1139728567903101422006-02-11T23:43:00.000-06:002006-02-12T10:29:01.410-06:00How to be a MenschIf you haven't discovered <a href="http://blog.guykawasaki.com">Guy Kawasaki's blog</a> yet, add it to your news reader right now-- it's consistently pretty good. His latest post is on <a href="http://blog.guykawasaki.com/2006/02/how_to_be_a_men.html">How to be a Mensch</a>. He has pretty good advice on how to be a well-respected, noble person. Its certainly something I try to be.<br /><br />When I was in college, I was president of <a href="http://aepi.uchicago.edu">UChicago's AEPi chapter</a> for a year. As a mostly Jewish group, we were all well aware of what being a mensch means. When we were considering someone for membership, we would always used to ask ourselves: "Is this guy a mensch?" -- If so, these were the guys we pursued the most aggressively. Like in most recruitment situations, having great guys attracts more great guys, and makes for an all-around better chapter.<br /><br />"Menschdom" is not just something we can aspire to as people, but as a company as well (in a sense). We try to do this with Openomy. So in Guy Kawasaki style, here's a list of ways you can make your organization be more mensch-like:<ul><br /><li><b>Be approachable:</b> Your users *need* to trust you. I think its the little things that count the most here-- For example, we don't have any generic corporate email addresses may or may not have a person attached to them. If you have an Openomy question, we want you to email us directly.</li><li><b>Tell it to 'em straight:</b> This one is related to the previous point. One of the coolest emails we've ever received was a person complementing our <a href="http://openomy.com/privacy.html">privacy policy</a> and our <a href="http://openomy.com/termsofuse.html">terms of use</a>. They are written in plain English, no legalese, and they both explain things clearly.</li><li><b>Be Fair:</b> On our FAQ, we say: "Currently, all storage is 1gb. The plan is to increase this in the future. <i>Let us know what you think is fair</i>." (emphasis added). If you think our service is a rip off, we want to know about it. Everyone deserves to get their money's worth.</li><li><b>Set the right kind of goals:</b>Companies are supposed to be profit maximizing. While that may be true in general, I want my company to be "fun maximizing." We're here to build something cool, that we enjoy building, and that our users enjoy using. If your product is cool (and evangelizable as Guy would say), then the profits just take care of themselves. We take this approach to an extreme on Openomy: we have a list of projects that we eventually want to implement on the site. Instead of doing them in order we think of them, they are prioritized by how cool they are. While it does mean that a few features spend much more time on the list than others, it lets us whip out some coolness pretty regularly.</li></ul><br /><br />To elaborate on this last point: Of all of the blogs that have written about us, the post I'm the most proud of is not from a big name blog. Instead, its a post from back in November on a blog called <a href="http://blog.tempusfugate.com/2005/11/tidbits-morsels.htm">Tempus Fugate</a>, that said:<blockquote>They don't appear to have much of a business model, just a keen sense of "do-it-right"-edness. That's a technical term.<br /><br />The coolest fact about Openomy is that it appears to be running solely out of a desire to build something useful, learn some lessons, and potential help some people. This may not sound ordinary, but in the universe of online ventures, it can be anything but normal. I recommend you check them out. It's worth making note of their upbeat and positive attitudes and attention to detail.</blockquote><br />This blogger gets what being a mensch company means. Thanks for the kind words. (PS: The "business model" aspect is coming. While we value fun more than profits, the reality is that we can't pay for this out of pocket forever. The delay is related to the last bulletpoint: adding credit card processing isn't really that fun :))<br /><br />When <a href="http://iseff.com">Ian</a> and I were coming up with names for our <a href="http://openomy.com">Openomy</a> servers, we symbolically named one our most important servers 'mensch.openomy.com'. Actually, all of our servers are named after Yiddish words-- can you guess the names of the rest?<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-113972856790310142?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com2tag:blogger.com,1999:blog-18333045.post-1138484573302263412006-01-28T14:45:00.000-06:002006-01-28T15:42:53.486-06:00Using DarcsThe <a href="http://hatbm.com">caboose blog</a> has a good <a href="http://habtm.com/articles/2006/01/27/darcs-for-rails-users">intro to using darcs for version control.</a> <br /><br />I was first exposed to darcs when I heard a cool talk by David Roundy, the <a href="http://abridgegame.org/darcs/">author of darcs</a> at ICFP 05 last September (darcs is probably the most popular Haskell software out there, aside from the Haskell compilers). The talk brought up other distributed SCMs, such as the <a href="http://svk.elixus.org/">subversion-based SVK.</a><br /><br /><a href="http://iseff.com">Ian</a> and I started out using subversion for <a href="http://openomy.com">Openomy</a> but kept having trouble with branching: the process of looking through commit logs to find the right revision numbers to merge was really annoying, and we screwed it up more than once. It got to the point where merging branches actually made us nervous! <br /><br />We decided to try something new and give darcs a shot-- we haven't looked back since. We don't use it in a purely decentralized manner: Ian and I each have our own repositories, but we keep centralized production and development repositories on our servers that we push to whenever we're done with new functionality. The merging headache we faced with subversion is totally gone, and we can pick individual patches to promote to production and hold others back in dev. It's a really great SCM and I encourage other developers to give it a try. <a href="http://abridgegame.org/darcs/manual/">Here's a link to the darcs manual</a> to get you started.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/18333045-113848457330226341?l=blog.mauricecodik.com%2Findex.html'/></div>Maurice Codikhttp://www.blogger.com/profile/05885954890842001668noreply@blogger.com0