中国开发网: 论坛: 程序员情感CBD: 贴子 538763
xyzero: Testing
Testing

I don't need to test my programs. I have an error-correcting modem.

Om I. Baud

Leaving bugs in your programs gives the maintenance programmer who comes along later something interesting to do. A well done bug should leave absolutely no clue as to when it was introduced or where. The laziest way to accomplish this is simply never to test your code.

1.
Never Test
: Never test any code that handles the error cases, machine crashes, or OS glitches. Never check return codes from the OS. That code never gets executed anyway and slows down your test times. Besides, how can you possibly test your code to handle disk errors, file read errors, OS crashes, and all those sorts of events? Why, you would have to either an incredibly unreliable computer or a test scaffold that mimicked such a thing. Modern hardware never fails, and who wants to write code just for testing purposes? It isn't any fun. If users complain, just blame the OS or hardware. They'll never know.
2.
Never, Ever Do Any Performance Testing
: Hey, if it isn't fast enough, just tell the customer to buy a faster machine. If you did do performance testing, you might find a bottleneck, which might lead to algorithm changes, which might lead to a complete redesign of your product. Who wants that? Besides, performance problems that crop up at the customer site mean a free trip for you to some exotic location. Just keep your shots up-to-date and your passport handy.
3.
Never Write Any Test Cases
: Never perform code coverage or path coverage testing. Automated testing is for wimps. Figure out which features account for 90% of the uses of your routines, and allocate 90% of the tests to those paths. After all, this technique probably tests only about 60% of your source code, and you have just saved yourself 40% of the test effort. This can help you make up the schedule on the back-end of the project. You'll be long gone by the time anyone notices that all those nice "marketing features" don't work. The big, famous software companies test code this way; so should you. And if for some reason, you are still around, see the next item.
4.
Testing is for cowards
: A brave coder will bypass that step. Too many programmers are afraid of their boss, afraid of losing their job, afraid of customer hate mail and afraid of being sued. This fear paralyzes action, and reduces productivity. Studies have shown that eliminating the test phase means that managers can set ship dates well in advance, an obvious aid in the planning process. With fear gone, innovation and experimentation can blossom. The role of the programmer is to produce code, and debugging can be done by a cooperative effort on the part of the help desk and the legacy maintenance group.

If we have full confidence in our coding ability, then testing will be unnecessary. If we look at this logically, then any fool can recognise that testing does not even attempt to solve a technical problem, rather, this is a problem of emotional confidence. A more efficient solution to this lack of confidence issue is to eliminate testing completely and send our programmers to self-esteem courses. After all, if we choose to do testing, then we have to test every program change, but we only need to send the programmers to one course on building self-esteem. The cost benefit is as amazing as it is obvious.
5.
Ensuring It Only Works In Debug Mode
: If you've defined TESTING as 1
#define TESTING 1 this gives you the wonderful opportunity to have separate code sections, such as
#if TESTING==1
#endif which can contain such indispensable tidbits as
x = rt_val; so that if anyone resets TESTING to 0, the program won't work. And with the tiniest bit of imaginative work, it will not only befuddle the logic, but confound the compiler as well.

Choice Of Language

Philosophy is a battle against the bewitchment of our intelligence by means of language.

Ludwig Wittgenstein

Computer languages are gradually evolving to become more fool proof. Using state of the art languages is unmanly. Insist on using the oldest language you can get away with, octal machine language if you can (Like Hans und Frans, I am no girlie man; I am so virile I used to code by plugging gold tipped wires into a plugboard of IBM unit record equipment (punch cards), or by poking holes in paper tape with a hand punch), failing that assembler, failing that FORTRAN or COBOL, failing that C, and BASIC, failing that C++.

1.
FØRTRAN
: Write all your code in FORTRAN. If your boss ask why, you can reply that there are lots of very useful libraries that you can use thus saving time. However the chances of writing maintainable code in FORTRAN are zero, and therefore following the unmaintainable coding guidelines is a lot easier.
2.
Avoid Ada
: About 20% of these techniques can't be used in Ada. Refuse to use Ada. If your manager presses you, insist that no-one else uses it, and point out that it doesn't work with your large suite of tools like lint and plummer that work around C's failings.
3.
Use ASM
: Convert all common utility functions into asm.
4.
Use QBASIC
: Leave all important library functions written in QBASIC, then just write an asm wrapper to handle the large->medium memory model mapping.
5.
Inline Assembler
: Sprinkle your code with bits of inline assembler just for fun. Almost no one understands assembler anymore. Even a few lines of it can stop a maintenance programmer cold.
6.
MASM call C
: If you have assembler modules which are called from C, try to call C back from the assembler as often as possible, even if it's only for a trivial purpose and make sure you make full use of the goto, bcc and other charming obfuscations of assembler.
7.
Avoid Maintainability Tools
: Avoid coding in Abundance, or using any of its principles kludged into other languages. It was designed from the ground up with the primary goal of making the maintenance programmer's job easier. Similarly avoid Eiffel or Ada since they were designed to catch bugs before a program goes into production.

