views:

3388

answers:

41

Soon, I expect to be asked to revise and improve existing code written by engineers and scientists.

I've noticed that non-programmers do not share the same programming 'eye' as computer-scientists and full-time programmers.

As someone coming from a non-computer-science background, I want to know what mistakes non-traditional programmers (specifically engineers and scientists) tend to commit.

One problem that I've picked up on is an over-reliance on unnecessary Boolean logic (complex if-else statements). What else do we tend to do incorrectly?

+9  A: 
Malfist
+1: I think debugging is a nightmare, especially when one doesn't half understand the language s/he's writing in
Zaid
I have found scientists and engineers do a better job of debugging. At least they understand you shouldn't change the inputs on each run.
Martin Beckett
@martin, you change your inputs on each run when debugging?
Malfist
What are the nine rules? :)
André Laszlo
`I read it in the bathroom over a couple weeks ;)` I thought you said it was short... didn't you get hungry?
MattH
Dear god why were you in the bathroom for a couple of weeks?!? Never mind, I really don't want to know.
Chris Lively
May be he found the cover too scary? All that bugs...
mlvljr
Oh come on now, no one else is a bathroom reader?
Malfist
Good book, but basically you can get the entire value out of it by just reading the list of nine rules on one of the first few pages. This book could have easily been a brochure. On the plus side for engineers, most of the examples are from EE bugs.
JohnFx
+13  A: 

I think the most common problem is simply complete ignorance of how computers work.

See Schlemiel the Painter's Algorithm.

Peter Alexander
unfortunately I think this is true for too many "real programmers" aswell :/ (real as opposite to non programmers in the question)
f4
yeah - see my comment to tvanfosson above
klochner
+3  A: 

One common mistake is that they request/or foresee/ sometething to be done in 3 days whilst it would take 3 months.

John
this is general problem of almost every person, even technical ones.
Kugel
Yup, this is lack of *experience* "traditional" programmers suffer from as well as non-traditional ones.
Pekka
+13  A: 

Failing to understand the space, time, complexity, or readability aspects of the code they write and take advantage of algorithms and/or data structures that would significantly improve performance and/or readability/maintainability. Typically, they implement the most naive algorithms and data structures which are almost invariably slower and take more space than necessary, using code that is hard to read and/or maintain.

For example, my son (studying engineering and taking his first programming class) had an assignment to write a program to convert back and forth between two different units for each of temperature, speed, and distance. His first attempt used a series of nested if statements to select the proper conversion function. His second attempt (and what I imagine most of the class ended up with) was to use a switch statement. I suggested that the way I would go about it was to use a map of units to conversion functions. Retrieve the correct function from the map and simply go about applying it. The naive algorithm requires up to 5 comparisons for each operation. The map-based algorithm does a simple lookup to find the function.

EDIT: FWIW, here's my implementation using the "map". The problem specification indicates that the both values and units are given as numeric. For my purposes I assumed a mapping of 0 = Farenheit, 1 = Celsius, 2 = inches, 3 = cm, 4 = mph, 5 = kph. The C# implementation uses lambdas for the functions, but includes help and the ability to specify the full unit name instead of a number so it's a bit more complex. I know that it could use more error checking. :-)

#include <stdio.h>

double TempFToC( double f )
{
    return (f - 32) * 5.0 / 9.0;
}

double TempCToF( double c )
{
    return (c * 9.0 / 5.0) + 32;
}

double DistanceInToCm( double in )
{
    return in * 2.54;
}

double DistanceCmToIn( double cm )
{
    return cm / 2.54;
}

double SpeedMPHToKPH( double mph )
{
    return mph * 1.609344;
}

double SpeedKPHToMPH( double kph )
{
    return kph / 1.609344;
}

int main(int argc, char* argv[])
{
    double value;
    int units;

    double (*converters[])(double) = {
        TempFToC,
        TempCToF,
        DistanceInToCm,
        DistanceCmToIn,
        SpeedMPHToKPH,
        SpeedKPHToMPH
    };

    char* labels[] = { "C", "F", "cm", "in", "KPH", "MPH" };

    printf( "Input value and units: " );
    while (scanf("%lf %d",&value,&units) > 0)
    {
        if (units < 0 || units > 5)
        {
            printf( "Invalid units.  Try again.\n" );
        }
        else
        {
            printf( "%lf %s\n", converters[units](value), labels[units] );
        }
        printf( "Input value and units: " );
    }
}

EDIT: Even better version for linear transformations

#include <stdio.h>

double transform( double original, double scale, double offset )
{
    return original * scale + offset;
}

