Menu
Coddy logo textTech

Dissimulation de l’information en Go

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 50 sur 107.

La dissimulation de l’information va au-delà du simple fait de rendre les champs non exportés. Il s’agit de concevoir vos types de manière à ce que le code externe ne connaisse que ce qu’il a besoin de connaître. Rien de plus.

L’objectif est d’exposer le comportement par l’intermédiaire de méthodes tout en gardant la structure interne complètement cachée. Considérez cette approche :

type Counter struct {
    value    int
    maxLimit int
}

func NewCounter(limit int) *Counter {
    return &Counter{maxLimit: limit}
}

func (c *Counter) Increment() bool {
    if c.value >= c.maxLimit {
        return false
    }
    c.value++
    return true
}

func (c *Counter) Value() int {
    return c.value
}

Le code externe ne sait pas que Counter utilise un int en interne. Il pourrait s’agir d’un float64, d’une tranche ou de quelque chose de complètement différent. L’implémentation peut changer sans affecter le code qui utilise Counter, tant que les méthodes se comportent de la même manière.

Ce principe s’applique également aux fonctions utilitaires. Gardez la logique interne non exportée :

// Exporté - partie de l'API publique
func (c *Counter) Reset() {
    c.value = 0
}

// non exporté - helper interne
func (c *Counter) isAtLimit() bool {
    return c.value >= c.maxLimit
}

En masquant isAtLimit(), vous êtes libre de le modifier ou de le supprimer ultérieurement. La dissimulation des informations crée une limite claire entre ce que votre paquet promet aux utilisateurs externes et son fonctionnement interne.

challenge icon

Défi

Facile

Construisons un système de portefeuille sécurisé qui démontre la dissimulation des informations. Vous allez créer un portefeuille numérique dont le suivi interne du solde et l’historique des transactions sont complètement masqués du code externe : seul le comportement est exposé par l’intermédiaire de méthodes.

Vous organiserez votre code sur deux fichiers :

  • wallet.go : créez une structure Wallet qui masque tout son état interne. Le portefeuille doit suivre en interne le solde actuel et une limite de dépenses, mais le code externe ne doit jamais savoir comment ces données sont stockées ou représentées. Exposez le comportement au moyen de ces méthodes :
    • NewWallet(limit float64) *Wallet - constructeur qui crée un portefeuille avec la limite de dépenses donnée et un solde nul
    • Deposit(amount float64) bool - ajoute de l’argent au portefeuille et renvoie true en cas de réussite (le montant doit être positif)
    • Spend(amount float64) bool - retire de l’argent si le solde est suffisant ET si le montant ne dépasse pas la limite de dépenses, puis renvoie true en cas de réussite
    • Balance() float64 - renvoie le solde actuel
    • Status() string - renvoie un message d’état au format suivant : Balance: $[balance] (Limit: $[limit])
    Conservez toute logique auxiliaire (comme la vérification de la validité d’une transaction) dans des fonctions ou méthodes non exportées. Il s’agit de détails d’implémentation internes qui pourraient changer ultérieurement.
  • main.go : lisez la configuration du portefeuille et les transactions à partir de l’entrée, créez un portefeuille, effectuez les opérations et affichez les résultats après chaque action.

Les entrées suivantes seront fournies :

  • Ligne 1 : limite de dépenses
  • Ligne 2 : montant du dépôt
  • Ligne 3 : premier montant dépensé
  • Ligne 4 : deuxième montant dépensé

Après avoir créé le portefeuille, affichez son état initial. Effectuez ensuite chaque opération et affichez soit l’état mis à jour (en cas de réussite), soit Transaction failed (si l’opération a été refusée). Formatez tous les montants en dollars avec deux chiffres après la virgule.

Par exemple, avec 50, 100, 30 et 80, votre sortie doit être :

Balance: $0.00 (Limit: $50.00)
Balance: $100.00 (Limit: $50.00)
Balance: $70.00 (Limit: $50.00)
Transaction failed

La dernière transaction échoue parce que 80 $ dépasse la limite de dépenses de 50 $, même si le solde est suffisant. Le portefeuille applique ses règles en interne sans révéler comment il prend ces décisions. Le code externe appelle simplement les méthodes et reçoit les résultats, sans jamais connaître les détails de l’implémentation interne.

Essayez vous-même

package main

import (
	"fmt"
)

func main() {
	// Lire les entrées
	var limit float64
	var depositAmount float64
	var spend1 float64
	var spend2 float64

	fmt.Scanln(&limit)
	fmt.Scanln(&depositAmount)
	fmt.Scanln(&spend1)
	fmt.Scanln(&spend2)

	// TODO: Créer un nouveau portefeuille avec la limite de dépenses donnée

	// TODO: Afficher le statut initial

	// TODO: Perform deposit and print result (status or "Transaction failed")

	// TODO: Effectuer la première dépense et afficher le résultat

	// TODO: Effectuer la deuxième dépense et afficher le résultat
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Go en ligne