59

Quality is subjective, of course. To be a little more specific: What is most likely to result in shipping buggy, fragile, or otherwise sub-par products that make more work for you and your group down the line?

Here's a breakdown of the responses so far, sorted by responsible party and then by votes.

Management:

  • (Aggressive) Deadlines
  • Lack of/arbitraily changing specifications
  • Belief that programmers are interchangeable/more is better
  • Overall poor communication/management
  • Overtime/fatigue

Developers:

  • Copy and pasted, duplicated, or insufficiently refactored code
  • Lack of interest
  • Bad legacy code
  • Lack of knowledge
  • Relying too heavily on the debugger

Both:

  • Lack of coding standards
  • Using the wrong technology for the job
  • Lack of a solid architecture/design
  • Haste (in all its forms)
73 accepted

"Aggressive" deadlines.

43

Lack of specification is our biggest problem, followed by arbitrarily changing specifications.

Change control is frowned upon because it's regarded as a bureaucratic exercise that merely functions as a barrier to progress. Hence the inevitable chaos surely ensues...

In fact, this has been a key complaint in most of my jobs.

Everyone agrees in the benefits of change control, until their app needs an extra feature delivered yesterday ('because we've already agreed it with the customers') or they need it to work backwards or upside down ('we need it for the new service we're offering; how difficult can it be??').

Dilbert: "I'll design the system as soon as you give me the user requirements."
Business Guy: "Better yet, you could build the system, then I'll tell your boss that it doesn't meet my needs."
D: "I don't mean to frighten you, but you'll have to do some actual work,"
BG: "That's crazy talk."

31

Nothing hurts the quality of your code like existing bad code, especially code with unmitigated side-effects. This is when code does different things depending on how many times it's been called, or depends on other things being called first in order to not launch the missiles.

24

copy and pasting code .... !DRY (Don't Repeat Yourself)

22

Lack of interest.

Seriously, if my heart is not in it then that code ends up the proverbial red-headed step-child. Sad, angry and alone.

19

Management believing that developers are all the same, so if they can get a bunch for cheap then they must end up ahead.

12

Not fixing broken windows!

11

I have to admit that tight deadlines have often hurt the quality of my code - leading me to submit code that worked as opposed to code that I could be proud of.

In an ideal world, I suppose we'd all have time to refactor and refine before check-in, but it seldom happens that way.

8

Code duplication

Where code is duplicated, either inadvertently or by cut-and-paste coding. Then slight changes in one of the duplicate copies lead to

  • Bugs fixed in one part of the code and not another
  • Slightly different behaviour in different parts of the application
  • More code to test and debug
8

Communication, Failure of.

  • Customers and users communicate their conceptual model of the ideal program to me. If this communication fails, I will get the wrong idea of what to build. This comminication can fail in two ways: misunderstanding and lack of understanding. Misunderstanding is when I get a clear idea but it is the wrong idea. This produces code that might work but is ultimately of no value to the user, and therefor clutters up the code base and needs to be removed. Lack of understanding is when I get the right idea but it is too vague to properly guide my coding. This produces code that tries to do the right thing, but in the wrong way, or fails in some other way. If the vague idea is clarified, then it might be possible to refactor or restructure this code to work.
  • I communicate with the computer through code written in a programming language. A language consists of two components: syntax and semantics. APIs are a big part of what comprises the semantics of a programming language. If I, as a programmer, don't fully understand the syntax or the semantics, or both, of the programming language that I use, then the best thing that could happen is a compile time failure, or startup failure, but that isn't always the case. Especially in the case of complex APIs. Misunderstanding the semantics that some API presents, often through faulty assumptions, is a very common source of bugs. People might argue that you should proove your assumptions through testing, but i don't think the world is that black and white. I believe that if the need for testing is too great, then that is often a sign that an API isn't being clear enough in communicating how it is suppose to be used. Unclear usage specifications is the source of assumptions.
  • Along the same vein, existing code communicate with me. The previous programmer documented how he understood the system and how he intended it to work. But he did so in a language that, while free of dualities, is often unfit for the purpose of human to human communication - or at least hard to get right like that. Modern programming languages are full to the brim with abstractions, but sadly these abstractions are often either not abstracting away enough details, or they are abstracting away the wrong details. Like misunderstanding an API, this leads to assumptions. But not just assumptions on a method, function or class level, but on a whole architectual or conceptual level.

There is no doubt in my mind; failure of communication, in the many forms that it might take, and on the many levels that it might manifest, is the worst poison to quality that i know of.

7

Lack of coding standards coupled with aggressive deadlines. This leads to messy, fractured, half-assed code.

6

Overtime. Nothing beats it since in it's wake all the listed symptoms appear.

6

Mental fatigue hurts the quality of my code.

Making programmers work for 8 hours is horrible for a profession that involves creative thinking.

5

My lack of knowledge on a subject. I can't think of a single time where I haven't looked at something after I wrote it and realized that had I known something about the existing system, or some some way to write the code differently I could have made a better choice. I can attribute it to a tight deadline etc., but when it comes down to it, I am the one who took 10 steps to do something that could have been done in 5.

5

Customers failing to use it correctly.

Yes, I'm kidding.

5

Definitely for me is lack of (or unclear) specification. If I knew before hand how every one of my API would behave I would make test units, make them check everything the API provides or not and ensure that everything would be tested.

The problem is, I'm always "creating", and sometimes a class method didn't existed five minutes ago and it was only created because I'm working in some other interface and I wondered that the first method exist, so I do create it just for rapidly coming back to the method I'm really interested.

And what happen? This second helper method gets implemented very bare bones not checking for everything it should, because what I want is get it running fast enough to comeback to the main problem.

I always say to myself, I have to comeback to that method and make it better later, but not now. But this later sometimes is so late that I only comeback to the method when I find out it introduces a new bug to the whole system because I started using it everywhere and didn't remember that it was incomplete.

Everything should be perfect if you could always make specifications first, tests later and then code, but world isn't perfect right, sometimes you need code to tomorrow, and forget the tests.

4

Using the wrong technology for the task has hurt me in the past. Whether it's the wrong programming language, too little hardware, or too much application stack, using the wrong tool for the job from the start is just demoralizing.

4

Lack of a solid architecture and high level design. A fully-formed design with the proper level of abstraction and modularization will make for maintainable code even when the requirements change or are incorrect.

4

Lack of planning - an amazing amount of trouble could be avoided if a few minutes of thought was used before implementing. Normally this is related to a lack of communication, and deadline pressure always makes it much worse.

4

Not that anyone will see this answer, but:

Me. I hurt the quality of my code the most. Despite trying to suck less every year. :)