int main(int argc, char* argv[])
{
    double value;
    int units;

    double factors[][2] = {
        { 0.555556, -17.777778 }, { 1.8, 32.0 },
        { 2.54, 0.0 }, { 0.393701, 0.0 },
        { 1.609344, 0.0 }, { 0.621371, 0.0 }
    };

    char* labels[] = { "C", "F", "cm", "in", "KPH", "MPH" };

    printf( "Input value and units: " );
    while (scanf("%lf %d",&value,&units) > 0)
    {
        if (units < 0 || units > 5)
        {
            printf( "Invalid units.  Try again." );
        }
        else
        {
            printf( "%lf %s\n", transform( value, factors[units][0], factors[units][1] ), labels[units] );
        }
        printf( "Input value and units: " );
    }
}
tvanfosson
Funny that you mention switch statements as if they were an upgrade to if-else; we were told the same thing!
Zaid
They can be, switch statements are often easier to read than switch statements.
Malfist
I remember my first programming exercise. Input: `({})`, Output: true; Input: `({)}`, Output: false. With `<>` and `[]` brackets too. Instead of using stack - had nested ifs all around. Pure nightmare. :D
Arnis L.
This example doesn't illustrate the point; a switch statement is usually a simple jump table under the hood, and in many languages (depending on compiler) would be significantly faster than a map lookup in this case.
Cory Petosky
@Cory Petosky, the MAP would still be a better solution because it's expandable without increasing code complexity. Sure, switch statements are faster to the computer, but not to the programmer.
Malfist
@Cory -- implemented correctly (in C) the map is really just an array lookup and function invocation on the result. You just need a single test to make sure the index is in range. It's hard to imagine that the compiler could improve on that in optimizing a switch statement.
tvanfosson
On a similar note, I had a student that was writing a parser that would write to file. Instead of writing each line as he went, he appended each line to a massive string that would eventually get written. He couldn't understand why it ran so slow.
klochner
@klochner: and I had to check someones flash code why it ran so slow. I couldn't even code in flash but I would take a look. I noticed he was using complete photoshop psd files, which were scaled on the fly by the flash runtime. hahaha. Some people just don't have a clue. ;^)
Toad
Faster or not, it's much more scalable than a huge switch-statement.
Skurmedel
Because the example wasn't as clearly related to my point as I intended, I expanded my answer to include other measures of code quality -- for which the example is much better. I still think that the "map" solution is better than switch if implemented correctly from a performance as well as a readability perspective, but I'd rather people didn't quibble over the example's applicability.
tvanfosson
The map solution would be faster in interpreted languages.
klochner
<snark> Your son is lucky to have your work to turn in. ;)
Casey
I haven't shown him my code and won't until he tells me that he's turned his assignment in. I suspect, actually, if he turned in work based on my idea the prof would mark it down since it wasn't the expected solution.
tvanfosson
I'd go one step further. Since these are all linear transformations, you could just store pairs of numbers (a,b) in the map and then use the same function a+b*x for conversion.
shura
That would have required me to use a little algebra to transform the formula for Farenheit to Celsius, but it's certainly a better way.
tvanfosson
I agree with @klochner - 'The map solution would be faster in interpreted languages.'. @tvanfosson - I'm sure that you could have chosen a better example to illustrate your point.
Jim G.
+25  A: 

The re-creation of many parts of an already existing program that are already there or are present in a library.

Primetime
+1: I was asked to do this in the past...
Zaid
A common mistake of traditional programmers as well.
Dour High Arch
AKA: re-inventing the wheel.
Ash
AKA: DRY: Don't Repeat Yourself
rohancragg
+47  A: 

One that's common in engineering code (and fairly unusual elsewhere) is assuming that floating point is the same as real numbers. I've seen quite a bit of code that's perfectly correct from a theoretical viewpoint, but uses algorithms that are numerically unstable.

Jerry Coffin
This is also common amongst new programmers and those who are unaware of how computers work (see Poita_'s answer)
ChrisF
@ChrisF:yes and no. The difference is that scientists and engineers really will get things theoretically correct (often things that are quite large and complex). Code from many neophytes isn't even theoretically correct.
Jerry Coffin
I was thinking of cases where you get asked why `(equation that equals 4) / 2.0` produces `1.9999` or `2.00001` as the answer (as a simple example)
ChrisF
I actually am from an engineering background and only graduated a few years ago. I went to Rutgers University. Given the importance of numerical algorithms to modern engineering, we actually were required to take a class in numerical analysis, so that we understood the basic concepts of numerical stability, etc.
dsimcha
@dsimcha:I'm glad to hear that -- unfortunately, it's nowhere close to universally true. It also tends to be worse with scientists than engineers. Engineers are at least accustomed to practical limitations in applying theories -- they just aren't always aware of the practical limitations outside their own field. Scientists frequently treat practical limitations as something akin to a disease, and refuse to consider them at all.
Jerry Coffin
@ChrisF: But 1.999999... does equal 2 :)
Duncan
I agree with ChrisF: this is common to ALL new programmers. Especially ones that have yet to spend hours (or days) trying to figure out why their pretty financial algorithm is sometimes off by a few pennies (or worse).
Chris Lively
I have to wonder why more languages don't have first-class fixed-point arithmetic built-in. Dealing with fixed-point values, like currency is very common in application code.
Zak
+65  A: 

