Alan Cox on Writing Better Software
Andy Gimblett writes "Alan Cox recently gave a talk in which he discussed some current and emerging techniques for producing higher quality software. Some of these will be familiar to Slashdot readers, such as validation tools, type checking, etc, but others seem heavily influenced by his recent MBA. In particular, he has a lot to say about Quality Assurance in the software world, and the kinds of things we should be doing (and some people are doing) to make better software. Story and lots of quotes at Ping Wales, and video at IT Wales."
unit tests
not a panacea, but it does go far.
Simpy
I see that the word "Free" doesn't appear in this story's synopsys.
How would Alan apply his quality methods to projects which member might never meet due to geographical contingencies ?
Trolling using another account since 2005.
...isn't just for end-users! If you anticipate that others will be working on future versions/releases of your software, good commenting can make the job SOOOOO much easier for the next codemonkey.
I'd say commenting is doubly important in OSS projects, as it involves many sets of eyes trying to comprehend what you coded.
There's a Mercedes gap too. I want one and can't afford one, but it's not government's job to do anything about it.
here here. as a coder i tend to get things working as they should be, but the user comes along and does something completely different. i've found that the key lies in trying to break the code, and when you get it so that it doesn't break, you're halfway there. i try to code for at least a 'mars rover' level of reliability.
Unit testing is essential, but it's not a panacea. In particular, beware of two pitfalls:
1) "The unit tests passed, so it works." This assumption is flawed on several levels. First, and most fundamentally, even if all unit tests pass, there is still the issue of whether your software works as a whole. Software often has "emergent logic" and UI scenarios that are difficult or impossible to test (after all, that's not what unit testing is for, but some people seem to think it is).
Second, just because a test passes, doesn't always mean the API works. This is especially important if you didn't write the tests yourself. Just because a unit test CLAIMS it tests X, doesn't mean it does. Is the test complete? Any false positives? Is the test just a skeleton that was intended to be implemented later but never was? I've had all these bite me in the past.
2) "That particular test has NEVER passed, so there's something wrong with the test. We just ignore it now." Bzzzt! Wrong! There's a REASON it never passed. It's either not implemented properly, just a stub that fails waiting for someone to write an implementation, or maybe you just think the feature it tests actually works. Look closer. The test might be trying to tell you something.
If you are careful with unit tests, they can be very rewarding and useful (especially for regression testing, where they are invaluable), but put too much confidence in them or depend on them to do the kind of overall testing they were never designed to do, and you will fail long before your first test does.
What people should realize, is that it can cost quite a bit of effort to build a unittest. I.e. if you write some code that reads several rows from a database and as a result writes a bunch of rows in another table, you need to run scripts before and after your unittest. It's of course all doable, it's just that it's sometimes more work than writing the method itself.
8 of 13 people found this answer helpful. Did you?
But the real key is reducing the number of defects introduced into software. Testing only finds existing errors. If the number of errors are low from using good requirements, design and development practices then testing becomes less expensive and time consuming.
And what then when the customer wants some hard evidence about what has been done? What then? What will you provide to them? How does your irrational hatred of managers actually assure quality in concrete steps?
A good manager does all the detail work and keeps track of everything. My post was about what they haven't been doing much of lately.
I don't hate managers, and to suspect that I might by reading my previous post means you failed to understand it.
Quality in business comes from many different people in any given project. Software quality can be adversely affected by morale, and you guessed it -- programmers have some of the lowest morales in the business world today; they are often not respected by management, they have the highest workloads, and they have no time for social lives.
If managers listened, and remained silent or inquisitive instead of arbitrary or antagonistic, software quality would be up.
The dangers of knowledge trigger emotional distress in human beings.
The links seem dead so I will add my .02. The programmer's view of the software should not be confined to the source code control system. Programmers should know how to install and implement the software they design and code. Programmers should have some personal experience supporting the software they code. NOTHING highlights the weaknesses of your software faster than being forced to work a support line/forum, etc. Establish personal relationships with employees in the sales force and management. You will be able to be more influential in the company if you do this. Establish personal relationships with your customers. You can use them to push your agendas. Paying customers have some of the most pull with your company. Use this to your advantage.
Unfortunately, when schedules get tight, it's things like unit testing (and testing in general) that get cut. The more emphasis we get on the importance of QA the better our industry will be.
Against stupidity, the gods themselves contend in vain.
Study Mock objects
You can't help but be frustrated when dealing with projects that were obviously "proof of concept" which then evolved directly into the actual "product". Hard to resist but just plain stupid. I wish more open source projects had strict standards.
yomomma.org/
We used to implement code reviews at my former workplace, but they were more "sanity checking" peer reviews than anything else. They didn't take very long, and it gave one or two other people a chance to see how understandable or generally logical the changes were.
That type of thing doesn't work as well for large changes, but we found that for small ones it sometimes can be a useful thing.
Mainframe/UNIX Bit Twiddler and long time Windows/Linux Hobbyist.
The Theorem Theorem: If If, Then Then.
This has several important benefits:
www.eFax.com are spammers
Viewing your code in assembler? Comment every 3 lines? You must be kidding, or trolling.
The top 5 things are:
1) Meeting the requirements
2) Stability
3) Maintainability
4) Expandibility
5) Efficiency
You said "speed" at number 2. 4 and 5 just reiterate that. Are you a speed freak? Games coder, perhaps? :-)
:D
Robustness is WAY more important than speed. Forget speed. Really. Forget it. Then forget it some more. I'm an assembler coder and I could do without the competition
These are some things i guess is necessary for good software
1) Reviews at all stages.(Reqs/design/dev)
2) While at development, u sure must know whats the most efficient way to code a design (which libraries are more suitable etc)
3) Unit testing and Integration testing (when the project is huge)
Some practices that managers can really use to take the pressure off the team
1) Try giving buffers to the team (seriously, it works)
2) Proper Code management (Lotsa rework and pressure come due to lack of this)
3) Proper tracking and status updates to the customers
the engineers who wrote the code actually write tests
Do NOT get the engineer who wrote the code to also write the test.
It's fairly fundamental - the engineer who wrote it will have a prejudiced view of what should/will work.
Get someone else to do it and get a valuable fresh insight.
The only way to create error-free software is using a guaranteed error-free interface (I'm not talking Java, we should go much further), which has to be the base of the operating system to be actually error-free.
As a nice by-product, developing applications will be much easier.
It's quite surprising to me that there's no mention here of unit testing, or any sort of automated testing where the engineers who wrote the code actually write tests.
It's better if you get different people to write the tests. Otherwise the engineers might subconsciously make assumptions in their unit tests that real-world use might not.
Managing people to be happy and productive is not the only quality assurance activity you can do.
I ask you again, how does your four-part list concretely assure software quality? The human issue is just a really small part of the software quality. You have tight schedules, inane processes, nonexistent budgets, requirements from some other galaxy, need I go on?
How does for example listening to people automagically track the number of defects? Or make sure there's a responsible person for certain code modules? Or make sure the test cases are written, run and kept up-to-date?
The problem is not so simple as you put it. Yes, listening to people will help but it's not the whole solution nor the end-all to this dilemma.
If someone is arbitrary or antagonistic, speak up and give constructive feedback, tell them to stop being such. If you are reprimanded for that, why work in such a place?
It's fashionable to bash managers, but how many of you will not speak out about things which are wrong when you have the chance, then complain about it being so? If your managers don't listen when you do that, find another job with better managers.
I'm not claiming silver bullet status. Far from it. I'm simply stating that software engineering requires contracting and better interface design techniques as part of its standard repetoire. Add these to the hard work and discipline you mention.
(Also note these are not tools, but techniques.)
remember Sammy Jankis
you only need to validate the functionality in the method itself is working. from your sig it seems you're using java. junit with an embedded axion database allows for extremely easy testing of a method that uses a database connection for its work. of course, you have to setup your test by creating a table, and inserting any base data. getting that basic framework is as simple as writing the method itself. you'll probably double your time in writing the actual method. i'd think the return on that investment is "priceless".
Surprising you dont seem to think good software should meet the users/customers requirements. That would be first on the list for me. Software must do what the user wants or it is a total failure as far as I am concerned. In general I would agree with your points. Code should be robust, testable, maintainable and reasonably performant. I prefer the source code to be documented well and autogenerate documenation from it rather than maintain duplicate documentation.
I am also a big fan of profiling code, and for server apps, proper load testing is and absolute must. It often only finds the low hanging fruit as performance bottle necks tend to be resource based eg the database is usually the 'culprit'. Profiling and code coverage/ code analysis are valuable tools though to identify critical paths and likely sources of problems and help developers gain a clearer picture of how the application actually works.
Do not try to read the dupe, thats impossible. Instead, only try to realize the truth
What truth?
There is no dupe
If you are bug hunting then the code review needs to be an explanation of what the code does. "We get a foo, we have to decide if its in US or UK format so we compute both checksums and .. oh umm.. I'll come back later'
It's very different to things like design reviews. They have their place too. A lot of things Linus rejects are really design review things. Its not uncommon to get a "Yes this needs fixing but do it this way instead". It works well providing the person saying that has good judgement.
Bad code review, bad tools, bad compilers and bad managers are _all_ useless
If this happens to you on a regular basis then you are probably a better-than-average developer. Which is just fine as long as we find a way to make your work more average. And code reviews seem to do the job.
Seriously, the productivity spread between developers (20 times as effective... adding more people... Thank you Mr. DeMarco) is what a lot of very strict process models and practices (such as code reviews) really attack - and it is a good thing, too. Because otherwise developer workforce does not scale well.
The productivity spread is the enemy of plans, predictions, estimations and bureaucracy. Bureaucracy is the most successful human scaling mechanism.
In other news: Big cooperations have difficulty exploiting the individual genius of low-level members of their workforce.
You can attach boosters to anything. It just costs more. -
Anonymous Coward on Sunday November 07, @12:26PM
Unit testing doesn't find bugs, it just ensures that you didn't regress the obvious or break something that your previously fixed.
With end user applications, on average, a couple hours of active ad-hoc testing and test case development per week finds 95% more bugs than hundreds to thousands of automated unit tests will.
For an API, unit testing might be more effective, but APIs are much simpler to test than full end user applications.
The human issue is just a really small part of the software quality.
Trust me. All problems in software engineering are human issues.
It helps nothing if a guy in the team is a hero or super hero or the brightest expert if the human factros are a mess.
All problems in software projects are simple:
1) lack of understanding -- people do not understand the problem domain
2) lack of insight -- people do not realize they suffer from (1)
3) lack of problem aware ness -- people do not realize that there ARE problems and that they have to SOLVE them
4) blaming other people -- as soon as it gets obvious that (1) to (3) is happening, a solution is not searched but a guy to shift the blame on
This are the core problems. All so called Software Process or Software Engineering tools and habits only soften those problems. A issue tracking tool, e.g. makes it harder to shift blame. As the author of the issue, the assigner and the asignee are known. Same for version control.
As soon as the simplest tools and the simplest habbits get established, people start working together. Working together or not working together. Thats the big point.
How good a certain guy at certain technology is, thats less important. That guy can learn or can be placed at a different work area. If you have such a guy you made your first mistake anyway allready. That again was a human issue (he tricked you in believing he is good, or you misjudged). So cope with it buy educating him or fix it by replacing him.
It's fashionable to bash managers And rightfull so!
For a software project you need no managers! At least not a manager in the traditional sense. A managers job is to get the staffing and the budget done right. Furher he has to be able to understand the development speed/quality of the team and communicate the teams results to the budget owners or customers. Most managers don't do that but make technical descissions about stuff they have no clue about! E.G. my latest project we used a JDO engine (of a so called market leader lol, well the simple piece of software costed Euro 500). We had hughe problems in certain areas of the software and spend about Euro 50.000 in internal development costs in working around those problems.
The team wanted to switch to Hibernate. The manager descided: NO! This is in spite the fact that we made a thouroughfull investigation about costs and benefits and showed we start saving money after 3 weeks and would have speeded up the development process by spending less time in DB mapping etc.
Thats just a simple example. So, we had a human issue again! The coders failed to communicate! The manager failed to understand!
The project was close to run overtime, because of that issue. It was over budget because of that issue.
Nevertheless Alan Cox is right in his analysis. Better coding habits and better strategies and better tools and better languages of course have an impact. The limit however are allways the humans.
angel'o'sphere
Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
First, it is not necessary for unit tests to be absolutely complete to be useful. Anything that finds a hitherto-undiscovered flaw is valuable - extremely valuable.
Second, that there are bugs in a unit test is not, in practise, that big of a deal. At worst it means is you haven't tested a unit as thoroughly as you think you have. Unfortunate, but not a disaster. Perhaps two people should write their own units tests for a single module, and then compare the bugs they found in the module. An interesting experiment I think.
My experience with unit testing is that it greatly speeds up the development process. Trying to get a half dozen classes all up and working simultaneously is an arduous task that can take god-knows-how-long. Trying to get one class up and working through unit tests is generally straightforward and predictable.
And the quality of the component goes up. Waaaaaay up. It is rare when I write a unit test and don't catch at least one bug, thus easily paying for itself.
It is not a case of unit testing versus reviewing. It should be a case of unit testing and reviewing.
Man, if only there were unit tests for slashdot postings... Ah, wait, we have those (lameness filter!) and they don't help at all!
You tacitly assume that it is possible to get solid requirements. When writing avionics software, I'm sure you can, because the problem is well understood and we have good science/math to back it up (eg. GPS nav system).
But in most sofware projects it is impossible to create requirement ahead of time, mostly because the problem you are trying to solve is new and we don't understand it well enough yet.
Are there requirements for the web browser? Were they created before the code was written? WHat about requirements for MS Word?
...richie - It is a good day to code.
On UNIX you did this instead:This was revolutionary. Really. It's not perfect, but it's so much better than what we were using at the time that it's no wonder people couldn't wait for AT&T and re-implemented UNIX from scratch several times.
This is the same kind of improvement we need in our interfaces for GUIs, databases, network services, and so on. Even the Berkeley socket interface is too complex... all those details of address formats and address structures? Those shouldn't be there... you should be able to do this:Yes, there's libraries that do this, but they all have the same socket()...gethostbyname()...connect() stuff under the hood. This should be handled at the system call level.
As for GUIs... Plan 9 is about the only one I've seen that looks like it's even trying to reach the level of clarity, safety, and consistency we need.
What you say is mostly true. Managers often get on my nerves too. Especially at crunch time. I also know a few developers that actually expect the code they write will never fail.
What ever the case, good management will know when to get involved and when not to. There are always signs of problems. As an example: Many years ago I worked at a company that was second marketing several different Unix machines under their own name. We did a lot of work to make them as compatable as possible to give customers a real choise. A whole group of tests were thrown together to try and test this. At any time over 80 percent produced some kind of failure messages on all or some of the different platforms. This was in the late 80's and 2 consultants were brought in to look at the test and failures. They were supposed to fix the tests where needed and report on real problems. 3 or 4 months later, on a saturday, I was trying to use the tests to validate some compatability changes I had made. They all passed. A couple of months before nothing had passed. I expected some success but not complete by a long shot. Every test I needed had simply been commented out in the latest snapshot of the tests. They had done nothing at all. When confronted they had no excuse but "we are still identifing tests that fail". They were gone about 2 hours later.
Point being, I think most quality failures are from both managment and development being secretive, self serving and practicing a lot of CYA. I guess these are the reasons why I like OSS. Secretive and CYA has a very hard time occuring and self serving comes about because the programmer gets reconized for both managing and developing on a project far above industry standard quality levels.
If you want an example of managment gone bad take a look at ISO 9000 time sinks.
Heavy type-checking relies on the same theory that more buerocracy is the solution to quality.
The earlier you catch a bug, the easier it is to fix. That's been proven. Heavy type-checking catches bugs at compile time. Dynamic type-checking may leave bugs until the user runs over them.
Is the array row-first or column-first? If rows and columns are different types, then the compiler will tell me when I got it wrong. I don't find that chasing that bug later, when it could be anywhere in a thousand lines of code, is a more efficent way to quality. Sure, it means a few more casts when I want to add rows and columns, but I've never found that a problem.
Type-checking doesn't always make the code harder to read. In a type-checking language, "if (a==0)" lets me know that a is a number. In several non-type-checking languages, a could be just about anything. It's possible that you can't figure out what a is, even after looking around the code; it's possible that the else part of that statement may have to deal with a being a list, or a record, or a string. There is no local checks you can make to discover that; you may have to read every line of code to discover what type a is.
you (and many others) are confusing software requirements with design and implementation. if you can conceive it to write the code you *can* write some level of requirements. requirements are not the design of the system. a simple requirement can spawn many many many design decisions. however, in the end you want the software to meet the requirements, usually irrespective of the implementation that gets you there. what you find is that some design decisions are routinely made to meet a requirement, this does not make them the same.
Stunned by the horrible quality of the software in the megacorp I work for, I was complaining to a dot-com millionaire friend of mine who got rich on a different company. It was enlightening.
He related the experience of meeting one of their VPs. Turns out the VP was famous for having realized that every customer service call was an opportunity to SELL MORE PRODUCT. Their profits went up. Wooo-hooo! Writing SHIT CODE actually made them MORE MONEY.
I realized it was the same with my company. On all the on-line forums I hear "I'd never buy any other brand. I once had this horrible problem, and their customer service was so responsive! They fixed the problem!" It never seems to occur to customers that if the product actually WORKED they wouldn't have needed to call support in the first place. Shit code boosts our profits, too. People get a warm fuzzy talking to good customer support, no matter how bad the technology is.
There are other ways to benefit from bad code, especially if you dominate the market. Releasing a new version? If you botch the backward compatibility it forces everyone to upgrade! Profit!
So, what's all this nonsense about better code?
Been there, done that. I could not agree more. But I have had a number of good managers in the past. Did a stint as manager myself at one time. I backed off because, like you, I just plain like to be productive and I think like an engineer. This may it difficult to deal with those above me.
My direct manager right now is acutally one of the best I have seen. The other 3 or 4 layers above are lost and clueless most of the time. Their buzz word at the moment is ISO 9000.
I think your comments bring up another issue. F**k up move up is often not just a saying. I have made friends and lost friends in the past for my opinions but if one of my fellow programmers is just plain incompetent, lazy, or an ass hole then they need to go. I don;t encorage moving them to get them out of my hair. I have done this before and somehow I always ended up having to deal with them again.
There is also the type that are just biding their engineering time till they can become a manager. I have generally found these guys to be less than worthless. They are usually garanteed to make the worst managers.
These are the criteria I usually find good in a manager and tried to use as one:
1. Have a good broad software background. If working at the kernel level (including driver) have a basic understanding of hardware
2. Understand how software impacts the potential customers and their needs. Books have been written on this, most of them wrong.
3. Know your employees and their stengths and weaknesses. Use this to build a team that can and will perform.
4. Trust the team but keep track of everything anyways.
5. Process is a must but it should be pretty lightweight. Make it enforcable and do not waiver in ensuring the necessary pieces occur.
6. Insulate your engineers from most of the stuff above. Not all, just most of it. Usually controlling the flow will suffice (often this involves rumor squashing).
OK enough for now.
All his points are valid, but (a) dangerous when taken as gospel, and (b) miss the forest for the trees.
What kills software is complexity. I've been writing code professionally (i.e. getting paid for it) since I was 15. It's been 28 years. Starting with Dijkstra's "GOTOs Considered Harmful", I've seen fads to improve software reliability come and go: structured programming, object-oriented programming, garbage collection to handle memory leaks, etc; as well as programming languages prividing the syntactic and semantic sugar to support the fad du jure. Hasn't helped, has it?
The general problem is one of managing complexity: if you can "come from" anywhere to a snippet of code, how can you ensure that all your assumptions about the context you're in are valid? Similarly, if you can access a global variable, well, globally, how can you be sure it contains what you expect? How do you know all the ways your data can be accessed? How do you control when and where an object is destructed, or that all resources (memory being just one) are freed?
Either restrict who can do what, or restrict the assumptions you make about the things you are operating on.
Using a garbage collector restricts who can allocate and deallocate memory. Object oriented programming restricts who can muck with private members. Structured programming restricts how you can get somewhere. O.K. wise guy, how are you going to write a garbage collector without dealing with raw memory? Gee, you have to get your hands dirty. How are you going to deal with private members inside private member functions? Gee, looks a lot like functional programming with globals, doesn't it?. How, the heck are you going to compile that loop without a jump at the end? Gee, what was that about GOTOs?
The trend appears to be to try to find the "next great technique" which will provide the best bang for the buck when improving quality. All of them help. None of them enough. Frankly, this incremental approach is not going to solve the problem of defects that are a result of the product of human error and code complexity. We need to learn how to manage complexity on its own.
Are there any examples of success in managing complexity, and can we learn from them?
I think so.
The best example I can think of is a compiler. Look at how many different inputs it can handle and still produce correct machine code with a fairly low defect rate. I attribute this to the fact that its input is highly structured: it has to follow strict syntactic rulers. Thus, when compiling something, one has a great deal of knowledge about the context in which this occuring. Yes, you have to deal with semantic issues (types, declarations, etc.), but an unambiguous language should make this clear.
One can point out that programming languages are well-specified, so implementing a compiler is relatively easy. If only all requirements were so detailed. I don't think that's it, however: one can come up with very detailed specifications for a complicated system that's difficult to implement. A programming language, by contrast, can be syntactically expressed in a few pages of BNF.
Contrast this with a user interface, where various elements need to be enabled or disabled depending on what other elements have been previously activated, or used to gather data. How easy or difficult is it to "forget" to enable or disable a control? If you see a parallel with this problem and excessive use of GOTOs in a program, you're starting to get a feel for what I'm talking about.
What has happened in the past 25 years or so of programming language evolution is that the complexities of the past have been pushed and morphed into the complexities of the present. And tackling one in isolation (memory management) does nothing for a transformation of the same problem (resource management in general -- memory isn't the only thing that leaks), though it may provide the best bang defect-rate-reduction-wise
You could've hired me.
But I've come to realize, it [unit testing] just doesn't help to reduce big errors in system level design.
That's like saying that street maps don't tell you what the continent looks like. It's technically true, but it seems to miss the point.
Unit tests are for testing relatively small chunks of work. If you want to be sure the pieces work together, you do testing at higher levels. I think both are necessary for a solid system.
Personally, I think of my high-level tests as executable requirements. Every time I check in code, a server makes sure that all our tests, both unit and end-to-end, run happily. That's a big step up from the traditional requirements phone book that most people don't use except as an aid to yelling at someone.
In particular, programming methodologies such as Extreme Programming that require greater management involvement in the coding process will be treated with scorn; management wants less involvement, not more. As to whether or not the code actually works - once it's out the door and bonuses are in hand, who cares?
Well, for one, companies that want to make money. A company may be able to get away with shipping crap for a little while, but it's rare that somebody can do it for long. Why? It's not just that customers notice. A cruddy code base is hard to build on, so low initial quality means slow development for the life of the code base.
Once a manager has experienced doing a project right, it's pretty rare they want to go back to the old, painful, unproductive way of doing things.