Implementation and Testing

How much design effort is needed before coding starts?

It is a spectrum:

Use-case-driven development vs feature-driven development

The book pp428-429 compares the two approaches.

Starting to implement

Iteration / Release Planning

Software iterations and releases

Terminology

An iteration

Each iteration will involve activities of requirements capture, design, testing, and coding. So, its not like all the requirements are known at the start. For example:

A Release

Each release is assigned a sequence number: 0.5, 1.2, etc. Releases generally go through phases
  1. alpha release: Some basic features haven't been implemented yet and there are quite a few bugs. More for in-house testing.
  2. beta release: all features more or less work but will have a few bugs. Outside advanced users can use it.
  3. pre-release: generically refers to any non-final release, either alpha, beta, or whatever.
  4. final release: an "official" release; version number is at least 1.0.

The Iteration Planning Game

Iteration plans

For iterations 3-6 of your projects you will need to supply an iteration plan. See Iteration 3 for the specific requirements. The previous project examples show some example iteration plans, e.g. Group 3 from 2006's iteration 3 submitted plan

Making features or use cases that fit into iterations

Good ways to break up use cases include

Implementation Principles

Here are some random good principles for implementation, many of which are from the XP and Agile schools of thought.

Practice Collective Code Ownership

Continuous Integration

Build the whole system every couple of hours.

Have a coding standard

This is a standard intro programming topic you probably know well.

See the Information page Style section for guidelines for this course; here are a couple more:

Pair Programming

Pair programming is two people programming on one terminal.

Is it good? Bad? Ugly?

Refactoring

Refactoring is an independent future lecture topic.

Testing

Testing is a major component of commercial software development.

Testing Hierarchies

From small fragments to whole system.

Standard hierarchy from software engineering

We use the simpler XP testing hierarchy

Unit Testing

Write small tests for each nontrivial operation

Unit testing in Java with JUnit

Test Coverage

Test-first programing

Test-first programming is a major principle of XP.

Why write tests before code?

You are encouraged to experiment with test-first programming in your projects.

Degrees of importance of thorough testing

The degree of commitment varies by the size, complexity, and need for correctness of the project. Here are some points on the spectrum.

Acceptance testing

Specialized tests

Things that are harder to test automatically

You need to work harder to get some features automatically tested.

GUI Testing

This is an important topic since you cannot write automated tests for GUI's with just JUnit. Solutions include:

Distributed systems testing

This is also a difficult kind of application to test. New systems are "in beta" on these topics now.

Programming Idioms

A very good book describing Java programming idioms is Effective Java by Bloch. We are going to go through some of them

Consider using static factory methods in place of class constructors

(Bloch Item 1)

Why? Flexibility!

Here is an example from Bloch

Implementing the Singleton Pattern in Java

(Bloch's Item 2)

Its good to implement a singleton in a manner that guarantees the singleton behavior only.

Bloch example.

Minimize Accessibility

(Item 13.)

We've "talked the talk" about how good encapsulation is; this is one important way you need to "walk the walk" to implement encapsulation.

Bloch example about array access issues

Be Immutable Whenever Possible

(Bloch's Item 15) Bloch example.

There is strong precedence for this concept in programming languages.

Implementing immutable objects in Java A nice webpage on final and immutability: the final word on the final keyword.

When Using Inheritance be Clear and Robust or ... Don't Inherit

(Bloch item 17)

Since inheritance breaks class encapsulation, it can be a very good rope to hang yourself. This is related to the Open-Closed Principle (OCP).

Favor Composition Over Inheritance

(Bloch Item 16)

This is also very much related to The Open-Closed Principle (OCP).

Bloch Example showing how composition with delegation can work.

Avoid switch whenever possible

(same as Bloch item 20, replace unions with class hierarchies) Bloch Example.

And Many More!

The Bloch book has many more. Here is a highlight.
(Items 8 and 9) Overriding equals can be good, but you need to make sure your method satisfies all the things equals needs
See the API documentation for what equals needs to obey: it must for instance be transitive, reflexive, symmetric, and have a faithful hashCode implemented for it.
(Item 30) Use enums instead of int constants
int constants are for low-level C programmers only
(Item 38) Explicitly check method parameters for validity.
For instance, a Scrabble play where an empty set of tiles was passed should be caught by the method. Raise an exception.
(Item 45) Minimize the scope of local variables.
If a variable is declared only in the neighborhood where its used, it won't be abused elsewhere in the method. But, your methods should be small enough anyway that this should not be a problem.
(Item 58) Use checked exceptions for things the caller can recover from and unchecked exceptions for things tey can't recover from.
(unchecked exceptions are the ones subclassing RuntimeException which you don't have to declare throws on in method headers).
(Item 60) Reuse existing exceptions built into Java whenever possible.
Example: for a bad parameter passed to your method use IllegalArgumentException. If its null use NullPointerException.
(Item 61) Throw exceptions understandable by the caller only
Thus, if there is some low-level exception arising (SocketClosedException), catch it and rethrow it as (PlayerOfflineException) to keep the grubby low-level thing from leaking up.
(Item 65) Don't just catch and ignore exceptions
This sort of code is "on the edge" and will easily fall apart--the exception indicates a problem and you need to track it down to the source. (In Fowler's terms, this is a bad smell in code)