July 17, 2006
Steve McConnell on diseconomies of scale in software development:
Project size is easily the most significant determinant of effort, cost and schedule [for a software project].*
People naturally assume that a system that is 10 times as large as another system will require something like 10 times as much effort to build. But the effort for a 1,000,000 LOC system is more than 10 times as large as the effort for a 100,000 LOC system.
[Using software industry productivity averages], the 10,000 LOC system would require 13.5 staff months. If effort increased linearly, a 100,000 LOC system would require 135 staff months. But it actually requires 170 staff months.
Here's the single most important decision you can make on your software project if you want it to be successful: keep it small. Small may not accomplish much, but the odds of outright failure-- a disturbingly common outcome for most software projects-- is low.
I don't think the inverted, non-linear relationship between size and productivity on software projects will come as a shock to anyone; the guys at 37signals have been banging their drum on the virtues of small for over a year now. Isn't small the new big already?
But what I really want to focus on here is how you measure a project's size. What's big? What's small? McConnell is using lines of code (LOC) as his go-to measurement. Here's a table that illustrates the relationship between project size and productivity:
|Project Size||Lines of code (per year)||COCOMO average
|10,000 LOC||2,000 - 25,000||3,200
|100,000 LOC||1,000 - 20,000||2,600
|1,000,000 LOC||700 - 10,000||2,000
|10,000,000 LOC||300 - 5,000||1,600
Lines of code is a reasonable metric to determine project size, but it also has some problems, which are well-documented in the wikipedia entry on lines of code:
/* How many lines of code is this? */
for (i=0; i<100; ++i) printf("hello");
For one thing, different languages vary widely in the number of lines of code they produce. 100 lines of Perl will probably accomplish a lot more than 100 lines of C. So you have to be careful that you're really comparing apples to apples. Furthermore, skilled developers know that the less code you write, the fewer bugs you've created-- so they naturally distrust any productivity metric that weights absolute lines of code. And does code generation count?
Even with all its problems, the LOC metric is still where you should start, according to McConnell:
My personal conclusion about using lines of code for software estimation is similar to Winston Churchill's conclusion about democracy: The LOC measure is a terrible way to measure software size, except that all the other ways to measure size are worse. For most organizations, despite its problems, the LOC measure is the workhorse technique for measuring size of past projects and for creating early-in-the-project estimates of new projects. The LOC measure is the lingua franca of software estimation, and it is normally a good place to start, as long as you keep its limitations in mind.
Your environment might be different enough from the common programming environments that lines of code are not highly correlated with project size. If that's true, find something that is more proportional to effort, count that, and base your size estimates on that instead. Try to find something that's easy to count, highly correlated with effort, and meaningful for use across multiple projects.
The wikipedia article features this chart of Windows operating system size, in lines of code, over time:
|1993||Windows NT 3.1||6 million
|1994||Windows NT 3.5||10 million
|1996||Windows NT 4.0||16 million
|2000||Windows 2000||29 million
|2002||Windows XP||40 million
|2007||Windows Vista||~50 million
If you're wondering how much code the average programmer produces per day, I think you might be asking the wrong question. Lines of code is certainly a key metric for determining project size, but it's also easily manipulated and misinterpreted. It should never be the only data point used to make decisions; it's just one of many signposts on the road that helps you orient your project.
* what are the other most significant determinants? Number two is the type of software you're developing, and personnel factors is a very close third.
Posted by Jeff Atwood
I think LOC can be useful when you use it to gague relative measurements.
As you said, it wouldn't make sense to compare a C project with a Ruby project. But when comparing C to C, then it's more valid.
Perhaps the LOC should be qualified.
- LOC (Ruby)
- LOC (Scripting) vs LOC(Managed)
Something like that.
Disclaimer: I think Philip Su is an asshat. In my opinion, he's more dangerous to Microsoft than the mini-msft blog. Look closely at what he said in his Vista post that I linked above:
Vista is said to have over 50 million lines of code, whereas XP was said to have around 40 million. There are about two thousand software developers in Windows today. Assuming there are 5 years between when XP shipped and when Vista ships, those quick on the draw with calculators will discover that, on average, the typical Windows developer has produced one thousand new lines of shipped code per year during Vista. Only a thousand lines a year. [..] realize that the average software developer in the US only produces around (brace yourself) 6200 lines a year. So Windows is in bad shape -- but only by a constant, not by an order of magnitude.
The chart McConnell provides in Software Estimation defines a COCOMO average of 1,600 LOC per staff year for a 10 million LOC project.
So I think 1,000 LOC per staff year for a 50 million LOC project is, at the very least, average. I suspect, however, it is above average.
And writing an operating system is quite a challenge, among the more difficult of software projects, which would naturally have a lower LOC than, say, a website or line of business app.
So, in summary, Philip Su is an asshat.
But what I really want to focus on here is how you measure a project's size. What's big? What's small?
I build internal web apps and I've never really thought about what tells me if a project is big or small. But I know it's not lines of code.
The two things I use to gauge the size of my project is 1) data and 2) people.
People probably out ranks data, because the people tell me how many ways they need to use the data. If there needs to be half a dozen different interfaces, thats a bigger project because that ends up being the most time-consuming aspect of development. A smaller use based means smaller.
Data size (and nature) is the other factor for me. Obviously, the more data there is the more coding has to be done to manage and interact with it. But the nature of the data also tells me something about how careful I need to be with the data.
I've never really thought about how many lines of code any of the projects require. I'm now interested enough to look at some and see just how outrageous it is.
Great topic of thought...
The ternary operator is an excellent case for showing the limitations of LOC in estimating 'code length'.
One thing you quickly realise with Software Metrics is that they are only as good as the measurer. One must accept the limitations of each metric and interpret the measures with respect to those limitations in order to draw some useful conclusion on the notion of 'Size'.
LOC is an obvious 'length' metric but if it is used by itself it reveals little on complexity, functionality, redundancy and reuse within the code, therefore it is limited in its usefulness in attempting to understand Productivity, Effort and Cost which are the main drivers behind Project Size.
And then there are also those artifacts which aren't as obvious but drive up Size such as Specifications, Design documents etc. There isn't even a great concensus on how these are measured as yet.
You're totally right, Philip Su has blatantly compared Apples with Watermelons.
I think a project's size could be better determined by the number of decisions made, similar to the O() function.
Determining how many hundreds of decisions are made not only in the code, but during design could be a useful factor in measuring complexity. It would take some doing to really take this idea and flesh out a useful metric, but it's got more basis than merely lines of code.
Josh, that's Cyclomatic Complexity (McCabe) and is quite useful. However it is less useful if you have a lot of case statements, and it doesn't cover everything that makes OO code complex very well. But it is definintely useful IMO.
Keeping it small certainly reduces your chances of having an outright failure, but it also reduces your ability to do much.
Anyway, in the past I've used number of forms, batch jobs and reports, with a scale from easy/regular/hard/wicked, to work out the size of a particular project. But that only works when you understand the development tools and production environment extremely well, and there is only one or two 'wicked' forms, reports or batch jobs.
I've used that methodology with web and client/server applications, but it does tend to break down when writing a GUI-free tool, such as a web service or DLL.
LOC is interesting in hindsight, but impossible to predict in practice, and often hides the real complexity of a particular solution which may have required extensive work to refine it down to a few lines of code, or the simplicity of a tedious, but easy to create procedure with thousands of lines of ordinary drivel (like variable assignments).
When I worked in a consulting organisation, we found it most useful to identify whether the team really understood the business area, and its experience at solving similar problems. Anything new will take an unpredictable amount of time, because (by definition) you don't know what problems might be lurking around the next corner.
The number of internal dependencies in the software is presumably the critical factor, I'd have thought, and is also unlikely to increase linearly with number of lines of code.
The other problem with big projects is integration - you're constantly having to make sure that new APIs etc. that you are write are backwardly compatible as that's in practice the only way to integrate new code if you've got large numbers of people working on a project. That can easily take as much effort as actually writing the new code in the first place.
Question: how many of the LOC in Vista is "operating system", "shell", "web browser", "games", "utilities", "video editing tools", "DVD/WMA/MP3/MPG/AVI/etc player", etc, etc, etc?
No, seriously, when Windows XP shipped with an entry-level movie editor application it became hard to call it a single product.
If I was to sit down and plan to write the complete Vista distribution from scratch there would be a lot of lines of code to write. If I was doing one little section, then there'ld be many fewer lines. (Hey, I've got an ideas for managing complexity - break up a large project into many smaller projects that are complete in their own right, and layer more sophisticated functionality on top of the earlier projects. I wonder if I could patent that non-obvious business process?)
(Incidentally, when counting LOC, it's traditional to use a tool that processes the source code using standard formatting, so different brace styles and commenting patterns don't let developers artificially inflate/reduce their LOC count.)
It seems to me that the general notion of complexity, as noted several times, is probably the real measure of the size of a project. Numbers of objects in an OOP system, perhaps factored according to the (average?) number of members. The number of dependencies -- which entities interact with which other entities; presumably the more inter-entity commmunication, the more complex and/or bigger the project. The number of functions that the project's application accomplishes, if there is some way to measure that. Stuff like that, as per what Josh and MoZ are talking about.
Something about the "order of magnitude" comparison between 1000 and 10,000 LOC bothers me; seems too linear. "Size" as a square of the difference? Cube? Is there a logarithmic increase in complexity as a function of LOC?
Mike; in regards to the number of dependencies (inter-entity communication) we have various metrics that attempt to measure the amount of Coupling in programs. A good example could be the Coupling between Objects (CBO) that Chidamber and Kemerer developed in their Metric Suite for OOD.
Another attribute that I find interesting is Cohesion of Programs (of which there are numerous ways to measure it), which attempts to explain something about the 'relevancy' of the various components of a system.
Chidamber and Kemerer also came up with a simple metric for Cohesion in their suite, named Lack of Cohesion in Methods. Simply put, it tries to identify where an Object is trying to do too much for its own good.
You will quickly find when using such Metrics that there is 'No one metric to rule them all', and the most powerful tool is your own interpretation of what the measure is, whether it be LOC or something more absurd like Halstead's Software Science.
Do we get to count the lines of code we throw away?
I've never worked for a "software shop" but have always done software packages directly for the company that I'm employed by. There is no way I could judge a projects complexity by the number of lines of code, except in a very vague and useless way.
Much of my code time is of the type that I have to write communication software from one package or program to another. Lots of time, I need to refactor and throw away large chunks of code that become obsolete as my project requirements change, or as particular details of "how stuff actually works" come to light.
I think this is a classic case of measuring what's easy to measure, rather than measuring what's relevant.
Its hard to measure softer things like design decisions, interdependencies, complexity, so we don't.
And when taken to the extreme, where management uses LOC as a productivity metric, then everyone just games it with code like:
if (a b)
c = a;
c = b;
c = a b ? a : b;
To be honest, I think its a good day when I've *deleted* lots of code. So is that negative work?
Everyone is jumping on the 'LOC is a terrible measure of productivity' band wagon, but the article is using LOC to measure project size.
I agree the LOC is usuless as an ongoing productivity measure. But after the dust has settled and a project is "done" I can see using LOC as measure of project size.
The article points out that a project that is 10 times as large is actualy more than 10 times as difficult to implement. This is further support showing that LOC is not a good measure of productivity.
I'm going to go out on a limb and say Lines Of Code are completely irrelevant.
I agree, except there's clearly an order of magnitude jump in complexity between a 1,000 LOC project and a 10,000 LOC project.
So it's still useful for gauging relative size.
I think it's also, if properly calibrated to YOUR project, a useful project metric. But it should never be used as the only data point on a project!
I used to write rather decent assembler code in the 80s and 90s and I'm not busy being dead! I'm busy writing rather decent C++ ;-) No, LOC is no measure of productivity and certainly no measure of quality. Perhaps in the days of Fortran 77 it was, but the free-formatting of C, C++ and so on makes LOC irrelevant in my humble opinion.
whenever LOC is brought up, this Dijkstra quote is appropriate:
"This (LOC) is a very costly measuring unit because it encourages the writing of insipid code, but today I am less interested in how foolish a unit it is from even a pure business point of view. My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger."
I might have a net of 100 lines of code that is now functioning as I wanted it to, but I might have grossed about 500+ lines between yesterday and today.
With the new "agile" software development ways of thinking, wouldn't measuring how long it would take to meet a specific functional requirement be a better metric?
Let's say that you need to create a drag-n-drop interface that a you to quickly llowsassign work orders to support staff. (Just bare bones stuff for now..)
Requirement 1: Have enough of a database in place so you can create some dummy work orders and dummy support staff.
Requirement 2: Create the UI that handles the display of any new work orders.
Requirement 3: Create the UI that handles the display of all support staff members.
Requirement 4: Create/learn the drag-n-drop UI code that will allow you to drag work orders to a support staff member.
Requirement 5: Write the code to update the database to reflect the assignment of a work order to a support staff member.
Requirement 6: Refresh the UI to show the results of the previous requirement.
Now, all of these requirement should take just about the same amount of time, +/- 20%. 5 and 6 are pretty fast, so you can combine...but anyways...
If you break down functional requirements into pieces that "should" take an equal amount of time to complete, you can use this as something to measure against.....no?
Thanks MoZ! I knew I wasn't being at all original, but didn't know the term :)
I think complexity could be better based on number of objects (doesn't have to be oo) and number of interacting connections. Much like calculating the complexity of a neural network or other similar systems.
When I create a new class there may be lots of code, much of it filler and error checking but doesn't actually mean that class is complex. But if that class has to interact exteranlly lots and there are lots of other classes that do the same...things get more complex and more difficult for my brain to track.
In many ways the more difficult it is for your brain/mind to understand the workings...the more complex a project is. Maybe using a more common sense approach that actually relates to what we consider complex in the rest of the world should be applied to software engineering.
Lines of code is a very real and valuable metric. But here's the twist: Smaller is better.
More lines of code - more bugs.
More lines of code - greater cost.
More lines of code - less maintainability.
If you've thrown away 500 lines of code, and solved the problem with 100, you have 1/5th as many bugs, and 1/5th as many headaches down the line.
This is a victory, and--in our shop--a cause for celebration. As usual, Dijkstra has a good point.
"6200 lines a year"?
This must be language dependent, either that or I need to slow down.
Philip Su may be an asshat (after all, he writes a Microsoft blog, doesn't he?), but you're both quoting selectively.
Su writes, and you quote: "Vista is said to have over 50 million lines of code, whereas XP was said to have around 40 million. There are about two thousand software developers in Windows today. [... The] typical Windows developer has produced one thousand new lines of shipped code per year".
Su adds in parentheses, "(Yes, developers don't just write new code, they also fix old code. Yes, some of those Windows developers were partly busy shipping 64-bit XP. Yes, many of them also worked on hotfixes. Work with me here.)"
So it's disingenuous to quote just the first part and then attack Su's "conclusion". On the other hand, Su's parenthetical also misses the point. Does Su really believe that Windows Vista was created merely by adding 10 million LOC to XP? I bet at least one-third of XP's code (GUIs, file system innards,...) was totally scrapped and rewritten for Vista, which would make for some 15 million new LOC right there.
On the other hand, do you really believe that Vista is an "operating system" in the hacker sense of the term? "Writing an operating system is quite a challenge", definitely, but 45 million of Vista's 50 million LOC aren't "an operating system"; they're GUIs and office apps and screensavers and a Web browser and a .NET virtual machine and an API for the window manager and rules for pluralization in Turkish and hotkeys that make the windows zoom around in 3D. There is no fundamental difference between the vast majority of Vista and "a business app".
However, none of this back-and-forth posturing would be necessary if you'd just follow your own advice that LOC really is a terrible measure of productivity! Who cares if Redmond produces 1000 LOC a year or 100,000? Not I.
I've found that quite a handy metric for a quick overview is to look at the bug count, in two ways:
New bugs older than X number of days: By looking at the number of new bugs which are not being fixed in say, two weeks you get an idea of how behind the project is. If you are hemorrhaging 10 or 20 bugs a week, thats not so bad but more than 5 or 10% of your projects total bug count can cause pretty big problems I think
Bugs fixed per week / Bugs found per week: By using this metric, you have the handy psychological benefit of having a goal: Because the result approaches 1, when you reach that goal it feels good. Once you get past 1, you know the project is doing well.
It's really just personal preference, but I like having as many metrics as I can to determine how bad I am :-)
I find an appropriate way of measuring a project is in weight.
After weighing a couple files, I've decided that 1000 LOC = approx 28kb, I've used this as my benchmark of measurement.
This method doesn't discriminate between how you space your braces, or how much commenting you have - in fact, I would consider excess internal documentation a good thing, an indication of a more manageable and quality product.
Just make sure not to weigh any media too :)
A small personal project of mine was 40kb (1000 LOC). compared to a larger 192kb (7000 LOC) personal project, there's not too much of a jump in complexity, I'd mainly attribute it to an abundance of internal documentation in the larger project.
But when compared to the 1999kb (71,000 LOC) project at work - which has lax internal documentation, and was written by somebody else - I would say it is an order of complexity more difficult.
I would consider a day where I go through my code and heavily document it - doubling my LOC - a great day.
In summary, I find it hard to justify LOC as a good measure of anything - size, productivity, functionality, or complexity.
Doesn't anyone here have any actual training in metrics? Those of us who have been doing this for a while - and were properly trained - know that LOC, as bad as it is, does work. What you're all dancing around is the fact that, like any metric, IT MUST BE CALIBRATED to the environment.
BTW, a line of code is a line of code is a line of code, as long as you count consistently: I once had a project where we counted the lines three different ways to keep the lunatics upstairs happy, but, once each measurement was calibrated, they yielded identical results across products AND, strange as it seems to the uninitiated, even across languages. (The catch there is that the higher the level of the language being used, the less lines of code required to produce the same functionality - see the works of Halstead for a complete explanation.)
As far as using LOC and the limitations thereof, refer to Barry Boehm's work (the CoCoMo guy).
If you're a Function Points fan, just try to compare an embedded system's size to that of a typical COBOL app using the FP counting rules - it can't be done. BUT, it can when using LOC and full-blown CoCoMo.
Bottom line on counting: it doesn't matter how you count, as long as you consistently count the same way. Count comments or don't; count white space or don't; count declaration statements or don't; count multiple line statements as one statement or don't. As long as you do it the same way, it can be calibrated and used effectively.
HOWEVER, the BEST way is to maintain appropriate detailed records of productivity and refer to them. Just remember, you're asking for an ESTIMATE, not the final numbers. And ESTIMATES can vary as much as 16x at the beginning of a project.
Better to have a rock solid development process that runs the amateurs off and keep your software folks under control so they don't introduce unneeded functionality or experiment more than necessary.
If you want a challenge: count non-blank characters instead. Then you can argue over whether or not long variable names cost more than short ones. They can easily be shown to cause more compile errors due to typoes, but does the maintainability increase offset it?
Folks, this is a tempest in a teapot: use what works for your organization. Don't waste energy arguing over which end of a soft boiled egg is the right one to eat it from!
A few years ago I took on a component of a large project and removed 90% of the lines of code with the result that it was 10 times faster (and 95% less memory-hungry, and far more robust). This improvement meant it was no longer necessary to increase the cost of the embedded hardware it ran on by adding RAM.
Does this mean I should have been fired?
It's all features and value to the end user, and the one who does it in the fewest lines of maintainable code wins - Jon Galloway
So if none of the lines of code I write are maintainable does that mean I win?
In our company we take the absolute size for Add/Modify/Delete. But there is a weightage factor of 100% of new Added LOC, 67% for changed LOC, and 40% for deleted LOC. As per our experience this provides better results.
Steve, can you please let us know what is the source of your
[Using software industry productivity averages]?
For one thing, different languages vary widely in the number of lines of code they produce. 100 lines of Perl will probably accomplish a lot more than 100 lines of C. So you have to be careful that you're really comparing apples to apples.
I read a study somewhere that says the ratio of bugs per lines-of-code stays surprisingly constant irrespective of the language that is being used. This is a great reason to use languages that let you get more done in less LOC, such as Perl, Python (my favourite) or Ruby. Annoyingly I can't find a direct reference to cite on this.
Here's a related idea, again with no formal source though:
This is all very informal, but I heard someone say a good programmer can reasonably maintain about 20,000 lines of code. Whether that is 20,000 lines of assembler, C, or some high-level language doesn't matter. It's still 20,000 lines. If your language requires fewer lines to express the same ideas, you can spend more time on stuff that otherwise would go beyond those 20,000 lines.
I'm going to go out on a limb and say Lines Of Code are completely irrelevant. It's the sort of statistic you'd use to measure something you didn't understand - like phrenology or something. We've got no idea how to track how much business value we create per hour, so we're going to track a statistic that - though irrelevant - is easily quantifiable.
I work hard to write as little code as possible; does that make me less productive than someone who re-implements logging and user authentication in systems that natively support these features? It's all features and value to the end user, and the one who does it in the fewest lines of maintainable code wins. That maintainable part is important - I don't believe that 20,000 lines of assembler is nearly as maintainable as 20,000 lines of C#, mostly because the people who can write good assembler code are too busy being dead.
The scale is definately not linear as the number of lines of code increase.
I don't think LOC is an accurate metric. You could have 10,000s or lines of code for just doing mundane tasks, like adding parameters to the 1000s of stored procedures your system has.
Anyway, the project I am working on has 619,000 lines of csharp code (just the .cs files), not counting the aspx files and the many stored procedures, so counting everything it probably close to a million.
More useful tools are code complexity analysis tools. I ran one on the code base and many files were over 20 in complexity (cyclomatic) with the grand prize being 338! Not thats some serious spaghetti code! I think Jeff should organize a contest, most complex (in production) method in production gets a T-shirt. Everyone would have to use the same tool to do the analysis. Winner (if it can be called that) gets a free coding horror t-shirt.
After I ran the tools, I commented to a fellow employee that the code that I inherited will always have bugs in it, no matter how many we fix, just due to the nature of the amount of code in the system and the way it was written. The wasn't clearly understood because no one had taken any time to analyze the current code. Future enhancements and projects on this code base have a high percentage of failure due to the current state of the code.
I think any software project should strive to:
Keep number of lines of code to a minimum
Keep complexity of code to a minimum (using standard metrics)
I bet you'll find that most projects fail because there is too much code and it is too complex to manage and update (Bad design practices, nobody knows how it works, etc).
Any numbers on error rates if the programmer manages more or less than 20,000 lines of Code?
First guess: 58 to 74 bugs in that 20,000 lines of code.
Odds the 20,000 lines are defect free: Trace (1.9e-29)
Ave_bugs = 20,000 lines of code * 0.0033 professional blunder rate = 66
Sigma_bugs = sqrt(20,000 * 0.0033 * (1 - .0033)) = 8.1
Defect_free = (1-.0033)**20000 = 1.9e-29