Fog Creek Software
Discussion Board




Productivity advances

>> The real significant productivity advance we've had in programming has been from languages which manage memory for you automatically.  <

Joel, you're right about just everything, so I was surprised to see the above statement.  In fact, it's actually the abstraction level of the programming environment that affects productivity.  By this, I mean the amount of functionality in the generic code one is using.  I have objectively measured productivity on the last dozen projects, and it's certainly not true that it correlates to managed memory.  The range has been between .05 reqs/hour to 16 reqs / hour.  C# has been in the lower range.  The highest was with C++.  But the language has not been the critical factor.  The abstraction level and the architecture chosen were the two most important factors.  VB might be a slightly more productive environment, only because it provides more built in functionality.  This includes memory mgt, but we pay a heavy price for this.  One project failed because it was a garbage collected system.

Two other points:  1)  Like you pointed out, the problem with .NET is that it doesn't offer anything that the user actually cares about.  It's all about developers, which like you have decided, is not compelling.

2) Despite their obvious self interest, MS is correct in concluding that the desktop does make sense.  Our company has web style deployment for desktop software that rocks.  Since deployment is the only downside to the desktop, and that is really no problem, we're free to enjoy all the tremendous advantages.

Gunnar Skogsholm
Wednesday, June 16, 2004

Contrary to popular belief, C++ has memory management, in the form of smart pointers and collection templates in the STL. But if you learned C before C++ (so the only C++ concept you've ever picked up on is classes), you may not know about and/or use them.

To be fair to Joel, he didn't explicitly say the productivity advantage was because of memory management. He only implied it by saying the advantage was with languages that support memory management. But now I'm splitting hairs. :-P

Derek
Wednesday, June 16, 2004

No.

I and -- judging from many discussions with excellent programmers -- other people who have worked exensively in both types of environments would strongly agree with Joel.

My own experience makes me highly suspicious of your objective measurements.

How did you isolate the skill factor and the talent factor?  Those two, along with motivation and suitability of environment, are by far the most import determinants of productivity, and eclipse almost all else.  Did you use the same programmers for your experiments?  Had they reached an equally high degree of skill and comfort with C# and thel CLR *before* you began measuring?

How did you isolate the problem-space factors?  Did the programmers implement the same application twice?  If so, did you suitable mix the order -- C# first or C++ first, to isolate the learning-about-the-problem factor?

Cabby
Wednesday, June 16, 2004

To clarify, by "suitability of environment" I meant the workspace of the human doing the programming.  i.e. quiet, good light, good air, good display, sunlight, etc.

Cabby
Wednesday, June 16, 2004

Joel is completely right about the memory management issue.  Period.

Mr. Fancypants
Wednesday, June 16, 2004

Also, the fact that C++ has smart pointers doesn't help that much (and actually, without Boost or Loki or another library, it doesn't really have smart pointers -- YET.  auto_ptr doesn't count.  You'd be a fool to try and use that with STL containers).

Smart pointers help, yes, but they aren't the same as full garbage collection -- you still have to understand what they are doing and how they work and which type of smart pointer to use (weak vs strong reference) in which instance, and worry about the ownership semantics, etc or your code will have all sorts of problems that are potentially worse than a generic memory leak.

And even if smart pointers were 'the answer', so many APIs available for C++ programmers still use the old semantics of 'query buffer size, then call the method again' that you are still stuck using it, whereas with a language with true garbage collection from the start wouldn't have any APIs written for it using that style.

Mr. Fancypants
Wednesday, June 16, 2004

>> My own experience makes me highly suspicious of your objective measurements.

You need to read my post again.  I said I objectively measured productivity, not the causes of the productivity.  There are many different factors that affect productivity, but having to deal with the syntax of memory management is not one of them.  I agree that talent/knowledge is a prime factor, never said any different.  But holding that constant, architecture and the abstraction level of the environment are far more important than other factors.  For example, if one is using C++ and an application framework that does a lot of the work, then you can get far more work done in the same time.  But then you say, "ahh, but that's cheating, you're not comparing apples to apples". 

And that's exactly the point.  Almost all such comparisons do exactly that.  I'm personally not a language bigot and have no interest in which language is best, and any difference between general purpose languages at the same abstraction level are negligible, compared to other factors.  You may think you are comparing languages, when in fact, you are comparing MFC to the VB runtime (for example).  Or, unmanaged APIs to the .net base class libraries.

Gunnar Skogsholm
Wednesday, June 16, 2004

At least for business apps where the UI is often the most important part, the rise of component-based development seems to me like by far the biggest productivity enhancer of the last 10 or 12 years. 

Object-orientation has not proved to enhance productivity in itself, but most all of the environments where components are in wide use are object-oriented.  And object-orientation in the guise of components has enabled code reuse on a huge scale. 

In my mind the productivity gains from component-based development dwarf whatever gains have been produced by garbage collection. 

Herbert Sitz
Wednesday, June 16, 2004

What kind of components are you talking about, for example?  And in what ways does this improve your productivity?

Cabby
Wednesday, June 16, 2004

A data grid is probably the prototypical example of a "component".  Nobody (I hope) would even think of writing the low level code to display and manipulate table-based data in a grid nowadays.  Instead, they use a grid component that encapsulates all the functionality, is modular, and can be reused by plopping it onto a form wherever you need it and connecting it up to a data source.  Things didn't used to be like that.  Programmers used to deal with the relatively low level code that would handle displaying multiple rows of data, (give the illusion of) scrolling up or down through the records, etc, etc.  I don't even have any idea what that code looks like anymore; it's all internal to the grid component and I don't worry about it.

