> ## 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.

# Optimisez votre code SwiftUI : Deux méthodes pour éviter la duplication
- URL: https://mindsers.blog/fr/post/optimisez-votre-code-swiftui-deux-methodes-pour-eviter-la-duplication/
- Published: 2023-06-24T14:13:57.000Z
- Updated: 2023-10-15T18:39:58.000Z
- Author: Nathanaël Cherrier
- Tags: coding-tech, swift, best practices, cleancode, #lang-fr

La **duplication de code** est un vrai problème dans les applications. Avoir beaucoup de **code dupliqué** signifie “**maintenance compliquée**” mais aussi une expérience catastrophique.

J’ai deux méthodes pour éviter ce problème dans mes applications SwiftUI. Je vous les présente dans cet article.

## Composants custom pour une meilleure modularité du code SwiftUI

Comme on le ferait avec d’autres frameworks, SwiftUI permet de créer des vues de façon déclarative/descriptive.

Les vues sont composées d’autres vues et on peut répéter le schema à l’infini sur plusieurs niveaux.

```swift
struct SignInScreen: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 10) {
            Text("Se connecter")
            Spacer()
        }
    }
}

```

Dans l’exemple ci-dessus, la vue `SignInScreen` est composée d’un vue `VStack`, d’une vue `Text` et une vue `Spacer`. Même fonctionnement donc qu’un framework web ou le composant global va être composé de plusieurs composants plus petits.

Puisque les vues ne sont que des assemblages de vue, nous pouvons nous aussi créer nos propres vues pour rassembler des **éléments qui se répètent**.

```swift
struct SignInScreen: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 10) {
            TextField("Adresse e-mail", text: $email)

			DividerCustom()
            
            Button("Connexion") {
                // action
            }
        }
    }
}

struct SignUpScreen: View {
    var body: some View {
        VStack(alignment: .leading, spacing: 10) {
            TextField("Adresse e-mail", text: $email)

			DividerCustom()
            
            Button("Inscription") {
                // action
            }
        }
    }
}

struct DividerCustom: View {
    var body: some View {
        HStack(alignment: .center) {
            VStack {
                Divider()
                    .frame(height: 1.0)
                    .background(.green)
            }
            Text("ou")
            VStack {
                Divider()
                    .frame(height: 1.0)
                    .background(.green)
            }
        }
    }
}

```

La vue `DividerCustom` regroupe trois autres vues et forme ainsi une vue qui est rappelée dans la vue `SignInScreen` et `SignUpScreen`.

Modifier le code de `DividerCustom` va mettre à jour l’élément dans les deux composants où il est utilisé. Cela **évite donc que le code soit dupliqué** plusieurs fois dans l’application.

## Optimisation avec les modifiers et ViewModifier

Des fois, ce que l’on duplique ce n’est pas un ensemble de vues mais un ensemble de modifications sur une seule vue.

```swift
struct Buttons: View {
    var body: some View {
        Button {
            // action
        } label: {
            Label("Connexion avec Google", image: "GoogleLogo")
                .frame(maxWidth: .infinity)
        }
        .padding()
        .frame(minWidth: 300, alignment: .center)
        .background(backgroundColor)
        .foregroundColor(foregroundColor)
        .cornerRadius(30)
        .font(.Theme.regular(size: 16))

        Button {
            // action
        } label: {
            Label("Connexion avec Facebook", image: "FacebookLogo")
                .frame(maxWidth: .infinity)
        }
        .padding()
        .frame(minWidth: 300, alignment: .center)
        .background(backgroundColor)
        .foregroundColor(foregroundColor)
        .cornerRadius(30)
        .font(.Theme.regular(size: 16))

        Button {
            // action
        } label: {
            Label("Connexion avec GitHub", image: "GitHubLogo")
                .frame(maxWidth: .infinity)
        }
        .padding()
        .frame(minWidth: 300, alignment: .center)
        .background(backgroundColor)
        .foregroundColor(foregroundColor)
        .cornerRadius(30)
        .font(.Theme.regular(size: 16))
    }
}

```

Dans l'exemple ci-dessus, on veut afficher trois boutons de connexion pour différents services.

On ne veut pas changer le comportement d'un bouton classique ou même l'associer à d'autres vues pour qu'ils fonctionnent ensemble. Ce que l'on veut ici, c'est modifier le design du bouton et que tous les boutons se ressemblent.

On se retrouve donc avec 6 lignes de modification d'un bouton qui sont dupliquées à chaque fois qu'un nouveau bouton est créé.

Si je souhaite finalement modifier la largeur maximale du bouton, je vais devoir appliquer la modification manuellement pour chaque bouton.

Une solution pour éviter **la duplication de code** (et **simplifier la maintenance de l'application**) dans cette situation, ce sont les `ViewModifier`. Il s'agit d'une méthode pour appliquer des modifiers à plusieurs vues très simplement :

```swift
struct BasicButton: ViewModifier {
    let backgroundColor: Color
    let foregroundColor: Color
    
    func body(content: Content) -> some View {
        content
            .padding()
            .frame(minWidth: 300, alignment: .center)
            .background(backgroundColor)
            .foregroundColor(foregroundColor)
            .cornerRadius(30)
            .font(.Theme.regular(size: 16))
    }
}

```

Un `ViewModifier` est un `struct` avec une fonction `body`. C’est cette fonction qui va appliquer les styles à nos vue.

Pour l’utiliser on utilise le modifier générique `modifier()` comme suit:

```swift
Button {
  // action
} label: {
  Label("Connexion avec GitHub", image: "GitHubLogo")
    .frame(maxWidth: .infinity)
}
.modifier(BasicButton(backgroundColor: .black, foregroundColor: .white))

```

Voilà c’est tout !

`BasicButton` va appliquer les styles à notre vue `Button` sans plus d’effort.

Pour rendre le code un peu plus élégant, voici une petite astuce :

1. On ajoute tout d’abord une fonction à la classe `View` qui va appeler le modifier.Notons également l’utilisation des paramètres optionnels pour ne pas devoir les mentionner s’ils ne changent pas.
2. Et on appelle cette fonction depuis notre vue `Bouton` comme les modifiers classiques

Vous pouvez également limiter l'utilisation de ce modificateur à la vue `Button` en étendant la classe `Button` plutôt que `View`, comme nous l'avons fait ici.

L'inconvénient est que vous ne pourrez appeler le modificateur que directement sur la vue. Il ne pourra pas être chaîné à la suite d'autres modificateurs, car ceux-ci retournent un objet de type `View` et non `Button`.

## Conclusion

Comme déjà discuté, **éviter la duplication de code** n'est pas qu'une bonne pratique pour faire "joli". Il s'agit plutôt d'une des façons les plus simples d'**optimiser son code** pour **réduire le temps de développement** et le temps de **maintenance d'une application**.

N'hésitez pas à utiliser les `ViewModifier` ou la création de composants custom pour **optimiser votre code SwiftUI**.