Code that lacks abstraction.

For example cutting and pasting the same code over and over again when it could easily be rolled into a simple function.

Carlos Rendon
I just graduated and in my last semester or two, I was interacting with physics students a lot. I caught a few glimpses of their code and it tended to be one long function that cried out for refactoring.
Eric
+1 for dinging physics students
klochner
one of my former bosses told me that if I was cutting and pasting code that was a sure sign that a function/procedure was needed...
Leslie
I saw this a lot. However, *don't* just tell them to use a function. That leads to the dreaded "do everything" function. Horrors!
Zan Lynx
As a physics MS, I want to -1 your comment, but can't! Damn it all to he'll!!!
Pierreten
+24  A: 

Having worked with several financial types who have moved from purely business roles to power-user/programming roles the main issue that I tend to find with much of their code is that often there's a distinct lack of structure, layering and separation of concerns. I work mostly in C++, C# and Java so I'd personally prefer to see them using a bit more object oriented stuff... Unfortunately it often seems that code is added to whichever window happens to be open at the time and that most functions, classes and files tend to have far too much unrelated stuff going on in them. Also it often seems that it's too much trouble to create a new class or structure for a concept and so there are clumps of basic data types that need to be adjusted together but that aren't in a class...

The second most noticeable issue has often been a lack of reproducible releases; or even releases at all. Quite often the code is hacked on all day and whatever happens to be building is whatever happens to be running and that IS the production version.

The good news is that most of the guys I've worked with who had habits like this are quick to see the advantage of structuring their code better and of using a 'sensible' development -> test -> production release structure.

Len Holgate
I've seen a lot of these mistakes even from professional programmers. It's quite annoying when I can't reuse a chunk of code because it does a dozen other unrelated things too!
Matthew
+1 well said, often these sorts of people only need to be shown the error of their ways and they'll happily repent, lets not just laugh behind their backs. They're our colleagues not our enemies.
rohancragg
*"to whichever window happens to be open at the time"* - good phrase, i'll have to remember that.
Georg Fritzsche
+8  A: 

They put expensive calls inside of loops inside of loops inside of loops.

Spike Williams
Not only expensive, but redundant... Like repeatedly recalculating something that never actually changes inside the loop when they should have put it BEFORE the loop. I guess they put the calculation inside the loop because that's the closest place to exactly where they'll need the result. Thankfully compilers can often optimize that out anyways!
Brian Knoblauch
I hear you. Just find the highest number of nested loops, take the reciprocal and you've got the programmer placed on the beginners scale.BTW, this may of cause be hidden by putting inner loops into function/method calls, but none-the-less structures the code a lot better.
Christian Madsen
I've used and seen this used for assigning discrete-domain dimensions to objects/variables... a world of opportunities opens up when you realize that you can assign up to 27 dimensions (or pieces of data, depending on how you look at it) to the same variable. Multi-dimensional arrays just lend themselves to this kind of thing...
Zaid
+12  A: 

Variable names like A, B, alpha, beta, rho, sigma, etc. I think they are not too bad when they are used in a 1-1 relationship with quantities in a paper/book that you must have at hand in order to understand the algorithm; still I'm not comfortable with function names like updateTheta() in place of updateEstimate(), setSigma() in place of setVariance(), and so on...

Federico Ramponi
That's because engineers/scientists so used to the symbolic representations of quantities in formulas. I doubt that's an issue, especially seeing that it'll be written for an informed audience.
Zaid
IMHO beta, rho, sigma, x, etc. are perfectly reasonable names for variables if you're translating something directly from standard mathematical notation into code. It makes the mapping between the math representation and the code representation much clearer.
dsimcha
When Sigma but when they are spread throughout 1000 lines of code with slightly different meanings and at different levels of abstraction I don't agree anymore. Even on a paper, symbolic notation is shorthand for objects that have a meaning and a name. Why can't we use the proper names outside the functions or methods that implement the tricky formulas?
Federico Ramponi
@Federico: I completely agree. I was only defending this type of naming inside small, very mathy sections of code.
dsimcha
+1 - agreed....
Matt Joslin
+3  A: 

I suppose it depends on which level you are talking, but I would expect a lack of soundness.

It takes a logical mind to analyze a problem, but it takes a trained mind to actually decompose it adequately: Divide and Conquer for example, Dynamic Programming...

Also, this translate into a lack of structure in the program itself. Separation of concern and proper layering is not something innate. It takes practice to actually enginer a correct architecture... and even a good lot of programmers have been taught too much about hacking and not enough about designing.

