Effective Programming

Download Report

Transcript Effective Programming

Effective Programming
26-Jul-16
Why test?
“The new US stealth fighter, the F-22 Raptor, was deployed for
the first time to Asia earlier this month. On Feb. 11 [2007],
twelve Raptors flying from Hawaii to Japan were forced to turn
back when a software glitch crashed all of the F-22s’ on-board
computers as they crossed the international date line...every
fighter completely lost all navigation and communications
when they crossed the international date line. They reportedly
had to turn around and follow their tankers by visual contact
back to Hawaii...if they had not been with their tankers, or the
weather had been bad, this would have been serious.”
http://slashdot.org/index.pl?issue=20070225
Program design

“In preparing for battle I have always found that plans are
useless, but planning is indispensable.”
--Dwight D. Eisenhower





The same is true in programming
You must plan out your program in advance, so you know where you
are trying to go--but expect many changes along the way
Don’t just jump into coding with the first approach that occurs to you,
but consider alternate plans
Always be ready to refactor as needed
“How far you can go without destroying from within what you
are trying to defend from without?”
--Dwight D. Eisenhower

Actually, I don’t think this quote has any relevance to programming
Why refactor?


Refactoring: Making changes to your program that don’t affect
what the program does
Some refactorings:





The name of a method no longer accurately describes what it does, so
you want to rename it
You need more control over what a method does, so you want to add a
parameter
You need to use only part of what a method does, so you extract that
part into a separate method
You realize that a method is in the wrong class, so you move it to a
different class
Eclipse makes these and other refactorings relatively “safe”-that is, they are unlikely to break your program

Not all refactorings are as easy
Regression testing

Regression testing: Testing whether the program still
works, after you have made a change to it




JUnit tests are extremely useful for regression testing
A thorough set of tests gives you the confidence to refactor
Debugging is dangerous--fixing a bug is very likely to
introduce new bugs
It is a general rule that the difficulty of debugging a
program goes up as the square of the program size
Programming discipline

To write impressively good programs, here are some rules to
follow



Plan ahead--consider more than one design before you start programming
Refactor early and often
Test everything you can as thoroughly as you can--don’t let the code get
out of control





Writing tests before you write the code isn’t the only way to program, but it
improves your program design as well as your code
Start with “the simplest thing that could possibly work”
Insofar as possible, make only small changes to your program
Don’t add features until the code you already have is “completely”
debugged
It takes discipline to follow these rules--it’s easier to just jump in
and start writing code--but a methodical approach greatly
increases your chance of success
Testing philosophy

The purpose of unit tests is not to show that your program works,
but to show that it’s broken!

If you follow the “happy path” in your testing, where:








Objects are never null,
Strings are never empty or contain non-ASCII characters,
Arrays are always of non-zero length,
User input is always legal, and
The sun is always shining…
Your tests will be pretty much useless!
Your tests should be the sworn enemy of your program,
determined to expose every possible flaw, likely or unlikely
The point is to uncover all possible problems before your
customer (or your instructor) does, so you can fix them
Dealing with I/O

We can (in some cases) test our output methods


PrintStream originalOut = System.out;
OutputStream os = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(os);
System.setOut(ps);
We can even test our input methods

InputStream originalIn = System.in;
byte[] buf = "Some input string".getBytes();
InputStream is = new ByteArrayInputStream(buf);
System.setIn(is);
Dealing with GUIs

GUIs are not easy to test with JUnit-like software




There is a reasonably good, albeit not perfect, solution to the
problem of testing GUIs...
Don’t do any work in the GUI class!




There are programs that attempt to provide automatic JUnit tests for GUIs,
but I haven’t found any I like
If you want to write a GUI testing framework, you should explore
java.awt.Robot
Use the MVC (Model-View-Controller) approach
The GUI should only communicate between the user and the model
Of course, this is easier said than done, but still....
Even if a GUI “works,” that doesn’t make it easy to use


Of course you think your GUI is obvious
You should always have at least one other person try it out without help
from you--you will probably be surprised at the result
Creeping featurism



“Perfection is achieved, not when there is nothing more
to add, but when there is nothing left to take away.”
--Antoine de Saint-Exupery
In my opinion, the highest praise you can give to a
program is to say “it just works”
Unfortunately, most software competes on the basis of
how many features it offers


Sometimes you need those features
When you don’t need them, you are better off without them
The End
The original study that showed huge variations in
individual programming productivity was conducted in the
late 1960s by Sackman, Erikson, and Grant (1968). They
studied professional programmers with an average of 7
years’ experience and found that the ratio of intitial coding
time between the best and worst programmers was about
20:1; the ratio of debugging times over 25:1; of program
sizes 5:1; and of program execution speed about 10:1. They
found no relationship between a programmer’s amount of
experience and code quality or productivity.
-- Code Complete, page 548