Thanks for the feedback, jasode. Most of my piece was written from the perspective of Ruby, Python, and Node.js development, so your perspective on the state of affairs in Java is helpful. In this regard, Java sits in an interesting middle ground between Go and Ruby. Go completely relies on compile-time dependencies. Ruby completely relies on run-time dependencies.
Once piece of consistent feedback that I've gotten is that I didn't do a good enough job of clarifying that I was specifically dealing with the complexity of running applications. I'm pretty sure most people who have deployed Ruby or Python web applications would agree that deploying and running those applications is more complex that it needs to be. The examples of accidental complexity you gave are great examples of how it can manifest in code design.
I really liked your last point about the importance of use cases. I briefly alluded to that in the conclusion of my article, and I'm glad that you brought it up here. Use-case is extremely important.
Fair comment -- thanks for the feedback. I've received similar feedback from a friend who reviewed the post, and I completely agree. To be honest, I had to go ahead and publish what I had or it would have remained in my drafts forever. However, I'd like to follow up in the future and address some of the points you raise.
IMO, this is one area where Go shines. In a non-compiled language, you have to bear the burden of the upgrade process when writing code AND when running code. For example, if you update Python on you application servers and there is a breaking change, you break running applications that may not have been touched for weeks, months, or even years. With Go, you build a binary at the time the code was released and you never need to touch that binary again. Your binary can run forever even if breaking changes are introduced later.
As with Python, you still need to update code in subsequent releases to work with the breaking changes. However, in my experience, this isn't the hard part. The hard part is keeping your existing code running while staying on a recent version of your favorite language runtime. This is even more painful in an environment where multiple application run on the same server. If you write a new application using Ruby 1.9.x but an older application will only run on Ruby 1.8.x, you need to either split them across multiple servers or update the old application to run on 1.9.x. There are tools to handle this (rbenv, rvm, chruby, etc), but this is exactly the type of complexity I talk about reducing in my post.
I've had the same experience - very little need for generics in Go on a regular basis. I really appreciated the following snippet from http://robnapier.net/go-is-a-shop-built-jig:
"Probably the biggest complaint people have with Go is the lack of generics. And I did run into that in just the first couple of weeks of work on my project, and I wound up with a bunch of duplicated code to work around it. And then, when it was all working, I refactored out the duplicated code. And I refactored again. And in the end, the whole thing was simpler and shorter than what I would have done with generics. So again, in the end, Go turned out to be a language for solving real problems rather than a language filled with beautiful tools, and so you build real solutions rather than finding excuses to use your beautiful tools. Don’t try to make Go what it isn’t. If you’re trying to solve abstract CS problems in their most generalized forms, then you may find it frustrating. But if you’re trying to solve specific, practical problems in the forms professional developers typically encounter, Go is quite nice."
Per the blog post, Cloud Servers is no longer based upon an existing VPS product. Instead, it is based upon the OpenStack project that Rackspace started with NASA in 2010. http://en.wikipedia.org/wiki/OpenStack
Once piece of consistent feedback that I've gotten is that I didn't do a good enough job of clarifying that I was specifically dealing with the complexity of running applications. I'm pretty sure most people who have deployed Ruby or Python web applications would agree that deploying and running those applications is more complex that it needs to be. The examples of accidental complexity you gave are great examples of how it can manifest in code design.
I really liked your last point about the importance of use cases. I briefly alluded to that in the conclusion of my article, and I'm glad that you brought it up here. Use-case is extremely important.