No one's perfect, and no matter what we do, we are going to produce code that has bugs in it from time to time. What are some methods/techniques for reducing the number of bugs you produce, both when writing new software and changing/maintaining existing code?
How to reduce the number of bugs when coding
bug
Related Solutions
This depends wildly on the situation, the bug, the customer, and the company. There is always a trade-off to consider between correcting the implementation and potentially introducing new bugs.
If I were to give a general guideline to determining what to do, I think it'd go something like this:
- Log the defect in tracking system of choice. Discuss with management/coworkers if needed.
- If it's a defect with potentially dire consequences (e.g. your example #2), run, scream, jump up and down till someone with authority notices and determine an appropriate course of action that will mitigate the risks associated with the bug fix. This may push your release date back, save lives, wash your windows, etc.
- If it's a non-breaking defect, or a workaround exists, evaluate whether the risk of fixing it outweighs the benefit of the fix. In some situations it'll be better to wait for the customer to bring it up, since then you know you aren't spending time fixing/retesting things when it's not 100% required.
Mind you, this only applies when you're close to a release. If you're in full development mode, I'd just log the defect so it can be tracked, fix it, and call it done. If it's something that takes more than, say, half an hour to fix and verify, I'd go to the manager/team lead and see whether or not the defect should be fit into the current release cycle or scheduled for a later time.
Is the COCOMO model a good argument when defending a programming language choice?
No. COCOMO says nothing about language choice at all. It is a cost estimation tool to determine how much it will cost to build a given software system given a series of inputs. The latest iteration is COCOMO II, and there are web based tools to use when applying this model. Some of the inputs that go into COCOMO II include the estimated size in SLOC or function points, the team cohesion, maturity of the process, desired reliability, complexity, the capability of people filling different roles on the team, platform constraints, and schedule. The output is the estimate for effort, schedule, and cost for the project.
Only a handful of the inputs are related to technology and programming language. The key adjustment factors that cover these areas are the capabilities of the programmer, experience of the programmer in the application domain, experience with the platform and language, and the ability to obtain and use supporting tools.
As far as defending a language, the best that you can do with COCOMO is produce multiple estimates for different technologies and languages that the team knows to varying degrees. Perhaps there's one technology that the entire team knows and has successfully used before, so platform and language experience would be high, but that language has very few supporting tools so that would be lower. You can compare that to a language that perhaps only one person knows extremely well and a few people know a little about, calling the experience nominal, yet factoring in the rich tool set. Given two (or more) sets of effort, schedule, and cost estimates, you can compare to see which might be more effective to use.
Also, since the language is terse, the number of lines of code is reduced and you would get a better COCOMO rating.
There is no such thing as a COCOMO rating. COCOMO is an estimation tool that you can use to try to determine how much effort (person-months), schedule (months), and cost a project will require to complete. When estimating, this data is compared against the size of the project team and the business schedule to determine if it's realistic and to provide the project manager with information needed to control the project schedule.
For example, COCOMO might produce a schedule estimate of 15 months and a cost estimate of $500,000. However, the business schedule might call for 12 months and $450,000. This schedule and isn't unreasonable, and the project manager can use this information when controlling the project and negotiating with the customer.
But can this be applied in the first place or does the COCOMO model use the number of lines of code as a way to estimate a project's overall size (project size should be the same whether you implement it in a terse language or in an imperative one, but again, maybe I didn't understand the COCOMO model correctly)?
Although source lines of code (SLOC) is a valid input to COCOMO, estimating size using source lines of code is not recommended because the number of SLOC varies depending on programming language (among a number of other problems). Function points are a preferred method of size estimation. There are conversion ratios that allow you to estimate a number of function points and apply the ratio to determine the size of the system in a given programming language.
Now, comes the other parts to your question.
Currently, I'm following a course on embedded software development. The lecturer has chosen J as an architecture language for model-driven software development. J itself is a very terse programming language and one of his main arguments for this language is its terseness. Another argument is that through such a language and the reduced number of characters, you introduce less bugs and the time to fix bugs is reduced. [...] I feel that these arguments aren't valid. I find that there is a strong movement towards descriptive names and code that reads like natural language (alright, this might only be related to applications with lots of business logic and less math).
That's nice. In my experiences, the lecturer has more experience in the topic than the typical student. When they choose a given language, framework, platform, or technology to use to teach their content, they have a good reason to.
Terseness is, in my opinion, a rather poor measure to discuss a language on. There are far better criteria to use when choosing a language to implement a project in - platform support, tool support, available resources, team knowledge. With never having seen J before, it seems rather difficult to read. However, it might be very good at solving the particular problems that the project is trying to solve, and the people on the team might have experience with it. It might also be easy to learn.
In your specific case, of a class, you need to focus on the point - learning concepts and techniques. Not only will you learn about J (and learning new tools is always good), but you'll learn techniques that can probably be applied to other languages as well.
The question therefore is, can you really argue that usage of a terse programming language will result in less errors and that time to fix a bug is reduced?
My intuition says no, but that's beside the point. You need to factor in knowledge of the language, supporting tools (compilers, IDEs, static analysis), and process methodology (pair programming, code reviews, style guidelines), and more to have an adequate discussion of how to reduce errors and time-to-fix.
If you're interested in more about COCOMO and what it's all about, I'd recommend reading Software Engineering Economics and Software Cost Estimation with COCOMO II, both by Barry Boehm. Software Engineering Economics is mostly general software project management, cost estimation, and effort estimation. The portion of the book that discusses COCOMO discuses the COCOMO 89 version, which Boehm has said should no longer be used due to inaccuracies that were corrected in the COCOMO II version, however the rest of the sections of the book are still relevant.
Best Answer
Avoid fancy coding. The more complicated the code, the more likely there's bugs. Usually on modern systems, clearly written code will be fast and small enough.
Use available libraries. The easiest way to not have bugs writing a utility routine is to not write it.
Learn a few formal techniques for the more complicated stuff. If there's complicated conditions, nail them down with pen and paper. Ideally, know some proof techniques. If I can prove code correct, it's almost always good except for big, dumb, obvious bugs that are easy to fix. Obviously, this only goes so far, but sometimes you can formally reason about small but complicated things.
For existing code, learn how to refactor: how to make small changes in the code, often using an automated tool, that make the code more readable without changing the behavior.
Don't do anything too quickly. Taking a little time up front to do things right, to check what you've done, and to think about what you're doing can pay off big time later.
Once you've written the code, use what you've got to make it good. Unit tests are great. You can often write tests ahead of time, which can be great feedback (if done consistently, this is test-driven development). Compile with warning options, and pay attention to the warnings.
Get somebody else to look at the code. Formal code reviews are good, but they may not be at a convenient time. Pull requests, or similar if your scm doesn't support them allow for asynchronous reviews. Buddy checking can be a less formal review. Pair programming ensures two pairs of eyes look at everything.