Any of the 'big names' listed would be silly to put their names behind this. Microsoft could easily respond and point out dozens of their patents that both GNU programs and the Linux kernel are in violation of. It would be impossible to remove the code or work around the patents because some of the patents would be broad, fundamental, and obvious.
Rather, force Microsoft to sue if they want to do anything about it, and then watch the fire works as other big players get involved.
Microsoft violates other's patents just as much, if not more. Take this patent for instant messaging, held by AOL for instance: http://www.google.com/patents?vid=USPAT6539421&id= DiUPAAAAEBAJ&dq=%22instant+messaging%22
Having only very passing familarity with Eiffel, I'm not sure if I'm missing something, but I don't understand any significant benefit Eiffel's capabilities have over C++'s or a host of other languages with respect to design by contract.
So it has funky keywords to specify what the pre-conditions, post-conditions and invariants are, but is this really any different to putting assert() statements at the begin and end of your functions?
The obvious improvement in this area would be mathematically proving the pre-conditions, post-conditions, and invariants are always satisfied at compile time, but from the Eiffel overview of Design by Contract, it sounds like Eiffel only checks at runtime, the same way C++ does it. Is this correct? If so, what does Eiffel provide exactly that is better than C++ in this regard? Or is it just a little syntactic sugar to make the different kinds of assertions a little more clear?
It's hard to gauge exactly how stable this application is meant to be. If you write an application for almost any company they will say "yes it needs to be very very stable." But there is actually a large variance in that.
For some companies, an application has to be very stable because the company might lose, say, $100/minute when it goes down. But this is actually toward the bottom end of needing to be stable, and is pretty typical for most business software. Real stability is needed when a crash could mean a loss of millions of dollars, or loss of life.
Because you state portability to Windows as a requirement, I tend to doubt your application really needs to be that stable. Applications that need very high stability usually have one specified target platform.
Whatever your requirements are, the number 1 way to achieve stable software is by using the KISS principle as much as possible. However, if your requirements are in the latter category, you will absolutely need to use KISS to the maximum. Don't allow new features. Make the application as stupidly simple as possible.
Finally, you need to carefully consider what kind of 'stability' is needed. For software that needs to be super 'stable', producing the incorrect results can actually be worse than a crash. Writing code that is completely bug-free is much harder than writing code that simply doesn't crash.
In C++, the best approach is to take advantage of the type safety features of the language. Don't use things like void pointers, and use STL containers and so forth rather than allocating memory yourself. Keep the programming team as small as possible, and carefully vet the code.
If the program is truly in the "needs very very high reliability" category, then yes, write unit tests. If it's actually in the "complex program that we're going to add lots of features too, but we'd kinda like it to be stable too" category then unit tests are probably going to be a waste of time.
I really think that if you want to write a very stable application, using a 'novel' approach is not a good idea. Rather, use a tried and tested approach.
That's not to say Lisp can't be used to write stable applications. If you're familiar with Lisp, and you want to write a very stable application, then it's a good choice. If someone doesn't know Lisp, then using it to write a very stable application is probably a very bad idea.
Re:An error in one of his essays
on
Joel On Software
·
· Score: 1
It is not 'dubious' that his code was bad: his code was almost certainly bad.
If you get a crash report, look at the top level of the call stack, and see it's due to a 'NULL reference', you can be 99.9% sure that that NULL reference was caused by a NULL pointer dereference in a direct or indirect caller.
If you dismiss the bug as 'cosmic rays' because C++ doesn't allow NULL references, then you have made a misdiagnosis of the cause of the bug, and failed to fix something that might have easily been fixed.
By Joel's own admission, there were *hundreds* of reports like this.
In other words, there were some bugs involving classic NULL pointer dereferences all over the code, and Joel wasn't a skilled enough software engineer to work out what the problem was, instead deciding to blame it on the user's system.
Sure, I agree, some bugs aren't worth fixing. It might not be worth fixing a minor display glitch that is difficult to reproduce and track down. It might not be worth fixing printing software not working properly with a few obscure printers. Heck, sometimes it might not even be worth fixing a deeply-seeded memory leak that causes the program to fail after running for a very long time. I'm even willing to concede that in some cases a very very rare memory corruption bug might not be worth fixing, when your program isn't meant to be highly reliable.
But when you're working on a product intended to have millions of users, and you are allowing simple NULL-pointer dereferences into your code, something is SERIOUSLY wrong. That's just awful, awful coding.
He's clearly talking about distributing end user software (Juno) to end users, and then getting crash reports back. He just looked in the function at the top of the stack (maybe that's the only function he had access to in the crash log) and assumed that C++ can't have NULL references, so this must be a problem with the user's machine.
He says,
"When you have a million users, it is amazing what will crash, often because of severe low memory conditions or severely crappy computers," and his solution for the problem is, "you will find crashes in places like that and you won't believe your eyes. (And you won't fix them. Cosmic rays, man. Get a new computer and this time don't install every cool shareware taskbar lint gizmo you find. Sheesh.)"
No-where in the article does he blame this problem on another programmer. In fact his entire point is that no programming error can cause this problem. He says it's completely impossible, and blames it on the user's computer and says they should get a new one.
He is perhaps right about it being related to computers with little memory, in which case a call to malloc() or new [1] might have returned NULL, and then he's dereferencing and passing to this function, however a well-behaved program should check for this kind of thing, of course.
Prematurely blaming a crash on the environment the program is running on is generally a pretty clear sign of an inexperienced programmer....
[1] new can't return NULL in Standard C++, but he was probably using MSVC++ = 6, and that does.
An error in one of his essays
on
Joel On Software
·
· Score: 4, Interesting
and you would get crashes there because the r reference was NULL, even though that's completely impossible, there's no such thing as a NULL reference, C++ guarantees it
And then he goes onto blaming the problem on 'cosmic rays' and the user's computer.
While it is true that there is no such thing as a NULL reference in C++, the problem is still likely to be a simple bug in his software. There are many possible constructs that the C++ Standard leaves as 'undefined'. A conforming compiler can do anything it wants if you do something involving undefined behavior, and that includes creating a 'NULL reference'.
Just try this program:
#include <iostream>
void f(char& ref) { std::cout << "value of reference is " << (int)&ref << "\n"; }
int main() { char* p = NULL; f(*p); }
What's its behavior? It's undefined, because a pointer-to-NULL is dereferenced, and that's a big C++ no-no. It could be anything whatsoever according to the C++ standard.
The most common behavior though, and the behavior of my compiler is to output,
value of reference is 0
That's right, we have created us a 'NULL reference'.
I must admit, I'm a little surprised that someone who has so many years of experience as a programmer doesn't understand this, and instead blames it on the user's computer.
I know his book is mostly on a higher-level, looking into the management of software projects, but he seems to think that being a good programmer is fundamental to being a good manager...
Any of the 'big names' listed would be silly to put their names behind this. Microsoft could easily respond and point out dozens of their patents that both GNU programs and the Linux kernel are in violation of. It would be impossible to remove the code or work around the patents because some of the patents would be broad, fundamental, and obvious. Rather, force Microsoft to sue if they want to do anything about it, and then watch the fire works as other big players get involved. Microsoft violates other's patents just as much, if not more. Take this patent for instant messaging, held by AOL for instance: http://www.google.com/patents?vid=USPAT6539421&id= DiUPAAAAEBAJ&dq=%22instant+messaging%22
Having only very passing familarity with Eiffel, I'm not sure if I'm missing something, but I don't understand any significant benefit Eiffel's capabilities have over C++'s or a host of other languages with respect to design by contract.
So it has funky keywords to specify what the pre-conditions, post-conditions and invariants are, but is this really any different to putting assert() statements at the begin and end of your functions?
The obvious improvement in this area would be mathematically proving the pre-conditions, post-conditions, and invariants are always satisfied at compile time, but from the Eiffel overview of Design by Contract, it sounds like Eiffel only checks at runtime, the same way C++ does it. Is this correct? If so, what does Eiffel provide exactly that is better than C++ in this regard? Or is it just a little syntactic sugar to make the different kinds of assertions a little more clear?
It's hard to gauge exactly how stable this application is meant to be. If you write an application for almost any company they will say "yes it needs to be very very stable." But there is actually a large variance in that.
For some companies, an application has to be very stable because the company might lose, say, $100/minute when it goes down. But this is actually toward the bottom end of needing to be stable, and is pretty typical for most business software. Real stability is needed when a crash could mean a loss of millions of dollars, or loss of life.
Because you state portability to Windows as a requirement, I tend to doubt your application really needs to be that stable. Applications that need very high stability usually have one specified target platform.
Whatever your requirements are, the number 1 way to achieve stable software is by using the KISS principle as much as possible. However, if your requirements are in the latter category, you will absolutely need to use KISS to the maximum. Don't allow new features. Make the application as stupidly simple as possible.
Finally, you need to carefully consider what kind of 'stability' is needed. For software that needs to be super 'stable', producing the incorrect results can actually be worse than a crash. Writing code that is completely bug-free is much harder than writing code that simply doesn't crash.
In C++, the best approach is to take advantage of the type safety features of the language. Don't use things like void pointers, and use STL containers and so forth rather than allocating memory yourself. Keep the programming team as small as possible, and carefully vet the code.
If the program is truly in the "needs very very high reliability" category, then yes, write unit tests. If it's actually in the "complex program that we're going to add lots of features too, but we'd kinda like it to be stable too" category then unit tests are probably going to be a waste of time.
-Sirp.
I really think that if you want to write a very stable application, using a 'novel' approach is not a good idea. Rather, use a tried and tested approach.
That's not to say Lisp can't be used to write stable applications. If you're familiar with Lisp, and you want to write a very stable application, then it's a good choice. If someone doesn't know Lisp, then using it to write a very stable application is probably a very bad idea.
It is not 'dubious' that his code was bad: his code was almost certainly bad.
If you get a crash report, look at the top level of the call stack, and see it's due to a 'NULL reference', you can be 99.9% sure that that NULL reference was caused by a NULL pointer dereference in a direct or indirect caller.
If you dismiss the bug as 'cosmic rays' because C++ doesn't allow NULL references, then you have made a misdiagnosis of the cause of the bug, and failed to fix something that might have easily been fixed.
By Joel's own admission, there were *hundreds* of reports like this.
In other words, there were some bugs involving classic NULL pointer dereferences all over the code, and Joel wasn't a skilled enough software engineer to work out what the problem was, instead deciding to blame it on the user's system.
Sure, I agree, some bugs aren't worth fixing. It might not be worth fixing a minor display glitch that is difficult to reproduce and track down. It might not be worth fixing printing software not working properly with a few obscure printers. Heck, sometimes it might not even be worth fixing a deeply-seeded memory leak that causes the program to fail after running for a very long time. I'm even willing to concede that in some cases a very very rare memory corruption bug might not be worth fixing, when your program isn't meant to be highly reliable.
But when you're working on a product intended to have millions of users, and you are allowing simple NULL-pointer dereferences into your code, something is SERIOUSLY wrong. That's just awful, awful coding.
He's clearly talking about distributing end user software (Juno) to end users, and then getting crash reports back. He just looked in the function at the top of the stack (maybe that's the only function he had access to in the crash log) and assumed that C++ can't have NULL references, so this must be a problem with the user's machine.
He says,
"When you have a million users, it is amazing what will crash, often because of severe low memory conditions or severely crappy computers," and his solution for the problem is, "you will find crashes in places like that and you won't believe your eyes. (And you won't fix them. Cosmic rays, man. Get a new computer and this time don't install every cool shareware taskbar lint gizmo you find. Sheesh.)"
No-where in the article does he blame this problem on another programmer. In fact his entire point is that no programming error can cause this problem. He says it's completely impossible, and blames it on the user's computer and says they should get a new one.
He is perhaps right about it being related to computers with little memory, in which case a call to malloc() or new [1] might have returned NULL, and then he's dereferencing and passing to this function, however a well-behaved program should check for this kind of thing, of course.
Prematurely blaming a crash on the environment the program is running on is generally a pretty clear sign of an inexperienced programmer....
[1] new can't return NULL in Standard C++, but he was probably using MSVC++ = 6, and that does.