Pourquoi et comment utiliser les énumérations à la place des booleans

Cet article est inspiré de celui de Andrew Bancroft. Pour les anglophones, n’hésitez pas à le lire, c’est très bien écrit et expliqué.

L’idée n’est pas de remettre en cause l’utilisation des booléens ou leur existence mais plutôt de réfléchir aux cas où il serait peut-être mieux de préférer les énumérations aux booléens.

Bien sûr le choix entre booléen et énumération fait partie des habitudes de programmation de chacun et les deux méthodes fonctionnent. Par contre je vais vous expliquez pourquoi moi (après lecture de l’article d’Andrew), j’ai décidé de réserver les booléens à certain cas d’utilisation précis et les énumérations à d’autres.

En règle générale, je réserve les booléens au code interne de mon objet et les énumérations pour transposer simplement les informations lors des interactions avec cet objet. Le but étant de rendre le code toujours plus lisible et plus simple pour améliorer l’expérience de développement et de maintenance.

Le cas étudié

Pour vous faire comprendre simplement dans quel genre de cas il est bien d’utiliser l’énumération prenons un exemple.

Un webzine souhaite proposer à ses lecteurs une offre premium leur permettant d’accéder à des articles inédit et plus recherchés que les versions gratuites. Au moment de montrer aux lecteurs le contenu on souhaite donc tester si le lecteurs a souscrit à l’offre premium ou pas. A première vue les booléens s’adapteraient bien a la situation, mais si on veut savoir :

  1. si en effet il à souscrit à l’offre ou pas, afin de lui montrer son contenu ?
  2. s’il a souscrit mais son abonnement à expiré, afin de l’avertir et lui demander de renouveler son accès ?
  3. s’il n’a jamais souscrit à l’offre, afin de lui proposer une offre de bienvenue ?

Si l’on reste sur l’idée des booléens, on se retrouve après réflexion avec plusieurs méthodes dans notre objet Reader qui servent à la même chose — indiquer l’état d’abonné du lecteur en nous renvoyant un booléen — et il faudra faire plusieurs tests dans notre code métier pour comprendre pleinement la situation de l’utilisateur :

  • isSubscriber
  • isSubscriptionExpired
  • isNonSubscriber

Pourquoi les énumérations ?

Vous avez sûrement déjà compris où est ce que je veux en venir. Dans notre cas l’utilisation des booléens est un peu lourde et le code ne sera pas très lisible pour le pauvre développeur qui utilisera notre classe.

public enum SubscriberStatus { case CurrentSubscriber case ExpiredSubscriber case NonSubscriber }

Si par contre nous n’avons qu’une seule méthode dans notre objet Reader qui renvoie l’état de l’abonnement par l’intermédiaire de l’énumération ci dessus ?

Cette méthode se présenterait comme suit :

func status() -> SubscriberStatus {  
    if true { 
        return .CurrentSubscriber 
    } 

    if true { 
       return .ExpiredSubscriber 
    } 

    return .NonSubscriber 
}

Les true ne sont là que pour l’exemple même si, me direz-vous, lorsque l’on utilise une structure conditionnelle – quelque soit le code métier – on utilise des booléens.

Je suis d’accord. Mais comme il est précisé plus haut dans l’article, dans beaucoup de cas nous utiliserons toujours les booléens dans notre code métier mais nous cherchons ici à clarifier et rendre plus lisible les interactions avec notre objet.

Je vous met aussi la version de Andrew qui est plus logique et utilise mieux les subtilité de Swift : subscriberStatus (ou status pour nous) est pour lui un attribut de Reader, il utilise donc un attribut en lecture seule qui calcule sa valeur à la volée lorsqu’on la demande.

public struct Reader {  
    public var subscriberStatus: SubscriberStatus {
        get {
            if (noSubscriptionOnFile()) {
                return .NonSubscriber
            }
            if (subscriptionOverdueForPayment()) {
                return .ExpiredSubscriber
            }
            return .CurrentSubscriber
        }
    }
    private func noSubscriptionOnFile() - > Bool {
        // Do what needs to be done to check if the registrant has a subscription on file or not
    }
    private func subscriptionOverdueForPayment() - > Bool {
        // Do what needs to be done to check if the registrant's subscription is overdue for payment
    }
}

Voici en bonus le playground du projet.

Nathanaël Cherrier

Ingenieur de développement mobile et web pour Econocom. Passionné par le développement en général, mais plus particulièrement par le développement web et mobile, je vous raconte mes petits secrets.

Subscribe to Mindsers IT

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!