|
I've spent the last 6+ years of my life being a C# programmer. Sure, I've done programming in other environments during that time, but I have been writing books on C#, my day job has involved C# (or, regrettably, VB.NET), and most of my hobby programming has revolved around the .NET Frameworks versions 1.0 through the current version 3.0, as well as explorations of C# 3.5 and other "Orcas" technologies such as LINQ, DLINQ, the Entity Framework, LINQ to Entities, and much more.
What I have come to notice is that there is a fundamental difference between the way Apple provides a developer experience and the way Microsoft provides a developer experience. In short, Apple's developer experience is purpose-driven and Microsoft's developer experience is capability-driven.
The capability-driven developer experience is what most of us who are .NET Framework developers (and other Microsoft-provided environments) are familiar with. Basically the philosophy here is to provide the developer with a plethora of tools and capabilities. Virtually anything that the developer wants to accomplish (with .NET Framework 3.0) is possible. The only limiting factors here are the skill of the developer, the free time of the developer, and quite often the patience of the developer. When the developer is given this massive framework that is chock full of tools that can do virtually everything, they are often overwhelmed by the experience. It takes an incredibly long time to master the entire framework, and as a result you end up with specialists and generalists with little gap in the middle. You have people who can "do a decent job" on pretty much any task, and then you have folks who specialize and can create unbelievably powerful stuff. This creates people who are experts in WCF network programming or people who are experts in building unbelievably beautiful WPF-based UIs, etc. You also have a prevailing mentality of "There's nothing I can't do with this framework." that inspires confidence in its adopters.
Pros: With this experience, you feel as though you have the world at your fingertips - you can feel the amount of raw power at the command of your language of choice. Sometimes extremely complex tasks can be accomplished in an unusually short amount of time.
Cons: Often developers find themselves writing wrapper libraries to encapsulate repetitive tasks performed by users and often-reproduced functionality by developers. The amount of time and effort expended to support common, frequently-consumed application functionality is often very similar to the amount of time it takes to perform really complex tasks. Often, extremely common user tasks can be very difficult to code.
The purpose-driven developer experience is one where, rather than delivering a flat, open tool chest that stretches from horizon to horizon, the developer is exposed to a relatively small (but flexible) tool chest. At some point, someone has done some research and figured out that 90% of the tasks performed by developers in this domain can be accomplished with the tools in the small chest. The tools in that chest are often relatively easy for developers to use, can be swapped and recombined in powerful and exciting ways, and the time-to-market for commonly used and experienced functionality is quite fast. If more advanced functionality is required, the developer can open a false bottom in the small chest - revealing a cave full of tools just as huge as the tools of the capability-driven developer experience. The real difference is that capability-driven experiences are flat APIs - virtually every single task is given equal weight and equal treatment, regardless of how obscure or common the task may be. In a purpose-driven developer experience, the goal is to make it so that the act of producing an application that satisfies the most common needs of developers in the domain is quick, easy, simple, and elegant.
Pros: Producing compelling applications that do things that users want done all the time is easy. Simple things appear simple, complex things appear complex. Tiered advancement from simple to complex can avoid some of the feeling of being smothered or overwhelmed by the development environment in question.
Cons: Complexity scales - in other words, some things may appear extremely difficult to novices because they don't yet fully grasp why or how the easy things have been made that way for them. The delaying of the exposure to complexity can often produce a "fish out of water" or "in over head" feeling in developers later in their learning curve.
At this point we're getting into my personal opinion, which is wholly subjective and based on many, many years of professional, contract, and hobby programming as well as over 6 years of writing books on the .NET Framework, blogging, speaking, teaching, and generally being a .NET pimp.
Those of you who have worked with Microsoft development environments know them to be capability-driven environments. Most of us feel that Microsoft delivers a vast pool of capability and then drops it at the feet of developers and then says, "Here. You can do some ridiculously cool stuff with this... we just don't know what yet." As you saw earlier in this blog post, there are pros and cons to both the capability-driven approach and the purpose-driven approach. However. It has been my personal experience that I have had a more enjoyable experience developing when the environment in which I am working makes 90% of what I want to do relatively easy while still allowing me to gain access to the hard-core meaty bits below for the remaining 10% of the super-complex activity.
I have found that in purpose-driven environments, when my purpose is one of the commonly known purposes, I have been vastly more productive. In environments where what I need done is obscure and only serves the needs of a minority of users, I have found that some (not all) purpose-driven environments hinder me. For example, Visual Basic (as in versions 3-6) is a really good example of an attempt at a purpose-driven environment. Microsoft took what it thought were the most commonly produced types of desktop applications and made them trivially simple to produce in Visual Basic. However, when you stepped outside the realm of what VB was prepared for, Microsoft's attempt to insulate the programmer from the complexity that lie beneath the VB "shim", it became nightmarish and often drove developers to other development environments such as Delphi or C++. The insulation from the complex often encouraged poor design, poor use of design patterns, and shoddy spaghetti code.
That said: there's nothing wrong with a purpose-driven environment so long as the purpose is not confining. In other words, if the environment is highly optimized to produce applications that do x, y, and z - that's fantastic. If you are building an x, y, or z application you will find the experience euphoric. Some purpose-driven environments (such as Visual Basic, which isn't even a true purpose-driven environment) make it difficult to build applications that to a,b, or c.
What I have found with Cocoa is that it is an ideal purpose-driven environment. It is highly optimized for building compelling, beautiful, efficient, highly productive desktop applications. While I can certainly use WPF to build those same beautiful, efficient, highly productive desktop applications in Windows Vista, what I am finding is that the amount of effort required to do things that should be mundane and trivial to the end users in WPF is very similar to the amount of effort required to do highly specialized, customized, niche-type activities. There is a laundry list of specific comparisons of activities that I could mention here, but my comparisons have all been done against Leopard, most of which are covered by the NDA. Rest assured I'll post my specific comparisons when the NDA on Leopard is lifted.
What I like about Cocoa so much is that I can rapidly prototype an application using the 90% of the highly optimized environment. Then, I can gradually add layers and layers of complexity on top of that and I feel no impedance or barrier to doing that. If I need the complexity, it is there for me, and nothing about Cocoa hinders my attempt to do things in nonstandard fashion. Heck, if I want to gain low-level access to C functions or perform UNIX tasks, I can do that. The flexibility of Objective-C coupled with the power and elegance of Cocoa reminds me very much of the feeling I got when I first learned Ruby on Rails.
I am not saying that .NET is better than Cocoa or the other way around. I am saying that, to me, Cocoa/Objective-C feels like a very well-designed purpose-driven developer environment. It has a clear set of goals and makes a certain type of functionality trivially easy to implement. The .NET Framework is a swiss army knife on steroids. It provides a toolchest that only Paul Bunyon could lift single-handedly but makes little to no assumption about how those tools should be used. Many developers feel that philosophy is the right one while other developers feel that the purpose-driven philosophy is right.
I'm not going to use this post to draw a line in the sand and say which environment I prefer - I'm too much of a Cocoa newb to make that assertion. However, I will say this: what I have learned just from the simple act of having an open mind has already made me a better .NET programmer, regardless of how I feel about Cocoa or Objective-C.
Great point Kevin. I was a C, C++ developer back in the late 80's only to
discover VB3 after trying to ignore it for so long. What I loved about VB3
vs C and C++ was that I could quickly develop the business logic of the
application without getting bogged down in the syntax of the language.
That was a big step back then. Now, after becoming a VB expert, I've been
very frustrated in the .NET world but couldn't put my finger on exactly
why. It's not the language any more. It's the environment! In VB6, if I
couldn't do it in VB, I'd find a WIN API call or two that allowed me to
solve the problem. I'd add to my knowlege of the API as the situation
required. But in .NET, I have to learn too much of the API before I can do
anything. And, the API either changes or grows on a frequent basis.
That's bang on Kevin. When I moved from Windows/Unix development to Mac
development, there were some really prolonged periods of feeling out of my
depth, followed by eureka moments of "wow that's really easy". Its weird
that Cocoa is so easy to use but actually has quite a steep learning curve.
For a nifty example of how to sublcass NSCell see http://www.brethorsting.c
om/uidesign/2006/07/subclassing_nscell_-_the_easy_way.html
One of the toughest hurdles I had to overcome when learning Cocoa coming
from the procedural C world was learning to look for the easy way. It's
been a long time so I don't remember the details, but I have a hazy memory
of one example of wanting to print an NSView. I started off thinking I'd
need to subclass the NSView, implement a print method, figure out what
methods I'd need to call in there to create a connection to the printer and
then I guessed I'd need to draw the view again to some special printer view
to make it actually print.