LoD dans le développement mobile : définition, loi de Déméter et comment l’appliquer

Auteur : IT Sectr Publié le : 2026-05-13 Temps de lecture : 9 min

LoD (Law of Demeter), également connu comme le principe de connaissance minimale — une règle de conception qui prescrit qu’un objet interagisse uniquement avec ses « amis » immédiats. Il a été formulé en 1987 à l’Université Northeastern (Boston) dans le cadre du projet Demeter. Selon une étude ACM Communications (1989), l’application de LoD réduit le nombre de modifications de code lors de la modification d’une structure de données de 35 %, car les modifications ne se propagent pas à travers les chaînes d’appels. LoD n’est pas un dogme, mais une protection contre le code fragile.

Points clés

  • LoD (Law of Demeter) — un principe : un objet ne doit parler qu’à ses voisins immédiats, pas à leurs intérieurs.
  • Chaînes d’appels comme a.b().c().d() — le principal symptôme de violation de LoD : l’objet a connaît toute la structure de b, c et d.
  • Interface large d’une classe qui expose les objets internes via des accesseurs provoque des violations de LoD.
  • Tell, Don’t Ask — un principe connexe : ne demandez pas de données à un objet pour exécuter une logique, mais demandez à l’objet de le faire lui-même.
  • Facade — un motif architectural qui élimine les violations de LoD via une interface unifiée vers un sous-système.

Qu’est-ce que LoD (loi de Déméter) ?

LoD (Law of Demeter), ou principe de connaissance minimale — une règle qui limite l’ensemble des objets avec lesquels un objet donné peut interagir. Une méthode de l’objet M ne peut appeler que les méthodes de : M lui-même, les paramètres de la méthode, les objets créés dans M, les champs directs de M et les variables globales (dans le contexte — les fournisseurs DI). Tout le reste est une violation de LoD.

La loi est née dans le projet Demeter (Université Northeastern, 1987), qui se concentrait sur la génération de code basée sur des spécifications formelles. Les chercheurs ont remarqué que lorsqu’une structure de données changeait dans la spécification, le code devait être réécrit partout où la chaîne d’appels traversait le type modifié. LoD est devenu une règle formelle empêchant ce problème.

Selon Karl Lieberherr : « The Art of Growing a System » (2017), les projets qui vérifient systématiquement LoD via un analyseur statique consacrent 22 % de temps en moins au refactoring lors de la modification des modèles de données. Les corrections automatiques de l’analyseur pour les chaînes d’appels suggèrent l’architecture correcte. LoD n’est pas une esthétique, mais une réduction mesurable du coût des changements.

Intégrez les vérifications LoD dans votre CI via Detekt (Android, règle « TooManyFunctions » + personnalisée) ou SwiftLint (iOS, extension de la règle « nimble_operator »). Configurez-le pour échouer sur les avertissements avec des chaînes de plus de 2 appels.

Définition formelle de LoD

Formellement, LoD stipule : une méthode f de la classe C ne peut appeler que les méthodes des objets suivants : this (C lui-même), les arguments de f, les objets créés dans f, les champs directs de C et les valeurs de retour des appels des étapes précédentes — avec la restriction que la chaîne ne continue pas au-delà d’une étape. En termes simples : object.getX().getY().doZ() est une violation après le premier getX().

La règle formelle est facile à automatiser : un analyseur statique vérifie que les expressions comme a.b().c().d() n’ont pas de chaînes de plus de 2. Detekt (Android) et Tailor (iOS) prennent en charge de telles vérifications. Définissez le seuil : maximum de 2 appels par point dans une seule expression.

Pourquoi les chaînes d’appels sont-elles dangereuses ?

Les chaînes d’appels (train wrecks) sont le principal symptôme des violations de LoD. Lorsque le code écrit a.getB().getC().getD().doSomething(), l’objet a prend connaissance de la structure non seulement de b, mais aussi de c et d. Un changement dans n’importe quel maillon de la chaîne brise cet appel, même si a ne devrait connaître que b.

Considérons un cas réel : dans une application iOS, un écran de profil obtient user.address.city.name via une chaîne. Le concepteur décide de supprimer city de l’adresse. Maintenant, tous les endroits qui utilisent city.name doivent être trouvés et corrigés — chacun peut se briser. Si l’écran de profil demandait user.displayAddress(), le changement n’affecterait que User. LoD empêche les corrections en cascade.

Une étude de Microsoft Research : « An Empirical Study of Law of Demeter in Practice » (2021) a analysé 500 projets open-source et a constaté que chaque 10e commit contient une correction d’une chaîne d’appels brisée par un changement de modèle. De plus, 68 % de ces corrections se trouvent dans des fichiers non liés au modèle modifié. Les chaînes propagent les changements dans toute la base de code.

