Menu
Coddy logo textTech

Masquage d'informations en Go

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

La dissimulation d'informations 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 sache que ce qu'il a besoin de savoir — rien de plus.

L'objectif est d'exposer le comportement à travers des 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 slice, ou de tout autre chose. 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é - fait partie de l'API publique
func (c *Counter) Reset() {
    c.value = 0
}

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

En masquant isAtLimit(), vous êtes libre de le modifier ou de le supprimer plus tard. Le masquage d'informations crée une frontière claire entre ce que votre package 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 d'informations. Vous allez créer un portefeuille numérique où le suivi du solde interne et l'historique des transactions sont complètement cachés du code externe — seul le comportement est exposé via des méthodes.

Vous organiserez votre code sur deux fichiers :

  • wallet.go : Créez une structure Wallet qui cache tout son état interne. Le portefeuille doit suivre le solde actuel et une limite de dépense en interne, mais le code externe ne doit jamais savoir comment ceux-ci sont stockés ou représentés. Exposez le comportement via ces méthodes :
    • NewWallet(limit float64) *Wallet - constructeur qui crée un portefeuille avec la limite de dépense donnée et un solde de zéro
    • Deposit(amount float64) bool - ajoute de l'argent au portefeuille, retourne true si l'opération réussit (le montant doit être positif)
    • Spend(amount float64) bool - retire de l'argent si le solde est suffisant ET que le montant ne dépasse pas la limite de dépense, retourne true si l'opération réussit
    • Balance() float64 - retourne le solde actuel
    • Status() string - retourne un message d'état au format : Balance: $[balance] (Limit: $[limit])
    Gardez toute logique d'assistance (comme la vérification de la validité d'une transaction) sous forme de fonctions ou de méthodes non exportées — ce sont des détails d'implémentation interne qui pourraient changer plus tard.
  • main.go : Lisez la configuration du portefeuille et les transactions depuis 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épense
  • Ligne 2 : Montant du dépôt
  • Ligne 3 : Montant de la première dépense
  • Ligne 4 : Montant de la deuxième dépense

Après avoir créé le portefeuille, affichez son état initial. Ensuite, effectuez chaque opération et affichez soit l'état mis à jour (en cas de succès), soit Transaction failed (si l'opération a été rejetée). Formatez tous les montants en dollars avec deux décimales.

Par exemple, avec 50, 100, 30 et 80, votre sortie devrait ê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 car $80 dépasse la limite de dépense de $50 — même s'il y a assez de solde. Le portefeuille applique ses règles en interne sans exposer comment il prend ces décisions. Le code externe appelle simplement des méthodes et reçoit des résultats, sans jamais connaître les détails de l'implémentation interne.

Aide-mémoire

La dissimulation d'informations consiste à concevoir des types de manière à ce que le code externe ne sache que ce qu'il a besoin de savoir. Exposez le comportement via des méthodes tout en gardant la structure interne complètement cachée.

Exemple d'un type avec une implémentation cachée :

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 connaît pas la représentation interne (cela pourrait être un int, un float64, ou n'importe quoi d'autre). L'implémentation peut changer sans affecter le code qui l'utilise.

Gardez les fonctions d'aide non exportées :

// Exported - part of public API
func (c *Counter) Reset() {
    c.value = 0
}

// unexported - internal helper
func (c *Counter) isAtLimit() bool {
    return c.value >= c.maxLimit
}

La dissimulation d'informations crée une frontière claire entre ce que votre package promet à l'extérieur et la manière dont il fonctionne à l'intérieur.

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: Effectuer le dépôt et afficher le résultat (statut ou "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