A few other examples of components I use:  a "RichView" textbox editing component that basically gives you a text editor/word processor within a little data control, an Outlook bar menu component, toolbar component, etc.  All of these can simple be plopped onto a form wherever I want them.  (I program in Delphi, but development environments for VB, VS.NET,  and others provide similar functionality.

Anybody who is writing this functionality from scratch is wasting their time.  And in fact, it would even be difficult to build one of these components from complete scratch nowadays, since these components are themselves built up from smaller components. 

As much as possible, I try to design my applications so I can take advantage of pre-existing functionality in my components, and so the code I write is just used to "glue" the components together so that they mesh to form a coherent "application".  I can't even imagine what it would be like to program without components anymore.

Herbert Sitz
Thursday, June 17, 2004

>> I don't even have any idea what that code looks like anymore; it's all internal to the grid component and I don't worry about it.  <<

Yes, agreed and this is what I mean by the 'abstraction level' of the development environment.  If you have more high level pieces of code (components) doing work for you, you get work done faster.  For example, comparing 4 projects, each implementing a 2000 req UI:

minimal OO generics/components      ~250,000 LOC
some OO generics/components          ~100,000 LOC
significant OO generics/components    ~30,000 LOC
massive OO generics/components            3,771 LOC

Productivity is just really high when all you have to worry about is 3,771 line of code.  Believe me, the time it takes to add a destructor is completely negligible.

Gunnar Skogsholm
Thursday, June 17, 2004

I tend to agree with the original poster. My main languages are C, C++ and Ruby (although I do a bit ofJJava and VBA when someone sticks a gun to my head). I have worked on some pretty big projects (big telecoms simulators).

I think the major contributor to productivity is how well thought out the solution is.

When I am mentoring more junior or less experienced staff, I always encourage them to thiink out the solution, and try and find the elegant solution (within a reasonable timeframe - usually an hour or two for most feature mods).

Usually the best thought out solutions prove to be the easiest to implement and (most imprtantly) to maintain or modify.

I am not denying that memory management is a factor, but I think it is not that significant a factor. The most important thing is to provide an approriate serious of abstractions in order to simplify the code in the right ways.

Perhaps having to think less about memory management helps, but I usually find that if the abstractions are right, the memory management is reasonably straightforward. If it is wrong, the memory handling can be a nightmare. ...I have just come across a Java app I have been doing some enhancements on that regularly manages to swallow all a modern laptop's memory.

Plus ça change, mais c'est la même chose.

treefrog
Thursday, June 17, 2004

Gunnar -- I think we're in complete agreement.

Given only these two choices, which would you choose for higher productivity?

(1)  C++ with garbage collection, but without a rich component framework/library,

OR

(2)  C++ without garbage collection, but with a rich component framework/library (a la Borland's VCL or .NET's FCL).

Except for some cases where the available components might be of little use (e.g., in developing a device driver or system software), I really can't imagine anyone keeping a straight face while telling me that they think Option (1) would be more productive.  For your average business or productivity application, Option 2 lets you leverage and reuse potentially hundreds of thousands or millions of lines of proven, tested code.  Garbage collection may be nice, but it can't compare.

Herbert Sitz
Thursday, June 17, 2004

tree frog and Herbert,  I couldn't agree more.  In fact, option 2 is repulsive to me, since I believe that the lack of deterministic finalization makes it unsuitable for most apps.  We did a big WinForm app that was supposed to be replacing a hybrid fortran / vb6 application.  We really had a difficult time getting production quality code out of .NET.  Part of this was caused by trying to do it with pre-release, alpha, beta 1, beta 2, release 2002.  It was better with 2003/.net 1.1, but our mistake was believing that databinding actually works well enough for production quality code.  With herculean efforts, we did get past that, only to find out that the performance was terrible compared to lightning fast fortran.  The difference was so great that the customer killed the project. 

It's kind of like the principle of 'clean as you go'.  With a non-GC system, you take a little time to type 'delete'.  A GC environment actually encourages a development pattern of making as much mess as you want, since you know the maid will clean it all up.  The code slows down because it's doing a lot more allocating and cleaning up.

It violates the good pattern of not putting off an operation until later, if you know the info now.  If at a certain point in the code, you know the information necessary for an operation, don't deliberately forget that information only to have to reconstruct that info later in order to the processing.

At destructor time, you know that the object is no longer needed.  Why force the GC to reconstruct that info?

That said, I really like .NET.

Gunnar Skogsholm
Thursday, June 17, 2004

Gunnar -- Hmm, seems like you may be disputing that garbage collection is an advance at all. . . (at least in its current implementations).

Herbert Sitz
Thursday, June 17, 2004

>> Hmm, seems like you may be disputing that garbage collection is an advance at all. . <<

Yes, I am.  What does it do for the user?  Memory leaks just aren't a problem.  It's a QA issue that's neglible since we have great tools to find memory leaks.  It's a totally developer centric idea, which is consistent with the unix world from which it originated.  It's bad to deliberately forget something, and then reconstruct it later. 

I don't believe that MS would have gone down this path if it weren't for Java.  I'm told that were two camps on the garbage collection issue and it escalated all the way to the top.  I also don't see why a non garbage collected system is inconsistent with the concept of managed code.  Why can't managed C++ be non GC?

Gunnar Skogsholm
Friday, June 18, 2004

*  Recent Topics

*  Fog Creek Home