Skip to article frontmatterSkip to article content

Comment écrire une fonction ?

IUT d'Orsay, Université Paris-Saclay
Les fonctions courtes

Credits: Memegenerator

Qu’est-ce qu’une fonction courte ?

Voici une fonction longue :

#include <cmath>
#include <vector>

using namespace std;

// Generates a list of prime numbers up to maxValue 
// using the Sieve of Eratosthenes
vector<int> generatePrimes(int maxValue) {
    // Prime numbers are only possible starting from 2
    if (maxValue < 2) {
        return vector<int>();
    }

    int rangeSize = maxValue + 1;
    vector<bool> isPrime(rangeSize, true);
    isPrime[0] = isPrime[1] = false;

    // Mark non-prime numbers using the Sieve of Eratosthenes
    // Any non-prime number n must have at least one factor <= sqrt(n)
    for (int currentNumber = 2; currentNumber <= sqrt(rangeSize); currentNumber++) {
        if (isPrime[currentNumber]) {
            for (int multiple = 2 * currentNumber; multiple < rangeSize; multiple += currentNumber)
                isPrime[multiple] = false;
        }
    }

    // Store all prime numbers in a new vector
    vector<int> primes;
    for (int number = 0; number < rangeSize; number++) {
        if (isPrime[number])
            primes.push_back(number);
    }

    return primes;
}

Que fait cette fonction ?

Crible d’Ératosthène

Crible d’Ératosthène (Credits: Wikipedia)

Comment écrire une fonction courte ?

Petites boucles et peu d’indentations

Responsabilité unique

Un seul niveau d’abstraction

Maintenant, appliquons nos principes au code précédent.

#include <cmath>
#include <vector>

using namespace std;

// Generates a list of prime numbers up to maxValue 
// using the Sieve of Eratosthenes
vector<int> generatePrimes(int maxValue) {
    // Prime numbers are only possible starting from 2
    if (maxValue < 2) {
        return vector<int>();
    }

    int rangeSize = maxValue + 1;
    vector<bool> isPrime(rangeSize, true);
    isPrime[0] = isPrime[1] = false;
    
    markNonPrimes(isPrime);

    return collectPrimes(isPrime);
}

// Marks non-prime numbers using the Sieve of Eratosthenes
void markNonPrimes(vector<bool>& isPrime) {
    // Any non-prime number n must have at least one factor <= sqrt(n)
    for (int currentNumber = 2; currentNumber <= sqrt(isPrime.size()); currentNumber++) {
        if (isPrime[currentNumber]) {
            markMultiplesAsNonPrime(isPrime, currentNumber);
        }
    }
}

void markMultiplesAsNonPrime(vector<bool>& isPrime, int prime) {
    for (int multiple = 2 * prime; multiple < isPrime.size(); multiple += prime) {
        isPrime[multiple] = false;
    }
}

vector<int> collectPrimes(const vector<bool>& isPrime) {
    vector<int> primes;
    for (int number = 0; number < isPrime.size(); number++) {
        if (isPrime[number])
            primes.push_back(number);
    }
    return primes;
}

Comment écrire une fonction simple ?

Pas de duplications de code

Peu d’arguments

bool isEven(int number);

double squareRoot(int number);

void printMessage(const string& message);
void removeVowels(string& inputString);
void switchPower(bool onOrOff);
Point createPoint(int xCoordinate, int yCoordinate);
Matrix multiply(const Matrix& leftMatrix, const Matrix& rightMatrix);
bool verifyBehavior(const SomeType& expected, const SomeType& actual);
Circle makeCircle(double xCoordinate, double yCoordinate, double radius);

Pas d’effets secondaires

void activateUser(const vector<User>& users, int validUserId) {
    users[validUserId].activate();
    sendActivationNotification(users[userId].getName() + "@example.com");
}
void activateUserAndSendNotification(const vector<User>& users, int validUserId) {
    users[validUserId].activate();
    sendActivationNotification(users[userId].getName() + "@example.com");
}