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:
Developers:
Both:
"Aggressive" deadlines.
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."
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.
copy and pasting code .... !DRY (Don't Repeat Yourself)
Seriously, if my heart is not in it then that code ends up the proverbial red-headed step-child. Sad, angry and alone.
Management believing that developers are all the same, so if they can get a bunch for cheap then they must end up ahead.
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.
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
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.
Lack of coding standards coupled with aggressive deadlines. This leads to messy, fractured, half-assed code.
Overtime. Nothing beats it since in it's wake all the listed symptoms appear.
Mental fatigue hurts the quality of my code.
Making programmers work for 8 hours is horrible for a profession that involves creative thinking.
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.
Customers failing to use it correctly.
Yes, I'm kidding.
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.
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.
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.
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.
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. :)
Other programmers;-)
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.
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 [1]
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:
also, any serious software house should take a look at this: The Joel Test: 12 Steps to Better Code [2]. 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.
[1] http://rads.stackoverflow.com/amzn/click/0932633439Insufficient separation of concerns, i.e. classes that do too much. A prime example is user interface code directly querying the database.
sometimes, due to not much time, I have insufficient refactoring (when I use "spaghetti coding" to speed up development).
I'd say quantic specifications, that change every day or so because the client doesn't exactly know what he needs.
I would say insufficient test.
Ofcourse, no one is perfect. Tests will make sure of that ;)
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...
late paychecks
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...
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.
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.
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.
Based on my experiece so far I would say:
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!! ;)
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.)
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.
I think it is a combination of things:
architecture astronauts
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:
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.
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.
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 [1]
Layering, the Level metric and the Discourse of Method [2]
82 code metrics definition [3]
Code metrics on Coupling, Dead Code, Design flaws and Re-engineering [4]
[1] http://codebetter.com/blogs/patricksmacchia/archive/2009/06/28/fighting-fabricated-complexity.aspxInconsistency. 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.
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.
From commercial experience, constant design requirement changing.
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.
If a tech savvy good manager is absent, project quality will suffer a lot for medium sized and above projects.
Aggressive deadlines + late requirements.
Nothing makes good code bad faster than trying to retrofit it to handle a new requirement.
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 [1] 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.
[1] http://www.sqaforums.com/showflat.php?Cat=0&Number=434579&page=3&fpart=1&vc=1Bad coffee ;-)
Other programmers;-) ++ specifically permies ....ohhhhh... ;)
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.