Dealing With Others

Hell is other people.

Jean-Paul Sartre — No Exit 1934

There are many hints sprinkled thoroughout the tips above on how to rattle maintenance programmers though frustration, and how to foil your boss's attempts to stop you from writing unmaintainable code, or even how to foment an RWAR that involves everyone on the topic of how code should be formatted in the repository.

1.
Your Boss Knows Best
: If your boss thinks that his or her 20 year old FORTRAN experience is an excellent guide to contemporary programming, rigidly follow all his or her recommendations. As a result, the boss will trust you. That may help you in your career. You will learn many new methods to obfuscate program code.
2.
Subvert The Help Desk
: One way to help ensure the code is full of bugs is to ensure the maintenance programmers never hear about them. This requires subverting the help desk. Never answer the phone. Use an automated voice that says "thank you for calling the helpline. To reach a real person press "1" or leave a voice mail wait for the tone". Email help requests should be ignored other than to assign them a tracking number. The standard response to any problem is " I think your account is locked out. The person able to authorise reinstatement is not available just now."
3.
Keep Your Mouth Shut
: Be never vigilant of the next Y2K. If you ever spot something that could sneak up on a fixed deadline and destroy all life in the western hemisphere then do not openly discuss it until we are under the critical 4 year event window of panic and opportunity. Do not tell friends, coworkers, or other competent people of your discovery. Under no circumstances attempt to publish anything that might hint at this new and tremendously profitable threat. Do send one normal priority, jargon encrypted, memo to upper management to cover-your-a$$. If at all possible attach the jargon encrypted information as a rider on an otherwise unrelated plain-text memo pertaining to a more immediately pressing business concern. Rest assured that we all see the threat too. Sleep sound at night knowing that long after you've been forced into early retirement you will be begged to come back at a logarithmically increased hourly rate!
4.
Baffle 'Em With Bullshit
: Subtlety is a wonderful thing, although sometimes a sledge-hammer is more subtle than other tools. So, a refinement on misleading comments: create classes with names like FooFactory containing comments with references to the GoF creational patterns (ideally with http links to bogus UML design documents) that have nothing to do with object creation. Play off the maintainer's delusions of competence. More subtly, create Java classes with protected constructors and methods like Foo f = Foo.newInstance()that return actual new instances, rather than the expected singleton. The opportunities for side-effects are endless.
5.
Book Of The Month Club
: Join a computer book of the month club. Select authors who appear to be too busy writing books to have had any time to actually write any code themselves. Browse the local bookstore for titles with lots of cloud diagrams in them and no coding examples. Skim these books to learn obscure pedantic words you can use to intimidate the whippersnappers that come after you. Your code should impress. If people can't understand your vocabulary, they must assume that you are very intelligent and that your algorithms are very deep. Avoid any sort of homely analogies in your algorithm explanations.

Roll Your Own

You've always wanted to write system level code. Now is your chance. Ignore the standard libraries and write your own. It will look great on your resumé.

1.
Roll Your Own BNF
: Always document your command syntax with your own, unique, undocumented brand of BNF notation. Never explain the syntax by providing a suite of annotated sample valid and invalid commands. That would demonstrate a complete lack of academic rigour. Railway diagrams are almost as gauche. Make sure there is no obvious way of telling a terminal symbol (something you would actually type) from an intermediate one — something that represents a phrase in the syntax. Never use typeface, colour, caps, or any other visual clues to help the reader distinguish the two. Use the exact same punctuation glyphs in your BNF notation that you use in the command language itself, so the reader can never tell if a (...), [...], {...} or "..." is something you actually type as part of the command, or is intended to give clues about which syntax elements are obligatory, repeatable or optional in your BNF notation. After all, if they are too stupid to figure out your variant of BNF, they have no business using your program.
2.
Roll Your Own Allocator
: Everyone knows that debugging your dynamic storage is complicated and time consuming. Instead of making sure each class has no storage leaks, reinvent your own storage allocator. It just mallocs space out of a big arena. Instead of freeing storage, force your users to periodically perform a system reset that clears the heap. There's only a few things the system needs to keep track of across resets — lots easier than plugging all the storage leaks; and so long as the users remember to periodically reset the system, they'll never run out of heap space. Imagine them trying to change this strategy once deployed!

