Productivity in programming of C++ programmers

P

Pete Becker

ChadBl said:
A good developer will take more time to do a job right the first time around

I consider myself a good developer, and I generally that I do the best
job the third time around. The first two attempts are mostly for
learning.
 
J

Jerry Coffin

Dear,
May I ask how productivity of a(C++) programmer can be measured?

You can ask, but about the only accurate answer I know is
"subjectively."
If it is measured by number of code lines per day, what are the
estimated productivity of a programmer at beginer, intermediate (Me),
advance, master, guru,and sifu (B.Stroustrup, H.Sutter, S. Meyer)?

Ultimately, what you want to measure is the value of what is produced.
Line counts have already been sufficiently excoriated to render my
doing so superfluous.

Feature counts have been suggested as an alternative, but IMO, they're
only marginally better in most cases. The problem is that a poor
design will often be composed of a large number of discrete features.
A better design will tend to have fewer features, but each will be
more general and they'll work together better -- in fact, the ability
to "compose" features is often the most important feature of all.

As such, when looking at a significant piece of code, the feature
count will often have about the same significance as the line count
(in fact, the two often roughly mirror each other).

Unfortunately, most other objective measures seem little or no better,
at least to me. People have been studying software metrics of various
sorts for decades now, but I've yet to see one that impressed me as
being even close to as good as a pair of experienced eyes looking at
the code. One of the major problems is that while many software
metrics do reasonably well for specific types of code, most of them
run into major problems for other types of code.

Just for example, one of the oldest and best-known software metrics is
McCabe Cyclometric Complexity. This is based on a count of the number
of decision points in a module (e.g. if, for, while statements).
Unfortunately, even with relatively average types of code, the
correlation between its result and the maintainability of the code is
close to zero, and seems to be negative about as often as positive.
This is poor correlation at best, but if you add (for one example)
even a trivial finite state machine, it can blow up entirely,
basically doing its best to tell you that FSMs (in general) are evil
and impossible to read.
 
B

Bob Hairgrove

On 10 Aug 2004 14:28:32 -0700, (e-mail address removed) (Jerry Coffin) wrote:

[snip]
Feature counts have been suggested as an alternative, but IMO, they're
only marginally better in most cases. The problem is that a poor
design will often be composed of a large number of discrete features.
A better design will tend to have fewer features, but each will be
more general and they'll work together better -- in fact, the ability
to "compose" features is often the most important feature of all.

As such, when looking at a significant piece of code, the feature
count will often have about the same significance as the line count
(in fact, the two often roughly mirror each other).

What about "feature creep"?

I would say that, ideally, "line creep" should grow logarithmically
with "feature creep", not directly proportional (or even exponential).

If this can be obtained, maximum efficiency has been reached.
 
C

ChadBl

That '3rd attempt is gold' is what should be done. It's like writing a
magazine article -- the first time through is a rough draft, then you go
over it and use better words in some places, fix the parts where you're
taking too long to get to the point, and you end up with a working copy. The
third time around, you do more tweaks to the article, and then you have
gold.

Developing software is the same way. Reworking your code 3 times is part of
a *single* process, and if you're not given enough time and the correct
environment to complete the entire cycle, then that code will,
understandably, be subpar for what you can really produce.

However, in the real world (business run by the whims of marketing), the
focus is usually placed on producing software in rapid quantity, not
quality. So I guess the original question of how to measure Productivity
isn't going to have a single answer, because each company has its own goals
in terms of software production -- they either want so-so software shoved
out of the door once every 6 months so that a fresh version is always on the
shelves, or they want to spend a year to make it as reliable and usable as
possible.
 
D

David

Dear,
May I ask how productivity of a(C++) programmer can be measured?
If it is measured by number of code lines per day, what are the
estimated productivity of a programmer at beginer, intermediate (Me),
advance, master, guru,and sifu (B.Stroustrup, H.Sutter, S. Meyer)?
Thanks for your guidance.
NguyenMai

P/S: Similar post has been sent to comp.lang.c++.moderated (probably
takes longer time)

The productivity of "a programmer" can be measured by any number of
factors. The only useful measurements, IMO, are the features added,
the quality of the code, the quality of the product, and the problems
found in the field (negative, of course).