3

sometimes, due to not much time, I have insufficient refactoring (when I use "spaghetti coding" to speed up development).

3

I'd say quantic specifications, that change every day or so because the client doesn't exactly know what he needs.

3

poor quality work is the result of bad management, not technology. it is the responsibility of project management to create an environment where programmers can get their work done (which is all programmers want to do - code).

many answers can be found in the following book:

Peopleware (1999) Tom DeMarco

probably one of the best books i have read this year, very easy to read - it practically reads itself and when you finish one chapter you want to keep going and do the next. it is a management book, so about 50% will be lost on programmers. but you will find yourself reading going "yeah yeah, i know, i know".

it also helped me feel more confident about taking a stand about bad management practices i have seen throughout my career. ive often felt as though i was rocking the boat or that it wasnt my place to make trouble about a particular bad practice since i should do what my boss wanted because he was paying my salary.

for me, this is what i have seen most impacts quality of code:

  1. unhappy programmers (a bad environment will drastically lower programmer output and quality of code).
  2. no project schedule. if you want to combat unrealistic deadlines, this is the power you need. without this, you cant make a case to management about how long it will take to finish a project, so they will tell you when it needs to be ready by.
  3. no bug tracking system (sounds simple, but it will be a massive help).

also, any serious software house should take a look at this: The Joel Test: 12 Steps to Better Code. whenever i arrive at a new company i do this review. commonly companies are at about 3 out of 10 (only 10 points are really relevant for web software dev). within a few months i usually get things to around 8, which results in massive improvements.

hope this has been helpful.

2

I would say insufficient test.

Ofcourse, no one is perfect. Tests will make sure of that ;)

2

Relying on a debugger, rather than my brain. Don't get me wrong, debuggers are a great, important tool, I just find that I sometimes stop thinking when I can't figure out why some variable is set to the wrong value at that point in the code...

2

Not enough contact with the end user. Specifically in requirements definition and UI design.

Note that the end user is often not identical with the person known to your team as the customer (or customers representative). I really mean the poor sods who will actually have to work with your software...

2

Having too big functions that do too much. Function/variable names that no longer match their meaning. So basically a lack of refactoring. Which is a result of trying not to miss deadlines. Which are set by management that have always ideas that must be implemented as fast as possible.

2

Other programmers;-)

2

Haste.

It doesn't matter if it comes from the outside (unrealistic deadlines) or the inside ("oh, this is a no-brainer"). Doing things quickly means doing things without thinking them through sufficiently, and that means doing them wrong.

2

Insufficient separation of concerns, i.e. classes that do too much. A prime example is user interface code directly querying the database.

1

late paychecks

1

Usually the thing that hurts my code the most is my own penchant for focusing too closely on the problem. As a consequence I tend to miss side effects that are disruptive for dependent components. Our application is a large, component-based app and small changes in the way a component works can have deleterious effects on the operation of other components.

The second largest cause of problems in my code is also a developer issue: I over-complicate. I tend to try to over-generalize a solution when it's still in the "one" phase of the "zero-one-infinity" spectrum. This leads to code that is difficult to understand when reading it over, later, and difficult to configure properly to run.

1