Tricks In Offbeat Languages

Programming in Basic causes brain damage.

Edsger Wybe Dijkstra

*
SQL Aliasing
: Alias table names to one or two letters. Better still alias them to the names of other unrelated existing tables.
*
SQL Outer Join
: Mix the various flavours of outer join syntax just to keep everyone on their toes.
*
JavaScript Scope
: "Optimise" JavaScript code taking advantage of the fact a function can access all local variables in the scope of the caller.
*
Visual Basic Declarations
: Instead of:
dim Count_num as string
dim Color_var as string
dim counter as integer use:
Dim Count_num$, Color_var$, counter%
*
Visual Basic Madness
: If reading from a text file, read 15 characters more than you need to then embed the actual text string like so:
ReadChars = .ReadChars (29,0)
ReadChar = trim(left(mid(ReadChar,len(ReadChar)-15,len(ReadChar)-5),7))
If ReadChars = "alongsentancewithoutanyspaces"
Mid,14,24 = "withoutanys"
and left,5 = "without"
*
Delphi/Pascal Only
: Don't use functions and procedures. Use the label/goto statements then jump around a lot inside your code using this. It'll drive 'em mad trying to trace through this. Another idea, is just to use this for the hang of it and scramble your code up jumping to and fro in some haphazard fashion.
*
Perl
: Use trailing if's and unless's especially at the end of really long lines.
*
Lisp
: LISP is a dream language for the writer of unmaintainable code. Consider these baffling fragments:
(lambda (*<8-]= *<8-[= ) (or *<8-]= *<8-[= ))

(defun :-] (<) (= < 2))