I would certainly hope that your goal for the day is not to write
100 (or whatever amount of) lines of code. I would hope that at whatever
skill rating you are at, that there is a plan to accomplish a certain
number of tasks in the coming days and that you have a specific few to
accomplish in your next session. Sessions can consist of coding, designing,
documenting, verifying, or whatever mix is reasonable.

At the low end I would expect the developer to spend time deciding what
relatively small task to accomplish, how to accomplish that task, testing
and verifying that the code works, and then perhaps rewriting it into a
form that could be used in the desired project. Once complete, another
task or so could be added.

Experience and accumulated tools can enhance the size of the tasks
accomplished. The more advanced developers would show that they can
combine a larger number of tasks and relationships and design ever larger
projects, and then build the project in pieces that make sense for the
overall project. Its also helpful to be able to document the design
so that others might be able to help create the overall project.

David
 
S

Siemel Naran

Lines of code is the worst metric to measure a programmers productivity.
It stimulates wrong behavior; you don't want programmers to maximize the
number of lines of code to accomplish a certain task.

Good point. Consider the concept of refactoring. Writing un-refactored
code usually leads to code harder to maintain, yet it is easier to write.
Writing factored code is more difficult, yet the resulting code is shorter
and easier to maintain.

Often, to refactor we will write out the main generic algorithm and capture
the specific details varying between specific algorithms as small virtual,
template, or parameterized functions.
 
P

Phlip

Siemel said:
Good point. Consider the concept of refactoring. Writing un-refactored
code usually leads to code harder to maintain, yet it is easier to write.
Writing factored code is more difficult, yet the resulting code is shorter
and easier to maintain.

One can make refactoring slightly easier by deliberately seeding a design
with a bit of cruft, then taking it out.

For example, to pass a test, you make the minimum edit. Don't yet reconcile
the new ability with all the existing code. If you need to clone an entire
function and change one line, if that passes the test, do it.

When you get a green bar, you are free to clean up the design. Perform
minimal Extract Method Refactors on the common code in those two functions,
and write new little delegating methods. The two lines you change are now
all that's left-over. Give this situation a better structure, and /voila/:
You have a new design. And you might not notice just when growing that new
design involved other regions of the code.

(From here, see my "Contractive Delegation" post now showing on a
near you.)
 
S

Siemel Naran

Phlip said:
Siemel Naran wrote:

One can make refactoring slightly easier by deliberately seeding a design
with a bit of cruft, then taking it out.

For example, to pass a test, you make the minimum edit. Don't yet reconcile
the new ability with all the existing code. If you need to clone an entire
function and change one line, if that passes the test, do it.

When you get a green bar, you are free to clean up the design. Perform
minimal Extract Method Refactors on the common code in those two functions,
and write new little delegating methods. The two lines you change are now
all that's left-over. Give this situation a better structure, and /voila/:
You have a new design. And you might not notice just when growing that new
design involved other regions of the code.

(From here, see my "Contractive Delegation" post now showing on a
news:comp.object near you.)

Is there anything wrong if we write factored code from the start? For
example, if I know in my initial design that I want to support both yearly
and transaction items, then I can immediately write an item class, then
derive transaction and yearly item from it. Any harm?

In a similar manner, I may make functions inline before profiling. For
example, std::complex::real() would be inline. Mostly because it's easier
to write, uses fewer lines of code. But in any case, it seems the inline
should make things faster.
 
P

Phlip

Siemel said:
In a similar manner, I may make functions inline before profiling. For
example, std::complex::real() would be inline. Mostly because it's easier
to write, uses fewer lines of code. But in any case, it seems the inline
should make things faster.

Low level code details (exception safety, const correctness, smart pointers,
copy operators, namespaces) can't be tested-first. Just write them.

In the case of "inline", you mean writing member function definitions inside
their classes. So answer this: Why are the classes in header files? Do you
have any classes in header files that could be in .cpp files?
 
P

Phlip

Siemel said:
Is there anything wrong if we write factored code from the start?

In pure TDD theory, yes. In practice, if I write the same program three
times, the third time needs less screwing around, and the result's still
better. Upfront planning works the same.
For
example, if I know in my initial design that I want to support both yearly
and transaction items, then I can immediately write an item class, then
derive transaction and yearly item from it. Any harm?

