03.03.10 | kl. 08:17 | Aktuelt, Prosabladet
Koden nedenfor er fra "Principles, Patterns and Practices of Agile Software Development" af Robert C. Martin. Christian Horsdal, softwareudvikler og -arkitekt, Mjølner Informatics, synes, det er et godt eksempel på god kode, fordi:
PrimeGenerator.java (final)
/* This class Generates prime numbers up to a user specified maximum. The algorithm used is the Sieve of Eratosthenes. Given an array of integers starting at 2: Find the first uncrossed integer, and cross out all its multiples. Repeat until there are no more multiples in the array.*/
public class PrimeGenerator
{
private static boolean[] crossedOut;
private static int[] result;
public static int[] generatePrimes(int maxValue)
{
if (maxValue < 2)
return new int[0];
else
{
uncrossIntegersUpTo(maxValue);
crossOutMultiples();
putUncrossedIntegersIntoResult();
return result;
}
}
private static void uncrossIntegersUpTo(int maxValue)
{
crossedOut = new boolean[maxValue + 1];
for (int i = 2; i < crossedOut.length; i++)
crossedOut[i] = false;
}
private static void crossOutMultiples()
{
int limit = determineIterationLimit();
for (int i = 2; i <= limit; i++)
if (notCrossed(i))
crossOutMultiplesOf(i);
}
private static int determineIterationLimit()
{
// Every multiple in the array has a prime factor that is less than or equal to the sqrt of the array size, so we don't have to cross out multiples of numbers larger than that root. //
double iterationLimit = Math.sqrt(crossedOut.length);
return (int) iterationLimit;
}
private static void crossOutMultiplesOf(int i)
{
for (int multiple = 2*i;
multiple < crossedOut.length;
multiple += i)
crossedOut[multiple] = true;
}
private static boolean notCrossed(int i)
{
return crossedOut[i] == false;
}
private static void putUncrossedIntegersIntoResult()
{
result = new int[numberOfUncrossedIntegers()];
for (int j = 0, i = 2; i < crossedOut.length; i++)
if (notCrossed(i))
result[j++] = i;
}
private static int numberOfUncrossedIntegers()
{
int count = 0;
for (int i = 2; i < crossedOut.length; i++)
if (notCrossed(i))
count++;
return count;
}
}
1
16.03.10 | kl.17:00 | Anders
Koden i eksemplet er da pæn, men er den solid? Dens brug af globale variabler (med lokalt scope) virker overflødig og ugennemtænkt:
- Det er ugennemsigtigt hvilke data hvilke funktioner afhænger af og hvilke data de producerer.
- Levetiden af de allokerede data er uklar. Sandsynligvis vil de blive liggende i hukommelsen længe efter at brugeren er holdt op med at interessere sig for sine primtal. Måske er det en tanketorsk, måske er forfatteren bare ligeglad.
- Generatoren kan producere forkerte resultater eller crashe, hvis den bruges i et multithreaded program.