All in all: I would expect Spaghetti Code or a Big Ball of Mud.

Matthieu M.
+3  A: 

A lot of coders nowadays don't have an understanding of things at a lower level (due to higher abstractions masking it away).

Things people don't seem to grasp:

  • Bit manipulation (and therefore failing to create sensible if statements)
  • Passing data by reference is very beneficial to speed for large types/arrays/etc
  • The distinction of interpreted/compiled in languages
  • Where are my variables stored (in web languages(cookies/session/db/postdata/etc))

In languages like .net, especially with frameworks bolted on top (asp.net)... things can get very magical for coders who don't want to know hows things work or are done. This results in buggy code, security issues, performance problems and bad maintainable code

Toad
... AKA exactly what this guy already said: http://stackoverflow.com/questions/2283153/where-do-non-traditional-programmers-especially-engineers-scientists-go-wrong/2283189#2283189
Pete
+28  A: 

Not using version control software. They usually drag their heels about using subversion until that day it save their backside.

rschuler
Yea, I'm from an engineering background and I was programming for several years before I was convinced of the value of source control. I only learned it when I was forced to because I got into developing some open-source mathematical software.
dsimcha
You mean the day it doesn't save their backsides, because they weren't using it ...
Duncan
This might be a plus in their favor. I call it the Neophyte Garbage Collector.. ;)
Chris Lively
Source control is also a must when having to collaborate on software. Bloody pain to share code the manual way.
Hannes Nel
There are plenty of so-called software shops that don't yet use version control, so don't throw stones at the sci-eng community while we still live in glass houses...
rohancragg
A: 

How they organize information: no domain driven design happening there.

Dr. Zim
A: 

Gotos.

I don't know how representative that is, but when I made my first reasonably complex software at the end of Electrical Engineering college, a microcontroller software in C, I was throwing gotos all over the place until a Computer Engineering colleague at the same lab gave me the heads up, and my advisor (professor) seconded him. I grudgingly refactored the code, half doubting it would really bring any real improvement at all. As soon as I finished and resumed new development, I started to realise what a huge improvement that was.

Emilio M Bumachar
Aah, the legacy of FORTRAN...
Zaid
+1  A: 

Knowing only one tool and using it exclusively. I've known people in the science and business worlds who can almost do magic with spreadsheets, but who can't really accomplish something with anything else. E.g., I once had to write a program to parse an Excel file after it has been copied to a Linux system when other methods would have been more appropriate if they'd have been used in the first place.

GreenMatt
+3  A: 

Both new and experienced programmers make this mistake all the time: Not profiling. Some don't even know what profiling is, much less why you do it.

If I could pound anything into people it would "Don't guess, know!"

darelf
A: 

If your native tongue is not English then I would look for non-English function and type names. One of the codebases I maintained contained lots and lots of enums in Hebrew.

maayank
+2  A: 

tl;dr version - A common mistake made by non-programmers is simply not knowing what the hell they're doing in the first place.

Sit back and let me tell you a story.

I worked at a small consulting company that serviced a large $product company. This large company was expanding its operations and used a system built by one of their engineers to track costs, materials, etc.

This engineer left, but for months the company (mostly) comfortably ran his software. We had actually heard a bit about it because we worked for people elsewhere in the company who had to use it. The main complaint was the slowness.

One day, his program stopped working. This was Very. Very. Bad.

Me and my boss went to the client's site at their request and expense to see if we could help. After getting the system back up and running, we were asked if we could do any optimizing while we were there. Not a problem.