Those are features. Yes there is harm.

Given a hard problem, TDD generates a solution, with a firm design hosting
flexible bug-free features, sooner than expected. This is why Agile
processes fear too much abstract design planning. Complexity that's too easy
to add becomes hard to remove.

"Designing" means organizing the relations between the structure of objects
in memory and their behavior in time. Structure is bone, behavior is muscle,
and perfecting their design is difficult. The best way to seek simplicity is
to start with it.

The most important kind of duplication to fold is definitions of behavior.
Folding them together forces structures to grow new flexibilities. Mature XP
projects do _not_ refactor mercilessly, despite engineers are _required_ to
refactor when they see poor code quality. They don't. Adding new features
requires extending the existing design, just as if it had been brilliantly
planned.

These pressures force code to follow a curve of minimum complexity. Add a
feature, and the code puffs up. Air bubbles form in it.

If you then add another feature, the air bubbles harden, becoming more
difficult to remove.

If you instead refactor to force out any speculative code, the effect is
like hitting your substance with a big heavy hammer. You crush out all those
air bubbles. When you add the next feature, it has less chances of more air
bubbles, and less chances of them hardening.
 
D

David

Is there anything wrong if we write factored code from the start? For
example, if I know in my initial design that I want to support both yearly
and transaction items, then I can immediately write an item class, then
derive transaction and yearly item from it. Any harm?
<snip>