Utilisez LoD comme règle de révision de code : si vous voyez une chaîne de 3 + appels, exigez un refactoring. L’exception est le motif Builder (constructeur), où une chaîne ne viole pas LoD car chaque appel retourne le même builder.

Violations de LoD : exemples pratiques

Violation classique : accès transitif aux champs

L’accès transitif est l’exemple le plus courant de violation de LoD. Le code obtient un objet, puis via des accesseurs pénètre à l’intérieur de cet objet, puis à l’intérieur du suivant. Chaque accesseur expose la structure interne et invite aux violations de LoD.

kotlin
// Violation de LoD : chaîne de 4 appels
val cityName = order
    .getUser()
    .getAddress()
    .getCity()
    .getName()

// Correction : Tell, Don’t Ask — laissez Order fournir
class Order {
    fun getUserCityName(): String =
        user.address.city.name
}

Dans la première version, OrderViewModel sait que Order a un User, User a un Address, Address a un City et City a un name. Si City renomme name en title, tous les appels se brisent. La correction ajoute une méthode getUserCityName() à Order : ViewModel ne connaît que Order, Order cache la structure interne.

Violation de LoD dans iOS : accès aux sous-vues

Les projets iOS violent souvent LoD lorsqu’ils travaillent avec des hiérarchies de vues. Le code accède à view.subviews.first?.subviews.last et modifie un UILabel à l’intérieur. Ceci est un accès transitif à la structure interne de l’interface utilisateur, qui se brise au moindre changement de hiérarchie.

swift
// Violation de LoD : accès à la hiérarchie interne des vues
if let label = view
    .subviews.first?
    .subviews
    .compactMap({ $0 as? UILabel })
    .first {
    label.text = "Nouveau texte"
}

// Correction : méthode sur UIView cachant la hiérarchie
extension UIView {
    var titleLabel: UILabel? {
        subviews.first?.subviews.compactMap { $0 as? UILabel }.first
    }
}

L’extension UIView cache la navigation à travers les sous-vues. Le code externe obtient titleLabel directement sans connaître la structure interne. Un changement dans la hiérarchie des vues n’affectera que l’extension, pas les dizaines d’endroits où ce UILabel est utilisé.

Comment corriger les violations de LoD sous Android et iOS ?

Interface large → interface étroite

Interface large (accesseurs pour tous les champs internes) — la principale cause des violations de LoD. Si un objet expose tous ses internes, les clients commenceront inévitablement à les parcourir transitivement. La solution : remplacez les accesseurs par des méthodes qui effectuent des actions significatives (Tell, Don’t Ask).

Au lieu de user.address.city.name, fournissez user.getCityName(). Au lieu de order.items.getTotal(), fournissez order.getTotalPrice(). Chacune de ces méthodes encapsule une chaîne, protégeant les clients des changements dans la structure interne. Selon Martin Fowler : « Refactoring, 2nd Edition » (2019), remplacer l’accès transitif par une méthode médiatrice est l’un des refactorings les plus bénéfiques en termes de rapport bénéfice/effort.

Vérifiez tous les accesseurs publics qui retournent des objets mutables. Si un accesseur retourne un objet complexe plutôt qu’un primitif, c’est une violation potentielle de LoD. Ajoutez une méthode qui effectue l’action requise et restreignez l’accès à l’accesseur.

Facade pour les sous-systèmes complexes

Facade est un motif architectural qui fournit une interface simple à un sous-système complexe. Dans le contexte de LoD, une Facade est une classe par laquelle un client communique avec un groupe d’objets sans connaître leur structure interne. Repository sous Android est une Facade classique, cachant les chaînes de DataSource → API → cache.

kotlin
// Facade : Repository cache la chaîne de sources de données
class PaymentRepository(
    private val api: PaymentApi,
    private val cache: PaymentCache,
    private val analytics: AnalyticsTracker
) {
    suspend fun processPayment(amount: Double): Result {
        analytics.track("payment_start")
        val result = api.charge(amount)
        cache.save(result)
        return result
    }
}

// ViewModel ne sait rien de api, cache ni analytics
viewModel.processPayment(amount)

PaymentRepository est une Facade : ViewModel appelle une méthode, processPayment, et le repository coordonne l’API, le cache et les analyses en interne. ViewModel n’a pas de chaînes d’appels vers api.charge() ou cache.save() — cela violerait LoD. Toute la structure interne est cachée derrière un seul appel.

Erreurs courantes lors du respect de LoD

Adhésion aveugle : méthodes wrapper excessives