So I sit down and open up Access (ugh). I open up a couple reports and notice a few views (or whatever Access calls them. It's been too long to remember) used a lot. I open them up and am instantly smacked by a true nightmare.

SELECT ID, Blah, Blah, Blah
FROM [BUILDING1-1]
UNION
SELECT ID, Blah, Blah, Blah
FROM [BUILDING1-2]
UNION
SELECT ID, Blah, Blah, Blah
FROM [BUILDING2-1]
UNION
...

This went on for over 200 buildings. There were views like this that got everything, some that filtered, etc.

I already knew what was going to happen when I actually went to look at where the data was stored but out of morbid curiosity had to go look anyway.

C:\db-data\>dir
BUILDING1-1.dbf
BUILDING1-2.dbf
BUILDING2-1.dbf
....
BUILDING56-9.dbf

Our final offer was a rewrite with an import, but they just chugged along with the clunky Access thing because they only needed it for a few more months. That suited me just fine.

aehiilrs
Ouch! Talk about object-orientation gone wrong...
Zaid
+1  A: 

I think that a programmer can answer your question remembering what he did when he made its first programs.
My common errors were:

  • repeat (like copy and paste) blocks of code;
  • difficult in choosing the simplest way of doing things;
  • problems to debug an application;
  • multiple threading issues.
Maurizio Reginelli
You were using multiple threading as a beginner? I'm impressed. Perhaps that's why you had debugging problems.
Duncan
+2  A: 

Occasionally, the best programmers are scientists and engineers. A good example is Walter Bright, the designer of the D programming language and author of the Zortech C++ compiler. His degree is in mechanical engineering. Compared to comp sci or software engineering degrees, I think an engineering degree gives one a good eye for practicality, problem solving and the necessity of tradeoffs. I see way too many CS/software engineering people getting caught up in holy wars or focusing too much on theory instead of Making It Work.

P.S. I'm a little bit biased because I'm also not a full time programmer. My degree is in biomedical engineering and I'm a research scientist. However, my research area is bioinformatics and I deal with huge datasets, so I regularly have to write code, and some of it needs to scale to 16 cores.

dsimcha
"Making It Work" is sort of the problem. If you just "Make It Work" then you ignore efficiency and run time. You ignore elegance and reusability and debugabilty... If All you want is the answer once, then you toss the code, then sure. Make It Work... otherwise be a bit more careful...
Brian Postow
The second step is "make it right."
Duncan
@Brian: But this is how much scientific computing is: All you want is the answer once. Even when this is not the case, you sometimes don't realize it until you've already written quick and dirty code. I've realized that it's best to refactor code into something maintainable as soon as you realize you need something more than the answer once, but if I wrote all code with the assumption that it needed to be clean and maintainable, even if it was **probably** only going to be run once, I'd never get anything done.
dsimcha
This is why somepeople call Perl a Write Once Read Never language... If it's longer than 50 lines, you're going to have to read it again, if only to debug it later after lunch... it pays to make things maintainable.
Brian Postow
I'm a CS student.My research is also in bioinformatics, especially in machine learning techniques. A few months ago I got a lot of code which I had to "clean up" a bit. The problem is it was written from people who had no idea about programming (they followed the "quick and dirty method", the only important thing was to write code that works). It was a NIGHTMARE. Of course I could not clean up much and started rewriting it. About the code: no documentation/comments, very inefficient, no sign of BASIC computer engineering rules etc. Conclusion: the WORST programmers are scientist and engineers.
George B.
Perl can be written very nicely.
Zan Lynx
@Brian: But this is the other extreme. Even throwaway code should follow common-sense readability guidelines to the extent that they are easy to implement. This is important for debuggability and tweakability. You should use named constants instead of hard-coded values, use decent variable names, and use functions instead of cut-and-paste even in throwaway code, even if it's slightly more work. However, you shouldn't spend a lot of time on high-level design, worrying about loose coupling, ease of change, configurability or reusability until you need a lasting solution.
dsimcha
@Duncan: You're right, "make it right" is the second step. It's just that some people that call themselves design gurus treat it like it's the first. Also, if your code only needs to run once, you might not need **any** second step.
dsimcha
A lot of making code readable / maintainable comes down to how you organize your thoughts before you write the code. A lot is also simple trivial things like good use of whitespace/indentation and good variable or function names. Once these skills are learned, the write-time cost of doing it right is often minimal.
Adam Luchjenbroers
@dsimcha: In essence, throwaway code needs to be designed to be understandable because you have to make sure it's working right right now. That will also help you if it suddenly becomes non-throwaway, because it's a lot easier to refactor code you understand.
David Thornley
@David Thornley: This is exactly my point. Basic common sense readability does matter even in throwaway code. What I'm against is worrying about design at a higher level. It's perfectly possible to have code that can be easily understood and debugged, uses good names, is indented properly, etc. but is very tightly coupled and specific to the problem you're trying to solve now, rather than being general/loosely coupled/modular/easy to change w/o massive refactoring. Basic readability is a lot easier to get right than good high-level design and for throwaway code it's all you need.
dsimcha
+17  A: 

Speaking as a non-traditional programmer (electrical engineer), I think the biggest stumbling points for me were:

  • Design- most programs I used to write were just cobbled together messes. There was very little planning (because I didn't have the experience or skill). Lots of scientists/engineers only do straight procedural programming. We typically don't understand the standard techniques such as OO or TDD unless we really make an effort.

  • Lack of data structure/ library knowledge. We typically find one workable answer and use it over and over again until stuff breaks. We like (read: use) MATLAB for a reason: it does things, has C syntax, and we couldn't care less that it's a patchwork mess because we use <1% of the libraries/functionality.

  • Software practices (version control etc)- of course if they haven't been exposed to it they ain't gonna know. But honestly if they are working on one man code-ups it doesnt really matter for the most part. Yes, you could arrive at some sticky situations but those are few and far between in my experience. Testing is another sticky point. Combine the blog-isms "Ya Ain't Gonna Need It" and "We Ain't Gonna Unit Test It" and you have us all pegged.

temp2290
Version control is perhaps *more* important for one-man coders; on a team, at least other people may have an older version of the code knocking around. If you're on your own, it's all too easy to be screwed. Also recommended: use an editor which keeps multiple history copies, in case you lose older code that was never checked in.
Barry Kelly
Most of the one-man engineer types who run sans-version-control learn (from painful experience) at least to ZIP stuff. A guy with no zips, and his only copy of the source code is on the laptop, which has that hard drive that sometimes fails to spin up. .... I've met that guy too. Anybody else?
Warren P
As a fellow EE, amen. It seems like I craft the hardware and system, and just get the software functional. As soon as I meet spec for my timing, I can go back and tweak my noise levels because that will give me a measurably better product. The balance for me is: I'll spend a pile of time explaining the hardware to the programmer, will the programmer produce code that saves me at least that much time back?But, then, that's why I spend time cruising SO, to make better software development a habit.
ArielP
Most EE programs I've seen treat code as one giant circuit, with sheer indifference to hierarchical design.
Paul Nathan
I disagree. I also have an EE degree, but I think every problem and deficiency can be overcome with good books, study and hard work.
gmuller
+2  A: 

Failure to understand data structures in any form, from an array up to and including objects. This is generally paired with Carlos Rendon's symptom for truly horrific code:

int d1, d2, d3, d4; // ...
int x1, x2, x3, x4, x5; // ...
int y1, y2, y3, y4, y5; // ...

d1 = (y2 - y1) / (x2 - x1);
d2 = (y3 - y2) / (x3 - x2);
// ...
Cory Petosky
@Cory: you've lost me with this example - what are you trying to show?
Zaid
@Zaid - the code is calculating the slope (difference in x axis over a jump in the y axis) at different points from a list of points. An array of a record (struct) or object type would be much better here. Basically, the programmer didn't understand loops and replicated them by copy and pasting.
Barry Kelly
@Barry: Gotcha. BTW, slopes are 'rise-over-run' (change in `y` over change in `x`), not the other way round.
Zaid
@Zaid: Good catch, fixed.
Cory Petosky
Beware of division by zero.
Loadmaster
+8  A: 

I have a lot of experience working with code written by Biologists. Fundamentally, (as someone else mentioned) the lack of abstraction is a major problem.

Basically, Scientists don't think like Programmers. They don't solve problems in a way that tends to be useful for programming. Engineers tend to do ok on this front. Computer Scientists (and Mathematicians) tend to work top down. "Here is my problem, how do I break it up?" Engineers tend to work bottom up "Here are my tools, how do I use them to solve the problem?". Scientists want to design an experiment or something. I'm not sure what, but it gets REALLY messy really fast..

This is all in my experience...

Brian Postow
Good insight...
Zaid
A: 

Do you mean like meta-language? Where a programmer submit a logic that is very high-level?

Or do you mean you actually look at code for debugging?

In either case, I think a common problem depends on the language itself. In some cases, people try to do things that the language does itself. The most common pitfall for a programmer to make is "inventing" the wheel again. If you know of solutions that are built into the language, or provided by its libraries, then go with that and don't go with self-made problems.

Daniel
+2  A: 

Not understanding libraries, and doing everything from scratch. A long time ago, a guy wrote his own integration routine in FORTRAN, and he obviously had never heard of Simpson's rule. Somebody pointed him at the wall of one lab that was essentially documentation for dozens of FORTRAN functions and subroutines he could use.

David Thornley
yes. Also not TRUSTING libraries. "Yeah, there's a library for that, but I can probably do it better myself..." This one is actually a bigger problem among Real Programmers. (as in olden days Real Programmers...)
Brian Postow
That's because in the olden days libraries really couldn't be trusted :) (who preferred using DOS interrupts to print to the screen rather than just making a pointer?)
Earlz
@Earlz: In the olden days, people made small libraries that worked well, and there was none of this nonsense about DOS interrupts because there wasn't any MS-DOS. At pretty much any time, you could get good and reliable libraries for scientific and engineering applications.
David Thornley
A: 

I knew a guy who took up programming after he retired from farming. I think he actually got the hang of it quicker than some of the people in my CS classes, but not having a mathematical background he would often write code like this:

switch ( i ) {
    case 0:
        j = 1;
        break;

    case 1:
        j = 2;
        break;

    case 3:
        j = 4;
        break;

    case 4:
        j = 8;
        break;

...
Duncan
aw sweet, that's like something from http://thedailywtf.com
rohancragg
+3  A: 

Not understanding how assignment works.

int x;
int y;
x=10;
y=x;
x=x; //make sure x doesn't lose it's value

and not understanding how to name their variables. It always seems to be one of these declared for something "significant" (as in, global variable or something not specific to only one function)

int n;
int NumberForCountOfLettersInString;

And not understanding how arrays make life simpler

int x1,x2,x3,x4;
x1=1;
x2=2;
x3=3;
x4=4;

which could simply be made

int[4] x;
for(int i=0;i<4;i++){
  x[0]=i;
}

And finally, not understanding why you shouldn't copy and paste code blindly.

Earlz
The point about variable assignment is probably the only one that's truly specific to this topic and not just "newbie programming mistakes." Math and sciences folks especially are used to algebraic equations and short variable names; imperative code can sometimes be a leap (but then again, functional code is a natural transition).
Aaronaught
I never met a truly OLD TIMER engineer who didn't LOVE arrays. After all, if it's in fortran 77, you need it, and if it wasn't, you don't.
Warren P
+1  A: 
  1. Obsessive hand optimization of code, insetad of writing clear and understandable algorithmic code and letting the compiler take care of the minute optimization details.

  2. Use of poor algorithms and lots of redundant overhead (usually due to basic misunderstanding of what's going on at the bare metal level).

Loadmaster
+8  A: 
  • They don't test the code thinking that is a waste of time.

  • They don't use automation.

  • They don't measure results.

  • They use one big limited tool instead of preparing an army knife of effective tools to accomplish to most common task in the quickest way.

  • They just click and fix over and over again waiting each time for fifteen minutes of a manual build that doesn't work in the integration environment.

  • They think that DRY is a type of Martini.

gicappa
+1 The last made my day
Helper Method
@gicappa: You're the only one who's mentioned automation so far. I'd appreciate it if you could you explain it in more detail as I'm not sure what you mean by it.
Zaid
Automation mean that when it's possible all repetitive task should be automated by using scripts in whatever language you want. Automation is important because you don't want to spend time over and over again solving the same problem or making monkey-clicks. Build process is the most outstanding example: "It works for me" is not a professional answer it can be avoided by using automated builds and continuous integration. If it works on the integration box it means that I can reproduce a working environment and eventually deploying it.
gicappa
+3  A: 

No use of principles and concepts such as DRY or automated testing. They also usually do no get the big idea behind code refactoring... "if it works, why change it?".

I also noticed that some would overcomplicate some code by overusing stuff like recursion. Ok it's a bit cooler, but it's really not readable.

marcgg
+1 Sadly, I hear the "if it works, why change it?" nearly every week from so-called professionals
Helper Method
A: 
  • Getting something to work without understanding HOW it actually works, or what they actually did to make it work.
  • Not adhering to "Solving the problem first, then writing the code".
Helper Method
A: 

For a semester in college I took a graduate level class in the Chemical and Biological Engineering Department on doing protien simulations in water, which basically involved modeling lots of 3D interactions and then doing some statistical analysis on them.

My experience was that the engineers could get a solution. It would work just fine, and be completely correct. In general it would use the most naive approach, and the code wouldn't be well architected. But it worked.

I came from a Physics and Computer Science background, so while I could also get it to work, I could gather more data faster than they could. By using the correct data structures (think oct-trees and uniform grids), I could run orders of magnitude more steps with orders of magnitude more molecules in less time.

Looking at our statistical results, their data could get them around 3 digits of accuracy, and mine could get at least 10. I've frequently wondered since then what it would be like to work in an environment where I provided technical support to people like that in order to improve their results.

Chris
@Chris: You'd probably face a *lot* of resistance to change. Engineers trust their code because they've toiled away at it for so long until they eventually get it to work. For someone to come along later and say that what they've done can be done better in much less time does not go down well unless there's a promise of improved performance.
Zaid
+2  A: 

I'm a non-traditional programmer. An Electrical/Biomedical engineer who has now migrated over into the world of software development.

Speaking from personal experience, the worst mistakes I made when programming first started becoming my core role were:

  1. Writing very ambiguous code (especially horribly nested loops and vague variable names. I also had a bizarre obsession with multi-dimensional arrays)

  2. Lack of proper commenting and documentation

  3. Poor use of version control

  4. Not using any kind of framework or organised file structure

While I was making these transgressions I KNEW I was doing the wrong thing. However, at the time I was working in an R&D prototyping house and the company line was "Do it and fix the problems and documentation later".

Yes, I did get a new job. I now work in a place that insists on using coding best practices. Suffice to say, I've come a LONG way since. It's amazing what a difference workplace culture can make on the quality of your code.

Ganesh Shankar
Great answer... this is the sort of thing I was originally after
Zaid
That's good to hear! I never thought people would want to know about how I used to be a bad programmer ;) I think the best thing that ever happened was when I got a mentor (in my new job) who was a programmer with a large amount of experience and a focus on "doing things right". Getting to know a framework (in my case it was being introduced to Ruby on Rails) really helped as well as it gave me some structure to work within.
Ganesh Shankar
The fundamental need here is to get something working properly fast, and good programming practices assist that.
David Thornley
A: 

I'm working with some people who have to use C syntax to generate logical conditions for driving equipment. So I see things like:

 if(5 < a < 7)...

 if( cond1 )
     if(cond 2) result(x);
 else
     if(cond 3) result(y)


 if(a=5)....

 if(cond)
 {
     return x;
     b=5;
 }


 if(cond);
 {
  ....
 }

Helper Method: yes, it will. It's equivalent to ( (a<7) > 5); it will be always false because both 0 and 1 (possible results of a<7) are less than 5.

Same asx==y==5 is equivalent to (y==5 && x==1) || (y!=5 && x==0)

SF.
The 1st line works in C?
Helper Method
+2  A: 

I've found there to be a good number of attitude and abilities when it comes to scientifically based software developers. A good number of them in my experience (particularly from physics) have been really quite good.

I have had terrible trouble with a few of them though and I think a lot of it comes down to the fact that software developers, no matter what their background, who take a pride in their work and actually enjoy it create code that is much better. Those whose primary focus is not this tend to generate proportionally poor/strange/misguided code.

On a number of occasions I've seen more scientifically minded individuals being nearly forced into writing code, and I mean production code, when their heart is really not in it. Added to this is the fact that they had to half learn C++ to a level where things 'appeared' to work correctly and I'm sure I don't need to tell you the end result. I think keeping developers on the development side and scientists on the science side is a good thing for everybody concerned. That way we won't have to endure code where someone open a file, reads a single value, closes it and loops over this process n-thousand times - yes, I have seen this...

acju
A: 

Lack of use of design patterns.

orokusaki
A: 

The classic problems I see with non-programmers are these(obv. generalization & not applicable to all):

  1. Electrical Engineers treat code as a circuit. There's no abstraction at all. Usually the code is very 'flat'. Part of the reason for that is VHDL tends to be written flat, as the compilers are fairly dumb about optimizing/generating between levels of abstraction.

  2. Mathematicians have one-liner style functions with 1-letter variables. The code has abstraction, but due to the 1-letter naming, no one else can read it. Ever.

Paul Nathan
A: 

It is very hard for an engineer, who used to write programs for microcontrollers or PLC's, to change the way of thinking and start applying Object Oriented Programming concepts and to write good OOP code.

rem
@rem: You need to qualify this statement. Engineers *can* most probably write decent OO code, provided they have the appropriate training/exposure.
Zaid
@Zaid I generally agree with you, and there are books and maybe even trainings on OOP programming of industrial controllers but the fact is that, mostly, in practice, even advanced PLC programming doesn't require deep knowledge and understanding of OOP. I know that from my own experience. And from my own experience I know how hard to change the way of thinking that I meant.
rem
A: 

As I said on a comment above, I think every deficiency can be overcome with study and books. The greatest errors an engineer/scientist can do as a programmer is think they "know to program". Study, learn, read! Programming is science, must be treated like that.

gmuller
This doesn't address the question in the OP. Even after getting to know the language, non-traditional programmers may code in a different style that rankles with those from a computer science background.
Zaid
+1  A: 

Most of the time engineers/scientists are the worst "programmers". But there are times that their expertise is required.

I'll speak only for engineers because it happens to know a few things about this strange kind of species. Engineers have a different background: they are not trained to "fight" with bits and bytes. Most of the engineers learned to program in Fortran. I mean Fortran 66/70 spaghetti code... But they are trained to solve problems.

What we have to realize is that there are some special applications, like structural or car-crash analysis applications that are simply impossible for a normal software team to manage. The required technical background is so vast and the priorities are so different than most "normal" applications.

For example, the cars we drive are structurally analyzed by engineers using Fortran codes, written between late 60's and early 70's... A car-crash analysis involves the solution of a system of more than 200000 simultaneous equations (sometimes the number raises to 1 million)... NASA did all of the great achievements by using the same ugly Fortran codes. And the list is endless.

I'm not defending the unstructured ugly programs I mentioned above: I've seen such codes and believe me: you don't want to even look at them! All I'm saying is that these programs get the job done. And their job is to make us travel with safe, build our earthquake resistant homes, etc.

Simply a matter of different priorities.

ileon
@ipapasa: This answer doesn't really address the question. About the only thing I see here which *may* be relevant is the reference to spaghetti code, which is too broadly defined to be something to look out for and refactor.
Zaid
@Zaid: The potential problems in systems that were written by engineers cannot be classified easily. It depends on the language used, how old the system is, the number of team members (too many people involved increase the level of inconsistency), etc. For example old Fortran programs use procedures, with no arguments, that depend heavily in COMMON statements, which make maintenance very very difficult by outsiders. In such cases I carefully remove variables from commons and add them to the procedure. In C programs, we usually find many fixed arrays or lack of proper data structures.
ileon