> ## Content Index
> Fetch the complete content index at: https://mindsers.blog/llms.txt
> Use this file to discover other available public pages before exploring further.

# Injection de dépendances et découplage dans une application Swift iOS
- URL: https://mindsers.blog/fr/post/injection-de-dependance-et-decouplage-dans-une-application-swift-ios/
- Published: 2016-09-14T06:13:00.000Z
- Updated: 2021-08-22T19:49:22.000Z
- Author: Nathanaël Cherrier
- Tags: swift, coding-tech, ios, decoupling, dependency injection, best practices, #lang-fr

Il n'y a pas longtemps nous avons discuté de [l'injection de dépendance et du découplage dans leur globalité](https://mindsers.blog/fr/post/decouplez-votre-code/). C'est un principe que j'essaie d'appliquer à tous mes projets.

J'ai donc tenté la chose dans mes applications iOS. Le gros problème est la structure même d'une application iOS : le centre du projet (et de l'application du coup) sont les `ViewController` qui sont, pour la plupart des cas, liés aux objets créés dans interface builder. Difficile donc, d'injecter mes dépendances à l'initialisation de mon contrôleur.

Une grande partie de la navigation se fait par les `segue`, là aussi tout est géré par le système et l'injection de dépendance ainsi que le découplage semble impossible.

## Découplage du code métier

Pour rappel, le découplage consiste à réduire au maximum les dépendances de notre code aux différents éléments extérieurs (framework, plateforme, etc.).

Le but étant :

- des changements de structure simplifiés
- des tests plus simples à écrire
- du code simplifié
- du code plus réutilisable

Dans mon projet iOS, je vois l'ensemble comme un framework. Comment pourrais-je découpler mon code de façon à ce que le code métier soit réutilisable si je devais changer de framework ? Pour une application web en Swift, par exemple.

## Expérimentations.

Je suis une règle simple dans ma recherche du découplage : **éviter au maximum de mettre du code métier dans des fichiers propres à un projet iOS**. J'en viens à me construire une micro-application dans l'application.

Je tiens à préciser que ce que je fais ici n'est pas forcément la meilleure solution. J'explique juste la méthode que j'utilise en ce moment. Libre à chacun de juger si la méthode lui convient ou s'il faut en améliorer certains aspects.

Voici un exemple de structure dans un de mes projets. Il s'agit d'une application de conversion de devises.

```
Class/
    RatesProvider/
        RatesProvider.swift
        FixerIOProvider.swift
        YahooProvider.swift
    Converter.swift
Controller/
View/
Model/
AppDelegate.swift

```

Pour tout ce qui est des dossiers `Controller`, `View`,`Model`, et du fichier `AppDelegate.swift` je pense que vous voyez très bien de quoi il s'agit et ce n'est pas vraiment le sujet ici.

Ce qui nous intéresse, c'est le dossier `Class`. C'est là que je range mes classes métiers. Dans ces fichiers, il n'y a aucune référence à du code "Swift iOS". Par exemple, je n'y importe pas `UIKit`. Si je copie ce dossier dans un projet [Vapor](https://github.com/vapor/vapor?ref=mindsers.blog) il fonctionnera.

Pour ce qui est des interactions entre les classes métier, je pratique intensivement le découplage par injection de dépendances. Exemple :

Pour convertir (`Converter()`) une valeur USD en valeur EUR, j'ai besoin de connaitre les taux de change pour cette paire de devises : Je vais utiliser un service — provider — qui me fournira ces valeurs régulièrement mises à jour. Nouvelle responsabilité, nouvelle classe. (`FixerIOProvider()`)

Je pourrais éventuellement changer de provider à l'avenir : Je définis un contrat (ou `protocol` en Swift) qui va définir les modalités pour qu'un provider puisse être utilisé dans mon application (`RatesProvider()`). Ma classe `Converter` demandera à utiliser des objets respectant le protocole `RatesProvider`. Je fais en sorte que `FixerIOProvider` implémente `RatesProvider`.

Effectivement, je finis par vouloir changer de provider ; de FixerIO je passe à Yahoo Finances. J'écris la classe `YahooProvider` qui implémente le protocole `RatesProvider` et je la passe a `Converter()` en lieu et place de `FixerIOProvider()`. Aucun autre changement n'est nécessaire.

Mes classes doivent au maximum être indépendantes les unes des autres. J'ai plus de fichiers, mais je gagne en flexibilité et mon code est bien plus agréable à lire, plus simple à comprendre.

### Quid du container d'injection de dépendance ?

Pour beaucoup, l'injection de dépendance ne va pas sans container. Et il est vrai que ça a des avantages. Mais je n'en utilise pas dans mes projets iOS.

Je n'ai malheureusement pas trouvé de solution qui me convienne pour l'instant. Ce qui existe ne me plait pas vraiment. Ce que j'ai codé n'est pas top non plus.

Donc en attendant de trouver mieux, j'utilise le [Factory Pattern](https://en.wikipedia.org/wiki/Factory%5Fmethod%5Fpattern?ref=mindsers.blog).

## Conclusion : découpler une application iOS, c'est possible !

Voilà ce que je retiens. Le but n'est pas de réinventer le fonctionnement d'interface builder, l'appel aux contrôleurs et tout le reste. Apple a bien assez d'ingénieurs pour ça.

Nous ce que l'on veut, c'est séparer notre code métier du code projet iOS exactement comme on l'aurait fait avec Symfony si on codait en PHP. Et ça, c’est possible.

Bien-sûr, comme on l'a vu, il y a encore une bonne marge de progression, mais je continue à chercher.