Take the 2-minute tour ×

Normally what happens is that I work on something for a while and then when I am done I check it in(After the test/review process of course). Sometimes I have to go back and fix something that I got wrong the first time due to me not understanding the problem enough, lack of testing, etc..

What is an acceptable rate for this? Ideally you would hope that you never have to go back but sometimes you do. What rate does the average programmer have and what is the expert programmers rate? Do people track this? Lastly what kind of checks are best at preventing this?

PS: I am not counting the cases where the requirements have changed and you have to go back in.

I know that there is no real answer to this so let me change the actual question to: "What general checks could be implemented, before code is sent for review or checked in, that would help prevent the need to revisit the change later?"

share|improve this question
Acceptable to whom? Personal acceptance? Project manager acceptance? Client acceptance? User acceptance? –  StuperUser Nov 1 '11 at 16:53
Depends on the size of the code, the number of unit tests you have, did or can you run static analysis on the code, the complexity of the code, if you have used a new API that you are not familiar with and how good your requirements are. –  Scott Wylie Nov 1 '11 at 16:58
I would say personal acceptance and employer acceptance. Part of my thought here is that these are the types of bugs that will not be seen by the customer just the other developers/test team. –  barrem23 Nov 1 '11 at 16:58

7 Answers 7

It's impossible to quantify. What is important is the total impact those bugs have, not the total number of bugs.

I would recommend you to look into Test Driven Development/Unit Testing if you want to reduce the number of bugs in your code.

share|improve this answer

As to your original question, what's "acceptable" is impossible for us to answer. You yourself must decide how much reworking you can do while still moving ahead at the required pace of new development. Such has been the goal of project managers for decades.

No matter what system of development you're using (waterfall, UML, Rational Rose, Agile), two things are absolutely required:

  • The client must have communicated to you exactly what the code should do in the general case when performing some task. This isn't as impossible as it sounds; usually the "general case" breaks down to a "nominal case", an "exceptional case", and an "error case". The situations for these should be described and the expected behavior of the system in these situations defined.
  • Given requirements at a level of specificity that covers all expected scenarios, the code must adhere to the requirements. For the nominal, exceptional and error cases, the system should perform as defined before it is released to the customer.

Given these two things have happened for each task the system is capable of performing in all known situations, you have done all that is humanly possible to ensure a quality product. However, there will still be "defects"; the code cannot be guaranteed to perform as expected outside of the known scenarios, which may have inadvertently excluded some possible scenarios. That's not your fault as a developer; either you as an analyst did not think to ask what should happen in some particular case (probably because it seemed to fall into some defined situation), or the client did not properly define the requirements such that all possible cases were covered. Happens all the time. What happens as a result from a business perspective depends on the design methodology and business pattern, but you as a developer will probably eventually extend the code to cover the missed situations, and then you will verify that the system still works in all other situations.

This is where TDD really shines; if you accept that regression of functionality due to the introduction of defects in future work is possible, then it naturally follows that having a test that is always available to prove that the code will meet the requirements (and thus that you wrote what you thought you wrote) is an invaluable means to avoid said regression.

share|improve this answer

The aim is to get to a stable, useable (or shippable) system as quickly as possible.
So I don’t see any real problem in having to revisit a change, provided each change is moving the system in the correct direction and it is not making it harder for anyone else to do their job.

The worse sin is to break something that the customers are already using, hence the need for automated regression tests, customers are a lot more forgiving if the new bits are not 100% the first time they see them.

share|improve this answer

Test your code. Make sure you have at least some unit tests around your code to check the tricky bits, and preferably completely covering any components that your changes touch. Run through the user stories you implemented to make sure they work as expected. Find out what tests the QA team will be performing to test the change, so you can try those tests out yourself.

share|improve this answer

It really depends on your development practices and where you're checking into. When committing to a development/experimental branch, it's not important at all. Get the code in. It doesn't matter if it's messy when you're working on it, just as it doesn't matter too much if a car mechanic gets dirty when working on an engine or changing the wheels.

Where it matters is when you're going to a mainline or support branch. There you should take great care to make sure that before commit that the code both:

  • Builds, and
  • Passes its test suite.

Ideally that will be a one-step check driven by your build system (if it isn't, it's too many steps!)

Once it passes those checks, which should include sufficient new tests to show that you've fixed the problem without introducing new faults, then commit. (A good method is to get the code to a good state on a working branch before merging back to mainline; a DVCS like Git makes this much easier.) Then have a Continuous Integration system rerun the build and tests from a clean check-out so that you can know you've not missed anything stupid (integration tests might be run less often, as they're more expensive but they're also important); if that shows problems, fix those immediately and don't be embarrassed about any loss of face. The aim should be to have the mainline (or supported branches, depending on project/site rules) buildable and clean at all times.

share|improve this answer

What I do is to create packages and classes diagrams representing the static structure of my application. Not too much just the structure and I got the code in synchronization with the diagram. My diagrams are not just views of the real world but they are the real world !!

Once I finished this first draft modeling stage I then code, test and deploy. In real project I always need to go back to my code. I can then either change at code level or at graphical level using UML class diagrams. The graphical view is really faster and it is just done by drawing or refactoring my current diagrams. I then again code, test and deploy. And again and again. This iteration approach is really fast and very efficient because not only the structure is creating at objet level using the class diagram but also the database using database stereotypes and then hibernate.

This works really well because I don't use Model Driven Development with a code generator but only direct mapping and synchronization between UML model, code and databases. There is also no mix between my code and model like with EMF. Code and model are syncrhonized on demand and keep separately. I like UML class diagrams, multiple iterations and hate Model Driven Development code generator because if the code is generated then you can not change it manually at test and deployment level !!

share|improve this answer

There is a set of practices which helps to raise quality of code:

  1. Unit testing is a must.
  2. Continuous integration will help to run unit-tests automatically and provide convenient reporting.
  3. Static analysis (inspections) helps detecting source code vulnerabilities and frequent coding errors which cannot be caught on the compile time.
  4. Dynamic analysis - autotests, performance analyzers, memory & leaks analysis, etc.

Personally I have several types of branches (in version control system) with different commit and code quality policies.

  • experimental branches have no control over code at all. One exception is that code should compile before commit.
  • trunk & maintenance branches have also unit-tests and continuous integration enabled.
  • release branches have all of the aforementioned enabled: unit-tests, continuous integration, static analysis, dynamic analysis and even copy-paste detectors.

So, the recommendation is very simple: use different policies and tools for different types of source code repository branches.

share|improve this answer

Your Answer