I work that way. If you have a clear idea what portion of the code
should be abstracted you may do so. It might be best to keep the design
simple in the generic portion so as to minimize the time you need to
code up a single task that now has a few extra concepts embedded. I
leave lots of comments (//@@@ in C++) that let me know where I've left
incomplete concepts for further development. As for knowing when some
concept may need to be generalized, that may be known in advance,
become obvious sometime later, or never really be needed. We just need
to insure that we don't over develop concepts and get away from our
desired work.

David
 
S

Siemel Naran

N4M said:
May I ask how productivity of a(C++) programmer can be measured?
If it is measured by number of code lines per day, what are the
estimated productivity of a programmer at beginer, intermediate (Me),
advance, master, guru,and sifu (B.Stroustrup, H.Sutter, S. Meyer)?
Thanks for your guidance.

Also, there are companies that in the interview ask you how many lines of
code you've written. One even said they won't consider anyone who wrote
less than 5000 lines. Not sure what they're after, though there is some
sense to the question.

So how about:

int main() {
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
std::cout << "hello world!\n";
...
}
 
P

Phlip

Siemel said:
Also, there are companies that in the interview ask you how many lines of
code you've written. One even said they won't consider anyone who wrote
less than 5000 lines. Not sure what they're after, though there is some
sense to the question.

I know a guy who has a very nice Web appliance, written in Java, unaware of
his line count. Testing and refactoring were working. I started copying
Reggae files to his workstation, he asked why, I said I'm making room for
your program, he said it wasn't that big, and I showed him. Here's your
biggest folder, and it's all full of source.

All interview questions reveal something about the hiring company...
So how about:

int main() {
std::cout << "hello world!\n";
std::cout << "hello world!\n";

You cheat! You didn't write them, you copied them!
 
P

Phlip

David said:
I work that way. If you have a clear idea what portion of the code
should be abstracted you may do so. It might be best to keep the design
simple in the generic portion so as to minimize the time you need to
code up a single task that now has a few extra concepts embedded. I
leave lots of comments (//@@@ in C++) that let me know where I've left
incomplete concepts for further development. As for knowing when some
concept may need to be generalized, that may be known in advance,
become obvious sometime later, or never really be needed. We just need
to insure that we don't over develop concepts and get away from our
desired work.

There are those who think planning designs causes bugs, and lowers
maintainability.

So, how much time do you spend debugging? And how well have modules written
like this been re-used and maintained over time?
 
D

David

Hi Phlip,

There are those who think planning designs causes bugs, and lowers
maintainability.

I would disagree with that general statement. I am generally opposed
to teams or individuals that design way too much in advance, whithout
a clear idea of where the project is going to go.

If done well, a forethinking design can be a good plan for growth.
When done poorly, the implemented design may not actually match the
problem and have to be reworked or worked around later.

I think it all comes down to your (you, team, company) ability to
design up front. You may be good at working out much of the design
in advance or taking it in more reasonable steps and refactoring
along the way. Its best to know your abilities and limits and
work productively.
So, how much time do you spend debugging? And how well have modules written
like this been re-used and maintained over time?

In the sense of debugging after the fact (as in post release) next to
none. Its been years since I've had a problem. Now, that doesn't mean
my code is absolutely perfect, or even all mine. I've inherited many
projects and written many of my own. Over time, the frailties of those
code bases have been improved to be more reliable.

I have adopted many ideas that go into developing an idea. Its well
thought out in advance, months if possible. Those designs don't usually
differ much from my initial ten minute impression of the project. It
does give me time to plan all the work and fill in the holes as to what
will be needed in terms of code, skills, and so on. I wil not write
any code that has not been tested by myself to its abilities. So, if
I write 100 lines today (I prefer the term concepts, FPs, or stories)
they must all be tested and approved. If they can fail, and most code
can, I absolutely must be able to debug the problem at a distance.
That is, the customer calls in to customer support with a vague description,
and I must be able to diagnose and fix the problem very quickly. I
generally do this by using extensive logs lying around. You must be
able to be able to trace back what has happened and where the failure
was. My first teachers insisted on writing code that worked within
three tries. In today's terms, that means when I start coding, I
have about three times for the entire [compile, run, validate, verify]
process to work. Most of my stuff is based on the usual C++ GUI
code on Windows these days. I also do a fair amount of embedded
work. It doesn't need to be this reliable, I just find it much better
to work this way. In a sense, I've been using most of what you'd
call agile, XP, and a few dozen models, for years.

As for reuse, I prefer to reuse as much as possible. A message
composer is likely to be used in several places -- an embedded project,
in a critical path (say a service), or in an application (GUI).
Look at my past posts and see what I've asked for help with. Its
mostly finding the proper way to accomplish a task which then becomes
(a class, template, or model) for doing that task well in the future.
If there was a problem later, I can point to all the code where the
mistake was made, what it might affect, and how to go about correcting
the problem.

I'd like to say more, but I have to get to work. I can't
summarize my 28 years of aquiring good techniques based on
the writings, teachings, and so on of other peoples work in
just a few lines of a post. We all need to understand there
are many ways to perform our daily tasks and seek to improve
them.

Take care,

David
 
J

Jerry Coffin

[ ... ]
What about "feature creep"?

It sucks. What else can be said? :)
I would say that, ideally, "line creep" should grow logarithmically
with "feature creep", not directly proportional (or even exponential).

If this can be obtained, maximum efficiency has been reached.

Nah -- maximum efficiency is when you add a feature by removing code.
Of course, it indicates that the code was previously somewhat
inefficient, but truly optimal code is truly rare.
 
L

lilburne

Jerry said:
Just for example, one of the oldest and best-known software metrics is
McCabe Cyclometric Complexity. This is based on a count of the number
of decision points in a module (e.g. if, for, while statements).
Unfortunately, even with relatively average types of code, the
correlation between its result and the maintainability of the code is
close to zero, and seems to be negative about as often as positive.
This is poor correlation at best, but if you add (for one example)
even a trivial finite state machine, it can blow up entirely,
basically doing its best to tell you that FSMs (in general) are evil
and impossible to read.

I remember a paper about 10-12 years ago that examined a lot of the
weaknesses in these metrics. The problem with McCabe is that you if you
do a random permutation of the input source you'll get the same metric
result as you got for the original. The metric for a 6 deep nested loop
is the same as 6 loops one after the other.

What McCabe tells you is that big functions are bad.

However, you do get a number which you can use to beat people up with.
For example "This code is shit and it has a McCabe metric of 200".

The McCabe tools can be useful for pin pointing potential problem
points. For example you can get automated reports generated for code
changes that might need some independent review. I also find the
function graphing to be useful to see when cut&paste has been used.
 
L

lilburne

Siemel said:
In a similar manner, I may make functions inline before profiling. For
example, std::complex::real() would be inline. Mostly because it's easier
to write, uses fewer lines of code. But in any case, it seems the inline
should make things faster.

One of my pet hates.

I make all developers remove inline functions from their code unless
they can demonstrate a measurable speed up. Even then they don't get to
stuff them in the header.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top