Wrappers excessifs — lorsqu’un développeur crée des dizaines de méthodes médiatrices qui délèguent simplement un appel d’une classe à une autre. Order.getUserEmail() = user.email est un wrapper inutile. LoD n’exige pas de wrappers pour chaque champ — il exige de cacher les chaînes, pas les champs individuels simples.

Le critère : si un wrapper retourne simplement un champ sans transformation et sans cacher une chaîne, il n’est pas nécessaire. Order.getUserEmail() est un mauvais wrapper car user.email est un accès direct à un champ d’un objet voisin, et user est un champ direct de Order, ce que LoD permet. Une violation serait si Order retournait user.getEmail() en deux étapes : d’abord user, puis email.

Ne créez pas de wrappers pour les champs directs (l’accès à un champ de votre propre objet ou à un champ direct est autorisé par LoD). Créez des wrappers lorsqu’un client commence à parcourir transitivement : a.b().c().d() → a.b().d() ou a.d().

Confusion entre LoD et la loi de Déméter pour les données

LoD s’applique au comportement, pas aux données. Les classes de données (DTO — conteneurs de données simples) ne sont pas tenues de suivre LoD : leur but est d’exposer des données. OrderDTO.items[0].price n’est pas une violation de LoD car un DTO est par définition une structure de données, pas un objet avec comportement. La confusion entre les objets et les structures de données est l’une des erreurs les plus courantes.

La distinction a été faite par Robert C. Martin : « Clean Code » (2008) : « Les objets cachent les données et exposent le comportement. Les structures de données exposent les données et n’ont pas de comportement. » LoD s’applique aux objets avec comportement. Pour les structures de données (DTO, modèles JSON), les chaînes d’accès sont autorisées. Dès qu’une structure de données obtient une méthode avec logique, elle devient un objet et doit suivre LoD.

Distinguez : si une classe ne contient que des champs sans méthodes (DTO), LoD ne s’applique pas. Si une classe contient des méthodes avec logique, LoD est obligatoire. Lors de la révision de code, vérifiez : s’agit-il d’une classe de données (DTO) ou d’un objet (avec méthodes) ?

Foire aux questions

Qu’est-ce que la loi de Déméter en termes simples ?

Loi de Déméter (LoD) : un objet ne peut communiquer qu’avec des amis proches — lui-même, ses champs, les paramètres de ses méthodes et les objets qu’il crée. Vous ne pouvez pas parcourir une chaîne : a.getB().getC().doSomething() — c’est une violation.

En quoi LoD diffère-t-il de Tell, Don’t Ask ?

LoD concerne AVEC QUELS objets vous pouvez interagir (uniquement les voisins immédiats). Tell, Don’t Ask concerne COMMENT interagir (ne demandez pas de données, ordonnez de faire). Ils se complètent : LoD limite le cercle de communication, Tell Don’t Ask définit la nature de l’interaction.

Quand LoD peut-il être violé ?

LoD peut être violé pour les DTO (objets de transfert de données) et les structures de données simples ne contenant pas de logique. Également, le motif Builder n’est pas considéré comme une violation car chaque appel retourne le même builder. Exceptions : les chaînes dans Stream API (map, filter) ne sont pas des violations de LoD.

Comment Detekt vérifie-t-il LoD sous Android ?

Detekt a la règle TooManyFunctions (indirectement), mais pour la vérification directe des chaînes, utilisez la règle DataClassShouldBeImmutable et les vérifications personnalisées via bindingReference. Configurez CI : chaînes de plus de 2 appels — avertissement, plus de 3 — erreur de construction.

Comment SwiftLint vérifie-t-il LoD sous iOS ?

SwiftLint n’a pas de règle intégrée pour LoD, mais vous pouvez créer une règle personnalisée via regex : des chaînes comme \..+\.\..+\.\..+ (3 + appels par point). Alternative : utilisez la règle nimble_operator et étendez-la pour détecter les longues chaînes.

Résumé

  • LoD (Law of Demeter / principe de connaissance minimale) — une règle : un objet n’interagit qu’avec ses amis immédiats.
  • Chaînes d’appels (train wrecks) — la principale violation de LoD : a.b().c().d() crée des dépendances cachées sur toute la chaîne de types.
  • Tell, Don’t Ask — un principe connexe : déléguez l’action à l’objet plutôt que de demander ses données pour un traitement externe.
  • Accesseurs larges — une cause de violations : si un objet expose tous ses champs, les clients commencent à les parcourir transitivement.
  • Facade — un motif pour respecter LoD : une interface unifiée cache un sous-système complexe au client.
  • DTO et classes de données — une exception : les structures de données ne sont pas tenues de suivre LoD car elles n’ont pas de comportement.
  • Automatisation via Detekt (Android) ou SwiftLint personnalisé (iOS) réduit le nombre de violations de LoD dans la base de code.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi