Jeff Atwood has an interesting post today where he says his current laptop may be the last one he buys. The argument is that tablets are a better option now, with longer battery life, less lap overheating, and a nicer form factor. But well, tablets are not for me. I always need a keyboard, a full version of Windows, I rarely need to run on the battery for very long, and the tablet form factor just doesn’t work for me. I like my screen to stand on its own, even on my lap, and having a separated keyboard is just clumsy. The surface looks like an interesting compromise, but the lack of a robust hinge makes it a no-go for me. Also, I want a single machine that works for everything I do.
I usually buy my desktop machines with a very different approach from the Atwoods and Hanselmans of the world: they seem to always go for the best and change them often, whereas I go for older, cheaper parts that I swap out to make the computers last as long as possible. Buying lots of new devices all the time feels icky to the environmentalist in me.
The last machine I retired was twenty years old and the only reason I changed it was that I got a case for free with the replacement parts I needed. Granted, the case was the only remaining original part. But still, I’ve made it last by swapping old parts with new ones as needed, and it’s been a very economical solution. I never go for the top-of-the-line, makes-your-eyes-bleed-with-ecstasy graphics cards, processors and memory. Instead, I buy year-old-ish parts, in that sweet spot where they have gotten extremely inexpensive but are still the equivalent of last year’s best. Last year was awesome last year, remember? And before you ask, I do most of my gaming on Xbox, so I really don’t need a gaming type of PC.
Laptops are different however: you can’t swap parts so easily. A couple of years ago, I started using my laptop as my main machine. This has the advantage that I can work anywhere with the same tools and data, even if I’m not connected. In my home office, in my rocker in front of the TV, in a coffee house or on the plane. Nothing to copy onto it before I leave, it’s all already there, always, like a little cloud that follows me everywhere I go. Laptops are awesomely light and small nowadays, and they can still pack all the power that I need. When I started working freelance last year, I shopped around and after considering a MacBook Air, I settled on a Samsung Series 9 with 6GB of RAM and 256GB of SSD. I did not want to have to change anything on the machine, and the Samsung was the only machine that reached out of the box all my requirements, one of which was to be very small, and another that I could hook it to a large external screen.
A year after, I still love that machine. I’ve had an issue with the quality of the plastics, and had to replace the piece that surrounds the keyboard after it cracked (covered under the awesome 3-year warranty), and I do resent the lack of anything else than HDMI when I talk at conferences, but overall it’s a fantastic piece of technology and a near-perfect fit for me.
Would I surrender the advantages of having everything I need in a form factor that I like for a hipper tablet? Of course not. As I said, tablets are not for me. They may be fantastic devices, but I need my Visual Studio, my keyboard and my hinge.
Is it the ultimate laptop? Of course not. I wouldn’t mind a retina-like screen, double the SSD, and a little more battery juice.
So why am I telling you all that? In today’s hardware market, we have more variety and form factors than we ever had before: phones, tablets, hybrids, laptops, ridiculously small and cheap microcontrollers that can output HD video, and of course desktops. That’s choice, people, and if you can handle it, it’s a wonderful thing to have. Pick what fits your life and work styles (and make it last).
To those of us who have been around for a while, namespaces have been part of the landscape. One could even say that they have been defining the large-scale features of the landscape in question.
However, something happened fairly recently that I think makes this venerable structure obsolete. Before I explain this development and why it’s a superior concept to namespaces, let me recapitulate what namespaces are and why they’ve been so good to us over the years…
Namespaces are used for a few different things:
- Scope: a namespace delimits the portion of code where a name (for a class, sub-namespace, etc.) has the specified meaning. Namespaces are usually the highest-level scoping structures in a software package.
- Collision prevention: name collisions are a universal problem. Some systems, such as jQuery, wave it away, but the problem remains. Namespaces provide a reasonable approach to global uniqueness (and in some implementations such as XML, enforce it). In .NET, there are ways to relocate a namespace to avoid those rare collision cases.
- Hierarchy: programmers like neat little boxes, and especially boxes within boxes within boxes. For some reason. Regular human beings on the other hand, tend to think linearly, which is why the Windows explorer for example has tried in a few different ways to flatten the file system hierarchy for the user.
1 is clearly useful because we need to protect our code from bleeding effects from the rest of the application (and vice versa). A language with only global constructs may be what some of us started programming on, but it’s not desirable in any way today.
2 may not be always reasonably worth the trouble (jQuery is doing fine with its global plug-in namespace), but we still need it in many cases. One should note however that globally unique names are not the only possible implementation. In fact, they are a rather extreme solution. What we really care about is collision prevention within our application. What happens outside is irrelevant.
3 is, more than anything, an aesthetical choice. A common convention has been to encode the whole pedigree of the code into the namespace. Come to think about it, we never think we need to import “Microsoft.SqlServer.Management.Smo.Agent” and that would be very hard to remember. What we want to do is bring nHibernate into our app.
And this is precisely what you’ll do with modern package managers and module loaders. I want to take the specific example of RequireJS, which is commonly used with Node.
Here is how you import a module with RequireJS:
var http = require("http");
This is of course importing a HTTP stack module into the code. There is no noise here. Let’s break this down.
Collision prevention (2) is very elegantly handled. Whereas relocating is an afterthought, and an exceptional measure with namespaces, it is here on the frontline. You always relocate, using an extremely familiar pattern: variable assignment. We are very much used to managing our local variable names and any possible collision will get solved very easily by picking a different name.
Wait a minute, I hear some of you say. This is only taking care of collisions on the client-side, on the left of that assignment. What if I have two libraries with the name “http”? Well, You can better qualify the path to the module, which is what the require parameter really is.
As for hierarchical organization, you don’t really want that, do you?
RequireJS’ module pattern does elegantly cover the bases that namespaces used to cover, but it also promotes additional good practices.
First, it promotes usage of self-contained, single responsibility units of code through the closure-based, stricter scoping mechanism. Namespaces are somewhat more porous, as using/import statements can be used bi-directionally, which leads us to my second point…
Sane dependency graphs are easier to achieve and sustain with such a structure. With namespaces, it is easy to construct dependency cycles (that’s bad, mmkay?). With this pattern, the equivalent would be to build mega-components, which are an easier problem to spot than a decay into inter-dependent namespaces, for which you need specialized tools.
I really like this pattern very much, and I would like to see more environments implement it. One could argue that dependency injection has some commonalities with this for example. What do you think? This is the half-baked result of some morning shower reflections, and I’d love to read your thoughts about it. What am I missing?