(defun !(!)(if(and(funcall(lambda(!)(if(and '(< 0)(< ! 2))1 nil))(1+ !))
(not(null '(lambda(!)(if(< 1 !)t nil)))))1(* !(!(1- !)))))
*
Visual Foxpro
: This one is specific to Visual Foxpro. A variable is undefined and can't be used unless you assign a value to it. This is what happens when you check a variable's type:
lcx = TYPE('somevariable') The value of lcx will be 'U' or undefined. BUT if you assign scope to the variable it sort of defines it and makes it a logical FALSE. Neat, huh!?
LOCAL lcx
lcx = TYPE('somevariable') The value of lcx is now 'L' or logical. It is further defined the value of FALSE. Just imagine the power of this in writing unmaintainable code.
LOCAL lc_one, lc_two, lc_three... , lc_n

IF lc_one
DO some_incredibly_complex_operation_that_will_neverbe_executed WITH
make_sure_to_pass_parameters
ENDIF

IF lc_two
DO some_incredibly_complex_operation_that_will_neverbe_executed WITH
make_sure_to_pass_parameters
ENDIF

PROCEDURE some_incredibly_complex_oper....
* put tons of code here that will never be executed
* why not cut and paste your main procedure!
ENDIF

Miscellaneous Techniques

If you give someone a program, you will frustrate them for a day; if you teach them how to program, you will frustrate them for a lifetime.

Anonymous

1.
Don't Recompile
: Let's start off with probably the most fiendish technique ever devised: Compile the code to an executable. If it works, then just make one or two small little changes in the source code...in each module. But don't bother recompiling these. You can do that later when you have more time, and when there's time for debugging. When the hapless maintenance programmer years later makes a change and the code no longer works, she will erroneously assume it must be something she recently changed. You will send her off on a wild goose chase that will keep her busy for weeks.
2.
Foiling Debuggers
: A very simple way to confound people trying to understand your code by tracing it with a line debugger, is to make the lines long. In particular, put the then clause on the same line as the if. They can't place breakpoints. They can't tell which branch of an if was taken.
3.
S.I. vs American Measure
: In engineering work there are two ways to code. One is to convert all inputs to S.I. (metric) units of measure, then do your calculations then convert back to various civil units of measure for output. The other is to maintain the various mixed measure systems throughout. Always choose the second. It's the American way!
4.
CANI
: Constant And Never-ending Improvement. Make "improvements" to your code often, and force users to upgrade often - after all, no one wants to be running an outdated version. Just because they think they're happy with the program as it is, just think how much happier they will be after you've "fixed" it! Don't tell anyone what the differences between versions are unless you are forced to - after all, why tell someone about bugs in the old version they might never have noticed otherwise?
5.
About Box
: The About Box should contain only the name of the program, the names of the coders and a copyright notice written in legalese. Ideally it should link to several megs of code that produce an entertaining animated display. However, it should never contain a description of what the program is for, its minor version number, or the date of the most recent code revision, or the website where to get the updates, or the author's email address. This way all the users will soon all be running on different versions, and will attempt to install version N+2 before installing version N+1.
6.
Ch ch ch Changes
: The more changes you can make between versions the better, you don't want users to become bored with the same old API or user interface year after year. Finally, if you can make this change without the users noticing, this is better still - it will keep them on their toes, and keep them from becoming complacent.
7.
Put C Prototypes In Individual Files
: instead of common headers. This has the dual advantage of requiring a change in parameter data type to be maintained in every file, and avoids any chance that the compiler or linker will detect type mismatches. This will be especially helpful when porting from 32 -> 64 bit platforms.
8.
No Skill Required
: You don't need great skill to write unmaintainable code. Just leap in and start coding. Keep in mind that management still measures productivity in lines of code even if you have to delete most of it later.
9.
Carry Only One Hammer
: Stick with what you know and travel light; if you only carry a hammer then all problems are nails.
10.
Standards Schmandards
: Whenever possible ignore the coding standards currently in use by thousands of developers in your project's target language and environment. For example insist on STL style coding standards when writing an MFC based application.
11.
Reverse the Usual True False Convention
: Reverse the usual definitions of true and false. Sounds very obvious but it works great. You can hide:
#define TRUE 0
#define FALSE 1 somewhere deep in the code so that it is dredged up from the bowels of the program from some file that no one ever looks at anymore. Then force the program to do comparisons like:
if ( var == TRUE )
if ( var != FALSE ) someone is bound to "correct" the apparent redundancy, and use var elsewhere in the usual way:
if ( var ) Another technique is to make TRUE and FALSE have the same value, though most would consider that out and out cheating. Using values 1 and 2 or -1 and 0 is a more subtle way to trip people up and still look respectable. You can use this same technique in Java by defining a static constant called TRUE. Programmers might be more suspicious you are up to no good since there is a built-in literal true in Java.
12.
Third Party Libraries
: Include powerful third party libraries in your project and then don't use them. With practice you can remain completely ignorant of good tools and add the unused tools to your resumé in your "Other Tools" section.
13.
Avoid Libraries
: Feign ignorance of libraries that are directly included with your development tool. If coding in Visual C++ ignore the presence of MFC or the STL and code all character strings and arrays by hand; this helps keep your pointer skills sharp and it automatically foils any attempts to extend the code.
14.
Create a Build Order
: Make it so elaborate that no maintainer could ever get any of his or her fixes to compile. Keep secret SmartJ which renders make scripts almost obsolete. Similarly, keep secret that the javac compiler is also available as a class. On pain of death, never reveal how easy it is to write and maintain a speedy little custom java program to find the files and do the make that directly invokes the sun.tools.javac.Main compile class.
15.
More Fun With Make
: Have the makefile-generated-batch-file copy source files from multiple directories with undocumented overrwrite rules. This permits code branching without the need for any fancy source code control system, and stops your successors ever finding out which version of DoUsefulWork() is the one they should edit.
16.
Collect Coding Standards
: Find all the tips you can on writing maintainable code such as the Square Box Suggestions and flagrantly violate them.
17.
IDE, Not Me!
: Put all the code in the makefile: your successors will be really impressed how you managed to write a makefile which generates a batch file that generates some header files and then builds the app, such that they can never tell what effects a change will have, or be able to migrate to a modern IDE. For maximum effect use an obsolete make tool, such as an early brain dead version of NMAKE without the notion of dependencies.
18.
Bypassing Company Coding Standards
: Some companies have a strict policy of no numeric literals; you must use named constants. It is fairly easy to foil the intent of this policy. For example, one clever C++ programmer wrote:
#define K_ONE 1
#define K_TWO 2
#define K_THOUSAND 999
19.
Compiler Warnings
: Be sure to leave in some compiler warnings. Use the handy "-" prefix in make to suppress the failure of the make due to any and all compiler errors. This way, if a maintenance programmer carelessly inserts an error into your source code, the make tool will nonetheless try to rebuild the entire package; it might even succeed! And any programmer who compiles your code by hand will think that they have broken some existing code or header when all that has really happened is that they have stumbled across your harmless warnings. They will again be grateful to you for the enjoyment of the process that they will have to follow to find out that the error was there all along. Extra bonus points: make sure that your program cannot possibly compile with any of the compiler error checking diagnostics enabled. Sure, the compiler may be able to do subscripts bounds checking, but real programmers don't use this feature, and neither should you. Why let the compiler check for errors when you can use your own lucrative and rewarding time to find these subtle bugs?
20.
Combine Bug Fixes With Upgrades
: Never put out a "bug fix only" release. Be sure to combine bug fixes with database format changes, complex user interface changes, and complete rewrites of the administration interfaces. That way, it will be so hard to upgrade that people will get used to the bugs and start calling them features. And the people that really want these "features" to work differently will have an incentive to upgrade to the new versions. This will save you maintenance work in the long run, and get you more revenue from your customers.
21.
Change File Formats With Each Release Of Your Product
: Yeah, your customers will demand upwards compatibility, so go ahead and do that. But make sure that there is no backwards compatibility. That will prevent customers from backing out the newer release, and coupled with a sensible bug fix policy (see above), will guarantee that once on a newer release, they will stay there. Extra bonus points: Figure out how to get the old version to not even recognise files created by the newer versions. That way, they not only can't read them, they will deny that they are even created by the same application! Hint: PC word processors provide a useful example of this sophisticated behaviour.
22.
Compensate For Bugs
: Don't worry about finding the root cause of bugs in the code. Simply put in compensating code in the higher-level routines. This is a great intellectual exercise, akin to 3D chess, and will keep future code maintainers entertained for hours as they try to figure out whether the problem is in the low-level routines that generate the data or in the high-level routines that change various cases all around. This technique is great for compilers, which are inherently multi-pass programs. You can completely avoid fixing problems in the early passes by simply making the later passes more complicated. With luck, you will never have to speak to the little snot who supposedly maintains the front-end of the compiler. Extra bonus points: make sure the back-end breaks if the front-end ever generates the correct data.
23.
Use Spin Locks
: Avoid actual synchronization primitives in favor of a variety of spin locks -- repeatedly sleep then test a (non-volatile) global variable until it meets your criterion. Spin locks are much easier to use and more "general" and "flexible " than the system objects.
24.
Sprinkle sync code liberally
: Sprinkle some system synchronization primitives in places where they are not needed. I came across one critical section in a section of code where there was no possibility of a second thread. I challenged the original developer and he indicated that it helped document that the code was, well, "critical!"
25.
Graceful Degradation
: If your system includes an NT device driver, require the application to malloc I/O buffers and lock them in memory for the duration of any transactions, and free/unlock them after. This will result in an application that crashes NT if prematurely terminated with that buffer locked. But nobody at the client site likely will be able to change the device driver, so they won't have a choice.
26.
Custom Script Language
: Incorporate a scripting command language into your client/server apps that is byte compiled at runtime.
27.
Compiler Dependent Code
: If you discover a bug in your compiler or interpreter, be sure to make that behaviour essential for your code to work properly. After all you don't use another compiler, and neither should anyone else!
28.
A Real Life Example
: Here's a real life example written by a master. Let's look at all the different techniques he packed into this single C function.
void* Realocate(void*buf, int os, int ns)
{
void*temp;
temp = malloc(os);
memcpy((void*)temp, (void*)buf, os);
free(buf);
buf = malloc(ns);
memset(buf, 0, ns);
memcpy((void*)buf, (void*)temp, ns);
return buf; }
* Reinvent simple functions which are part of the standard libraries.
* The word Realocate is not spelled correctly. Never underestimate the power of creative spelling.
* Presume malloc will always return successfully.
* Make a temporary copy of input buffer for no real reason.
* Cast things for no reason. memcpy() takes (void*), so cast our pointers even though they're already (void*). Bonus for the fact that you could pass anything anyway.
* Never bothered to free temp. This will cause a slow memory leak, that may not show up until the program has been running for days.
* Copy more than necessary from the buffer just in case. This will only cause a core dump on Unix, not Windows.
* It should be obvious that os and ns stand for "old size" and "new size".
* After allocating buf, memset it to 0. Don't use calloc() because somebody might rewrite the ANSI spec so that calloc() fills the buffer with something other than 0. (Never mind the fact that we're about to copy exactly the same amount of data into buf.)
29.
How To Fix Unused Variable Errors
: If your compiler issues "unused local variable" warnings, don't get rid of the variable. Instead, just find a clever way to use it. My favorite is...
i = i;
30.
It's The Size That Counts
: It almost goes without saying that the larger a function is, the better it is. And the more jumps and GOTOs the better. That way, any change must be analysed through many scenarios. It snarls the maintenance programmer in the spaghettiness of it all. And if the function is truly gargantuan, it becomes the Godzilla of the maintenance programmers, stomping them mercilessly to the ground before they have an idea of what's happened.
31.
A Picture is a 1000 Words; A Function is 1000 Lines
: Make the body of every method as long as possible - hopefully you never write any methods or functions with fewer than a thousand lines of code, deeply nested, of course.
32.
One Missing File
: Make sure that one or more critical files is missing. This is best done with includes of includes. For example, in your main module, you have
#include <stdcode.h> Stdcode.h is available. But in stdcode.h, there's a reference to
#include "a:\\refcode.h" and refcode.h is no where to be found.
33.
Write Everywhere, Read Nowhere
: At least one variable should be set everywhere and used almost nowhere. Unfortunately, modern compilers usually stop you from doing the reverse, read everywhere, write nowhere, but you can still do it in C or C++.

Philosophy

The people who design languages are the people who write the compilers and system classes. Quite naturally they design to make their work easy and mathematically elegant. However, there are 10,000 maintenance programmers to every compiler writer. The grunt maintenance programmers have absolutely no say in the design of languages. Yet the total amount of code they write dwarfs the code in the compilers.

An example of the result of this sort of elitist thinking is the JDBC interface. It makes life easy for the JDBC implementor, but a nightmare for the maintenance programmer. It is far clumsier than the FORTRAN interface that came out with SQL three decades ago.

Maintenance programmers, if somebody ever consulted them, would demand ways to hide the housekeeping details so they could see the forest for the trees. They would demand all sorts of shortcuts so they would not have to type so much and so they could see more of the program at once on the screen. They would complain loudly about the myriad petty time-wasting tasks the compilers demand of them.

There are some efforts in this direction: NetRexx, Bali, and visual editors (e.g. IBM's Visual Age is a start) that can collapse detail irrelevant to the current purpose.

The Shoemaker Has No Shoes

Imagine having an accountant as a client who insisted on maintaining his general ledgers using a word processor. You would do you best to persuade him that his data should be structured. He needs validation with cross field checks. You would persuade him he could do so much more with that data when stored in a database, including controlled simultaneous update.

Imagine taking on a software developer as a client. He insists on maintaining all his data (source code) with a text editor. He is not yet even exploiting the word processor's colour, type size or fonts.

Think of what might happen if we started storing source code as structured data. We could view the same source code in many alternate ways, e.g. as Java, as NextRex, as a decision table, as a flow chart, as a loop structure skeleton (with the detail stripped off), as Java with various levels of detail or comments removed, as Java with highlights on the variables and method invocations of current interest, or as Java with generated comments about argument names and/or types. We could display complex arithmetic expressions in 2D, the way TeX and mathematicians do. You could see code with additional or fewer parentheses, (depending on how comfortable you feel with the precedence rules ). Parenthesis nests could use varying size and colour to help matching by eye. With changes as transparent overlay sets that you can optionally remove or apply, you could watch in real time as other programmers on your team, working in a different country, modified code in classes that you were working on too.

You could use the full colour abilities of the modern screen to give subliminal clues, e.g. by automatically assigning a portion of the spectrum to each package/class using a pastel shades as the backgrounds to any references to methods or variables of that class. You could bold face the definition of any identifier to make it stand out.

You could ask what methods/constructors will produce an object of type X? What methods will accept an object of type X as a parameter? What variables are accessible in this point in the code? By clicking on a method invocation or variable reference, you could see its definition, helping sort out which version of a given method will actually be invoked. You could ask to globally visit all references to a given method or variable, and tick them off once each was dealt with. You could do quite a bit of code writing by point and click.

Some of these ideas would not pan out. But the best way to find out which would be valuable in practice is to try them. Once we had the basic tool, we could experiment with hundreds of similar ideas to make life easier for the maintenance programmer.

I discuss this further in the SCID student project.

An early version of this article appeared in Java Developers' Journal (volume 2 issue 6). I also spoke on this topic in 1997 November at the Colorado Summit Conference. It has been gradually growing ever since. I have had quite a few requests for permission to build links here. You are welcome to create links, but please don't repost the essay since the original changes frequently.

If you enjoyed this essay you might like this one on how to write like a newbie. There is a ton of stuff on this site quite unlike anything else on the web. Have a quick look at my home page or my Java Glossary which is a central place to find out everything you ever wanted to know about Java or perhaps my Gay & Black Glossary. If you want a bird's eye view of all the things I'm involved in, see the CMP_homehome page.

You might also enjoy the famous essay Worse Is Better on doing the right thing.

Contributors

The following are some of the people who contributed to this list. My lawyers recommended I exclude those who taught by example.

* Hugh McDonald, hugh@symac.dyndns.org
* Gareth Meyrick, gareth@pangloss.ucsf.edu
* Jarle Stabell, jarle.stabell@dokpro.uio.no
* Ko-Haw Nieh, niko@quality.com
* Jim Johnson, jimj@jumpmusic.com
* Jim Hyslop, Jim.Hyslop@mars.leitch.com
* George Ruban, gruban@geocities.com
* Mats Carlid, mats@adbk.se
* John P. McGrath, JPMcGrath@JPMcGrath.net
* Brian Hurt, brianh@bit3.com
* Chris Schlenker, Christoph.Schlenker@gfk.de
* Nicholas Widdows, nicholas.widdows@traceplc.co.uk
* Greg Compestine, gregcompestine@caleb-bldr.com
* Carl L. Gay, sigue@thecia.net
* Leonid Efros, l_efros@hotmail.com
* Richard W. Noble, rwnoble@san.rr.com
* Simon Broad, simon.broad@macro4.com
* Doron Rajwan, doron@capella.co.il
* Austin Rosenfeld, ablomi@yahoo.com
* Wes Groleau, wwgrol@ftw.rsc.raytheon.com
* Joshua Schpok, schpok@hotmail.com
* Russ Fink, rfink@bbn.com
* John Matthews, John.Matthews@nectech.co.uk
* Neugroschl Scott, Neugroschl.Scott@LittonDSD.com
* Scott Herod, scott@evt.com
* Allan Stokes, allan@stokes.ca
* Martin Minow, minow@pobox.com
* Wolfgang Formann, w.formann@neuss.netsurf.de
* Jym Dyer, jym@igc.org
* Ted Dennison, dennison@ssd.fsi.com
* Tom Farrell, tfarrell@skepsis.com
* Daniel von Asmuth, radical@tux.warande.net
* Bob Morris, bob@bomoco.com
* Neil Hancock, neil.hancock@macro4.com
* Dirk Hauberg, dirkhauberg@amic.de
* Nathan Laan, nlaan@ualberta.ca
* James J. Besemer, jb@cascade-sys.com
* William Harris, william@carsinfo.com ()
* David Pottage, david.pottage@insignia.com
* Marian ION, marian.ion@telestore.fr
* Torrey Hoffman, thoffman1@hotmail.com
* Paul Green, Paul_Green@stratus.com
* Harry Bearman, hbearman@pdxinc.com
* Stephen Friedl, friedl@mtndew.com
* Gil Williamson, gil@humbug.co.uk
* Bear Giles, bear@coyotesong.com
* Ray Trent, rat@synaptics.com
* Maarten Sneep, sneep@nat.vu.nl
* Greg Lindstrom, glinds@acxiom.com
* Jeff Johnson, jeff@san-dc.com
* James J. Beseme, jb@cascade-sys.com
* Babette Turner-Underwood, babettet@tmi.ca
* Bent Nielsen, bn@dksin.dk
* Richard Sanders, Richard_Sanders@Dell.com
* James Brown, james.brown-eds@eds.com
* Steve Loughran, slo3@iseran.com
* Jonathan Deber, Univerity Of Toronto
* Ben Tilly, Ben_Tilly@trepp.com
* David Williss, dwilliss@inetnebr.com
* Bernice Maslan, bernice.maslan@360.com
* Kari Hoijarvi, Kari.Hoijarvi@vaisala.com
* Asha Goldberg, asha@jps.net
* Christopher M. Jones, christopher_j@uswest.net
* Tim Russell, Tim.Russell@versatel.nl
* Damian Wright, damian@radmark.co.za
* Will Green, will.green.01@bbc.co.uk
* Paul Rennison, EXT-Paul.Rennison@nokia.com
* Karl-Johan Karlsson, karka728@student.liu.se
* Kevin Lamont, kevin.lamont@warthog.co.uk
* Dave Cridland, dac@felspar.com
* Jonathan Anderson, andersjl@letu.edu
* Rick Thorne, rick.thorne@lmco.com
* John Lloyd Kramer, jlkramer@artsci.wustl.edu
* Dave Pilkington, pilkington@imo-online.com
* Hal Breidenbach, hal.breidenbach@delphiauto.com
* Jeff Gray, jeffg@magtech.com.au
* Chris Hazard, chris.hazard@valpo.edu
* Colin Brown, colin.brown@met.co.nz
* Compestine, Greg, gregcompestine@caleb-bldr.com
* Frank Klemm, pfk@fuchs.offl.uni-jena.de
* Tim Tyler, tt@cryogen.com
* Donald L. Dobbs, donaldldobbs@home.com
* Bill Michaelson, bill@cosi.com
* Stephen White, swhite@ox.compsoc.net

An early version of this article appeared in Java Developers' Journal (volume 2 issue 6). I also spoke on this topic in 1997 November at the Colorado Summit Conference. It has been gradually growing ever since. I have had quite a few requests for permission to build links here. You are welcome to create links, but please don't repost the essay since the original changes frequently.

If you enjoyed this essay you might enjoy other parts of the website. Have a look at my home page or the Java Glossary which is a central place to find out everything you ever wanted to know about Java or perhaps my Gay & Black Glossary.

You might also enjoy the famous essay Worse Is Better on doing the right thing.

Operation Termite

All great programmers are paranoid.

Roedy

There is another way of interpreting this essay, as a terrorist manual.

About the only thing you know for sure about how the next war will be fought is that it won't be fought the same way as the last time.

I find it highly unlikely a rogue nation would attack the United States with an ICBM. Why?

1. ICBMs are expensive.
2. They are big and easy to detect long before they are launched. Even with 1962 technology, Kennedy found out about the Cuban missiles.
3. They justify total annihilation in response. It is easy to tell where they came from.
4. They would do little long term damage, At most a few cities would be hit. America would still dominate the world afterward, probably more fiercely and iron-handedly than ever.

If one of these Iraqi ICBMs were ever to be built, for considerably less than a trillion dollars and with almost 100% probablity of success, the US could simply march in and take it away, the same way they took away SCUDS and biological weapons, somewhat less politely than last time. That approach would be far more reliable than relying on untestable high tech.

There are far cheaper, safer and more effective ways to break America's power. What are the alternatives:

1. poisoning the water supply.
2. Oklahoma style bombings. Tim VcVeigh did not invent these.
3. Operation Termite.

Termites attack invisibly, quietly, patiently and slowly. Suddenly the whole building collapses.

What is it that gives America the power to dominate the world? It is not a huge population. It is not astoundingly rich natural resources. She mostly imports them now. It is her computers which enable her to dominate world commerce.

Some years ago I wrote an essay about the EIDE controller flaw and its insidious ability to subtly corrupt data. Back then I explained that insidious corruption would cause more long term damage than outright destruction because eventually all archived backups would be corrupted too.

There are millions of ways to insidiously corrupt data and program source. America is a sitting duck for a patient terrorist with a small bank account and a copy of this essay.

The catch is, even if the terrorist is discovered, if he has been sufficiently clever, there will be no way to undo the damage or to retaliate. The damage will continue to slowly rot away the underpinning of American power.

America is willing to spend a trillion or two worrying about the much more minor effect of a less-likely ICBM attack. Oddly it is totally unwilling to spend even a few million to think about how to defend against this sort of attack.

We have already seen what havoc a few pimply faced Bulgarian school boys could do with an Internet prank. What do you think a team of patient pros could do? Where do you think some of them are working right now planting the necessary hooks for the attack? arguing against any need for concern for a defense? claiming defense is impossible? designing feeble security systems? Perhaps that turkey sitting next to you writing unmaintainable code is actually a highly-skilled terrorist spy.

You learn what sells.

Lucy Van Pelt
人生的目的只有两件事:第一,得到你想要的;第二,得到之后就去享受它。
但是只有最聪明的人才能做到第二点。

我的话很重要,你们一定要反复理解,直到弄不明白为止!

相关信息:


欢迎光临本社区,您还没有登录,不能发贴子。请在 这里登录