Based on my experiece so far I would say:

  1. Lack of or no code reviews during development iterations
  2. No unit tests for the code that is written
  3. Not having the tests integrated with the build process
  4. Lack of frequent and consistent communication between all parties seeing this through
  5. Long development cycles. This can cause additional unnecessary complexity
1

tight time line and requirements which kept changing.

stubborn management which promise customers time line lifted out from a rabbit's hat without consulting with the developers first usually helps a lot!! ;)

1

Since I maintain quite a bit of code, I would have to say the thing that hurts the quality of my code the most is...the original developers.

(I kid...sort of.)

1

Letting the code quality degenerate by implementing "quick" solutions without testing them enough and ensuring that the code is robuts, maintainable and elegant. When the code starts to degenerate, soon the team cares less and less, until the whole application is a pile of excrement.

1

For me it's the customers changing their requirements every other day. This results in ugly code full of band aids. It would be nice to tell the customer "no" but then if the code doesn't do what they want it's useless.

0

If a tech savvy good manager is absent, project quality will suffer a lot for medium sized and above projects.

0

Aggressive deadlines + late requirements.

Nothing makes good code bad faster than trying to retrofit it to handle a new requirement.

0

As you say, quality is subjective, and unless you define quality I don't believe you can answer this question. We had an interesting debate on the definition of quality on SQAforums a while back, which included a number of directly opposing views.

The simple and obvious direct answer to your question is insufficient or inappropriate testing.

0

Inconsistency. I find that rarely I am "right" coming out of the chute, or requirements change, or you have bad data, or whatever - but I have found over the years it is far more acceptable to be consistently wrong (or on that odd occassion right!) than to be inconsistent and wrong.

That extends to your code, your database, your SCM practices, everything.

And for a bonus: Don't hard-code values. Use a database, config file or some way of specifying those values at runtime.

0

Usually the worst thing is interruptions. It takes time to get into the ?Flow? and then the phone rings or someone bursts through the door and starts talking to you. Lack of concentration is responsible for most of my mistakes.

Another thing is untestable code. When you can?t test the code that you have written, the code becomes ?legacy? even thought it was written a couple of weeks ago. This is bad especially when you don?t work alone and your teammate wants to understand what the hell did you mean when you wrote this piece of shit.

0

architecture astronauts

0

Aggressive deadlines can be a problem. I'm "fortunate" that I haven't bumped up against the issue that much at my current job.

A bigger problem is that I don't feel like we emphasize the craftsmanship aspect (and, improving on it) enough as a group. I do my best to try and improve on my own. I guess I'd flag that as lack of interest. I suppose it's a significant hazard at an internal IT shop that isn't actually selling software - a significant part of my work week is juggling walk up requests and there's often not time to revisit existing code to improve it, even if it's demonstrably better to do so from a maintenance standpoint.

We have coding standards but they are not seriously enforced, which sort of renders them pointless. For awhile, it seemed like I was the only one following them. That's a problem too, but I think it goes back to lack of interest.

0

From commercial experience, constant design requirement changing.

0

I think it is a combination of things:

  1. Aggressive Deadlines
  2. Poorly documented/understood requirement
  3. Lack of task tracking, from requirement creation, development, tested, approved, and released
  4. Poor use of test suites
  5. Developer turn-over
0

As we use Delphi to code, a big part of our code is in the components we use. While most of these work fine, two issues I have with them contribute to a degradation of our code:

  1. Incomplete and/or incorrect documentation: I don't know half of the available exceptions that can be thrown by these components, so I have to resort to using Generics until I get the appropriate exceptions listed. Very time consuming. Also, When I'm trying to use a function in a component, and I only have documentation for part of that function, I have to guess at how the entire thing is meant to be used. Please complete the documentation.

  2. Too many warnings/hints: There are three component suites that I use heavily (and I know hundreds of other Delphi developers use) that throw tons of warnings and hints at me out of the box. I've had to spend a couple of weeks on each of them (because of the sheer number of them) to get the code cleaned up to where I'm not generating these hints and warnings. Most of them are stupid items too, that take two seconds to fix like incorrect casts and unused variables. If I'm paying $200-$500 a license, is it too much to ask to have your code cleaned up? I'd like to only see my own issues and memory leaks.

0

NDepend documentation comes with some pretty cool and advanced online blog posts, articles and white books concerning code quality of .NET code:

Fighting Fabricated Complexity

Layering, the Level metric and the Discourse of Method

82 code metrics definition

Code metrics on Coupling, Dead Code, Design flaws and Re-engineering

-1

Bad coffee ;-)

-2

Other programmers;-) ++ specifically permies ....ohhhhh... ;)

-5

Refactoring and Unit Test do not affect the quality of software. Refactoring makes it easier to maintain, and unit tests validate the software works as expected, but they don't affect the quality; they are tools that allow you to measure quality.

Anyway, lack of communication, whether is among team members, with customers, or with designers through specifications, is one of the major causes of bad quality software.